diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 4805b6c9..2da6a069 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -37,7 +37,7 @@ body: attributes: label: System Info description: Output of `npx envinfo --system --npmPackages vitepress --binaries --browsers` - render: sh + render: Text placeholder: System, Binaries, Browsers validations: required: true diff --git a/.github/contributing.md b/.github/contributing.md index 9cbd4e62..24a4a745 100644 --- a/.github/contributing.md +++ b/.github/contributing.md @@ -30,6 +30,8 @@ After cloning the repo, run: ```sh # install the dependencies of the project $ pnpm install +# setup git hooks +$ pnpm simple-git-hooks ``` ### Setup VitePress Dev Environment diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..f8cd3d5a --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,16 @@ +### Description + + + +### Linked Issues + + + +### Additional Context + + + +--- + +> [!TIP] +> The author of this PR can publish a _preview release_ by commenting `/publish` below. diff --git a/.github/workflows/cr-comment.yml b/.github/workflows/cr-comment.yml new file mode 100644 index 00000000..203b7e11 --- /dev/null +++ b/.github/workflows/cr-comment.yml @@ -0,0 +1,18 @@ +name: Add continuous release label + +on: + issue_comment: + types: [created] + +permissions: + pull-requests: write + +jobs: + label: + if: ${{ github.event.issue.pull_request && (github.event.comment.user.id == github.event.issue.user.id || github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'COLLABORATOR') && startsWith(github.event.comment.body, '/publish') }} + runs-on: ubuntu-latest + + steps: + - run: gh issue edit ${{ github.event.issue.number }} --add-label cr-tracked --repo ${{ github.repository }} + env: + GITHUB_TOKEN: ${{ secrets.CR_PAT }} diff --git a/.github/workflows/cr.yml b/.github/workflows/cr.yml new file mode 100644 index 00000000..7dd5c4c7 --- /dev/null +++ b/.github/workflows/cr.yml @@ -0,0 +1,49 @@ +name: CR + +env: + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' + +on: + pull_request: + branches: [main] + types: [opened, synchronize, labeled, ready_for_review] + paths-ignore: + - '.github/**' + - '!.github/workflows/cr.yml' + - '__tests__/**' + - 'art/**' + - 'docs/**' + - '*.md' + push: + branches: [main] + paths-ignore: + - '.github/**' + - '!.github/workflows/cr.yml' + - '__tests__/**' + - 'art/**' + - 'docs/**' + - '*.md' + tags-ignore: + - '*' + +permissions: {} + +concurrency: + group: ${{ github.workflow }}-${{ github.event.number }} + cancel-in-progress: true + +jobs: + release: + if: ${{ ((github.event_name == 'pull_request' && !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')) || (github.event_name == 'push' && !startsWith(github.event.head_commit.message, 'release:'))) && github.repository == 'vuejs/vitepress' }} + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v3 + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: pnpm + - run: pnpm install + - run: pnpm build + - run: npx pkg-pr-new publish --compact --no-template --pnpm diff --git a/.github/workflows/lock-threads.yml b/.github/workflows/lock-threads.yml index b7f2ed09..c76a2acb 100644 --- a/.github/workflows/lock-threads.yml +++ b/.github/workflows/lock-threads.yml @@ -2,22 +2,25 @@ name: Lock Threads on: schedule: - - cron: 0 0 * * * + - cron: 38 4 * * * workflow_dispatch: permissions: issues: write pull-requests: write + discussions: write concurrency: group: lock jobs: action: + if: github.repository == 'vuejs/vitepress' runs-on: ubuntu-latest steps: - - uses: dessant/lock-threads@v4 + - uses: dessant/lock-threads@v5 with: issue-inactive-days: 7 pr-inactive-days: 7 exclude-any-issue-labels: 'keep-open' + exclude-any-pr-labels: 'keep-open' diff --git a/.github/workflows/release-tag.yml b/.github/workflows/release-tag.yml index 1c44cac0..84a03487 100644 --- a/.github/workflows/release-tag.yml +++ b/.github/workflows/release-tag.yml @@ -7,11 +7,12 @@ on: jobs: release: + if: github.repository == 'vuejs/vitepress' runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Create Release for Tag id: release_tag diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 00000000..f5826155 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,18 @@ +name: Close stale issues and PRs +on: + workflow_dispatch: + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + with: + days-before-stale: 30 + days-before-close: -1 + stale-issue-label: stale + stale-pr-label: stale + # action has a bug that keeps removing the stale label from stale PRs + # it's thinking that the PR is updated when the stale label is added + remove-pr-stale-when-updated: false + operations-per-run: 1000 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 516ff3f2..51d3fffe 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,45 +1,47 @@ name: Test -env: - NODE_OPTIONS: --max-old-space-size=6144 - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' - VITEST_SEGFAULT_RETRY: 3 - on: push: branches: [main] pull_request: branches: [main] - types: [opened, synchronize, reopened] workflow_dispatch: +permissions: {} + concurrency: group: ${{ github.workflow }}-${{ github.event.number || github.sha }} cancel-in-progress: true jobs: test: - runs-on: ubuntu-latest - strategy: matrix: - node_version: [16, 18, 20] + os: [ubuntu-latest] + node_version: [20, 22, latest] + include: + - os: windows-latest + node_version: 22 + + runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v3 - name: Set node version to ${{ matrix.node_version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node_version }} cache: pnpm - name: Install deps run: pnpm install + env: + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - name: Install Playwright run: pnpm playwright install chromium diff --git a/.gitignore b/.gitignore index 81c00934..64331052 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ examples-temp node_modules pnpm-global TODOs.md +*.timestamp-*.mjs diff --git a/.npmrc b/.npmrc index 6c6d3995..ab953072 100644 --- a/.npmrc +++ b/.npmrc @@ -1,2 +1,2 @@ shell-emulator=true -resolution-mode=highest +auto-install-peers=false diff --git a/.prettierignore b/.prettierignore index 9b706e19..32f2a7ad 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,3 +5,5 @@ pnpm-lock.yaml cache template temp +!CHANGELOG.md +.temp diff --git a/CHANGELOG.md b/CHANGELOG.md index e1582cbf..4d737c93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,1217 +1,1901 @@ -# [1.0.0-beta.1](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.76...v1.0.0-beta.1) (2023-05-22) - +## [2.0.0-alpha.5](https://github.com/vuejs/vitepress/compare/v2.0.0-alpha.4...v2.0.0-alpha.5) (2025-04-21) ### Bug Fixes -* **config:** set scrollOffset to 0 is not effect ([#2395](https://github.com/vuejs/vitepress/issues/2395)) ([8153f23](https://github.com/vuejs/vitepress/commit/8153f23c901a6200661813e65f0d8eb602ad46da)) -* **theme:** features section layout is not consistent ([#2382](https://github.com/vuejs/vitepress/issues/2382)) ([26f21d9](https://github.com/vuejs/vitepress/commit/26f21d95dfbd671477d425e6b8ac5b0172a846ac)) -* **theme:** some global properties in localSearch are missing ([#2396](https://github.com/vuejs/vitepress/issues/2396)) ([4896811](https://github.com/vuejs/vitepress/commit/489681117f46a803704b6ec80546a5e787e19df2)) -* **theme:** custom target and rel in navbar links for mobile is missing ([#2400](https://github.com/vuejs/vitepress/issues/2400)) ([f364a5d](https://github.com/vuejs/vitepress/commit/f364a5d1d3c066c9728beb5d07576d6cb4b0640d)) +- don't remove shiki styles from `pre` and remove unnecessary transformers (#4652) ([db58af5](https://github.com/vuejs/vitepress/commit/db58af5c66e563e7663084057a9853d8f2da984c)), closes [#4652](https://github.com/vuejs/vitepress/issues/4652) +- normalize url fragments in internal links to correctly resolve to anchors ([#4628](https://github.com/vuejs/vitepress/issues/4628)) ([e25d080](https://github.com/vuejs/vitepress/commit/e25d0805505db2f1116e99d38a488d5cb39ed426)), closes [#4605](https://github.com/vuejs/vitepress/issues/4605) +- **theme-default:** ensure proper sizing of SVG hero images ([#4639](https://github.com/vuejs/vitepress/issues/4639)) ([7d94481](https://github.com/vuejs/vitepress/commit/7d9448192079e59493aa5c1e86cdf6d6deae8e36)) +### Features +- add `isHome` frontmatter option (#4673) ([544cd81](https://github.com/vuejs/vitepress/commit/544cd8125985b9e3af7fee68ea9592d159799e01)), closes [#4673](https://github.com/vuejs/vitepress/issues/4673) +- add `custom-block-title-default` class when default title is used for containers ([#4643](https://github.com/vuejs/vitepress/issues/4643)) ([63079bf](https://github.com/vuejs/vitepress/commit/63079bff03b15861d174199f7361a2aff84380e0)) +- add `dir=ltr` by default on code block pre elements instead of relying on css ([19faa16](https://github.com/vuejs/vitepress/commit/19faa16169b44f52bedf1401b4a97b2a8ffdeacb)) +- **default-theme:** make VPButton slottable ([#4689](https://github.com/vuejs/vitepress/issues/4689)) ([0b70397](https://github.com/vuejs/vitepress/commit/0b7039719782e85119ad22be5c89ef3d233ffaae)) +- support distributed config files ([#4660](https://github.com/vuejs/vitepress/issues/4660)) ([c5e2e4d](https://github.com/vuejs/vitepress/commit/c5e2e4db818c06f3c1b458753f22fb6ec1609628)) +- **theme:** make "Take me home" button's link customizable ([#4658](https://github.com/vuejs/vitepress/issues/4658)) ([0267dca](https://github.com/vuejs/vitepress/commit/0267dcafa20beea24ef359d24bb1fa99e1ffda49)) -# [1.0.0-alpha.76](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.75...v1.0.0-alpha.76) (2023-05-18) +### Performance Improvements +- call `module.enableCompileCache()` ([70de34c](https://github.com/vuejs/vitepress/commit/70de34c0387d9668ada3ea9a795f9ebee3535f5b)) +- hoist expensive operations in useLayout ([e5ab067](https://github.com/vuejs/vitepress/commit/e5ab0676a9a8dc607e213eb691439b2e4ee472b7)) -### Bug Fixes +### BREAKING CHANGES -* **a11y:** mobile and theme switcher ([#2354](https://github.com/vuejs/vitepress/issues/2354)) ([d6c0985](https://github.com/vuejs/vitepress/commit/d6c0985002ee792b1e8e052f71cdd6bd72c315ad)) -* **build:** uniform handling of windows slash in localSearchPlugin ([#2358](https://github.com/vuejs/vitepress/issues/2358)) ([b31933f](https://github.com/vuejs/vitepress/commit/b31933fbdd7aabfe080234407153aefa8f6a3f30)) -* hmr when `base` is set ([#2375](https://github.com/vuejs/vitepress/issues/2375)) ([484ff5d](https://github.com/vuejs/vitepress/commit/484ff5dd4bd2e5c2d5168437895d400a39f2bfa8)) -* **theme:** don't update opacity on hover ([#2326](https://github.com/vuejs/vitepress/issues/2326)) ([35f8b89](https://github.com/vuejs/vitepress/commit/35f8b896372e75e62882df613a49e8945e7bc832)) +- `useLocalNav` and `useSidebar` are removed in favor of `useLayout`. To migrate, just do find and replace. Sidebar controls are no longer exported, but we didn't find any usage on GitHub. If there is demand, we can export respective composables later. `DefaultTheme.DocSidebar` and `DefaultTheme.DocLocalNav` types are also removed. +- `vp-adaptive-theme` class is no longer added to code blocks when there is single theme. Theme authors supporting single code theme can use `.shiki:not(.shiki-themes)` as selector. Alternatively, it might be better to use the bg/fg variables set on the `.shiki` block to keep things generic. +- `vp-code` class is no longer added to code blocks. Use `.shiki` or `pre.shiki` or `[class*='language-'] pre` instead. People not customizing their themes are not affected. +## [2.0.0-alpha.4](https://github.com/vuejs/vitepress/compare/v2.0.0-alpha.3...v2.0.0-alpha.4) (2025-03-09) -### Features - -* **cli:** add shortcuts ([#2353](https://github.com/vuejs/vitepress/issues/2353)) ([97065ce](https://github.com/vuejs/vitepress/commit/97065cefc22e4772c0295c5ad23a87eea286f46b)) -* **theme:** add focus trap to local search dialog ([#2324](https://github.com/vuejs/vitepress/issues/2324)) ([2f482af](https://github.com/vuejs/vitepress/commit/2f482afaabdb4206b87e2453d0099257693c4653)) -* **theme:** open search box on pressing slash too ([#2328](https://github.com/vuejs/vitepress/issues/2328)) ([c20bd28](https://github.com/vuejs/vitepress/commit/c20bd283319158135e2d850485970dfc5fe82812)) +### Bug Fixes +- **build/regression:** langAlias not working ([06ae2bf](https://github.com/vuejs/vitepress/commit/06ae2bf3a4ee02351530b0bd055e577ca6509d62)), closes [#4581](https://github.com/vuejs/vitepress/issues/4581) +- don't hardcode `tabindex` attr in table renderer ([#4082](https://github.com/vuejs/vitepress/issues/4082)) ([aadc517](https://github.com/vuejs/vitepress/commit/aadc517c69fb239bdda99173bbc123ace567484b)) +- hmr not working for watched files in path loaders ([e271695](https://github.com/vuejs/vitepress/commit/e271695d716247455ca620948f814e6c8ca0e3c4)), closes [#4525](https://github.com/vuejs/vitepress/issues/4525) +- ignore non-text content in permalink generation and fix types of markdown.config ([a8a1800](https://github.com/vuejs/vitepress/commit/a8a1800ae578be88027aa4ec7561ada4d055b888)) +- prevent reload on first server start in fresh installations ([d8a884e](https://github.com/vuejs/vitepress/commit/d8a884ed0f754523765058a70149cdbaf6942341)) +- properly merge classes in custom containers ([#4128](https://github.com/vuejs/vitepress/issues/4128)) ([8aad617](https://github.com/vuejs/vitepress/commit/8aad617446c03d39a65a0b21e9fce43bc484af1e)) +- rebuild dynamic routes cache on server restart ([9f54714](https://github.com/vuejs/vitepress/commit/9f54714e7db69fd4902f1917f927456c71b5a292)), closes [#4525](https://github.com/vuejs/vitepress/issues/4525) +### Features -# [1.0.0-alpha.75](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.74...v1.0.0-alpha.75) (2023-04-30) +- allow matching region end in snippets without tag ([#4287](https://github.com/vuejs/vitepress/issues/4287)) ([1a2f81d](https://github.com/vuejs/vitepress/commit/1a2f81de4d6549dd1adf86ae131d1a861158bd2d)) +- improve region regexes for snippet plugin ([1a6684c](https://github.com/vuejs/vitepress/commit/1a6684cf1054d326bc1dd6eeb9fb78b150ac2b2a)) +- support using header anchors in markdown file inclusion ([#4608](https://github.com/vuejs/vitepress/issues/4608)) ([b99d512](https://github.com/vuejs/vitepress/commit/b99d5123c9b2afdc7461089e03476c34d7816faf)), closes [#4375](https://github.com/vuejs/vitepress/issues/4375) [#4382](https://github.com/vuejs/vitepress/issues/4382) +## [2.0.0-alpha.3](https://github.com/vuejs/vitepress/compare/v2.0.0-alpha.2...v2.0.0-alpha.3) (2025-02-24) ### Bug Fixes -* **build:** reset regex lastIndex before testing ([188893c](https://github.com/vuejs/vitepress/commit/188893c2c1569e332e8776581cfa40b4c5f1168e)) -* **cli/init:** remove trailing slash from npm scripts ([64ecedc](https://github.com/vuejs/vitepress/commit/64ecedc73f3e7010de85381d946af1c95404820e)) -* **theme:** hide local nav on home page ([f07587a](https://github.com/vuejs/vitepress/commit/f07587af8a51f92a5ec491e5789dd088e28067b5)), closes [#2312](https://github.com/vuejs/vitepress/issues/2312) -* **theme:** local search get 404 on build when use route rewrites in windows ([#2301](https://github.com/vuejs/vitepress/issues/2301)) ([494c634](https://github.com/vuejs/vitepress/commit/494c634eb1d77963e555a736fa057dcb23700989)) -* **theme:** vitepress data not properly injected in app when use localSearch ([#2299](https://github.com/vuejs/vitepress/issues/2299)) ([69c7646](https://github.com/vuejs/vitepress/commit/69c7646dafe7a774e0717e032f697b008d9cf7aa)) - +- **build:** `--minify` not working as documented ([9b5c037](https://github.com/vuejs/vitepress/commit/9b5c0377cd3474447c84b2901801287f3caf3d82)), closes [#4523](https://github.com/vuejs/vitepress/issues/4523) +- **build:** deterministic code group ids ([#4565](https://github.com/vuejs/vitepress/issues/4565)) ([b930b8d](https://github.com/vuejs/vitepress/commit/b930b8d5310f1691d8d9f009f45b70122e4ce800)) +- **markdown:** include content of all tokens in heading ids ([68dff2a](https://github.com/vuejs/vitepress/commit/68dff2af8547ae70f6622ac826affd76f2f6378e)), closes [#4561](https://github.com/vuejs/vitepress/issues/4561) +- **client:** set correct oldURL and newURL for hashchange ([#4573](https://github.com/vuejs/vitepress/issues/4573)) ([d1f2afd](https://github.com/vuejs/vitepress/commit/d1f2afdf0fbb022f12cc12295723b3b7c7ef5cb1)) +- **theme:** allow interactions behind scroll shadow ([#4537](https://github.com/vuejs/vitepress/issues/4537)) ([091d584](https://github.com/vuejs/vitepress/commit/091d5840ae15b64e04e8c07fbc0263a2749571bd)) +- **theme:** code block contrast ratio ([#4487](https://github.com/vuejs/vitepress/issues/4487)) ([5dccaee](https://github.com/vuejs/vitepress/commit/5dccaeef055beb109919f8990032975a0d630384)) +- **build:** fix flaky embedded languages highlighting ([#4566](https://github.com/vuejs/vitepress/issues/4566)) ([1969cf4](https://github.com/vuejs/vitepress/commit/1969cf4f3b93ad105595e4e2f8b030b04eb1c975)) ### Features -* add `filePath` to `PageData` ([#2140](https://github.com/vuejs/vitepress/issues/2140)) ([b24acc6](https://github.com/vuejs/vitepress/commit/b24acc6991570aa054a99b8d3977b8b4d0255418)) -* **build:** allow using `@` prefix with `@include` ([#2292](https://github.com/vuejs/vitepress/issues/2292)) ([a3b38d1](https://github.com/vuejs/vitepress/commit/a3b38d18824343fd5b571a7a9a5d2c4ccf29e8e1)) -* preserve user log level ([#2310](https://github.com/vuejs/vitepress/issues/2310)) ([a647cd3](https://github.com/vuejs/vitepress/commit/a647cd384320101f6df31e03960dd2c40808c49c)) -* **theme:** support light shiki themes ([#2319](https://github.com/vuejs/vitepress/issues/2319)) ([d0f0012](https://github.com/vuejs/vitepress/commit/d0f0012aea4cc71fb28f60f2dd649c23aae146b8)) - +- **cli:** support custom `srcDir` ([#4270](https://github.com/vuejs/vitepress/issues/4270)) ([518c094](https://github.com/vuejs/vitepress/commit/518c0945f159aae679ef710bb48ae3ab3891cc9f)) +- **cli:** support custom npm scripts prefix ([#4271](https://github.com/vuejs/vitepress/issues/4271)) ([e5a0ee8](https://github.com/vuejs/vitepress/commit/e5a0ee8161752a77c5bb9546245a940cb5f28fb8)) +- **build:** dynamic routes plugin overhaul ([#4525](https://github.com/vuejs/vitepress/issues/4525)) ([a62ea6a](https://github.com/vuejs/vitepress/commit/a62ea6a832a33b756642b24ad5d38c248e08b554)) +- **build:** update to shiki v3 ([#4571](https://github.com/vuejs/vitepress/issues/4571)) ([52c2aa1](https://github.com/vuejs/vitepress/commit/52c2aa178d4b3fa98b863cf28f0ccf6d2aabcd93)) +- **build:** use `markdown-it-async`, remove `synckit` ([#4507](https://github.com/vuejs/vitepress/issues/4507)) ([8062235](https://github.com/vuejs/vitepress/commit/80622356f1d648577ee47ee3a44b04bb015ee462)) ### BREAKING CHANGES -* **theme:** Styling for code blocks might break, especially if you were earlier overriding it for light theme. Those workarounds are no longer required. VitePress will now show code blocks and groups in light mode too if a light shiki theme is specified. - +- markdown-it-async is used instead of markdown-it. If you're using custom content renderer for local search, you'll need to do `await md.renderAsync` instead of `md.render`. +- Internals are modified a bit to better support vite 6 and handle HMR more correctly. For most users this won't need any change on their side. +- shiki is upgraded to v3. There shouldn't be any breaking change but if you see any issue, please report it. +## [2.0.0-alpha.2](https://github.com/vuejs/vitepress/compare/v2.0.0-alpha.1...v2.0.0-alpha.2) (2025-01-23) -# [1.0.0-alpha.74](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.73...v1.0.0-alpha.74) (2023-04-24) +### Bug Fixes +- fix docsearch navigation and rendering ([e035027](https://github.com/vuejs/vitepress/commit/e0350275b39258a61ee867840ce1c6f5b2cecf2a)) +- **types:** support preload built-in shiki languages as string ([#4513](https://github.com/vuejs/vitepress/issues/4513)) ([4f77b4f](https://github.com/vuejs/vitepress/commit/4f77b4fdfdbe945e482348a57731bff5fb4672fc)) -### Bug Fixes +### Features -* **build:** allow data-loaders files in packages to be found (closes [#2272](https://github.com/vuejs/vitepress/issues/2272)) ([84cf457](https://github.com/vuejs/vitepress/commit/84cf45772ed59f5eae747c15fbffc375768007b8)) -* **router:** scroll back to the hash anchor even if it is already selected ([#2265](https://github.com/vuejs/vitepress/issues/2265)) ([f3d3332](https://github.com/vuejs/vitepress/commit/f3d3332fff72d1df6f70c5893bfc90442b1776fb)) +- allow `markdown.config` and `markdown.preConfig` to accept async function ([#4512](https://github.com/vuejs/vitepress/issues/4512)) ([b88ae8d](https://github.com/vuejs/vitepress/commit/b88ae8d4a11a20104b2007c2631eb7aeb123d965)) +- support same page navigation in `router.go` and expose decoded hash and query from the `route` object ([#4511](https://github.com/vuejs/vitepress/issues/4511)) ([23d3281](https://github.com/vuejs/vitepress/commit/23d3281ed6f1111ab15708ca1fd86202674f8ef7)) +## [2.0.0-alpha.1](https://github.com/vuejs/vitepress/compare/v1.6.2...v2.0.0-alpha.1) (2025-01-22) ### Features -* allow using html in member description ([#2269](https://github.com/vuejs/vitepress/issues/2269)) ([f744364](https://github.com/vuejs/vitepress/commit/f7443643a4510a6c650f1a1bda977c1d55fddf64)) -* **search:** support custom `disableQueryPersistence` in local search ([#2273](https://github.com/vuejs/vitepress/issues/2273)) ([2f0f2d5](https://github.com/vuejs/vitepress/commit/2f0f2d5ac6efcab22bdb452e5c0780e7cd8f1498)) -* **theme:** mobile view show outline button after removing sidebar ([#2274](https://github.com/vuejs/vitepress/issues/2274)) ([25b9111](https://github.com/vuejs/vitepress/commit/25b9111222cbd3de008e18cac6554933d4db993e)) +- upgrade vite to v6 ([#4504](https://github.com/vuejs/vitepress/issues/4504)) ([6a2efc3](https://github.com/vuejs/vitepress/commit/6a2efc385c90b088241db05f5263b2f3e1f757cf)) +## [1.6.3](https://github.com/vuejs/vitepress/compare/v1.6.2...v1.6.3) (2025-01-22) +### Bug Fixes -# [1.0.0-alpha.73](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.72...v1.0.0-alpha.73) (2023-04-20) +- docsearch not rendering properly ([3e4120e](https://github.com/vuejs/vitepress/commit/3e4120e94805156bf63587fd633162433dbaf260)) +## [1.6.2](https://github.com/vuejs/vitepress/compare/v1.6.1...v1.6.2) (2025-01-22) ### Bug Fixes -* **search:** fix highlighting in detailed view ([1f4920c](https://github.com/vuejs/vitepress/commit/1f4920c60dc1be03444781539064be7b3ec9eb08)) -* **search:** local search showDetailedList not working in windows ([#2253](https://github.com/vuejs/vitepress/issues/2253)) ([09be057](https://github.com/vuejs/vitepress/commit/09be057ffb767e55d3a86f1a3664ebd0690f2fc5)) +- fix static content removal for lean chunks due to Vue 3.5 changes ([#4508](https://github.com/vuejs/vitepress/issues/4508)) ([8214cae](https://github.com/vuejs/vitepress/commit/8214cae21bb16842d8870d5867e974146c51fd61)) +## [1.6.1](https://github.com/vuejs/vitepress/compare/v1.6.0...v1.6.1) (2025-01-20) -### Features +### Bug Fixes -* outline link add title attribute ([#2261](https://github.com/vuejs/vitepress/issues/2261)) ([1f5798e](https://github.com/vuejs/vitepress/commit/1f5798e43771ae1e13921a39319345c89bb2298a)) +- **build:** escape `$` in replace pattern in dynamic routes plugin ([e812916](https://github.com/vuejs/vitepress/commit/e8129167c76104d59d31a77b16dff3458e6af5eb)), closes [#4499](https://github.com/vuejs/vitepress/issues/4499) +- **theme/regression:** broken hero heading at certain viewports ([37dbe89](https://github.com/vuejs/vitepress/commit/37dbe895d4cf813e6eb1289f24c637945eec0d1f)) +# [1.6.0](https://github.com/vuejs/vitepress/compare/v1.5.0...v1.6.0) (2025-01-20) +### Bug Fixes -# [1.0.0-alpha.72](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.71...v1.0.0-alpha.72) (2023-04-17) +- **build:** out of order css in prod builds ([241d17d](https://github.com/vuejs/vitepress/commit/241d17d9839f06b17c3898b1a8ba0f9fa12da0d1)), closes [#4098](https://github.com/vuejs/vitepress/issues/4098) +- **build:** properly strip vpi-social css declaration in debug mode ([c61182a](https://github.com/vuejs/vitepress/commit/c61182ab278350699b5d50461788478a340790aa)) +- **build:** respect `vite.clearScreen` in build ([8ea776a](https://github.com/vuejs/vitepress/commit/8ea776addc2c3bcabf3c707a9a81d6e0080a8fcb)), closes [#4468](https://github.com/vuejs/vitepress/issues/4468) +- **build:** specify mode for iconify ([8a5e8ea](https://github.com/vuejs/vitepress/commit/8a5e8ea4f5b7cba0a6c909d8949f0c20426104a6)) +- **theme:** apply `externalLinkIcon` option on `VPHome` ([#4492](https://github.com/vuejs/vitepress/issues/4492)) ([fe48943](https://github.com/vuejs/vitepress/commit/fe48943640895d859811b81f86d78c3e510dbe54)) +- **theme:** don't show external link icon for images ([096bba1](https://github.com/vuejs/vitepress/commit/096bba19fb61c4b2f8f527046b4b0fe2e91c6bd6)) +- **theme:** ignore footnote-ref for outline ([1832617](https://github.com/vuejs/vitepress/commit/183261753b04c2c96ddb8c10e520c748c6d3e613)), closes [#4402](https://github.com/vuejs/vitepress/issues/4402) +- **theme:** includes text to h1 tag for hero page ([#4472](https://github.com/vuejs/vitepress/issues/4472)) ([bd896c6](https://github.com/vuejs/vitepress/commit/bd896c638f8046f6546b5b32e8f98f3707aa8d05)), closes [#4453](https://github.com/vuejs/vitepress/issues/4453) +### Features -### Bug Fixes +- **build:** export normalize function from shared chunk ([616f63f](https://github.com/vuejs/vitepress/commit/616f63f5f08a57347f2800e2d147d5bcd1cd072d)), closes [#4401](https://github.com/vuejs/vitepress/issues/4401) +- **theme:** allow customizing skip to content label ([ff254dc](https://github.com/vuejs/vitepress/commit/ff254dcbe6f2bcc89c34d2d2f4050229dc094400)), closes [#4288](https://github.com/vuejs/vitepress/issues/4288) +- **theme:** export VPNavBarSearch ([23522ab](https://github.com/vuejs/vitepress/commit/23522ab83ff33802d382fa066578dd87eb06789d)), closes [#4476](https://github.com/vuejs/vitepress/issues/4476) +- **theme:** export VPFeatures ([#4356](https://github.com/vuejs/vitepress/issues/4356)) ([6442e17](https://github.com/vuejs/vitepress/commit/6442e174838aec9668325bb1199419908e7dd728)) -* **search:** don't directly access userConfig ([3e0e9d2](https://github.com/vuejs/vitepress/commit/3e0e9d2b27c02e250c5b350bf83dce9b95e217a8)) -* **search:** ready event is not fired on mac ([e37e5cb](https://github.com/vuejs/vitepress/commit/e37e5cb45a6c3507b906b9955897ce4e84adf500)) -* **theme:** local search showDetailedList not working in windows ([#2248](https://github.com/vuejs/vitepress/issues/2248)) ([8354f8f](https://github.com/vuejs/vitepress/commit/8354f8fb8649d429b2cb525dd6f35127faba7ae6)) +### Miscellaneous +- **build:** shiki transformers now use v3 [matching algorithm](https://shiki.style/packages/transformers#matching-algorithm) ([373f9b9](https://github.com/vuejs/vitepress/commit/373f9b933ee44f33a15ebdcfcb6db6dfac52f739)) +# [1.5.0](https://github.com/vuejs/vitepress/compare/v1.4.5...v1.5.0) (2024-11-04) -# [1.0.0-alpha.71](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.70...v1.0.0-alpha.71) (2023-04-16) +### Features +- on-demand social icons ([#4339](https://github.com/vuejs/vitepress/issues/4339)) ([05f2f0d](https://github.com/vuejs/vitepress/commit/05f2f0d26153ace74b6c023184224d4fada137c2)), closes [#4256](https://github.com/vuejs/vitepress/issues/4256) [#4135](https://github.com/vuejs/vitepress/issues/4135) [#4076](https://github.com/vuejs/vitepress/issues/4076) [#3809](https://github.com/vuejs/vitepress/issues/3809) [#3750](https://github.com/vuejs/vitepress/issues/3750) [#1214](https://github.com/vuejs/vitepress/issues/1214) [#2768](https://github.com/vuejs/vitepress/issues/2768) [#2861](https://github.com/vuejs/vitepress/issues/2861) + +## [1.4.5](https://github.com/vuejs/vitepress/compare/v1.4.4...v1.4.5) (2024-11-03) ### Bug Fixes -* **search:** esm interop mark.js import ([1b0a249](https://github.com/vuejs/vitepress/commit/1b0a249ad66288ff56675e4db905959ff0079726)) -* **search:** properly group nested headings ([b1c956c](https://github.com/vuejs/vitepress/commit/b1c956ce99505316842c157c76a4ec051eb7610b)), closes [#2238](https://github.com/vuejs/vitepress/issues/2238) +- lang lazy load not working with twoslash ([fc92a77](https://github.com/vuejs/vitepress/commit/fc92a77a5d871b5252bcb82639f5c3551d5c70bb)), closes [#4334](https://github.com/vuejs/vitepress/issues/4334) +- typo in missing language check ([dcb8450](https://github.com/vuejs/vitepress/commit/dcb8450f1166d7731c26a0eb5ec6d931bc283172)) +## [1.4.3](https://github.com/vuejs/vitepress/compare/v1.4.2...v1.4.3) (2024-10-31) +### Performance Improvements -# [1.0.0-alpha.70](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.69...v1.0.0-alpha.70) (2023-04-16) +- lazy load shiki languages ([#4326](https://github.com/vuejs/vitepress/issues/4326)) ([8299778](https://github.com/vuejs/vitepress/commit/829977876a21da4f0af5d27593a2d81eb9af0c33)) +## [1.4.2](https://github.com/vuejs/vitepress/compare/v1.4.1...v1.4.2) (2024-10-29) ### Bug Fixes -* **a11y:** increase touch target size of search icons ([4449867](https://github.com/vuejs/vitepress/commit/44498675aca3271596b041881d44e1524d744df6)) -* **search:** avoid body scroll when using local search ([#2236](https://github.com/vuejs/vitepress/issues/2236)) ([144a7d8](https://github.com/vuejs/vitepress/commit/144a7d8e4ee483475b6956090c267213a1e2f8e1)) -* **search:** better highlighting in detailed view ([#2234](https://github.com/vuejs/vitepress/issues/2234)) ([be83524](https://github.com/vuejs/vitepress/commit/be8352441f8b9a8561961c69f3e1794370101de2)) -* **search:** fix keyword highlighting and scrolling in excerpts ([ca8db8a](https://github.com/vuejs/vitepress/commit/ca8db8adca028bb982b819553b85ac19fe946e7e)) -* **search:** remove double base on importing excepts ([185213c](https://github.com/vuejs/vitepress/commit/185213c6ba4416071025fbf3c5ca7fadf311fdbf)), closes [#2230](https://github.com/vuejs/vitepress/issues/2230) -* **search:** remove extra /index from routes ([9e04b43](https://github.com/vuejs/vitepress/commit/9e04b435671accfcaee795ec8ec2833d8aa358f8)) -* **search:** show escape to close on footer ([6d5b4cd](https://github.com/vuejs/vitepress/commit/6d5b4cd784274786ad57cef378646320ba17faf1)) +- cache markdown-it instance and properly dispose shiki on config reload ([#4321](https://github.com/vuejs/vitepress/issues/4321)) ([45968cd](https://github.com/vuejs/vitepress/commit/45968cdc509e04f8e191d28ba7d8d97b08fc578e)) ([acfe97f](https://github.com/vuejs/vitepress/commit/acfe97f60872d251c75c5985ca9841f84392850d)) +- **regression:** hmr not working with markdown includes due to wrong cache key ([615aed5](https://github.com/vuejs/vitepress/commit/615aed5df700ad98f82a74fbc785d290d1c5a018)), closes [#4289](https://github.com/vuejs/vitepress/issues/4289) [#4303](https://github.com/vuejs/vitepress/issues/4303) +- remove explicit chinese fonts ([#4286](https://github.com/vuejs/vitepress/issues/4286)) ([668e9f7](https://github.com/vuejs/vitepress/commit/668e9f7050f236d571fe2fc2f41e5548d974b503)) ([b893550](https://github.com/vuejs/vitepress/commit/b8935502fbb590449e7d094bdde9c9ae1ac67d0c)), closes [#4286](https://github.com/vuejs/vitepress/issues/4286) +- **theme/a11y:** don't select search result unless mouse is actually moved ([e638d85](https://github.com/vuejs/vitepress/commit/e638d855cfc8e4e0c9b95c284548ae31233139f5)), closes [#4297](https://github.com/vuejs/vitepress/issues/4297) +- **theme:** add types for `VPLink`, `VPSocialLink` and `VPSocialLinks` exports ([#4284](https://github.com/vuejs/vitepress/issues/4284)) ([fcae4d5](https://github.com/vuejs/vitepress/commit/fcae4d5554df2130b9a7e5ad8e0cc83eccf88bec)) +- **theme:** don't escape html in `siteTitle` ([#4308](https://github.com/vuejs/vitepress/issues/4308)) ([bd690d6](https://github.com/vuejs/vitepress/commit/bd690d6a9b895f15d5906d245b404f02cfce7489)) +## [1.4.1](https://github.com/vuejs/vitepress/compare/v1.4.0...v1.4.1) (2024-10-13) + +### Bug Fixes + +- broken rewrites on windows ([#4268](https://github.com/vuejs/vitepress/issues/4268)) ([b46d6d3](https://github.com/vuejs/vitepress/commit/b46d6d3a204f5ce347647bfd1ab8073bf313afd6)) +- **client:** use `usePreferredDark` with `appearance: "force-auto"` ([#4263](https://github.com/vuejs/vitepress/issues/4263)) ([3e8fc40](https://github.com/vuejs/vitepress/commit/3e8fc40c3621da1ef35645d376dab7765b35bb40)) +- **client:** wrong script async check ([461a5b0](https://github.com/vuejs/vitepress/commit/461a5b001d29f95169f60fe28bc610e3f6e8fd66)) +- **theme:** bind missing no icon prop in the menu link component [#4260](https://github.com/vuejs/vitepress/issues/4260) ([b96712c](https://github.com/vuejs/vitepress/commit/b96712c0744f9ac7ebd65cf4087b2e9fd0d6762b)) +- **theme:** improve local search input a11y ([#4066](https://github.com/vuejs/vitepress/issues/4066)) ([92b92ae](https://github.com/vuejs/vitepress/commit/92b92aefcab9fbb28b51da70ee8ab21724098277)) ### Features -* **search:** allow force disabling detailed view ([40f1d1b](https://github.com/vuejs/vitepress/commit/40f1d1b6f6f2f6c43fd0d9bcf4b6bc1174ce4831)) -* **search:** make styling more configurable, align more with the theme ([#2233](https://github.com/vuejs/vitepress/issues/2233)) ([b2077c7](https://github.com/vuejs/vitepress/commit/b2077c70250d5c390d69ce31111a1c44769dbc78)) +- **experimental:** support passing function for rewrites ([#4274](https://github.com/vuejs/vitepress/issues/4274)) ([8436472](https://github.com/vuejs/vitepress/commit/8436472c7874cb16caf9432660b395ca9ba68f9d)) + +# [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)) -# [1.0.0-alpha.69](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.68...v1.0.0-alpha.69) (2023-04-15) +### 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 -* **search:** fix errors on empty titles ([6d363ec](https://github.com/vuejs/vitepress/commit/6d363ec9ffd6b27e1c77e5aab853471c6883c7bd)) -* **theme:** fix color of blockquote in custom containers ([#2173](https://github.com/vuejs/vitepress/issues/2173)) ([712a57f](https://github.com/vuejs/vitepress/commit/712a57fde74daa27f69319861d95f9dec6bc05ad)) +- 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 -# [1.0.0-alpha.68](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.67...v1.0.0-alpha.68) (2023-04-15) +- 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 -* **theme:** fix top of scrollbar being unusable ([#2224](https://github.com/vuejs/vitepress/issues/2224)) ([7178a22](https://github.com/vuejs/vitepress/commit/7178a22c9d317245e5167abf80f7081fbf87e78a)) +- 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) +### Bug Fixes -# [1.0.0-alpha.67](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.66...v1.0.0-alpha.67) (2023-04-15) +- don't reopen browser on restart when `vite.server.open` is specified ([6263db1](https://github.com/vuejs/vitepress/commit/6263db170a658ea887ef4b2bfe4b5239a820e0d9)), closes [#4040](https://github.com/vuejs/vitepress/issues/4040) +- **theme/regression:** typo in component props resulting in nested titles not showing in navbar ([01d0d45](https://github.com/vuejs/vitepress/commit/01d0d45292602cbb7de492f0c953ddb239842116)), closes [#4042](https://github.com/vuejs/vitepress/issues/4042) +# [1.3.0](https://github.com/vuejs/vitepress/compare/v1.2.3...v1.3.0) (2024-07-07) ### Bug Fixes -* **search:** avoid double base ([25a1fe9](https://github.com/vuejs/vitepress/commit/25a1fe90bddd021a1ce5e068d8cad455687647bf)) -* **theme:** navbar style ([#2202](https://github.com/vuejs/vitepress/issues/2202)) ([8ee6b90](https://github.com/vuejs/vitepress/commit/8ee6b905f5243a036c2dee7688539ef33e164f09)) - +- **build:** don't normalize links containing target or download property ([e24899a](https://github.com/vuejs/vitepress/commit/e24899a073d066486e5f7ae0c47ba6d901d5ae51)), closes [#3947](https://github.com/vuejs/vitepress/issues/3947) +- **build:** respect frontmatter.lastUpdated for pageData.lastUpdated and sitemap generation ([7fcf462](https://github.com/vuejs/vitepress/commit/7fcf462eb8c2be6e72b4426a8211fcd6961e4967)), closes [#3931](https://github.com/vuejs/vitepress/issues/3931) +- **build:** sort pageToHashMap to ensure stable assets ([e302328](https://github.com/vuejs/vitepress/commit/e302328a4ce3242cbfb7112e856840b7346aa16a)), closes [#4016](https://github.com/vuejs/vitepress/issues/4016) +- **client:** do nothing on anchor elements with empty href ([6461f5d](https://github.com/vuejs/vitepress/commit/6461f5d42b3bfed1d7959e1167fc77f61d08f314)), closes [#3950](https://github.com/vuejs/vitepress/issues/3950) +- don't do git log on non-existent file ([387acf7](https://github.com/vuejs/vitepress/commit/387acf71aa351e23ca3402713020a3571ad17155)), closes [#4008](https://github.com/vuejs/vitepress/issues/4008) +- don't reopen browser on restart ([d837e82](https://github.com/vuejs/vitepress/commit/d837e82bc8bde63df737be2a1290a2e70c8a0bf3)), closes [#4001](https://github.com/vuejs/vitepress/issues/4001) +- properly handle svg anchor elements ([b785bd6](https://github.com/vuejs/vitepress/commit/b785bd6ab3b5dd909aa955dc9e03b08e66b76294)) +- **theme:** add styles for h4 too ([b54d7b0](https://github.com/vuejs/vitepress/commit/b54d7b0d7cd1257bcadd25f9b69cba21d0a3dff6)) +- **theme:** deep watch sidebar groups and force render on match change ([97f9469](https://github.com/vuejs/vitepress/commit/97f9469b6d4eb7ba9de9a1111986581d1f704ec3)), closes [#3613](https://github.com/vuejs/vitepress/issues/3613) +- **theme:** dim color for all text like elements inside blockquotes ([5d3ed87](https://github.com/vuejs/vitepress/commit/5d3ed87f8530134fa709681ebadb2f3cfc68680e)), closes [#3929](https://github.com/vuejs/vitepress/issues/3929) +- **theme:** force update title attribute on hydration ([d348da7](https://github.com/vuejs/vitepress/commit/d348da770c2a68993d1a40d1c0223e42a681057a)), closes [#4004](https://github.com/vuejs/vitepress/issues/4004) +- **theme:** show filled nav bar when nav screen is open ([0fc70e2](https://github.com/vuejs/vitepress/commit/0fc70e2d0c29c92a1dceba035295a3fac84ffc00)) ### Features -* allow passing props and children/slots to defineClientComponent ([#2198](https://github.com/vuejs/vitepress/issues/2198)) ([4c24960](https://github.com/vuejs/vitepress/commit/4c2496043394d9b14376e74a5bf11ccea5e6e7d7)) +- allow using components in navigation bar ([#4000](https://github.com/vuejs/vitepress/issues/4000)) ([fa87d81](https://github.com/vuejs/vitepress/commit/fa87d8150d8185fa8a22cd6b6e762632b83f8231)) +- **cli/init:** allow passing target dir as command argument ([#3948](https://github.com/vuejs/vitepress/issues/3948)) ([99053ba](https://github.com/vuejs/vitepress/commit/99053baea7eb6aa62a11a2cfd4b1e6e60311dd63)) +- **markdown:** support including specific regions from markdown files ([#3978](https://github.com/vuejs/vitepress/issues/3978)) ([143b1e9](https://github.com/vuejs/vitepress/commit/143b1e91f3696507d33666ec5847e7b64a771bcf)) +- support `force-auto` as an option for appearance ([1e8bb48](https://github.com/vuejs/vitepress/commit/1e8bb48bc2891ea388bf0b9edd2f5b612bb1e85d)), closes [#3946](https://github.com/vuejs/vitepress/issues/3946) +- **theme:** export VPHomeContent ([#3960](https://github.com/vuejs/vitepress/issues/3960)) ([8aa6ccb](https://github.com/vuejs/vitepress/commit/8aa6ccbe32655f76c390d15568f69f83d079385d)), closes [#3954](https://github.com/vuejs/vitepress/issues/3954) +## [1.2.3](https://github.com/vuejs/vitepress/compare/v1.2.2...v1.2.3) (2024-06-04) +### Bug Fixes -# [1.0.0-alpha.66](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.65...v1.0.0-alpha.66) (2023-04-15) +- **theme,a11y:** handle overflow on long mathematical equation and make tables focusable ([#3932](https://github.com/vuejs/vitepress/issues/3932)) (closes [#3914](https://github.com/vuejs/vitepress/issues/3914)) ([afc611d](https://github.com/vuejs/vitepress/commit/afc611d399d2780550ae04caa0e73e1c0c69a680)) +- **types:** wrong types generated for markdown-it > mdurl ([48ca76c](https://github.com/vuejs/vitepress/commit/48ca76c523d9b979a678d52447f5ce324799e47f)), closes [#3935](https://github.com/vuejs/vitepress/issues/3935) +## [1.2.2](https://github.com/vuejs/vitepress/compare/v1.2.1...v1.2.2) (2024-05-21) ### Bug Fixes -* **search:** properly resolve page link ([609d447](https://github.com/vuejs/vitepress/commit/609d447ab50b2b8fb78a174e7d5aa0ff52411b0e)) -* **theme:** fix meta key not showing on search button ([e295160](https://github.com/vuejs/vitepress/commit/e2951604fd61336df9559ea16972d3ea76a49894)) +- dont escape ampersand twice in title ([7ea3572](https://github.com/vuejs/vitepress/commit/7ea357256c855ae0a9a142c14bbd5e7d344ef865)) +## [1.2.1](https://github.com/vuejs/vitepress/compare/v1.2.0...v1.2.1) (2024-05-21) -### Features +### Bug Fixes -* offline search ([#2110](https://github.com/vuejs/vitepress/issues/2110)) ([6c92675](https://github.com/vuejs/vitepress/commit/6c92675e33d3276a02b790a34083a68093b58c7f)) +- **a11y:** make code blocks accessible with keyboard ([#3902](https://github.com/vuejs/vitepress/issues/3902)) ([cb308b9](https://github.com/vuejs/vitepress/commit/cb308b9295e1e661c2c72fa4229b5c7d83278d49)) +- escape title properly in build ([49b1233](https://github.com/vuejs/vitepress/commit/49b1233378436054c07a6ef646d0029096124021)) +- **theme:** remove unnecessary navigation role on nav element ([af4717d](https://github.com/vuejs/vitepress/commit/af4717d6820233a011200d44abba53d0f66bfad3)) +# [1.2.0](https://github.com/vuejs/vitepress/compare/v1.1.4...v1.2.0) (2024-05-18) +### Bug Fixes -# [1.0.0-alpha.65](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.64...v1.0.0-alpha.65) (2023-04-04) +- **build:** show file info on error ([f0debd2](https://github.com/vuejs/vitepress/commit/f0debd20f48ab7eb58cfd142147531509d6c0209)) +- **dev:** match dev and prod routing behavior ([#3837](https://github.com/vuejs/vitepress/issues/3837)) ([b360ac8](https://github.com/vuejs/vitepress/commit/b360ac88df3bfd60e3498cc19066c0c90261ee4f)) +- **markdown:** entities and escapes not working properly ([#3882](https://github.com/vuejs/vitepress/issues/3882)) ([d5dbd70](https://github.com/vuejs/vitepress/commit/d5dbd704ceb215ebf3ce9b23deec6e6c90634f0a)) +- render 404 page completely on client to infer locale from browser path ([#3858](https://github.com/vuejs/vitepress/issues/3858)) ([728cb15](https://github.com/vuejs/vitepress/commit/728cb15677f4f84b33bed6bb2f70f47600ea1057)) +- **style:** prefer YaHei over DengXian ([f0a37b4](https://github.com/vuejs/vitepress/commit/f0a37b4b8445ec914700df054c0897721382e5b1)) +- **theme/regression:** custom font not applying in Chinese docs because of specificity ([fa2f38a](https://github.com/vuejs/vitepress/commit/fa2f38a0c3bd121dcb7e07420566087c19b10f96)), closes [#3864](https://github.com/vuejs/vitepress/issues/3864) +- **theme:** external link icon not visible for target \_blank links ([d08eeed](https://github.com/vuejs/vitepress/commit/d08eeed89726572f7ea341df59864cc72716751c)), closes [#3327](https://github.com/vuejs/vitepress/issues/3327) +- **theme:** fix invalid vp-offset in ssr ([9794877](https://github.com/vuejs/vitepress/commit/9794877347140c7b4955d735cd8867c260a5089d)) +### Features + +- **build/i18n:** support customizing copy code button's tooltip text ([#3854](https://github.com/vuejs/vitepress/issues/3854)) ([ed6ada7](https://github.com/vuejs/vitepress/commit/ed6ada7a688c466920f3e0ef33b7176b8eb01eee)) +- **build:** add localeIndex to md.env ([#3862](https://github.com/vuejs/vitepress/issues/3862)) ([0cbb469](https://github.com/vuejs/vitepress/commit/0cbb469842d74381ad56d44b7975f34c405b78f8)) + +## [1.1.4](https://github.com/vuejs/vitepress/compare/v1.1.3...v1.1.4) (2024-04-27) ### Bug Fixes -* **build:** remove extra line at end of code blocks ([#2191](https://github.com/vuejs/vitepress/issues/2191)) ([a681fd1](https://github.com/vuejs/vitepress/commit/a681fd11e32709367d673cf0d9d26e4288f27776)) +- **dev:** multiple server instances being created when editing config too quickly ([#3835](https://github.com/vuejs/vitepress/issues/3835)) ([729a890](https://github.com/vuejs/vitepress/commit/729a890669c363895cfac39ece046926cad36d01)) +- **theme/a11y:** add unique name to footer prev / next navigation landmark ([e60c101](https://github.com/vuejs/vitepress/commit/e60c101e50fa56d4cd54d434c5628cc7e2231318)) +- **theme/a11y:** remove duplicate assistive text from outline nav ([#3803](https://github.com/vuejs/vitepress/issues/3803)) ([733d986](https://github.com/vuejs/vitepress/commit/733d986a84f614484b04235546dc4cda0769e833)) +- **theme/i18n:** 404 page not showing localized text ([#3833](https://github.com/vuejs/vitepress/issues/3833)) ([cc11b8e](https://github.com/vuejs/vitepress/commit/cc11b8e41ec481320b03902bdc307d479a8ba838)) +- **theme:** disable keypress effect on search button ([ccc37bb](https://github.com/vuejs/vitepress/commit/ccc37bb80e4147b9ab91b0f5d7dfae9d51533460)) +- **theme:** don't use Chinese quotes on non-Chinese documents ([#3834](https://github.com/vuejs/vitepress/issues/3834)) ([75115f4](https://github.com/vuejs/vitepress/commit/75115f4f8223d67dab2dc82fadaf2941aabf6330)) +- **theme:** leaking event listener when going back/forward on Safari on iOS ([#3658](https://github.com/vuejs/vitepress/issues/3658)) ([#3671](https://github.com/vuejs/vitepress/issues/3671)) ([1a72181](https://github.com/vuejs/vitepress/commit/1a72181c06d78e5e6f293e3f6abdb15caa4d2f53)) +## [1.1.3](https://github.com/vuejs/vitepress/compare/v1.1.1...v1.1.3) (2024-04-18) +### Bug Fixes -# [1.0.0-alpha.64](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.63...v1.0.0-alpha.64) (2023-03-29) +- **build/regression:** markdown backslash escapes not working ([d02d1e9](https://github.com/vuejs/vitepress/commit/d02d1e923aacdb1e8061a3f76af30e8a13518277)), closes [#3808](https://github.com/vuejs/vitepress/issues/3808) +## [1.1.1](https://github.com/vuejs/vitepress/compare/v1.1.0...v1.1.1) (2024-04-18) ### Bug Fixes -* **build:** make `lastUpdated` work with git submodules ([#2149](https://github.com/vuejs/vitepress/issues/2149)) ([4c23003](https://github.com/vuejs/vitepress/commit/4c2300318952bfdaabd766a6f16f26419ee854da)) -* **theme:** fix color of table head row in custom containers ([#2160](https://github.com/vuejs/vitepress/issues/2160)) ([51ecd58](https://github.com/vuejs/vitepress/commit/51ecd580a29d9e2bea73d4d5897154954d750d9f)) -* **theme:** hide outline dropdown scrollbar when it does not overflow ([#2151](https://github.com/vuejs/vitepress/issues/2151)) ([ff26ff1](https://github.com/vuejs/vitepress/commit/ff26ff1e6683def53bfbe6cbd7656740c77f4bcc)) +- **client:** don't reload page on hash change ([#3777](https://github.com/vuejs/vitepress/issues/3777)) ([74b725a](https://github.com/vuejs/vitepress/commit/74b725a224438ef776fed25ee82274429d94ac83)) +- let vue compiler handle entity decoding ([f86ac56](https://github.com/vuejs/vitepress/commit/f86ac56b78da76f3061e6537b897bb13c1ed802d)) +- hot updating config file suppresses error logs ([#3592](https://github.com/vuejs/vitepress/issues/3592)) ([cd5adf3](https://github.com/vuejs/vitepress/commit/cd5adf3011d677263c93ce6f8066aaa7870b1dfc)) + +# [1.1.0](https://github.com/vuejs/vitepress/compare/v1.0.2...v1.1.0) (2024-04-09) +### Bug Fixes + +- **client:** hashchange should only be triggered for same page navigations ([#3768](https://github.com/vuejs/vitepress/issues/3768)) ([2a9fc2a](https://github.com/vuejs/vitepress/commit/2a9fc2a26b829bb3f28067ac6f4a41bc1e8b7a1e)) +- **client:** emit correct `Event` instance in hashchange event +- **theme:** remove small layout shift on `On this page` button ([#3767](https://github.com/vuejs/vitepress/issues/3767)) ([5f28e74](https://github.com/vuejs/vitepress/commit/5f28e74abfc984cdc7e0d9d9f7b7e15cb2b46923)) ### Features -* **build:** provide `siteConfig` in `transformPageData` context ([#2163](https://github.com/vuejs/vitepress/issues/2163)) ([3714741](https://github.com/vuejs/vitepress/commit/3714741b409f4e5f8df4cc42c7b59b065c8cc6f6)) -* **theme:** add `page-top/bottom` and `doc-top/bottom` slots ([#2139](https://github.com/vuejs/vitepress/issues/2139)) ([53d0099](https://github.com/vuejs/vitepress/commit/53d0099ffa99582f552d7dff5676734c965ceb05)) -* **theme:** allow moving aside to left ([#2138](https://github.com/vuejs/vitepress/issues/2138)) ([9e3cf0f](https://github.com/vuejs/vitepress/commit/9e3cf0fa7d2c2589d129ef931457ab40f513d187)) +- **client:** add `hash` property to `useData()` +- **theme:** update Inter to version 4 ([#3693](https://github.com/vuejs/vitepress/issues/3693)) ([#3694](https://github.com/vuejs/vitepress/issues/3694)) ([ffafa31](https://github.com/vuejs/vitepress/commit/ffafa31b9204f996f4b819684214fa631c224575)) +## [1.0.2](https://github.com/vuejs/vitepress/compare/v1.0.1...v1.0.2) (2024-04-01) +### Bug Fixes -# [1.0.0-alpha.63](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.62...v1.0.0-alpha.63) (2023-03-26) +- **theme:** text containing html not showing properly in mobile nav menu ([3c8b4c7](https://github.com/vuejs/vitepress/commit/3c8b4c706051592dd2cca0ae57e293254cbb51ce)) +## [1.0.1](https://github.com/vuejs/vitepress/compare/v1.0.0...v1.0.1) (2024-03-22) ### Bug Fixes -* **theme:** allow adding html as feature icons ([e5bc1e1](https://github.com/vuejs/vitepress/commit/e5bc1e10862a765f6790f5f08aa2bd76bb258532)) -* **theme:** remove label background of code-group tabs ([#2136](https://github.com/vuejs/vitepress/issues/2136)) ([eac03f2](https://github.com/vuejs/vitepress/commit/eac03f26e2d3ab47158ac2528210e95460f6c302)) +- **build:** vendor vue-demi to avoid resolution issues with yarn berry ([#3680](https://github.com/vuejs/vitepress/issues/3680)) ([5d3cb96](https://github.com/vuejs/vitepress/commit/5d3cb96ac364413aa9eb494bc91744bd8f4a2c79)) +# [1.0.0](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.45...v1.0.0) (2024-03-21) -### Features - -* more flexible `ignoreDeadLinks` ([#2135](https://github.com/vuejs/vitepress/issues/2135)) ([3235c23](https://github.com/vuejs/vitepress/commit/3235c23313d81f8f95b91779a48db839c02aa952)) +### Bug Fixes +- **build:** resolve pattern relative to srcDir instead of root in createContentLoader ([#3638](https://github.com/vuejs/vitepress/issues/3638)) ([59183e9](https://github.com/vuejs/vitepress/commit/59183e9cef112a004c8a8e2b365478af657858b0)) +- **localSearch:** remove empty titles that may appear in search results ([#3665](https://github.com/vuejs/vitepress/issues/3665)) ([f7aef3c](https://github.com/vuejs/vitepress/commit/f7aef3ca23dae39e226c85d7bb2579dbf7c758f3)) +- **theme:** fixed sidebar expand caret showing when no children are present ([#3657](https://github.com/vuejs/vitepress/issues/3657)) ([e13f932](https://github.com/vuejs/vitepress/commit/e13f93292ce1a2b1d5ba161fddfe947a1824a2b0)) +- **theme:** ignore inner-page items in next/prev link ([#3663](https://github.com/vuejs/vitepress/issues/3663)) ([b50a8a1](https://github.com/vuejs/vitepress/commit/b50a8a132577693817a15ab43fc4cc22670a8a65)) +- **theme:** local nav separator not visible on pages having no outline ([1909041](https://github.com/vuejs/vitepress/commit/190904171500ad22998c8666080fd58c867a59b5)) +### Features -# [1.0.0-alpha.62](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.61...v1.0.0-alpha.62) (2023-03-25) +- **theme:** allow selectively disabling external link icon on navbar items ([#3607](https://github.com/vuejs/vitepress/issues/3607)) ([5f6297c](https://github.com/vuejs/vitepress/commit/5f6297cb3df98926154235f31570e75820d4ea16)) +# [1.0.0-rc.45](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.44...v1.0.0-rc.45) (2024-03-06) ### Bug Fixes -* make md includes work with rewrites ([#1898](https://github.com/vuejs/vitepress/issues/1898)) ([3553f01](https://github.com/vuejs/vitepress/commit/3553f015a9138cb935d57487755d9d5717f79ae3)) -* **theme:** don't show outline when no header is there ([#2117](https://github.com/vuejs/vitepress/issues/2117)) ([42a0ef2](https://github.com/vuejs/vitepress/commit/42a0ef21c17da20c8f22565807578a05a0461df6)) -* **theme:** fix aside position when footer is there ([#2115](https://github.com/vuejs/vitepress/issues/2115)) ([aecdeb9](https://github.com/vuejs/vitepress/commit/aecdeb9b216803f407fe3b48574bf7664262ef01)) -* **theme:** properly align not found icon in algolia ([#2116](https://github.com/vuejs/vitepress/issues/2116)) ([83ce1b8](https://github.com/vuejs/vitepress/commit/83ce1b8c5e95d2e29e733d9312f514d725fe7f0b)) -* **theme:** use locale lang instead of navigator lang for last updated ([#2118](https://github.com/vuejs/vitepress/issues/2118)) ([56a7d9a](https://github.com/vuejs/vitepress/commit/56a7d9aa74bbb1d945c6ca3a3573b5e49ba3ca65)) +- **router:** hashchange not emitted in certain cases ([#3637](https://github.com/vuejs/vitepress/issues/3637)) ([f6bd99e...6c0125b](https://github.com/vuejs/vitepress/compare/f6bd99eb1311238e1114301a767634b139327916...6c0125b65513531870f00ebef1ae11096027875a)) +### Features +- set `__VITEPRESS__` for easy detection by plugins and other tools ([#3634](https://github.com/vuejs/vitepress/issues/3634)) ([f6bd99e](https://github.com/vuejs/vitepress/commit/f6bd99eb1311238e1114301a767634b139327916)) -# [1.0.0-alpha.61](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.60...v1.0.0-alpha.61) (2023-03-20) +# [1.0.0-rc.44](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.43...v1.0.0-rc.44) (2024-2-19) +### Reverts + +- types for internal components ([e703429](https://github.com/vuejs/vitepress/commit/e7034294731493a198cdd4789198f1c94f21b181)) + +# [1.0.0-rc.43](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.42...v1.0.0-rc.43) (2024-2-17) ### Bug Fixes -* **build:** skip warning for `txt` language ([#2109](https://github.com/vuejs/vitepress/issues/2109)) ([ac953ce](https://github.com/vuejs/vitepress/commit/ac953ce8bdeecb2854257613c849b82d38a91846)) -* decode when query selecting current hash ([1f2f1ff](https://github.com/vuejs/vitepress/commit/1f2f1ff43dbb3c1598810fe04608678426e4fed5)), closes [#2089](https://github.com/vuejs/vitepress/issues/2089) -* **theme:** prevent code-groups conflict with shiki-twoslash ([#2059](https://github.com/vuejs/vitepress/issues/2059)) ([ee6cda4](https://github.com/vuejs/vitepress/commit/ee6cda42d8631c5f1f6ef47ac1aec0b178a6cbf2)) +- handle process.env being undefined while process is not ([b63e0a0](https://github.com/vuejs/vitepress/commit/b63e0a0c57f886f49aa7e073ff623c918164bd0b)), closes [#3579](https://github.com/vuejs/vitepress/issues/3579) +- make local search work in combination with vue-i18n ([#3559](https://github.com/vuejs/vitepress/issues/3559)) ([6624bb7](https://github.com/vuejs/vitepress/commit/6624bb748610079b88e2dcef7ea1810833a54a85)) +- **theme:** adjust mathjax svg styles ([#3567](https://github.com/vuejs/vitepress/issues/3567)) ([2051100](https://github.com/vuejs/vitepress/commit/20511006dba516ca8c06ed1dd3516547af668a0e)) +### Features +- **theme:** auto style markdown content in home page ([#3561](https://github.com/vuejs/vitepress/issues/3561)) ([0903027](https://github.com/vuejs/vitepress/commit/09030272b4a5c8f723b7e11303265f24b7481575)) -# [1.0.0-alpha.60](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.59...v1.0.0-alpha.60) (2023-03-15) +### Performance Improvements +- **theme:** move svg icons to css ([#3537](https://github.com/vuejs/vitepress/issues/3537)) ([636cca0](https://github.com/vuejs/vitepress/commit/636cca042dfbca006af2d702ddec0a2ff601cb46)) -### Features +### BREAKING CHANGES -* support multiple selectors for scrollOffset ([86e2a6f](https://github.com/vuejs/vitepress/commit/86e2a6f97287c0999090d5af0e8362f3e48884db)) -* **theme:** add animation to mobile page outline dropdown ([a6b18a8](https://github.com/vuejs/vitepress/commit/a6b18a8b9aba706aa3a567ee7b2564437a0850aa)) +- The default theme now styles the markdown content in the home page. If you have custom styles that rely on the markdown content not being styled, you may need to adjust your styles, or add `markdownStyles: false` to the frontmatter of your home page. +# [1.0.0-rc.42](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.41...v1.0.0-rc.42) (2024-2-6) +### Bug Fixes -# [1.0.0-alpha.59](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.58...v1.0.0-alpha.59) (2023-03-15) +- **md:** dont break on nesting blockquotes inside gfm alerts ([8f8a6fe](https://github.com/vuejs/vitepress/commit/8f8a6feb053b3f521a2c90e343dffa7f98bb63b3)), closes [#3512](https://github.com/vuejs/vitepress/issues/3512) +- **theme:** correctly normalize paths ending with "index" ([#3544](https://github.com/vuejs/vitepress/issues/3544)) ([c582a8d](https://github.com/vuejs/vitepress/commit/c582a8d5fd82b84d412c7e6c84e74faeb23beac6)) +# [1.0.0-rc.41](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.40...v1.0.0-rc.41) (2024-2-1) ### Bug Fixes -* handle async enhanceApp when extending themes ([52b04f3](https://github.com/vuejs/vitepress/commit/52b04f324cc3a675ed87353d516a6302d282ccfb)) -* **theme:** improve Chinese font handling ([81ae1c7](https://github.com/vuejs/vitepress/commit/81ae1c79cd1c0c9c31f48100f131715efc68efbd)), closes [#2036](https://github.com/vuejs/vitepress/issues/2036) -* **theme:** move doc-footer-before slot into the footer ([b0160bc](https://github.com/vuejs/vitepress/commit/b0160bc2619b50e3bca2bf1bba60d68708a39145)), closes [#2082](https://github.com/vuejs/vitepress/issues/2082) - +- handle CRLF in snippet plugin ([5811b62](https://github.com/vuejs/vitepress/commit/5811b626576ec4569fa0079d921b8e328d87ca91)), closes [#3499](https://github.com/vuejs/vitepress/issues/3499) +- lazy evaluate known extensions to allow env set in config ([04f794b](https://github.com/vuejs/vitepress/commit/04f794bf55f8191ea9eed62f545b812f346017d8)) ### Features -* defineClientComponent helper ([2ad668c](https://github.com/vuejs/vitepress/commit/2ad668cd54174b37a8c68b389a5e31e0aae60828)) - +- **home:** add target and rel attribute to home actions ([#3528](https://github.com/vuejs/vitepress/issues/3528)) ([ab39fd8](https://github.com/vuejs/vitepress/commit/ab39fd8592c994fbc6feba5ee369ca1205c50f04)) +- rename shiki packages ([#3506](https://github.com/vuejs/vitepress/issues/3506)) ([b8487d3](https://github.com/vuejs/vitepress/commit/b8487d3a97679f5b2eb225ee1eb85754b66fee30)) +- wrap site title in span ([#3522](https://github.com/vuejs/vitepress/issues/3522)) ([6b1f951](https://github.com/vuejs/vitepress/commit/6b1f951928a3b9e53dcc9697327b5aba4a5905e2)) +- **theme:** add hero slots that are inside container ([#3524](https://github.com/vuejs/vitepres/issues/3524)) ([28870e6](https://github.com/vuejs/vitepress/commit/28870e68faf0ddaa418ffe0d4371316f6b0bcd02)) +### BREAKING CHANGES -# [1.0.0-alpha.58](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.57...v1.0.0-alpha.58) (2023-03-14) +- vitepress now uses shiki instead of shikiji. If you’re on the latest version and using shikiji specific features, you just need to change imports. The shikijiSetup hook is renamed to shikiSetup. +# [1.0.0-rc.40](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.39...v1.0.0-rc.40) (2024-1-22) ### Bug Fixes -* fix optional component imports from default theme ([7b0f289](https://github.com/vuejs/vitepress/commit/7b0f28915fc15e155fbb27d5153e25d004bdc294)) - +- **client:** handle head orphans added in initial load ([#3474](https://github.com/vuejs/vitepress/issues/3474)) ([5e2d853](https://github.com/vuejs/vitepress/commit/5e2d853e1a315216dce5fc98ee2efd15c724a25d)) +- **theme:** avoid selecting summary on toggling details ([77a318c](https://github.com/vuejs/vitepress/commit/77a318c2a348d341dd3ea1e1650fcf8ad3abfcd7)) +- **theme:** hover color for code links inside custom containers ([#3467](https://github.com/vuejs/vitepress/issues/3467)) ([d529ed4](https://github.com/vuejs/vitepress/commit/d529ed49756841f055024c559d09875501bc6d76)) +- **type:** fix missed `VPBadge` type in `theme.d.ts` ([#3470](https://github.com/vuejs/vitepress/issues/3470)) ([fcf828c](https://github.com/vuejs/vitepress/commit/fcf828c2a71892dad5af8d21e405f4d1e2cc280c)) +### Features -# [1.0.0-alpha.57](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.56...v1.0.0-alpha.57) (2023-03-14) +- support GitHub-flavored alerts ([#3482](https://github.com/vuejs/vitepress/issues/3482)) ([ac87d19](https://github.com/vuejs/vitepress/commit/ac87d19ca1bbc966e5fe1cca5f433f5ea4b11be3)) +- support specifying custom extensions to escape routing ([#3466](https://github.com/vuejs/vitepress/issues/3466)) ([c22f5d9](https://github.com/vuejs/vitepress/commit/c22f5d983f3e5d5c4f0ed0683a93ece564487c13)) +- **theme:** add npm icon ([#3483](https://github.com/vuejs/vitepress/issues/3483)) ([c882fa1](https://github.com/vuejs/vitepress/commit/c882fa1469a7bd0d6e28196e7a841adf48e803f1)) +# [1.0.0-rc.39](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.38...v1.0.0-rc.39) (2024-01-16) ### Bug Fixes -* **types:** allow void return in transformHead hook ([32dfaf5](https://github.com/vuejs/vitepress/commit/32dfaf5adc9db5e87995c67a7060169cbf835b09)) - +- **theme:** misaligned outline indicator ([#3458](https://github.com/vuejs/vitepress/issues/3458)) ([0ce5ece](https://github.com/vuejs/vitepress/commit/0ce5ece35687bdad7a65d61432419cfe3961a329)) +- **theme:** enter key behavior conflict with IME in search box ([#3454](https://github.com/vuejs/vitepress/issues/3454)) ([cd8ee6f](https://github.com/vuejs/vitepress/commit/cd8ee6fb32d8135e78c5827a36b79efad509042c)) +- **theme:** use`--vp-c-tip-` CSS variable for badge/block colors with type`tip` ([#3434](https://github.com/vuejs/vitepress/issues/3434)) ([78abf47](https://github.com/vuejs/vitepress/commit/78abf47b8b563d66db9d481a98bbdefac95cc84c)) ### Features -* expose page and assets on build hooks TransformContext ([468c049](https://github.com/vuejs/vitepress/commit/468c049ccd7648144761def11c88ebf70c0d4226)) -* **theme:** a11y improvements ([3b6a6d1](https://github.com/vuejs/vitepress/commit/3b6a6d1abdc42437d9e659ef598db1d93695db21)) -* **theme:** aria-label for social links ([6ca34c4](https://github.com/vuejs/vitepress/commit/6ca34c4236c076fb40fb0b4fb01c1f9783e2210c)) -* **theme:** page outline for mobile ([7182c42](https://github.com/vuejs/vitepress/commit/7182c4231f3c435f1471dfecacdce99d48270978)) -* **theme:** support extending default theme without importing fonts ([da1691d](https://github.com/vuejs/vitepress/commit/da1691d77e371892cbe566ba45ca24f1fa03dc7c)) -* **theme:** use more accessible header anchors [#2040](https://github.com/vuejs/vitepress/pull/2040) +- **theme:** export VPBadge ([#3431](https://github.com/vuejs/vitepress/issues/3431)) ([18981c1](https://github.com/vuejs/vitepress/commit/18981c1d1c74a4f4ca379a88b00c02ba5eace6db)) +# [1.0.0-rc.36](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.35...v1.0.0-rc.36) (2024-1-8) -### Performance Improvements +### Bug Fixes -* **theme:** preload font ([24735db](https://github.com/vuejs/vitepress/commit/24735dbcde15be41bc2697a4ea44001a1a583511)) +- avoid pushing to history when clicking on the current link ([#3405](https://github.com/vuejs/vitepress/issues/3405)) ([d279e63](https://github.com/vuejs/vitepress/commit/d279e63cb4d417420cdc3fb3e6e03c96b777289f)) +- **theme/regression:** external link icon not working ([c236570](https://github.com/vuejs/vitepress/commit/c236570f2806fe76bbc6a69568cf64ed5a3fc2ce)), closes [#3424](https://github.com/vuejs/vitepress/issues/3424) +- **theme/regression:** inter getting bundled even importing without-fonts entry ([#3412](https://github.com/vuejs/vitepress/issues/3412)) ([b03fb83](https://github.com/vuejs/vitepress/commit/b03fb83a4e67d92a865d90908ccbde3dd0f97373)) -### BREAKING CHANGES +# [1.0.0-rc.35](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.34...v1.0.0-rc.35) (2024-1-3) -* `markdown.headers` is now disabled by default. This means `PageData` will no longer include extracted headers by default unless this option is explicitly enabled. This is because the default theme now extracts page headers at runtime, so the data is no longer needed by default. +### Bug Fixes +- **client:** add computed dir and lang to html root ([c2b4c66](https://github.com/vuejs/vitepress/commit/c2b4c66e79fde7479f5f43841e1921a5c220c9a5)), closes [#3353](https://github.com//github.com/vuejs/vitepress/pull/3353/issues/issuecomment-1874753809) +- fill all empty code lines ([563020b](https://github.com/vuejs/vitepress/commit/563020ba61abda254af9a124ddafd12de644cd4e)), closes [#3305](https://github.com/vuejs/vitepress/issues/3305) +- fix theme chunking logic causing out-of-order styles ([#3403](https://github.com/vuejs/vitepress/issues/3403)) ([a6cd891](https://github.com/vuejs/vitepress/commit/a6cd891d95454b3130aaf08f499659d2585acc63)) +- invalidate module cache for subsequent builds ([#3398](https://github.com/vuejs/vitepress/issues/3398)) ([27f60e0](https://github.com/vuejs/vitepress/commit/27f60e0b7784603c6fb300bd8dce64515eb98962)) -# [1.0.0-alpha.56](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.55...v1.0.0-alpha.56) (2023-03-13) +### Features +- allow passing options to emoji plugin ([09e48db](https://github.com/vuejs/vitepress/commit/09e48db355f530c7a138437004659b61239f4b75)), closes [#3174](https://github.com/vuejs/vitepress/issues/3174) +- **theme:** allow specifying rel and target in logoLink ([6c89943](https://github.com/vuejs/vitepress/commit/6c899437c15b126b488e73c99cdaad77fc7e5611)), closes [#3264](https://github.com/vuejs/vitepress/issues/3264) [#3271](https://github.com/vuejs/vitepress/issues/3271) -### Bug Fixes +### Performance Improvements -* do not include head tags in inlined site data ([2f26693](https://github.com/vuejs/vitepress/commit/2f26693a1d78f24d5a62a9b988c457e7c299fc5c)) +- **localSearch:** add concurrency pooling, cleanup logic, improve performance ([#3374](https://github.com/vuejs/vitepress/issues/3374)) ([ac5881e](https://github.com/vuejs/vitepress/commit/ac5881eeac3f042a8fbf034edb99e5f2b45eaa2a)) +# [1.0.0-rc.34](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.33...v1.0.0-rc.34) (2023-12-30) +### Bug Fixes -# [1.0.0-alpha.55](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.54...v1.0.0-alpha.55) (2023-03-13) +- **build:** clear cache after build ([9568fea](https://github.com/vuejs/vitepress/commit/9568fea8fc50e625c8ef27c588eca3dbe5a44e81)), closes [#3363](https://github.com/vuejs/vitepress/issues/3363) +- **default-theme:** remove use of reactify for search i18n ([8687b86](https://github.com/vuejs/vitepress/commit/8687b86e1e00ae39ff9c8173aef04eb8a9cda0a8)) +- print errors when importing an invalid dynamic route ([#3201](https://github.com/vuejs/vitepress/issues/3201)) ([6d89a08](https://github.com/vuejs/vitepress/commit/6d89a08cb76674f4d92f54218f8af5624bcf4c47)) +- remove double title from home pages ([9f1f04e](https://github.com/vuejs/vitepress/commit/9f1f04e00a9722ec7369941c40d3d8ad86f61d35)), closes [#3375](https://github.com/vuejs/vitepress/issues/3375) +- **theme/i18n:** support customizing dark mode switch titles ([#3311](https://github.com/vuejs/vitepress/issues/3311)) ([50c9758](https://github.com/vuejs/vitepress/commit/50c9758d3fa1b60aad5399a0db890644ac44a522)) +### Features -### Bug Fixes +- support custom image lazy loading ([#3346](https://github.com/vuejs/vitepress/issues/3346)) ([55be3f1](https://github.com/vuejs/vitepress/commit/55be3f14d79eb578c9aa2e3bc7a90205c910005d)) +- support dir in frontmatter ([#3353](https://github.com/vuejs/vitepress/issues/3353)) ([203446d](https://github.com/vuejs/vitepress/commit/203446d69193483a46e1082bba5fbad0e35966fb)) +- **theme/i18n:** allow customizing sponsor link's text ([#3276](https://github.com/vuejs/vitepress/issues/3276)) ([9c20e3b](https://github.com/vuejs/vitepress/commit/9c20e3b5f80e4197c14c20fa751ec3c8c8219e8e)) +- **theme:** allow using VPBadge classes in sidebar ([#3391](https://github.com/vuejs/vitepress/issues/3391)) ([50a774e](https://github.com/vuejs/vitepress/commit/50a774ea7c70bb200e12c176d6691ab7144a73f9)) +- **theme:** new design for local nav and global header ([#3359](https://github.com/vuejs/vitepress/issues/3359)) ([d10bf42](https://github.com/vuejs/vitepress/commit/d10bf42c2632f1aacb905bc01b36274e9004cbd9)) + +# [1.0.0-rc.33](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.32...v1.0.0-rc.33) (2023-12-26) -* fix scroll to hash on new tab during dev ([9aafc88](https://github.com/vuejs/vitepress/commit/9aafc88d5951684b9b583a7a164840a9b87467b0)), closes [#653](https://github.com/vuejs/vitepress/issues/653) -* gracefully handle config update with syntax error ([470ce3d](https://github.com/vuejs/vitepress/commit/470ce3d3f3272639288cb888dc89d37f041df104)), closes [#2041](https://github.com/vuejs/vitepress/issues/2041) +### Features +- allow explicitly mark code element as `.vp-copy-ignore` ([#3360](https://github.com/vuejs/vitepress/issues/3360)) ([93122ee](https://github.com/vuejs/vitepress/commit/93122eee20cb6586026c1ffac04d9787861cc2f3)) +- **build:** enable VUE_PROD_HYDRATION_MISMATCH_DETAILS when DEBUG is truthy ([f4d4280](https://github.com/vuejs/vitepress/commit/f4d4280d7d1728a966bb04968a9bac10470c3d06)), closes [#422](https://github.com/vuejs/vitepress/issues/422) ### Performance Improvements -* inline site data on page ([22ace7b](https://github.com/vuejs/vitepress/commit/22ace7b075276c340d0ae2a1f260d119e82c6470)) -* kickoff main chunk fetch earlier in browsers without modulepreload support ([d64a76e](https://github.com/vuejs/vitepress/commit/d64a76eb366a270c56189096a5e0ae6b8ae23ea7)) +- implement concurrent promise pooling for render task ([#3366](https://github.com/vuejs/vitepress/issues/3366)) +# [1.0.0-rc.32](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.31...v1.0.0-rc.32) (2023-12-16) +### Features -# [1.0.0-alpha.54](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.53...v1.0.0-alpha.54) (2023-03-13) +- allow ignoring node in header ([#3331](https://github.com/vuejs/vitepress/issues/3331)) ([e4bf1e4](https://github.com/vuejs/vitepress/commit/e4bf1e48e6a1592d583b218425c1fa7497955dc5)) +- expose `shikijiSetup` hook ([#3344](https://github.com/vuejs/vitepress/issues/3344)) ([d12e23d](https://github.com/vuejs/vitepress/commit/d12e23ddf69480418078ff39846c99ecf2e1eb1b)) +- update shikiji, support twoslash ([#3339](https://github.com/vuejs/vitepress/issues/3339)) ([8800195](https://github.com/vuejs/vitepress/commit/880019545795fd075be89d94794bfbd05af461b5)) +# [1.0.0-rc.31](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.30...v1.0.0-rc.31) (2023-11-25) ### Bug Fixes -* fix chunking logic that causes breakage ([bed202d](https://github.com/vuejs/vitepress/commit/bed202dbcc8f3954c12aaef993369b29ff47211e)), closes [#2072](https://github.com/vuejs/vitepress/issues/2072) [#2073](https://github.com/vuejs/vitepress/issues/2073) [#2074](https://github.com/vuejs/vitepress/issues/2074) [#2075](https://github.com/vuejs/vitepress/issues/2075) +- **build:** make assets go through vite pipeline during dev too ([#3258](https://github.com/vuejs/vitepress/issues/3258)) ([c3d7f22](https://github.com/vuejs/vitepress/commit/c3d7f22bd313b09e6965ac3125ea662ce283ed2d)) +- **theme:** use VPLink for links in VPDocFooter ([#3248](https://github.com/vuejs/vitepress/issues/3248)) ([479a320](https://github.com/vuejs/vitepress/commit/479a320731313b8e7e0bad3f8383ae6bc05ed8e2)) +# [1.0.0-rc.30](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.29...v1.0.0-rc.30) (2023-11-23) +### Bug Fixes -# [1.0.0-alpha.53](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.52...v1.0.0-alpha.53) (2023-03-13) +- **client:** no onAfterRouteChanged called after popstate ([#3227](https://github.com/vuejs/vitepress/issues/3227)) ([60fc8fd](https://github.com/vuejs/vitepress/commit/60fc8fd24460eede1dc73768ad0aa53616da746f)), closes [#3226](https://github.com/vuejs/vitepress/issues/3226) +- **theme:** remove double padding from sidebar ([ef6d8d1](https://github.com/vuejs/vitepress/commit/ef6d8d1e4295c6ff967c17b5b9c20c04843da5a0)), closes [#3228](https://github.com/vuejs/vitepress/issues/3228) + +### Features + +- migrate to shikiji ([#3237](https://github.com/vuejs/vitepress/pull/3237)) ([75f18e4](https://github.com/vuejs/vitepress/commit/75f18e47334933b642d14b8b69b372cb1ebd4244)) +### BREAKING CHANGES + +- VitePress now uses shikiji instead of shiki for syntax highlighting. If you're using features like adding extra languages or custom aliases, please refer [shikiji docs](https://github.com/antfu/shikiji) for migration guide or comment on [#3237](https://github.com/vuejs/vitepress/pull/3237) if you need help. + +# [1.0.0-rc.29](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.28...v1.0.0-rc.29) (2023-11-19) ### Bug Fixes -* avoid circular dependency between siteData virtual module and useData() ([905f58b](https://github.com/vuejs/vitepress/commit/905f58b2a80cd1dd37b645dddde3d54b02cd60d4)), closes [#2072](https://github.com/vuejs/vitepress/issues/2072) [#2073](https://github.com/vuejs/vitepress/issues/2073) [#2074](https://github.com/vuejs/vitepress/issues/2074) +- **client:** regression - router not working without .html present ([d63cb86](https://github.com/vuejs/vitepress/commit/d63cb867b14ba49c8333ad0d69d33874e2ece6c6)), closes [#3225](https://github.com/vuejs/vitepress/issues/3225) +# [1.0.0-rc.28](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.27...v1.0.0-rc.28) (2023-11-18) + +### Bug Fixes + +- **ally:** clear up confusion with the title of theme switch ([#3215](https://github.com/vuejs/vitepress/issues/3215)) ([6761036](https://github.com/vuejs/vitepress/commit/67610363bcb354d33327e6b5c3c2d916ed025ffc)) +- **build:** support nested assetsDir ([02161d0](https://github.com/vuejs/vitepress/commit/02161d0f797cfa36d715119e8c7618770b1a6761)) +- wrong recognition of non-html extension leads to route error ([#3218](https://github.com/vuejs/vitepress/issues/3218)) ([c4abc95](https://github.com/vuejs/vitepress/commit/c4abc950af7061611e3b5eff93e767706bd12396)) ### Features -* createContentLoader ([d2838e3](https://github.com/vuejs/vitepress/commit/d2838e3755a8ef5861d1a921a336dfebc6156634)) -* **theme:** editLink can accept function ([#2058](https://github.com/vuejs/vitepress/issues/2058)) ([192708d](https://github.com/vuejs/vitepress/commit/192708de678115116f3477293742c155b8f48e5d)) +- **build:** html head meta generator ([#3219](https://github.com/vuejs/vitepress/issues/3219)) ([672e494](https://github.com/vuejs/vitepress/commit/672e4946ac3c24f3fc79469534e66cfaf6f23e67)) +- **client:** allow disabling link auto-prefetching ([#3220](https://github.com/vuejs/vitepress/issues/3220)) ([563dc89](https://github.com/vuejs/vitepress/commit/563dc899757e58d2261bcb31081283eb395fab0b)) +# [1.0.0-rc.27](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.26...v1.0.0-rc.27) (2023-11-17) +### Bug Fixes -# [1.0.0-alpha.52](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.51...v1.0.0-alpha.52) (2023-03-11) +- CSS missing after build ([#3217](https://github.com/vuejs/vitepress/issues/3217)) ([da73b58](https://github.com/vuejs/vitepress/commit/da73b58c795a65a09d028e0ca6acefa1170d3d5b)), closes [#3216](https://github.com/vuejs/vitepress/issues/3216) +# [1.0.0-rc.26](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.25...v1.0.0-rc.26) (2023-11-16) ### Bug Fixes -* fix line higlighting for empty lines ([9708510](https://github.com/vuejs/vitepress/commit/9708510cbd893f02916c95fabad5a8f07d52dbaf)) -* fix rewrites with non ascii chars ([6ce88da](https://github.com/vuejs/vitepress/commit/6ce88da3baa4bc9e6b8dc3254180ed995766c7ec)), closes [#2017](https://github.com/vuejs/vitepress/issues/2017) -* fix same page hash links with encoded chars ([e05a3f2](https://github.com/vuejs/vitepress/commit/e05a3f2b5aff54ec7e5211c1021c16814eb57e58)), closes [#1749](https://github.com/vuejs/vitepress/issues/1749) -* properly serialize header in outline ([8ab36d0](https://github.com/vuejs/vitepress/commit/8ab36d05fa4aa8b3707c1f89efc1c820ffaf9669)) -* remove @vue/devtools from force include ([9bd940f](https://github.com/vuejs/vitepress/commit/9bd940f22cae0ec88dc1670a31fb9ebc015e1f92)) -* respect user vue alias ([63f33d2](https://github.com/vuejs/vitepress/commit/63f33d2895d21c08903eb4d625c13d8d3721d861)), closes [#1065](https://github.com/vuejs/vitepress/issues/1065) -* **theme:** re-support dynamic headers ([657a7d3](https://github.com/vuejs/vitepress/commit/657a7d38df3c9022a7ef6977fd71a6bde6571cfc)) -* trim spaces from outline headers ([9ceff1d](https://github.com/vuejs/vitepress/commit/9ceff1d587f6b61529806c5eb705fc417b685ad9)) - +- "VPNavScreenMenuGroup" component HTML not supported ([#3148](https://github.com/vuejs/vitepress/issues/3148)) ([237ad85](https://github.com/vuejs/vitepress/commit/237ad859a982f3fa55f7bba0f98ca94707108618)) +- **build:** remove frontmatter in md file inclusion ([dbbffa2](https://github.com/vuejs/vitepress/commit/dbbffa2487cd1f9899916baa166591248fb24334)), closes [#3195](https://github.com/vuejs/vitepress/issues/3195) +- style links in footer ([#3178](https://github.com/vuejs/vitepress/issues/3178)) ([a482611](https://github.com/vuejs/vitepress/commit/a482611d17197a0b7afc403891cd95f344e7a55f)) ### Features -* allow disabling markdown.headers ([868a9ff](https://github.com/vuejs/vitepress/commit/868a9ff81ea445556bc7500dfe4210d253da9ceb)) +- switch to vite 5 and bump deps ([#3200](https://github.com/vuejs/vitepress/issues/3200)) ([d2238ee](https://github.com/vuejs/vitepress/commit/d2238eedb7c0c81b2d9f425e6f70f7019ad6a482)) +### BREAKING CHANGES -### Performance Improvements +- VitePress now runs on Vite 5. Please refer https://vitejs.dev/guide/migration for breaking changes and migration guide if you're relying on some Vite-specific things. -* improve default theme chunking ([f6cb4c0](https://github.com/vuejs/vitepress/commit/f6cb4c0d44108116c91b28a3fcde820093d94340)) +# [1.0.0-rc.25](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.24...v1.0.0-rc.25) (2023-11-05) +### Bug Fixes -### BREAKING CHANGES +- double-slash format url should be external link ([#3165](https://github.com/vuejs/vitepress/issues/3165)) ([7dbeac6](https://github.com/vuejs/vitepress/commit/7dbeac6df0dfc0da74dffc79998a85a3afa86874)) +- missing export types in localSearch ([#3157](https://github.com/vuejs/vitepress/issues/3157)) ([0761062](https://github.com/vuejs/vitepress/commit/0761062790b441eccd0d57d51903271f30e713af)) +- **theme:** table row background-color in custom containers ([#3179](https://github.com/vuejs/vitepress/issues/3179)) ([beecec1](https://github.com/vuejs/vitepress/commit/beecec16a8d62c18f46522d461db353c97199415)) +- **theme:** theme switch is not hidden on force-dark ([#3155](https://github.com/vuejs/vitepress/issues/3155)) ([2276c1d](https://github.com/vuejs/vitepress/commit/2276c1d4dac547bb09015fcd0df73825b32c5fad)) -* default theme config option `outlineBadge` has been -removed. Badges in headers are now always excluded when generating -outline text. +### Features +- export `mergeConfig()` ([#3143](https://github.com/vuejs/vitepress/issues/3143)) ([a850786](https://github.com/vuejs/vitepress/commit/a850786a566606fda20cc4ed71b79e975307b52a)) +### Performance Improvements -# [1.0.0-alpha.51](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.50...v1.0.0-alpha.51) (2023-03-09) +- reduce duplicate rendering in localSearch ([#3170](https://github.com/vuejs/vitepress/issues/3170)) ([878f437](https://github.com/vuejs/vitepress/commit/878f4378cdee3c41f7643d9c7693bb607344d0c2)) +# [1.0.0-rc.24](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.23...v1.0.0-rc.24) (2023-10-24) ### Bug Fixes -* **theme:** align number to code line ([#2044](https://github.com/vuejs/vitepress/issues/2044)) ([27e3adf](https://github.com/vuejs/vitepress/commit/27e3adf8ed888f03466fec2e10bc7589b0d010e8)) -* **theme:** remove log in VPContent ([747a04d](https://github.com/vuejs/vitepress/commit/747a04d3416a4014e46e41ebfdc734643268bc29)) - +- lock plugin-vue version ([aa75fd6](https://github.com/vuejs/vitepress/commit/aa75fd62643d51be647f6e5937c97b7c47bf9739)) +- **styles:** large blur radius is causing color issues with safari ([a31e143](https://github.com/vuejs/vitepress/commit/a31e143afac597034a8d77f516961b0d2857ac8d)) ### Features -* **theme:** add not-found layout slot ([#2054](https://github.com/vuejs/vitepress/issues/2054)) ([41987b6](https://github.com/vuejs/vitepress/commit/41987b6a880d99e78e48ae3b4a2e6b815e183348)) +- **template:** add types for theme config ([#3122](https://github.com/vuejs/vitepress/issues/3122)) ([56b3ce5](https://github.com/vuejs/vitepress/commit/56b3ce5032b1d3bcfd66a1a397d87172a6f113d7)) +# [1.0.0-rc.23](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.22...v1.0.0-rc.23) (2023-10-22) -### Performance Improvements +### Bug Fixes -* **a11y:** add aria-label to language button ([#2025](https://github.com/vuejs/vitepress/issues/2025)) ([322c633](https://github.com/vuejs/vitepress/commit/322c633fd0df15b2dfae62b54479d7cdb3255155)) +- don't normalize non-html/non-http links ([#3114](https://github.com/vuejs/vitepress/issues/3114)) ([da3d781](https://github.com/vuejs/vitepress/commit/da3d7812a143e3aa360845b89f573d4e1ec637dd)) +- **mpa:** properly emit assets in mpa mode ([#3115](https://github.com/vuejs/vitepress/issues/3115)) ([6cf1de5](https://github.com/vuejs/vitepress/commit/6cf1de5e9e15d4507054744b665ac15d5f9a05f1)) +- **theme/search:** prevent reactivity loss with i18n ([#3121](https://github.com/vuejs/vitepress/issues/3121)) ([50d61fa](https://github.com/vuejs/vitepress/commit/50d61faefacc3885efe99fe5477a3b815354a0c4)) +# [1.0.0-rc.22](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.21...v1.0.0-rc.22) (2023-10-15) +### Bug Fixes -# [1.0.0-alpha.50](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.49...v1.0.0-alpha.50) (2023-03-07) +- fixes a regression related with nanoid v5 ([#3090](https://github.com/vuejs/vitepress/issues/3090)) +# [1.0.0-rc.21](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.20...v1.0.0-rc.21) (2023-10-12) ### Bug Fixes -* avoid deprecation warning when using --force ([0c0b6cc](https://github.com/vuejs/vitepress/commit/0c0b6cc5a3a06bb0bee14dc854c7c1102a1b6657)) -* ensure HMR works properly for page outline ([1457681](https://github.com/vuejs/vitepress/commit/1457681484c873a7801729f9a9e11872b60b4868)), closes [#1281](https://github.com/vuejs/vitepress/issues/1281) -* extract all headers by default ([580a8e1](https://github.com/vuejs/vitepress/commit/580a8e1a551089e973745fd224d97aec9d3fa702)) -* respect command line minify and outDir options ([22047f3](https://github.com/vuejs/vitepress/commit/22047f3363af290687cb3077ff617ae550af6e8a)) -* **theme:** make tip box text color darker ([3158115](https://github.com/vuejs/vitepress/commit/3158115afc8f15bee3e35644a33328b02dee6d6d)) -* **theme:** prevent text wrapping in nav dropdown menu ([2a1abbe](https://github.com/vuejs/vitepress/commit/2a1abbe45e10b38f03795357cd52dc4f6cea5dfc)) - +- **build:** handle .mjs/.mts files as data / path loaders ([#3058](https://github.com/vuejs/vitepress/issues/3058)) ([7991180](https://github.com/vuejs/vitepress/commit/7991180080366f9eb0d43fe95d25b53cf7af652c)) +- **client:** only update head if needed ([#3017](https://github.com/vuejs/vitepress/issues/3017)) ([f2fc3dc](https://github.com/vuejs/vitepress/commit/f2fc3dc51b8019c18d5ab70a6b55b8333c91045a)) +- **theme:** search's configuration about buttonAriaLabel doesn't work ([#3070](https://github.com/vuejs/vitepress/issues/3070)) ([c08bd46](https://github.com/vuejs/vitepress/commit/c08bd46aa757e7a0bc28b2318fb38037d583b27d)) ### Features -* **data-loader:** defineLoader() type helper ([4673bb1](https://github.com/vuejs/vitepress/commit/4673bb187905374896b7a1a3b1a1e5ad3777bdc4)) -* **data-loader:** pass watched files into load() ([e29b6a0](https://github.com/vuejs/vitepress/commit/e29b6a051e89e23945e2acfdfca7057978929715)) -* deprecate Theme.setup ([868a586](https://github.com/vuejs/vitepress/commit/868a58670e747310bba1f0f900a76243c6473da3)) -* export loadEnv from vite ([7609704](https://github.com/vuejs/vitepress/commit/76097048f3570b3f2417ac76ef177ce16afb9116)) -* expose isNotFound on PageData, deperecate Theme.NotFound ([74caccd](https://github.com/vuejs/vitepress/commit/74caccda4342feee3ab980b1a446ef7ec4819e0f)) -* expose params at top level in useData() ([66f94fd](https://github.com/vuejs/vitepress/commit/66f94fd7a0f43882386d32769b6b98014154ffa6)) -* support $params in page components ([a4ac055](https://github.com/vuejs/vitepress/commit/a4ac055dbf42848206683611a8d15e09572441ac)) -* support Theme.extends ([f39b6a9](https://github.com/vuejs/vitepress/commit/f39b6a98d6d2cc9ba405204a4d7a91eadce64a0d)) -* **theme:** add `as` prop to `Content` ([#2011](https://github.com/vuejs/vitepress/issues/2011)) ([254e15b](https://github.com/vuejs/vitepress/commit/254e15beb9b895c081e301eb379cbc2551b3e53c)) -* **theme:** add `home-hero-info` slot ([#1807](https://github.com/vuejs/vitepress/issues/1807)) ([996a5f4](https://github.com/vuejs/vitepress/commit/996a5f47e9064da839aef9e81db22db70fa8d76d)) -* vitepress init command ([#2020](https://github.com/vuejs/vitepress/issues/2020)) ([38bbdad](https://github.com/vuejs/vitepress/commit/38bbdaddb72ec426865d731c2f443e545e5bbbd7)), closes [#1252](https://github.com/vuejs/vitepress/issues/1252) +- **md:** allow customizing container titles globally ([#3044](https://github.com/vuejs/vitepress/issues/3044)) ([bdb0800](https://github.com/vuejs/vitepress/commit/bdb080093f95ec43d013ea2ad537e567bdbb5a44)) +# [1.0.0-rc.20](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.15...v1.0.0-rc.20) (2023-09-24) +### Bug Fixes -# [1.0.0-alpha.49](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.48...v1.0.0-alpha.49) (2023-02-28) +- **build:** consistent route.path across dev and ssr ([#2997](https://github.com/vuejs/vitepress/issues/2997)) ([0d56855](https://github.com/vuejs/vitepress/commit/0d56855b54a97d4350485ee76c07a040fdc5738c)) +- **build:** don't show missing lang warnings with text specifiers in fences ([aa40cec](https://github.com/vuejs/vitepress/commit/aa40cecd48942506ffb063863c9b054e66f1d79e)) +- handle references in container titles ([7fbfe71](https://github.com/vuejs/vitepress/commit/7fbfe71b6cab2f091ba3d0c47a401fdc612b88b6)), closes [#3004](https://github.com/vuejs/vitepress/issues/3004) +- **hmr:** handle hmr in imported code snippets ([#3005](https://github.com/vuejs/vitepress/issues/3005)) ([e84f313](https://github.com/vuejs/vitepress/commit/e84f31371e9e5219d46ae58151667d24e12b77bb)) +- snippet hmr not working with rewrites ([a275049](https://github.com/vuejs/vitepress/commit/a2750492be7869ed48a5bde1ffbc177093356758)) +- selectively pass env for container titles ([1a9c32d](https://github.com/vuejs/vitepress/commit/1a9c32df12388386877c50daf9fc7924888eac07)), closes [#3007](https://github.com/vuejs/vitepress/issues/3007) +- **types:** add RegExp to markdown's allowed attributes ([#3008](https://github.com/vuejs/vitepress/issues/3008)) ([bc96b2b](https://github.com/vuejs/vitepress/commit/bc96b2bb5bc5361e55c46f270e3759c513db65d3)) +# [1.0.0-rc.15](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.14...v1.0.0-rc.15) (2023-09-20) ### Bug Fixes -* disable fuzzy link recognition by default ([2450710](https://github.com/vuejs/vitepress/commit/24507105b18362210632543b8a72893832b5940a)) -* dyamic routes w/ srcDir + relative imports ([b075ee5](https://github.com/vuejs/vitepress/commit/b075ee5be6785e671b19ded066c22a1d506ec508)) -* hmr on deps change of data loaders ([5913ebc](https://github.com/vuejs/vitepress/commit/5913ebc34f810e84b4ad482aa835e1a4e8beb404)) -* normalize all paths in config ([8e8fcd9](https://github.com/vuejs/vitepress/commit/8e8fcd9caa4194787c5fc81ad10d17cf82638b8f)) -* **theme:** "copy code" button not readable on hover state ([#819](https://github.com/vuejs/vitepress/issues/819)) ([#1892](https://github.com/vuejs/vitepress/issues/1892)) ([#1998](https://github.com/vuejs/vitepress/issues/1998)) ([c2de4ca](https://github.com/vuejs/vitepress/commit/c2de4caa345bdeda5252a8fc00cfcdbcc18d5d2d)) -* **theme:** tip custom container has wrong bg color for `` block ([d9a2e6e](https://github.com/vuejs/vitepress/commit/d9a2e6e8978f614d70f347be81b9b3b9df03d7a1)) -* update route configs on file add / delete ([bccce98](https://github.com/vuejs/vitepress/commit/bccce98c62d1ea405c55a6f72bab6f2ce27e2e65)) - +- **build:** allow using symlinks with code snippets ([f186901](https://github.com/vuejs/vitepress/commit/f186901a5157c904b3593089d72f2bad3530e7a3)), closes [#1617](https://github.com/vuejs/vitepress/issues/1617) +- **build:** handle importing code snippets not having an extension ([#2978](https://github.com/vuejs/vitepress/issues/2978)) ([e99aaad](https://github.com/vuejs/vitepress/commit/e99aaad9cf8ab3661e609cd2cf6ac7da57cb7eb5)) +- **build:** indentation being lost in code blocks ([5bb6bb0](https://github.com/vuejs/vitepress/commit/5bb6bb0a147ad43ca2d7069aad50fb9c6c2c11d6)), closes [#2988](https://github.com/vuejs/vitepress/issues/2988) +- **compat:** reset setRawMode on process exit ([#2994](https://github.com/vuejs/vitepress/issues/2994)) ([70fe47c](https://github.com/vuejs/vitepress/commit/70fe47c1dd69d39a40c83e919324d2b71f19bdaa)) ### Features -* dynamic routes ([24fa862](https://github.com/vuejs/vitepress/commit/24fa862c39d1b5c2ea6da6faf08cfe95e07f5d2f)) -* **theme:** enhance readability of custom containers ([#1824](https://github.com/vuejs/vitepress/issues/1824)) ([#1989](https://github.com/vuejs/vitepress/issues/1989)) ([472b6ec](https://github.com/vuejs/vitepress/commit/472b6ecf5e404bccc751bcf93b868ac30f43f22b)) +- allow passing fast glob options to `createContentLoader` ([4f9a60b](https://github.com/vuejs/vitepress/commit/4f9a60b0cfa2fa841465f6e8cc5f77ed3e023817)), closes [#2985](https://github.com/vuejs/vitepress/issues/2985) +# [1.0.0-rc.14](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.13...v1.0.0-rc.14) (2023-09-16) +### Bug Fixes -# [1.0.0-alpha.48](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.47...v1.0.0-alpha.48) (2023-02-26) +- **client:** router in invalid state after 404 ([#2972](https://github.com/vuejs/vitepress/issues/2972)) ([28ef0ea](https://github.com/vuejs/vitepress/commit/28ef0ea6f60ab33e9cf34ecef10e1515d84f7168)) +- **client:** scripts loading out of order when added through head ([#2970](https://github.com/vuejs/vitepress/issues/2970)) ([98679c9](https://github.com/vuejs/vitepress/commit/98679c9e82fcd3bbe3829640d0386cbd730e61ba)) +- customizing the starting line number even if globally set ([#2941](https://github.com/vuejs/vitepress/issues/2941)) ([0cd87b1](https://github.com/vuejs/vitepress/commit/0cd87b1bafa6158ded0bf741553816f3d9b43a89)) +- make algolia search work with indices that don't return absolute urls ([#2956](https://github.com/vuejs/vitepress/issues/2956)) ([2a34c6b](https://github.com/vuejs/vitepress/commit/2a34c6b3076bf418b3abbbca984fcb033743a611)), closes [#336](https://github.com/vuejs/vitepress/issues/336) [#805](https://github.com/vuejs/vitepress/issues/805) +- **theme:** remove extra padding from top when navbar is hidden ([#2575](https://github.com/vuejs/vitepress/issues/2575)) ([fd46dc9](https://github.com/vuejs/vitepress/commit/fd46dc9b8f8951b3196e4208d958d1ca0e1dc6e8)) + +### Features +- mathjax support ([#2977](https://github.com/vuejs/vitepress/issues/2977)) ([7271a95](https://github.com/vuejs/vitepress/commit/7271a959480261d60c01146d2e520d0f662e0380)) +- **theme:** allow forcing dark mode ([#2974](https://github.com/vuejs/vitepress/issues/2974)) ([1fb5d22](https://github.com/vuejs/vitepress/commit/1fb5d228a269e913163246e988806056b3f1b9d9)) +- **theme:** allow forcing site locale in last updated format ([#2973](https://github.com/vuejs/vitepress/issues/2973)) ([a18e5e4](https://github.com/vuejs/vitepress/commit/a18e5e48a442b09487cda8ab14e3b103ce270641)) -### Bug Fixes +# [1.0.0-rc.13](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.12...v1.0.0-rc.13) (2023-09-13) -* **compat:** remove use of array.at ([fd99590](https://github.com/vuejs/vitepress/commit/fd995906f61e5181ca8e1116dcd93eec65075056)) -* **theme:** add height constraints to hero image ([#1983](https://github.com/vuejs/vitepress/issues/1983)) ([803d5b6](https://github.com/vuejs/vitepress/commit/803d5b6d663b5293c70672ca5526a33f454e4a17)) -* **theme:** allow empty details in home feature ([#1936](https://github.com/vuejs/vitepress/issues/1936)) ([#1963](https://github.com/vuejs/vitepress/issues/1963)) ([b56351c](https://github.com/vuejs/vitepress/commit/b56351c7785b7a3a3413dcf24d7ac63c1f40fd2b)) -* **theme:** show external link icon in navbar ([#1881](https://github.com/vuejs/vitepress/issues/1881)) ([8e6e8d9](https://github.com/vuejs/vitepress/commit/8e6e8d9af534e124cb16552686b460e19d0f894f)), closes [#1948](https://github.com/vuejs/vitepress/issues/1948) -* **theme:** show external link icon on same line ([#1880](https://github.com/vuejs/vitepress/issues/1880)) ([6218b10](https://github.com/vuejs/vitepress/commit/6218b108bc78aed0ec1afd3d1cf4182e611eed90)) +### Bug Fixes +- **theme:** allow wrapping feature icons ([a1e1267](https://github.com/vuejs/vitepress/commit/a1e1267549e198b35455d055536cd0c6d1ad79ce)), closes [#2923](https://github.com/vuejs/vitepress/issues/2923) +- **theme:** local search enter key with the search result ([#2937](https://github.com/vuejs/vitepress/issues/2937)) ([00ef2f1](https://github.com/vuejs/vitepress/commit/00ef2f1db0369f50b3b634508e798b19b9525b34)) ### Features -* **build:** add support for custom languages ([#1837](https://github.com/vuejs/vitepress/issues/1837)) ([5a6d384](https://github.com/vuejs/vitepress/commit/5a6d3849527ee1dfd9f4299f5350cfa7641effb7)) -* **theme:** make prev/next links changeable ([#1972](https://github.com/vuejs/vitepress/issues/1972)) ([b8a5e8e](https://github.com/vuejs/vitepress/commit/b8a5e8e5b24b025c9a5e4850b72296f726ae71e5)) -* **theme:** support custom target and rel in navbar links ([#1993](https://github.com/vuejs/vitepress/issues/1993)) ([e2d4edf](https://github.com/vuejs/vitepress/commit/e2d4edf45b5ec890c088d3b0517b21a7b3eab9df)) - +- **theme:** add search insights boolean to algolia search ([#2940](https://github.com/vuejs/vitepress/issues/2940)) ([32aa2a7](https://github.com/vuejs/vitepress/commit/32aa2a7d179049e5a1ed809018c32418bf69e8d5)) +### Reverts -# [1.0.0-alpha.47](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.46...v1.0.0-alpha.47) (2023-02-20) +- Revert "feat(theme): use inert to avoid traverse menus and content with keyboard" (#2953) ([54891df](https://github.com/vuejs/vitepress/commit/54891df6149f4d0a871b16edf5f9a8a6fec639f9)), closes [#2953](https://github.com/vuejs/vitepress/issues/2953) [#2932](https://github.com/vuejs/vitepress/issues/2932) +# [1.0.0-rc.12](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.11...v1.0.0-rc.12) (2023-09-10) ### Bug Fixes -* **build:** show error stack in logs ([#1960](https://github.com/vuejs/vitepress/issues/1960)) ([c4d8d72](https://github.com/vuejs/vitepress/commit/c4d8d7225c2d8dd75f1640730e8d1425097e3aa3)) -* custom titles of code snippets inside code groups ([#1834](https://github.com/vuejs/vitepress/issues/1834)) ([bcb8cbf](https://github.com/vuejs/vitepress/commit/bcb8cbf3c839dc17c1eaee7e39edb3ecca236a27)) -* **types:** augment vite user config ([#1946](https://github.com/vuejs/vitepress/issues/1946)) ([5c9b75e](https://github.com/vuejs/vitepress/commit/5c9b75e325c27f63373c969e16035a9df5292cc9)) +- **theme:** prevent closing local search box on key enter ([#2933](https://github.com/vuejs/vitepress/issues/2933)) ([e544b41](https://github.com/vuejs/vitepress/commit/e544b411d91eba54154243b0af4cea3226c192c4)) +- **theme:** use brand color on search highlight ([dfc0fbf](https://github.com/vuejs/vitepress/commit/dfc0fbfcb4f255461bd90aef23a3dda1422b8335)), closes [#2902](https://github.com/vuejs/vitepress/issues/2902) + +### Features +- highlight nav by default when one of the items is matched ([#2893](https://github.com/vuejs/vitepress/issues/2893)) ([b1fbece](https://github.com/vuejs/vitepress/commit/b1fbece047ca503f2c59553f9e37a0aac4be52c9)) +- process md includes before building local search index ([#2906](https://github.com/vuejs/vitepress/issues/2906)) ([c6ff5c7](https://github.com/vuejs/vitepress/commit/c6ff5c76867dc59d5548cb33fd8447e23712bef5)) +- support for customizing the starting line number in a code block ([#2917](https://github.com/vuejs/vitepress/issues/2917)) ([c0ce7f7](https://github.com/vuejs/vitepress/commit/c0ce7f723e52682d9ca107e4ce4e0e5c82710e02)) +- **theme:** allow setting target in home features ([#2897](https://github.com/vuejs/vitepress/issues/2897)) ([cb49673](https://github.com/vuejs/vitepress/commit/cb4967313e5edcfd4bfc12aa10e75fec7b32e0c8)) +- **theme:** use inert to avoid traverse menus and content with keyboard ([#2932](https://github.com/vuejs/vitepress/issues/2932)) ([070fc0a](https://github.com/vuejs/vitepress/commit/070fc0a56ddb941e26a098ba7207b5d1e91b7b51)) -### Reverts +# [1.0.0-rc.11](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.10...v1.0.0-rc.11) (2023-09-10) -* "docs: add linkage for `code-groups` in `getting-started`" ([#1943](https://github.com/vuejs/vitepress/issues/1943)) ([ed90724](https://github.com/vuejs/vitepress/commit/ed90724022359358de582a3c00e86f381d57eeba)), closes [#1906](https://github.com/vuejs/vitepress/issues/1906) +### Bug Fixes +- **init:** missing mts extension on windows ([195ebe9](https://github.com/vuejs/vitepress/commit/195ebe9464e2cc9b208e7d6c8bc5fa9f92025fdc)), closes [#2886](https://github.com/vuejs/vitepress/issues/2886) +- respect attrs on custom containers ([8b76167](https://github.com/vuejs/vitepress/commit/8b76167ccfbe5bf21295db6905451e1c50ca4407)) +- temp workaround for broken navigation from 404 to home ([a18d544](https://github.com/vuejs/vitepress/commit/a18d5447f29f05d75bf0e20ff839e5c3bcdac390)), closes [#2891](https://github.com/vuejs/vitepress/issues/2891) +- **theme:** dropdown menu partially hidden by the homepage footer when it is too long ([#2904](https://github.com/vuejs/vitepress/issues/2904)) ([a60f079](https://github.com/vuejs/vitepress/commit/a60f079f996cc8ce9aeb189a25187fdbce2217ab)) +- **theme:** improve contrast of search highlight text ([#2887](https://github.com/vuejs/vitepress/issues/2887)) ([20f9770](https://github.com/vuejs/vitepress/commit/20f97702680b47eb9675770df4db94a3e3b94ef1)) +- **theme:** link hover color inside a custom block ([#2876](https://github.com/vuejs/vitepress/issues/2876)) ([39784ca](https://github.com/vuejs/vitepress/commit/39784ca55fdbefa97b7e9f892609ef8bdaeadf50)) +- **theme:** prevent layout shift in search button key ([#2889](https://github.com/vuejs/vitepress/issues/2889)) ([0088434](https://github.com/vuejs/vitepress/commit/0088434895e5df9afea5bb8e81c515a41e824c44)) +- **theme:** search button key misplaced on safari ([18adc07](https://github.com/vuejs/vitepress/commit/18adc07117cbf151b51aa205419496938a322a2e)) +- **types:** NavItem can only have either link or items ([#2880](https://github.com/vuejs/vitepress/issues/2880)) ([12ef12d](https://github.com/vuejs/vitepress/commit/12ef12d6330f61a29102e7a0d537e742ff20367f)) +### Features -# [1.0.0-alpha.46](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.45...v1.0.0-alpha.46) (2023-02-12) +- detect bun package manager ([#2874](https://github.com/vuejs/vitepress/issues/2874)) ([83270fe](https://github.com/vuejs/vitepress/commit/83270fe65767016a98cd59b6256f1361439cc7c8)) +- skip rendering if env.BUNDLE_ONLY is truthy ([#2890](https://github.com/vuejs/vitepress/issues/2890)) ([d40eb19](https://github.com/vuejs/vitepress/commit/d40eb1903be022c9dfe10136122f5dc5aacb71d3)) +# [1.0.0-rc.10](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.9...v1.0.0-rc.10) (2023-08-28) ### Bug Fixes -* **build:** prepend base to all internal non-relative links ([#1908](https://github.com/vuejs/vitepress/issues/1908)) ([dcf2941](https://github.com/vuejs/vitepress/commit/dcf29419f24bfb0fe99e424771be931bf77b9961)) -* **theme-default:** avoid preconnect without algolia ([#1902](https://github.com/vuejs/vitepress/issues/1902)) ([616fe5b](https://github.com/vuejs/vitepress/commit/616fe5b636050caa338cabede3794e658baa0ed6)) -* **theme-default:** remove duplicate judgments in `preconnect()` ([#1903](https://github.com/vuejs/vitepress/issues/1903)) ([48c9b11](https://github.com/vuejs/vitepress/commit/48c9b113161823133276198ebeb15131b83a7a75)) -* **theme:** make features support line wrapping ([#1913](https://github.com/vuejs/vitepress/issues/1913)) ([ea43076](https://github.com/vuejs/vitepress/commit/ea430760f507e3ba381c4ab01ec89a2111f35e8c)) - +- pseudo styles being removed with postcssIsolateStyles ([21b4f8c](https://github.com/vuejs/vitepress/commit/21b4f8caad8f0b9a570f00ac2662635062db8566)), closes [#2868](https://github.com/vuejs/vitepress/issues/2868) [#2867](https://github.com/vuejs/vitepress/issues/2867) +- resolve snippets from original file path - align with include behavior ([8aa032f](https://github.com/vuejs/vitepress/commit/8aa032f60cd52e674a401f79b3cb473ac7d22abb)) ### Features -* **build:** use vite logger ([#1899](https://github.com/vuejs/vitepress/issues/1899)) ([a00bb62](https://github.com/vuejs/vitepress/commit/a00bb621439b2571b3d33da6aa67c74ecd13d3c6)) -* **shiki:** support `ansi` code highlight ([#1878](https://github.com/vuejs/vitepress/issues/1878)) ([f974381](https://github.com/vuejs/vitepress/commit/f9743816a55503c387b9c71793a92eb38817650d)) -* **theme:** support disabling aside globally ([#1925](https://github.com/vuejs/vitepress/issues/1925)) ([dd0c4c6](https://github.com/vuejs/vitepress/commit/dd0c4c698c26d3e249d353c3baff568a8f406e8f)) +- allow overriding mdit-vue/component options ([4f01f1a](https://github.com/vuejs/vitepress/commit/4f01f1a09c84fced276e1a138a59ed1b9679ce15)) + +### Reverts +- "fix: createContentLoader generates invalid url when sets `base`" ([#2865](https://github.com/vuejs/vitepress/issues/2865)) ([6be5a7e](https://github.com/vuejs/vitepress/commit/6be5a7e830fab2361bde5a4194930b2898733a8b)) -### BREAKING CHANGES +# [1.0.0-rc.9](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.4...v1.0.0-rc.9) (2023-08-28) -* **build:** `base` is now prepended to all internal (non-relative) links, including any reference to a file present in the public directory. If you want the earlier behavior for such links, use absolute links. +### Bug Fixes +- **a11y/theme:** disable transitions if user prefers reduced motion ([fc5092f](https://github.com/vuejs/vitepress/commit/fc5092fb651487e69737fff04d3979f00c67dcc6)) +- **build:** respect preserveSymlinks ([#2780](https://github.com/vuejs/vitepress/issues/2780)) ([1bda710](https://github.com/vuejs/vitepress/commit/1bda710702f5569e26b24b44785d938296870884)) +- **cli/init:** print the correct packageManager ([#2787](https://github.com/vuejs/vitepress/issues/2787)) ([b388b0a](https://github.com/vuejs/vitepress/commit/b388b0a8c169e399f8da43368022454b6e8ea489)) +- **cli/init:** terminal message has not enough contrast ([#2786](https://github.com/vuejs/vitepress/issues/2786)) ([4d9d977](https://github.com/vuejs/vitepress/commit/4d9d9775190178d0eaea5b3cea86309ae420bd43)) +- restart server on theme creation/deletion ([#2785](https://github.com/vuejs/vitepress/issues/2785)) ([e0be677](https://github.com/vuejs/vitepress/commit/e0be677554a517e8b02fcaf930828bb052d1c4a4)) +- scroll-to-top in iOS when opens sidebar ([#2803](https://github.com/vuejs/vitepress/issues/2803)) ([3dab9a6](https://github.com/vuejs/vitepress/commit/3dab9a6be1b543cf52c7c61f1e439a7973cd6667)) +- stackblitz not working on firefox ([877f643](https://github.com/vuejs/vitepress/commit/877f643b133b70f01bbf397900829050a399893f)), closes [#2817](https://github.com/vuejs/vitepress/issues/2817) +- **theme:** docsearch variables not applying properly on ios beta ([436e99a](https://github.com/vuejs/vitepress/commit/436e99a594d42650f69c062fd095eb0502a76b34)) +- **theme:** improve logo svg and add `art` dir ([1f8c58a](https://github.com/vuejs/vitepress/commit/1f8c58aed0bf5a191021913dd7f9a87e9b75f3eb)) +- **theme:** prevent sidebar re-render unless there is actual change ([33962e0](https://github.com/vuejs/vitepress/commit/33962e04ebb2724e12b131f61ff00fe0aaf990f3)), closes [#2796](https://github.com/vuejs/vitepress/issues/2796) +- **theme:** revert 79 to 179 in yellow-soft ([#2858](https://github.com/vuejs/vitepress/issues/2858)) ([74fcb60](https://github.com/vuejs/vitepress/commit/74fcb60fb4ceb97b9ab0442a26e22a726af2dcc9)) +- **theme:** show only one carbon ad at a time ([5ced0cc](https://github.com/vuejs/vitepress/commit/5ced0cca837ac7fbf1884ab56255b29c69dbec40)) +- **theme:** ssr issues on deno ([e8edd0a](https://github.com/vuejs/vitepress/commit/e8edd0a05f43491656c00db36630f391caf64461)) +### Features -# [1.0.0-alpha.45](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.44...v1.0.0-alpha.45) (2023-01-31) +- allow customizing markdown renderer used for local search indexing ([#2770](https://github.com/vuejs/vitepress/issues/2770)) ([00dc1e6](https://github.com/vuejs/vitepress/commit/00dc1e6742273fe6fde74e7abbd160bd7724af4d)) +- export postcssIsolateStyles for vp-raw ([3c736c1](https://github.com/vuejs/vitepress/commit/3c736c1c95814d1ca43b4e99bda62b8ccc908cd5)) +- **theme:** allow overriding code copied text from css ([#2833](https://github.com/vuejs/vitepress/issues/2833)) ([e8ef1aa](https://github.com/vuejs/vitepress/commit/e8ef1aaabecd7374cdf6cefca6b02ff9d3d3573f)) +- **theme:** allow overriding last updated time in doc footer from frontmatter ([#2848](https://github.com/vuejs/vitepress/issues/2848)) ([9a062a6](https://github.com/vuejs/vitepress/commit/9a062a6dd63db3dc9d951f2973c4ab606594a11f)) +- **theme:** allow providing custom `toggle-appearance` function ([#2844](https://github.com/vuejs/vitepress/issues/2844)) ([a5f2eac](https://github.com/vuejs/vitepress/commit/a5f2eacf225ff1a9a82c10ae492658190f313fb0)) +- **theme:** allow setting rel and target on sidebar links ([e477cdf](https://github.com/vuejs/vitepress/commit/e477cdfd2f62144cd6331f45aaaa865185a64575)), closes [#2851](https://github.com/vuejs/vitepress/issues/2851) +- **theme:** export VPButton and VPSponsors ([#2767](https://github.com/vuejs/vitepress/issues/2767)) ([6960ec1](https://github.com/vuejs/vitepress/commit/6960ec1cf61e973ffb238af2b77ad7aaf8c83500)) +- **theme:** export VPImage ([#2814](https://github.com/vuejs/vitepress/issues/2814)) ([f242140](https://github.com/vuejs/vitepress/commit/f242140c47e8a15070f689d5a4e54c7d88100f96)) +- **theme:** improve color system ([#2797](https://github.com/vuejs/vitepress/issues/2797)) ([e4f5c51](https://github.com/vuejs/vitepress/commit/e4f5c51bbe25d42fd52a1cd47e83dda4254fdd7e)), closes [#2100](https://github.com/vuejs/vitepress/issues/2100) +### BREAKING CHANGES -### Bug Fixes +- `pathname://` protocol is dropped. Specify `target="_self"` or `target="_blank"` instead. Refer [docs](https://vitepress.dev/guide/routing#linking-to-non-vitepress-pages) to learn more. +- Shiki's default theme is now changed to `github-light` and `github-dark`. If you want to use the old theme, you can set `markdown.theme` in your config to `'material-theme-palenight'`. +- Internal logic of `isDark` is changed to use vueuse. It might impact your custom theme. You can customize its behavior using [`appearance`](https://vitepress.dev/reference/site-config#appearance) option. +- Default theme's color system is updated to make it more easily customizable. Refer the [PR](https://github.com/vuejs/vitepress/pull/2797) for new variables. + +# [1.0.0-rc.4](https://github.com/vuejs/vitepress/compare/v1.0.0-beta.7...v1.0.0-rc.4) (2023-08-08) + +### Bug Fixes + +- `createContentLoader` generates invalid url when `base` is set ([#2714](https://github.com/vuejs/vitepress/issues/2714)) ([0f38eb4](https://github.com/vuejs/vitepress/commit/0f38eb440492f3a486517714976fbfe6dfb30a09)) +- **build:** make outDir from cli work properly ([17378c0](https://github.com/vuejs/vitepress/commit/17378c064f3e6f166ce180f8d7eeced2f1cc4224)), closes [#2716](https://github.com/vuejs/vitepress/issues/2716) +- **build:** nested rewrites not working properly ([0f421d7](https://github.com/vuejs/vitepress/commit/0f421d72221495b8ef14195db3e3df9297ebc6ff)) +- **client:** handle empty hash in links ([#2738](https://github.com/vuejs/vitepress/issues/2738)) ([c6c983e](https://github.com/vuejs/vitepress/commit/c6c983ed73a019027b452b3eaf0ee4b502d38818)) +- fix sitemap path resolution ([481a5e3](https://github.com/vuejs/vitepress/commit/481a5e3cb55c6fda2c318180cfa0532ed34e4fc5)), closes [#2749](https://github.com/vuejs/vitepress/issues/2749) +- **theme:** align max-width media queries ([d31051a](https://github.com/vuejs/vitepress/commit/d31051a05106f97924be3cdb3919f24acc232b59)) +- **theme:** allow using h1 headings in outline ([e3f8fc7](https://github.com/vuejs/vitepress/commit/e3f8fc7972f5506cd9def08ad13c62141737318f)), closes [#1529](https://github.com/vuejs/vitepress/issues/1529) +- **theme:** close dropdown menus after an item is clicked ([#2380](https://github.com/vuejs/vitepress/issues/2380)) ([e54eea3](https://github.com/vuejs/vitepress/commit/e54eea3da0de640e7b343381bddf9a439d638954)) +- **theme:** don't reset scroll position on changing tab in code groups ([039798a](https://github.com/vuejs/vitepress/commit/039798a8c14a8c455e1187c5584c7f518c40f66a)), closes [#2732](https://github.com/vuejs/vitepress/issues/2732) [#2362](https://github.com/vuejs/vitepress/issues/2362) +- **theme:** dont show transparent navbar other than home ([#2742](https://github.com/vuejs/vitepress/issues/2742)) ([1d6254b](https://github.com/vuejs/vitepress/commit/1d6254b615b48ceef85267045e8fce976a7eafd5)) +- **theme:** hide outline marker on scroll to top ([81e7405](https://github.com/vuejs/vitepress/commit/81e7405e193e832442db9aedb50ed3dc741e92ed)) +- **theme:** outline marker flicks when navigating towards above ([e8ebf1b](https://github.com/vuejs/vitepress/commit/e8ebf1b0483e025b7d3bc3ea6eb3fa02d4acac93)), closes [#2665](https://github.com/vuejs/vitepress/issues/2665) [#2676](https://github.com/vuejs/vitepress/issues/2676) +- **theme:** override docsearch button bg ([063b0e5](https://github.com/vuejs/vitepress/commit/063b0e520a0b34db934371f56ddba212ceb3ba4c)), closes [#2735](https://github.com/vuejs/vitepress/issues/2735) +- **theme:** respect feature icon dimensions set from frontmatter ([93823a8](https://github.com/vuejs/vitepress/commit/93823a8566df22c57cb4fbc81fa65c34222ece5e)), closes [#1886](https://github.com/vuejs/vitepress/issues/1886) +- **theme:** scroll code group tab into view on selection ([1a6efba](https://github.com/vuejs/vitepress/commit/1a6efbae8e13eb6612aacdb8d384554e72e5f562)), closes [#2355](https://github.com/vuejs/vitepress/issues/2355) +- **theme:** update sidebar active link status on hash change ([#2736](https://github.com/vuejs/vitepress/issues/2736)) ([3840eaa](https://github.com/vuejs/vitepress/commit/3840eaae163cc9307c8d8525ad03c59752443b2b)) +- **regression/theme:** fix sidebar collapsing ([#2753](https://github.com/vuejs/vitepress/issues/2753)) ([9a4ee07](https://github.com/vuejs/vitepress/commit/9a4ee07260191adeb4c3810d95b044439609525c)) +- **cli:** generate mjs file on init if `"type": "module"` is not present ([23d7511](https://github.com/vuejs/vitepress/commit/23d751165f6def6fa6b3a5d7efd89b993a2780d8)) +- **theme:** language menu undefined text ([#2755](https://github.com/vuejs/vitepress/issues/2755)) ([c9d4655](https://github.com/vuejs/vitepress/commit/c9d465587a3b2188ff9922483a15d7096e6a3e6c)) + +### Features + +- **theme:** final re-brand ([#2727](https://github.com/vuejs/vitepress/pull/2727)) ([c0d838b](https://github.com/vuejs/vitepress/commit/c0d838bda0121fc162d1e6a43324f75290bc1b72)) +- allow html blocks inside code groups ([#2719](https://github.com/vuejs/vitepress/issues/2719)) ([7f0c18e](https://github.com/vuejs/vitepress/commit/7f0c18e01384d48380b64ba629229ec048f85453)) +- **build:** add `markdown.preConfig` option ([ce85726](https://github.com/vuejs/vitepress/commit/ce85726c127d9478274126374df9c37ee8b31167)), closes [#1382](https://github.com/vuejs/vitepress/issues/1382) +- **build:** allow overriding vite config loading ([#2750](https://github.com/vuejs/vitepress/issues/2750)) ([1bed154](https://github.com/vuejs/vitepress/commit/1bed154612661ac3783558cf82a7e94832ee4ff8)) +- **client:** allow customizing scrollOffset padding ([20b509c](https://github.com/vuejs/vitepress/commit/20b509c6e1d957c73be75da27635b23de42781d4)), closes [#2739](https://github.com/vuejs/vitepress/issues/2739) +- **client:** allow overriding props on Content ([1179484](https://github.com/vuejs/vitepress/commit/11794844327c65bd6086b1237b0d6568cb32a4cb)), closes [#2712](https://github.com/vuejs/vitepress/issues/2712) +- i18n with sitemap ([#2708](https://github.com/vuejs/vitepress/issues/2708)) ([7778187](https://github.com/vuejs/vitepress/commit/7778187f2dc31554fa7541da9648235c994d4ae8)) +- **search:** allow enabling detailed view by default ([4af5975](https://github.com/vuejs/vitepress/commit/4af597582cd8ae565e22c912f26f67123babcd61)), closes [#2690](https://github.com/vuejs/vitepress/issues/2690) +- **theme:** allow adding custom layouts ([f4a5c43](https://github.com/vuejs/vitepress/commit/f4a5c43cb00d70143cefcd9dfd9ba536f120ffda)), closes [#2547](https://github.com/vuejs/vitepress/issues/2547) +- **theme:** allow customizing default theme's 404 page ([d7e2254](https://github.com/vuejs/vitepress/commit/d7e225473bd072119c3ce76317db2b723be74f81)), closes [#2715](https://github.com/vuejs/vitepress/issues/2715) +- **theme:** allow customizing prev/next text from config file ([09a4fdc](https://github.com/vuejs/vitepress/commit/09a4fdc9b844a3e1877045afc496282b988f6f6b)), closes [#1373](https://github.com/vuejs/vitepress/issues/1373) +- **theme:** allow overriding logo link ([2a7422b](https://github.com/vuejs/vitepress/commit/2a7422bbbf91b852e27525d64627e9cff6eff294)), closes [#1683](https://github.com/vuejs/vitepress/issues/1683) +- **theme:** allow passing html in nav links ([69251b7](https://github.com/vuejs/vitepress/commit/69251b7484d8e4591841c32dd2f5a0179859cf14)), closes [#1652](https://github.com/vuejs/vitepress/issues/1652) +- **theme:** allow setting base path in sidebar items ([#2734](https://github.com/vuejs/vitepress/issues/2734)) ([52884d9](https://github.com/vuejs/vitepress/commit/52884d9d4b3ad294f4c4fcab637c4e07c80dde3a)) -* safari use `window.requestIdleCallback` ([#1871](https://github.com/vuejs/vitepress/issues/1871)) ([507b193](https://github.com/vuejs/vitepress/commit/507b193ef0e09afe667fccbf6de256cbc86de53f)) +### Reverts +- [#2689](https://github.com/vuejs/vitepress/issues/2689) ([#2722](https://github.com/vuejs/vitepress/issues/2722)) ([a56d608](https://github.com/vuejs/vitepress/commit/a56d608bec427ad51a9edb620d8fb01ebae29550)) +### BREAKING CHANGES -# [1.0.0-alpha.44](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.43...v1.0.0-alpha.44) (2023-01-31) +- Node v18+ is now required to run VitePress. +- VitePress now only provides ESM API. Refer [#2703](https://github.com/vuejs/vitepress/issues/2703) for details. +# [1.0.0-beta.7](https://github.com/vuejs/vitepress/compare/v1.0.0-beta.6...v1.0.0-beta.7) (2023-07-29) ### Bug Fixes -* take `` in SVG into account ([#1850](https://github.com/vuejs/vitepress/issues/1850)) ([010b3e5](https://github.com/vuejs/vitepress/commit/010b3e5ad99f5e61fd01e27d0c3144896a8f3d86)) -* **theme:** infer collapsible from collapsed ([#1865](https://github.com/vuejs/vitepress/issues/1865)) ([dea6cfa](https://github.com/vuejs/vitepress/commit/dea6cfa9cbccf4c6433295e80571acee9b260f71)) - +- **build:** `createContentLoader` generates invalid url when `srcDir` is set ([#2578](https://github.com/vuejs/vitepress/issues/2578)) ([74d9ba2](https://github.com/vuejs/vitepress/commit/74d9ba27b53c6fd09b91b58bba9c1f138a6ee6f1)) +- **build:** duplicate description tags with transformHead ([#2702](https://github.com/vuejs/vitepress/issues/2702)) ([68f25f5](https://github.com/vuejs/vitepress/commit/68f25f5a9cca1d059831184ad8876bb40326d9b6)) +- **build:** use vue dev build when DEBUG is truthy ([#2689](https://github.com/vuejs/vitepress/issues/2689)) ([b61f36d](https://github.com/vuejs/vitepress/commit/b61f36d85326912ca67f552ecbe89aa4ca0b1919)) +- **build:** remove index.html when using createContentLoader ([#2693](https://github.com/vuejs/vitepress/issues/2693)) ([6fc88a5](https://github.com/vuejs/vitepress/commit/6fc88a5cce431fa47330860155191f7b3eccb62e)) +- **search:** add useFocusTrap and mark.js to optimizeDeps ([#2682](https://github.com/vuejs/vitepress/issues/2682)) ([fb048a6](https://github.com/vuejs/vitepress/commit/fb048a6f7289a12a8e67724cee29e55252568489)) +- **theme:** incorrect header anchor icon position with multline headers ([#2694](https://github.com/vuejs/vitepress/issues/2694)) ([77c1b4d](https://github.com/vuejs/vitepress/commit/77c1b4d3cd3c47ffc5268ac24d0f983df443075d)) +- **theme:** code group tab divider not showing full-width ([#2701](https://github.com/vuejs/vitepress/issues/2701)) ([b39b491](https://github.com/vuejs/vitepress/commit/b39b4912af9664d14f5f7c658e64b96de3865f04)) +- **theme:** fix feature component always generating anchor tags ([51f28bf](https://github.com/vuejs/vitepress/commit/51f28bfac96bbb14ea0175c796e0d18fff3b2cc5)) +- **theme:** respect empty rel and target ([#2705](https://github.com/vuejs/vitepress/issues/2705)) ([60dd0a4](https://github.com/vuejs/vitepress/commit/60dd0a474b056ec884f3173a233f1fb951d96870)) ### Features -* **theme:** preconnect algolia when idle ([#1851](https://github.com/vuejs/vitepress/issues/1851)) ([1f77577](https://github.com/vuejs/vitepress/commit/1f775774da7ef51ae8e690bbd86f94c739611a65)) - +- sitemap generation ([#2691](https://github.com/vuejs/vitepress/issues/2691)) ([5563695](https://github.com/vuejs/vitepress/commit/5563695b1599165fa85ea69f15334e27ab6955bf)) +- **build:** custom excerpt for `createContentLoader` ([#2698](https://github.com/vuejs/vitepress/issues/2698)) ([13f94a6](https://github.com/vuejs/vitepress/commit/13f94a6663d5b4472ce380ee1c27e6124da8fec3)) +- **theme:** rel for feature links ([#2704](https://github.com/vuejs/vitepress/issues/2704)) ([5d18fd8](https://github.com/vuejs/vitepress/commit/5d18fd8978e418ce920aab357b180a58b1af3077)) +- **theme:** support custom page class ([#2696](https://github.com/vuejs/vitepress/issues/2696)) ([2ae90a2](https://github.com/vuejs/vitepress/commit/2ae90a234338ea074b536e5583d81fd565d8e3f3)) ### BREAKING CHANGES -* **theme:** `collapsible` is dropped from sidebar, use `collapsed` instead +- **build:** `createContentLoader` will now resolve globs relative to `srcDir` instead of `root` +# [1.0.0-beta.6](https://github.com/vuejs/vitepress/compare/v1.0.0-beta.5...v1.0.0-beta.6) (2023-07-22) +### Bug Fixes -# [1.0.0-alpha.43](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.42...v1.0.0-alpha.43) (2023-01-29) +- **build:** cannot handle file name containing single quote ([#2615](https://github.com/vuejs/vitepress/issues/2615)) ([9949f00](https://github.com/vuejs/vitepress/commit/9949f0046114fdbb59062ecc044aa0a735733e2e)) +- **build:** remove `=""` from boolean attributes in head ([#2620](https://github.com/vuejs/vitepress/issues/2620)) ([e02adfe](https://github.com/vuejs/vitepress/commit/e02adfe3eaed9761f71d1d263822c5f94618ee72)), closes [#1131 (comment)](https://github.com/vuejs/vitepress/issues/1131#issuecomment-1574092184) [#2607](https://github.com/vuejs/vitepress/issues/2607) +- **build:** resolve nested md inclusions properly ([e8074e6](https://github.com/vuejs/vitepress/commit/e8074e60ec5941e7b447f21a289e59e9a91a9e33)), closes [#2584](https://github.com/vuejs/vitepress/issues/2584) [#2586](https://github.com/vuejs/vitepress/issues/2586) +- **compat:** disable stdin-discarder ([#2640](https://github.com/vuejs/vitepress/issues/2640)) ([08c4bac](https://github.com/vuejs/vitepress/commit/08c4bacac5e1acaa95a9878e71781f65b49f48f4)) +- **hmr:** allow disabling md cache during dev ([#2581](https://github.com/vuejs/vitepress/issues/2581)) ([f60b32f](https://github.com/vuejs/vitepress/commit/f60b32f02f4236ec0c29f450c4fe79d6aabf5995)) +- invalid css ([b199885](https://github.com/vuejs/vitepress/commit/b199885b9bc55082914fa651407989a03e4e3a9f)) +- **lastUpdated:** use author date instead of commit date ([#2618](https://github.com/vuejs/vitepress/issues/2618)) ([47bf5bf](https://github.com/vuejs/vitepress/commit/47bf5bf991e48fd41b83613136396bc607751104)) +- **theme:** code block style is broken inside custom block ([#2664](https://github.com/vuejs/vitepress/issues/2664)) ([8ff431a](https://github.com/vuejs/vitepress/commit/8ff431a6bcce8cca04d9ea23ef92045a728d686a)) +- **theme:** don't show external link icon on social links ([f3a4597](https://github.com/vuejs/vitepress/commit/f3a459708d55b3b98a9d25b090e442beebcdaa92)) +- **theme:** fix doc footer's prev and next's size difference ([#2600](https://github.com/vuejs/vitepress/issues/2600)) ([f52a262](https://github.com/vuejs/vitepress/commit/f52a2629a7f565ff10b263bf7efd8e258c7d4979)) +- **theme:** fix sidebar's caret alignment issue with long text ([#2599](https://github.com/vuejs/vitepress/issues/2599)) ([01120a5](https://github.com/vuejs/vitepress/commit/01120a51d6d13f842678c6a1d418ac7bd3ccceca)) +- **theme:** fix theme without fonts emitting inter ([#2588](https://github.com/vuejs/vitepress/issues/2588)) ([71eb11f](https://github.com/vuejs/vitepress/commit/71eb11f72e60706a546b756dc3fd72d06e2ae4e2)) +- **theme:** invalid html -- article inside span ([d0e7374](https://github.com/vuejs/vitepress/commit/d0e73744412520fbbc36a8d701fa3aaaaa53ab35)) +- **theme:** re-export default ([#2606](https://github.com/vuejs/vitepress/issues/2606)) ([9fdee9c](https://github.com/vuejs/vitepress/commit/9fdee9c2a30eeccb500e6aff165887d79a1686ef)) +- **theme:** respect `--vp-nav-height` in local nav calculations ([#2663](https://github.com/vuejs/vitepress/issues/2663)) ([3912951](https://github.com/vuejs/vitepress/commit/3912951bad6f61950ba9da4f5cd3061218903e7d)) +- **theme:** support missing meta description tag ([#2639](https://github.com/vuejs/vitepress/issues/2639)) ([cfa870f](https://github.com/vuejs/vitepress/commit/cfa870f060934c4738c2f70e7b21ad13b6acdb42)) +- **theme:** two outlines at 1280px ([ceedb68](https://github.com/vuejs/vitepress/commit/ceedb68d3b22e5c5cc72be1777c6a3f7090d0a6a)), closes [#2668](https://github.com/vuejs/vitepress/issues/2668) +- **type:** `useSidebar()` type error ([#2643](https://github.com/vuejs/vitepress/issues/2643)) ([a07f959](https://github.com/vuejs/vitepress/commit/a07f959d472f1976d26c675066204eca9bc7c651)) +### Features -### Bug Fixes +- **build:** add `metaChunk` option to extract metadata to separate chunk ([#2626](https://github.com/vuejs/vitepress/issues/2626)) ([700fad1](https://github.com/vuejs/vitepress/commit/700fad192edef1f5d4681d714d3eaebbd77eab95)) +- **build:** support custom `assetsDir` ([#2497](https://github.com/vuejs/vitepress/issues/2497)) ([64d7c3b](https://github.com/vuejs/vitepress/commit/64d7c3ba54ed2dceabcc1cb65634381d7b42ce47)) +- **build:** support overriding meta viewport tag ([#2642](https://github.com/vuejs/vitepress/issues/2642)) ([94e2966](https://github.com/vuejs/vitepress/commit/94e2966babfe572a62c71907332450b18c6c9509)) +- **search:** allow excluding content from search results ([#2602](https://github.com/vuejs/vitepress/issues/2602)) ([37d5b27](https://github.com/vuejs/vitepress/commit/37d5b273fbfddd41958e5cae4cc874a81dd9298a)), closes [#2344](https://github.com/vuejs/vitepress/issues/2344) +- **search:** support `minisearch` customization ([#2576](https://github.com/vuejs/vitepress/issues/2576)) ([9fee554](https://github.com/vuejs/vitepress/commit/9fee5542cb4bd0b83ccad5d625cb4eca8f8abb25)) +- **theme:** allow using html text in VPHero ([#2635](https://github.com/vuejs/vitepress/issues/2635)) ([ec7643d](https://github.com/vuejs/vitepress/commit/ec7643dc1397d5b27158bd0865bd517f08e198a5)) +- **theme:** make navbar logo's height customizable by css variable ([#2644](https://github.com/vuejs/vitepress/issues/2644)) ([c2e79aa](https://github.com/vuejs/vitepress/commit/c2e79aa58387281e482f88e4f307a3c36da60f40)) +- **theme:** support footer frontmatter config ([#2574](https://github.com/vuejs/vitepress/issues/2574)) ([e79a13e](https://github.com/vuejs/vitepress/commit/e79a13eb42a0ab37713f09e7fd067cac559ab812)) -* **build:** hmr with rewrites when base is set ([a05956f](https://github.com/vuejs/vitepress/commit/a05956f38a5295cf038ecfc762c044dbc1cdf040)) +### Performance Improvements +- fix race conditions with cache ([#2579](https://github.com/vuejs/vitepress/issues/2579)) ([32d65d4](https://github.com/vuejs/vitepress/commit/32d65d40c55b7df1a814820d5117c360f9d449a4)) +# [1.0.0-beta.5](https://github.com/vuejs/vitepress/compare/v1.0.0-beta.4...v1.0.0-beta.5) (2023-07-03) -# [1.0.0-alpha.42](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.41...v1.0.0-alpha.42) (2023-01-29) +### Bug Fixes + +- **types:** `Sidebar` was exported multiple times breaking the config ([#2573](https://github.com/vuejs/vitepress/issues/2573)) ([a99dcf9](https://github.com/vuejs/vitepress/commit/a99dcf94436d6cbbd53ef5481a6ec5ffd8d887d2)) +# [1.0.0-beta.4](https://github.com/vuejs/vitepress/compare/v1.0.0-beta.3...v1.0.0-beta.4) (2023-07-02) ### Bug Fixes -* **build:** consider base when checking actual pathname ([#1858](https://github.com/vuejs/vitepress/issues/1858)) ([cf8ad1a](https://github.com/vuejs/vitepress/commit/cf8ad1a29133cc373a1a70720d36e02b38ba6898)) +- **build:** add `@vue/devtools-api` to `optimizeDeps.include` ([#2543](https://github.com/vuejs/vitepress/issues/2543)) ([b2a129f](https://github.com/vuejs/vitepress/commit/b2a129f49b8c83e528f594af977b1e901a57313e)) +- **client:** bypass client router for links explicitly specifying target ([#2563](https://github.com/vuejs/vitepress/issues/2563)) ([e95015f](https://github.com/vuejs/vitepress/commit/e95015f598846e318c60929f1ef6466a8cfbb729)) +- **client:** don't throw on using special chars in element ids ([#2560](https://github.com/vuejs/vitepress/issues/2560)) ([6b98113](https://github.com/vuejs/vitepress/commit/6b98113a4295e5db8d3876f176dab7e5a5b33e5c)) +- **client:** scroll not working on clicking an anchor in search box ([#2527](https://github.com/vuejs/vitepress/issues/2527)) ([c30e758](https://github.com/vuejs/vitepress/commit/c30e758585ef512eef68b33918832d4413839e9c)) +- **theme:** unresponsive back button with empty input in search box ([#2566](https://github.com/vuejs/vitepress/issues/2566)) ([fa3780f](https://github.com/vuejs/vitepress/commit/fa3780f8ef99b88e998523570f08a4e7f86dfd1b)) + +### Features +- **build:** support nested markdown includes ([#2545](https://github.com/vuejs/vitepress/issues/2545)) ([0c4210b](https://github.com/vuejs/vitepress/commit/0c4210bb5ed114fb8597786230cb145790578071)) +- **client:** add onBeforePageLoad hook for router ([#2564](https://github.com/vuejs/vitepress/issues/2564)) ([665f3b0](https://github.com/vuejs/vitepress/commit/665f3b02f828175d4df5c0f79263dfa6e3f601d2)) +- support selecting line range when importing md file ([#2502](https://github.com/vuejs/vitepress/issues/2502)) ([1ef33fe](https://github.com/vuejs/vitepress/commit/1ef33fe1c44875dc86835a698a708b1aa847e16e)) +- **theme:** allow customizing last updated date time format options ([#2332](https://github.com/vuejs/vitepress/issues/2332)) ([24abc7c](https://github.com/vuejs/vitepress/commit/24abc7c6bda66df6e7ed543531f52c87f52f52df)) +- **theme:** allow hiding navbar on specific pages via frontmatter ([#2565](https://github.com/vuejs/vitepress/issues/2565)) ([1e15001](https://github.com/vuejs/vitepress/commit/1e1500141bf6e2619caa7950f019016dc26d147f)) +- **theme:** expose `useSidebar` ([#2496](https://github.com/vuejs/vitepress/issues/2496)) ([c4909e4](https://github.com/vuejs/vitepress/commit/c4909e4298ec706cf1762cb36af03e5fd3637ccc)) +- **theme:** option to show icon for external links ([#2501](https://github.com/vuejs/vitepress/issues/2501)) ([52cfbc3](https://github.com/vuejs/vitepress/commit/52cfbc323615c3e017b656bb551e0d9de02d1e5f)) +### BREAKING CHANGES -# [1.0.0-alpha.41](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.40...v1.0.0-alpha.41) (2023-01-28) +- **client:** specifying `target="_self"` for internal links will now perform full reload. +# [1.0.0-beta.3](https://github.com/vuejs/vitepress/compare/v1.0.0-beta.2...v1.0.0-beta.3) (2023-06-20) ### Bug Fixes -* check document instead of window to detect browser ([#1833](https://github.com/vuejs/vitepress/issues/1833)) ([0f145cb](https://github.com/vuejs/vitepress/commit/0f145cb3c6568760199a9c8eee785aecaf0e0494)) -* **router:** avoid duplicate history entries ([#1827](https://github.com/vuejs/vitepress/issues/1827)) ([1553dbc](https://github.com/vuejs/vitepress/commit/1553dbce8eac9ed4a65312d4590d6b0f9261135c)) -* **theme:** don't show border on navbar when sidebar is there ([#1845](https://github.com/vuejs/vitepress/issues/1845)) ([3db532e](https://github.com/vuejs/vitepress/commit/3db532ed0999c9bddfd6bc90f6b627ae1b9178af)) +- **build:** disable validation for rewrite compiling ([69b2625](https://github.com/vuejs/vitepress/commit/69b2625623292591207b6b591f6b39019a054a43)) +- **theme:** prevent glitch when algolia chunk is loaded ([#2519](https://github.com/vuejs/vitepress/issues/2519)) ([51661de](https://github.com/vuejs/vitepress/commit/51661def8ff743733d391a61ffb2ab1b66473fd2)) +- use extends in template custom theme ([#2500](https://github.com/vuejs/vitepress/issues/2500)) ([7e39e02](https://github.com/vuejs/vitepress/commit/7e39e02185f5b18da09b01bd4c132a8b50e15b07)) +- revert!: sync defineConfig types with vite (#2529) ([cd03db8](https://github.com/vuejs/vitepress/commit/cd03db803d5e6b9f04e242f7843153dded73ccb2)), closes [#2529](https://github.com/vuejs/vitepress/issues/2529) ### Features -* **build:** allow ignoring only localhost dead links ([#1821](https://github.com/vuejs/vitepress/issues/1821)) ([fe52fa3](https://github.com/vuejs/vitepress/commit/fe52fa34201dcfa87ac4886fe285331f0ef89ba8)) -* **build:** expose vitepress site config to vite plugins ([#1822](https://github.com/vuejs/vitepress/issues/1822)) ([05430e4](https://github.com/vuejs/vitepress/commit/05430e45c90562b62796caba28c633070934d85f)) -* **build:** support rewrites ([#1798](https://github.com/vuejs/vitepress/issues/1798)) ([00abac6](https://github.com/vuejs/vitepress/commit/00abac611664e12710e5152d0259390b22c0e8ca)) -* stable `cleanUrls` ([#1852](https://github.com/vuejs/vitepress/issues/1852)) ([5ae4fbd](https://github.com/vuejs/vitepress/commit/5ae4fbde3843236e180e63e2cd2b7021efa0fad4)) -* **theme:** allow removing badge text from outline ([#1825](https://github.com/vuejs/vitepress/issues/1825)) ([5d2fc3f](https://github.com/vuejs/vitepress/commit/5d2fc3f9228c9b26dec26264d0951d0f43b3d90d)) -* **theme:** enable multi level sidebar nesting ([#1360](https://github.com/vuejs/vitepress/issues/1360)) ([#1835](https://github.com/vuejs/vitepress/issues/1835)) ([c35a1f0](https://github.com/vuejs/vitepress/commit/c35a1f0faee3702c0494fb22043ce058e7a2954c)), closes [#1361](https://github.com/vuejs/vitepress/issues/1361) [#1680](https://github.com/vuejs/vitepress/issues/1680) - +- **build:** allow using regex in rewrites ([f831767](https://github.com/vuejs/vitepress/commit/f831767764030c77cc79db4cc860e7d76afc1b6a)) +- **client:** expose dataSymbol ([a547530](https://github.com/vuejs/vitepress/commit/a5475304faad7db037e19a9ffe4d6f48a816e6ed)), closes [#2489](https://github.com/vuejs/vitepress/issues/2489) +### BREAKING CHANGES -# [1.0.0-alpha.40](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.39...v1.0.0-alpha.40) (2023-01-20) +- reverts the breaking changes in beta-2. `defineConfig` and `defineConfigWithTheme` no longer accept functions as argument. +# [1.0.0-beta.2](https://github.com/vuejs/vitepress/compare/v1.0.0-beta.1...v1.0.0-beta.2) (2023-06-11) ### Bug Fixes -* **theme:** nav bg not being applied on some viewport ([39294e0](https://github.com/vuejs/vitepress/commit/39294e0a4ec53b245da4344187de842d0044dac8)) +- **build:** create markdown env for localSearchPlugin ([#2322](https://github.com/vuejs/vitepress/issues/2322)) ([c9a98ac](https://github.com/vuejs/vitepress/commit/c9a98ac6bb854a7a24c08cfc23e84ebc243ba347)) +- **build:** use rimraf to handle temp folder deletion in windows ([#2483](https://github.com/vuejs/vitepress/issues/2483)) ([2f75769](https://github.com/vuejs/vitepress/commit/2f7576998587387ee32173b6de90f338fc7e85d3)) +- **search:** detailed view not working when page contains script setup ([80e734d](https://github.com/vuejs/vitepress/commit/80e734d67763fea449647b7b21dfde0bde1c360b)), closes [#2485](https://github.com/vuejs/vitepress/issues/2485) +- **theme:** adjust z-index for active code group marker ([#2413](https://github.com/vuejs/vitepress/issues/2413)) ([06c0fc5](https://github.com/vuejs/vitepress/commit/06c0fc5d5cd55e03b4eee14feac67b749e7283ed)) +- **theme:** properly show divider between navs ([#2481](https://github.com/vuejs/vitepress/issues/2481)) ([2bd55ec](https://github.com/vuejs/vitepress/commit/2bd55eca2e7d8384ac50c94b049310dc6173f849)) +- **theme:** use brand color in skip link in dark theme ([#2431](https://github.com/vuejs/vitepress/issues/2431)) ([62d1110](https://github.com/vuejs/vitepress/commit/62d1110848e9b8944d920232bee185d8066194dd)) +- **theme:** use document !== undefined check for browser ([#2417](https://github.com/vuejs/vitepress/issues/2417)) ([c869ea6](https://github.com/vuejs/vitepress/commit/c869ea64ae3c20aef60af1425b02e5797faa8d69)) +- **types:** sync defineConfig types with vite ([b3ded34](https://github.com/vuejs/vitepress/commit/b3ded34d8a9ca7a9a82e9b0cf705a2ed6233e881)) +- **types:** theme-without-fonts types for node ([#2416](https://github.com/vuejs/vitepress/issues/2416)) ([8e87c14](https://github.com/vuejs/vitepress/commit/8e87c14fba6a76d2dec8611f3d56c0c3a84accc0)) + +### Features +- **build:** support relative path for code snippet ([#1894](https://github.com/vuejs/vitepress/issues/1894)) ([90478b3](https://github.com/vuejs/vitepress/commit/90478b36cd4d161c2118a9e677384982805963b0)) +- **cli:** add shortcut for restarting server ([#2403](https://github.com/vuejs/vitepress/issues/2403)) ([64b06db](https://github.com/vuejs/vitepress/commit/64b06db3ece7c4c2e73dd28c2f349f521afa390a)) +- **theme:** add custom label for social links ([#2466](https://github.com/vuejs/vitepress/issues/2466)) ([c995b9f](https://github.com/vuejs/vitepress/commit/c995b9f61d90aa7671371373c5772ab59b516fc5)) +- **theme:** add semantic markup to local search dialog ([#2325](https://github.com/vuejs/vitepress/issues/2325)) ([4ddb96f](https://github.com/vuejs/vitepress/commit/4ddb96fe508578893ee5a44621b5bac098bd4710)) +- **theme:** allow prev/next links to be disabled globally ([#2317](https://github.com/vuejs/vitepress/issues/2317)) ([29a9647](https://github.com/vuejs/vitepress/commit/29a9647ee92efe8ea9a7c6698d5cacb22bf3e9ce)) +### Performance Improvements -# [1.0.0-alpha.39](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.38...v1.0.0-alpha.39) (2023-01-20) +- parallelize mpa chunks copy ([#2389](https://github.com/vuejs/vitepress/issues/2389)) ([6d7d195](https://github.com/vuejs/vitepress/commit/6d7d195adcf354b94e2a69c330264a3106ed5955)) +- **search:** use dom apis instead of regex-based section parsing ([#2486](https://github.com/vuejs/vitepress/issues/2486)) ([d62e6f6](https://github.com/vuejs/vitepress/commit/d62e6f6dd68e1ac31654e0da6102915a5a3709f0)) +- **theme/search:** prevent repeated rendering of same page ([#2398](https://github.com/vuejs/vitepress/issues/2398)) ([e7be720](https://github.com/vuejs/vitepress/commit/e7be720ede403598dcec0a520ccc7bacf4e8b276)) +### BREAKING CHANGES + +- **types:** `defineConfig` and `defineConfigWithTheme` can now accept functions that return the config object. This might break typings in some third-party plugins that rely on the type of these functions. + +# [1.0.0-beta.1](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.76...v1.0.0-beta.1) (2023-05-22) ### Bug Fixes -* **theme:** adjust the position of the curtain to avoid block sidebar ([#1816](https://github.com/vuejs/vitepress/issues/1816)) ([48f0b01](https://github.com/vuejs/vitepress/commit/48f0b015694c17767180eb2f75e9eb12c3f2a358)) -* **theme:** sidebar scrollbar is cropped by nav bar ([bd36224](https://github.com/vuejs/vitepress/commit/bd36224b45ee832765afcf4a57c211d362e4e6af)) +- **config:** set scrollOffset to 0 is not effect ([#2395](https://github.com/vuejs/vitepress/issues/2395)) ([8153f23](https://github.com/vuejs/vitepress/commit/8153f23c901a6200661813e65f0d8eb602ad46da)) +- **theme:** make features section layout consistent ([#2382](https://github.com/vuejs/vitepress/issues/2382)) ([26f21d9](https://github.com/vuejs/vitepress/commit/26f21d95dfbd671477d425e6b8ac5b0172a846ac)) +- **theme:** missing global properties in localSearch ([#2396](https://github.com/vuejs/vitepress/issues/2396)) ([4896811](https://github.com/vuejs/vitepress/commit/489681117f46a803704b6ec80546a5e787e19df2)) +- **theme:** support custom target and rel in navbar links for mobile ([#2400](https://github.com/vuejs/vitepress/issues/2400)) ([f364a5d](https://github.com/vuejs/vitepress/commit/f364a5d1d3c066c9728beb5d07576d6cb4b0640d)) +# [1.0.0-alpha.76](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.75...v1.0.0-alpha.76) (2023-05-18) +### Bug Fixes -# [1.0.0-alpha.38](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.37...v1.0.0-alpha.38) (2023-01-17) +- **a11y:** mobile and theme switcher ([#2354](https://github.com/vuejs/vitepress/issues/2354)) ([d6c0985](https://github.com/vuejs/vitepress/commit/d6c0985002ee792b1e8e052f71cdd6bd72c315ad)) +- **build:** uniform handling of windows slash in localSearchPlugin ([#2358](https://github.com/vuejs/vitepress/issues/2358)) ([b31933f](https://github.com/vuejs/vitepress/commit/b31933fbdd7aabfe080234407153aefa8f6a3f30)) +- hmr when `base` is set ([#2375](https://github.com/vuejs/vitepress/issues/2375)) ([484ff5d](https://github.com/vuejs/vitepress/commit/484ff5dd4bd2e5c2d5168437895d400a39f2bfa8)) +- **theme:** don't update opacity on hover ([#2326](https://github.com/vuejs/vitepress/issues/2326)) ([35f8b89](https://github.com/vuejs/vitepress/commit/35f8b896372e75e62882df613a49e8945e7bc832)) +### Features + +- **cli:** add shortcuts ([#2353](https://github.com/vuejs/vitepress/issues/2353)) ([97065ce](https://github.com/vuejs/vitepress/commit/97065cefc22e4772c0295c5ad23a87eea286f46b)) +- **theme:** add focus trap to local search dialog ([#2324](https://github.com/vuejs/vitepress/issues/2324)) ([2f482af](https://github.com/vuejs/vitepress/commit/2f482afaabdb4206b87e2453d0099257693c4653)) +- **theme:** open search box on pressing slash too ([#2328](https://github.com/vuejs/vitepress/issues/2328)) ([c20bd28](https://github.com/vuejs/vitepress/commit/c20bd283319158135e2d850485970dfc5fe82812)) + +# [1.0.0-alpha.75](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.74...v1.0.0-alpha.75) (2023-04-30) ### Bug Fixes -* **theme:** spacing between aside sponsors and ads section is missing ([5c2eb1b](https://github.com/vuejs/vitepress/commit/5c2eb1b3b0988ae98639543e60a740d6b40a17a5)) +- **build:** reset regex lastIndex before testing ([188893c](https://github.com/vuejs/vitepress/commit/188893c2c1569e332e8776581cfa40b4c5f1168e)) +- **cli/init:** remove trailing slash from npm scripts ([64ecedc](https://github.com/vuejs/vitepress/commit/64ecedc73f3e7010de85381d946af1c95404820e)) +- **theme:** hide local nav on home page ([f07587a](https://github.com/vuejs/vitepress/commit/f07587af8a51f92a5ec491e5789dd088e28067b5)), closes [#2312](https://github.com/vuejs/vitepress/issues/2312) +- **theme:** local search get 404 on build when use route rewrites in windows ([#2301](https://github.com/vuejs/vitepress/issues/2301)) ([494c634](https://github.com/vuejs/vitepress/commit/494c634eb1d77963e555a736fa057dcb23700989)) +- **theme:** vitepress data not properly injected in app when use localSearch ([#2299](https://github.com/vuejs/vitepress/issues/2299)) ([69c7646](https://github.com/vuejs/vitepress/commit/69c7646dafe7a774e0717e032f697b008d9cf7aa)) +### Features +- add `filePath` to `PageData` ([#2140](https://github.com/vuejs/vitepress/issues/2140)) ([b24acc6](https://github.com/vuejs/vitepress/commit/b24acc6991570aa054a99b8d3977b8b4d0255418)) +- **build:** allow using `@` prefix with `@include` ([#2292](https://github.com/vuejs/vitepress/issues/2292)) ([a3b38d1](https://github.com/vuejs/vitepress/commit/a3b38d18824343fd5b571a7a9a5d2c4ccf29e8e1)) +- preserve user log level ([#2310](https://github.com/vuejs/vitepress/issues/2310)) ([a647cd3](https://github.com/vuejs/vitepress/commit/a647cd384320101f6df31e03960dd2c40808c49c)) +- **theme:** support light shiki themes ([#2319](https://github.com/vuejs/vitepress/issues/2319)) ([d0f0012](https://github.com/vuejs/vitepress/commit/d0f0012aea4cc71fb28f60f2dd649c23aae146b8)) -# [1.0.0-alpha.37](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.36...v1.0.0-alpha.37) (2023-01-17) +### BREAKING CHANGES +- **theme:** Styling for code blocks might break, especially if you were earlier overriding it for light theme. Those workarounds are no longer required. VitePress will now show code blocks and groups in light mode too if a light shiki theme is specified. + +# [1.0.0-alpha.74](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.73...v1.0.0-alpha.74) (2023-04-24) ### Bug Fixes -* **build:** don't warn on blank lang in fences ([99ad162](https://github.com/vuejs/vitepress/commit/99ad162fb7b11ac80c787131714c9c8bf66fa8c7)) -* **theme:** prevent vertical scrollbar on code group tabs ([#1793](https://github.com/vuejs/vitepress/issues/1793)) ([#1805](https://github.com/vuejs/vitepress/issues/1805)) ([4314b57](https://github.com/vuejs/vitepress/commit/4314b5795918ceaa798dee550b79ff2e8a686b26)) +- **build:** allow data-loaders files in packages to be found (closes [#2272](https://github.com/vuejs/vitepress/issues/2272)) ([84cf457](https://github.com/vuejs/vitepress/commit/84cf45772ed59f5eae747c15fbffc375768007b8)) +- **router:** scroll back to the hash anchor even if it is already selected ([#2265](https://github.com/vuejs/vitepress/issues/2265)) ([f3d3332](https://github.com/vuejs/vitepress/commit/f3d3332fff72d1df6f70c5893bfc90442b1776fb)) + +### Features + +- allow using html in member description ([#2269](https://github.com/vuejs/vitepress/issues/2269)) ([f744364](https://github.com/vuejs/vitepress/commit/f7443643a4510a6c650f1a1bda977c1d55fddf64)) +- **search:** support custom `disableQueryPersistence` in local search ([#2273](https://github.com/vuejs/vitepress/issues/2273)) ([2f0f2d5](https://github.com/vuejs/vitepress/commit/2f0f2d5ac6efcab22bdb452e5c0780e7cd8f1498)) +- **theme:** mobile view show outline button after removing sidebar ([#2274](https://github.com/vuejs/vitepress/issues/2274)) ([25b9111](https://github.com/vuejs/vitepress/commit/25b9111222cbd3de008e18cac6554933d4db993e)) + +# [1.0.0-alpha.73](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.72...v1.0.0-alpha.73) (2023-04-20) +### Bug Fixes + +- **search:** fix highlighting in detailed view ([1f4920c](https://github.com/vuejs/vitepress/commit/1f4920c60dc1be03444781539064be7b3ec9eb08)) +- **search:** local search showDetailedList not working in windows ([#2253](https://github.com/vuejs/vitepress/issues/2253)) ([09be057](https://github.com/vuejs/vitepress/commit/09be057ffb767e55d3a86f1a3664ebd0690f2fc5)) ### Features -* add i18n feature ([#1339](https://github.com/vuejs/vitepress/issues/1339)) ([8de2f44](https://github.com/vuejs/vitepress/commit/8de2f4499d9364d85e6070ce4b94651a1902b101)), closes [#291](https://github.com/vuejs/vitepress/issues/291) [#628](https://github.com/vuejs/vitepress/issues/628) [#631](https://github.com/vuejs/vitepress/issues/631) [#902](https://github.com/vuejs/vitepress/issues/902) [#955](https://github.com/vuejs/vitepress/issues/955) [#1253](https://github.com/vuejs/vitepress/issues/1253) [#1381](https://github.com/vuejs/vitepress/issues/1381) -* support for teleports to body ([#1642](https://github.com/vuejs/vitepress/issues/1642)) ([09c2c52](https://github.com/vuejs/vitepress/commit/09c2c52d6c027f6e30fac33c2d11246a4a530c24)) -* **build:** don't hard fail on unknown languages in fences ([#1750](https://github.com/vuejs/vitepress/issues/1750)) ([1ae0596](https://github.com/vuejs/vitepress/commit/1ae05969396ef1651af56c66696ed77f8c4e7e85)) -* **theme:** refine overall styles ([#1049](https://github.com/vuejs/vitepress/issues/1049)) ([#1790](https://github.com/vuejs/vitepress/issues/1790)) ([471f00a](https://github.com/vuejs/vitepress/commit/471f00a68d1e3d8d925ab996f462adaf4f1261a0)) +- outline link add title attribute ([#2261](https://github.com/vuejs/vitepress/issues/2261)) ([1f5798e](https://github.com/vuejs/vitepress/commit/1f5798e43771ae1e13921a39319345c89bb2298a)) +# [1.0.0-alpha.72](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.71...v1.0.0-alpha.72) (2023-04-17) +### Bug Fixes -# [1.0.0-alpha.36](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.35...v1.0.0-alpha.36) (2023-01-11) +- **search:** don't directly access userConfig ([3e0e9d2](https://github.com/vuejs/vitepress/commit/3e0e9d2b27c02e250c5b350bf83dce9b95e217a8)) +- **search:** ready event is not fired on mac ([e37e5cb](https://github.com/vuejs/vitepress/commit/e37e5cb45a6c3507b906b9955897ce4e84adf500)) +- **theme:** local search showDetailedList not working in windows ([#2248](https://github.com/vuejs/vitepress/issues/2248)) ([8354f8f](https://github.com/vuejs/vitepress/commit/8354f8fb8649d429b2cb525dd6f35127faba7ae6)) +# [1.0.0-alpha.71](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.70...v1.0.0-alpha.71) (2023-04-16) ### Bug Fixes -* **build:** handle cleanUrls without trailing slash ([#1772](https://github.com/vuejs/vitepress/issues/1772)) ([2a80fbd](https://github.com/vuejs/vitepress/commit/2a80fbd14ae124eddb05deca71ebffa50de4c2ce)) -* **theme:** `activeMatch` support regexp ([#1754](https://github.com/vuejs/vitepress/issues/1754)) ([0913e0f](https://github.com/vuejs/vitepress/commit/0913e0fe69167c796b0c3c22706b26f4840c6493)), closes [#1771](https://github.com/vuejs/vitepress/issues/1771) -* **theme:** add cursor for summary of custom block details ([#1774](https://github.com/vuejs/vitepress/issues/1774)) ([167a474](https://github.com/vuejs/vitepress/commit/167a474cb8121d758c2aa863016dffbe8d0a1e55)) -* **theme:** wrap long words in `li` ([#1782](https://github.com/vuejs/vitepress/issues/1782)) ([48a42c1](https://github.com/vuejs/vitepress/commit/48a42c19b17417fea384bb0a7004d140b16d9c23)), closes [#1783](https://github.com/vuejs/vitepress/issues/1783) [#1405](https://github.com/vuejs/vitepress/issues/1405) +- **search:** esm interop mark.js import ([1b0a249](https://github.com/vuejs/vitepress/commit/1b0a249ad66288ff56675e4db905959ff0079726)) +- **search:** properly group nested headings ([b1c956c](https://github.com/vuejs/vitepress/commit/b1c956ce99505316842c157c76a4ec051eb7610b)), closes [#2238](https://github.com/vuejs/vitepress/issues/2238) +# [1.0.0-alpha.70](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.69...v1.0.0-alpha.70) (2023-04-16) + +### Bug Fixes + +- **a11y:** increase touch target size of search icons ([4449867](https://github.com/vuejs/vitepress/commit/44498675aca3271596b041881d44e1524d744df6)) +- **search:** avoid body scroll when using local search ([#2236](https://github.com/vuejs/vitepress/issues/2236)) ([144a7d8](https://github.com/vuejs/vitepress/commit/144a7d8e4ee483475b6956090c267213a1e2f8e1)) +- **search:** better highlighting in detailed view ([#2234](https://github.com/vuejs/vitepress/issues/2234)) ([be83524](https://github.com/vuejs/vitepress/commit/be8352441f8b9a8561961c69f3e1794370101de2)) +- **search:** fix keyword highlighting and scrolling in excerpts ([ca8db8a](https://github.com/vuejs/vitepress/commit/ca8db8adca028bb982b819553b85ac19fe946e7e)) +- **search:** remove double base on importing excepts ([185213c](https://github.com/vuejs/vitepress/commit/185213c6ba4416071025fbf3c5ca7fadf311fdbf)), closes [#2230](https://github.com/vuejs/vitepress/issues/2230) +- **search:** remove extra /index from routes ([9e04b43](https://github.com/vuejs/vitepress/commit/9e04b435671accfcaee795ec8ec2833d8aa358f8)) +- **search:** show escape to close on footer ([6d5b4cd](https://github.com/vuejs/vitepress/commit/6d5b4cd784274786ad57cef378646320ba17faf1)) ### Features -* allow `enhanceApp` to return a `Promise` ([#1760](https://github.com/vuejs/vitepress/issues/1760)) ([01ac579](https://github.com/vuejs/vitepress/commit/01ac57918767f44a0757414316e67072399ffb6d)) -* **build:** support interpolation inside code blocks ([#1759](https://github.com/vuejs/vitepress/issues/1759)) ([3b7ff8d](https://github.com/vuejs/vitepress/commit/3b7ff8d66e9eda3aab1fb126984efc63132bd22d)) +- **search:** allow force disabling detailed view ([40f1d1b](https://github.com/vuejs/vitepress/commit/40f1d1b6f6f2f6c43fd0d9bcf4b6bc1174ce4831)) +- **search:** make styling more configurable, align more with the theme ([#2233](https://github.com/vuejs/vitepress/issues/2233)) ([b2077c7](https://github.com/vuejs/vitepress/commit/b2077c70250d5c390d69ce31111a1c44769dbc78)) + +# [1.0.0-alpha.69](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.68...v1.0.0-alpha.69) (2023-04-15) +### Bug Fixes +- **search:** fix errors on empty titles ([6d363ec](https://github.com/vuejs/vitepress/commit/6d363ec9ffd6b27e1c77e5aab853471c6883c7bd)) +- **theme:** fix color of blockquote in custom containers ([#2173](https://github.com/vuejs/vitepress/issues/2173)) ([712a57f](https://github.com/vuejs/vitepress/commit/712a57fde74daa27f69319861d95f9dec6bc05ad)) -# [1.0.0-alpha.35](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.34...v1.0.0-alpha.35) (2023-01-03) +# [1.0.0-alpha.68](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.67...v1.0.0-alpha.68) (2023-04-15) + +### Bug Fixes + +- **theme:** fix top of scrollbar being unusable ([#2224](https://github.com/vuejs/vitepress/issues/2224)) ([7178a22](https://github.com/vuejs/vitepress/commit/7178a22c9d317245e5167abf80f7081fbf87e78a)) +# [1.0.0-alpha.67](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.66...v1.0.0-alpha.67) (2023-04-15) ### Bug Fixes -* **theme:** adjust styles for copied button ([#1751](https://github.com/vuejs/vitepress/issues/1751)) ([565ae71](https://github.com/vuejs/vitepress/commit/565ae711b9b90ad2fe820cdbaa04a9d41506ac53)) -* **theme:** adjust styles for diff indicator in code blocks ([#1755](https://github.com/vuejs/vitepress/issues/1755)) ([a642ea2](https://github.com/vuejs/vitepress/commit/a642ea2526f5638243283bd37ef9ba0af350d407)) -* **theme:** prevent layout shift on carbon ads ([f6c5e1f](https://github.com/vuejs/vitepress/commit/f6c5e1f098d1fd4d4f6325a21adbb088c32a0740)) -* **theme:** refresh ads per page navigation ([#1734](https://github.com/vuejs/vitepress/issues/1734)) ([8db20fe](https://github.com/vuejs/vitepress/commit/8db20fe02240bb1d3c02da738740f2433edb1e8b)) +- **search:** avoid double base ([25a1fe9](https://github.com/vuejs/vitepress/commit/25a1fe90bddd021a1ce5e068d8cad455687647bf)) +- **theme:** navbar style ([#2202](https://github.com/vuejs/vitepress/issues/2202)) ([8ee6b90](https://github.com/vuejs/vitepress/commit/8ee6b905f5243a036c2dee7688539ef33e164f09)) +### Features +- allow passing props and children/slots to defineClientComponent ([#2198](https://github.com/vuejs/vitepress/issues/2198)) ([4c24960](https://github.com/vuejs/vitepress/commit/4c2496043394d9b14376e74a5bf11ccea5e6e7d7)) -# [1.0.0-alpha.34](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.33...v1.0.0-alpha.34) (2023-01-01) +# [1.0.0-alpha.66](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.65...v1.0.0-alpha.66) (2023-04-15) + +### Bug Fixes + +- **search:** properly resolve page link ([609d447](https://github.com/vuejs/vitepress/commit/609d447ab50b2b8fb78a174e7d5aa0ff52411b0e)) +- **theme:** fix meta key not showing on search button ([e295160](https://github.com/vuejs/vitepress/commit/e2951604fd61336df9559ea16972d3ea76a49894)) +### Features + +- offline search ([#2110](https://github.com/vuejs/vitepress/issues/2110)) ([6c92675](https://github.com/vuejs/vitepress/commit/6c92675e33d3276a02b790a34083a68093b58c7f)) + +# [1.0.0-alpha.65](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.64...v1.0.0-alpha.65) (2023-04-04) ### Bug Fixes -* **build:** dedent of a single-line region ([#1687](https://github.com/vuejs/vitepress/issues/1687)) ([7de7fff](https://github.com/vuejs/vitepress/commit/7de7fff4178251a6173ac67b52de50176830f539)) -* **build:** handle `-` in title of code blocks with line highlighting ([#1743](https://github.com/vuejs/vitepress/issues/1743)) ([ce9467e](https://github.com/vuejs/vitepress/commit/ce9467e389a2776f3230cb31e596cf9e575cc0df)) -* handle cleanUrls with subfolders when using a trailing slash ([#1575](https://github.com/vuejs/vitepress/issues/1575)) ([195d867](https://github.com/vuejs/vitepress/commit/195d867ee9bb51a4c112534b34bda7bcd0c2c3f5)) +- **build:** remove extra line at end of code blocks ([#2191](https://github.com/vuejs/vitepress/issues/2191)) ([a681fd1](https://github.com/vuejs/vitepress/commit/a681fd11e32709367d673cf0d9d26e4288f27776)) + +# [1.0.0-alpha.64](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.63...v1.0.0-alpha.64) (2023-03-29) + +### Bug Fixes +- **build:** make `lastUpdated` work with git submodules ([#2149](https://github.com/vuejs/vitepress/issues/2149)) ([4c23003](https://github.com/vuejs/vitepress/commit/4c2300318952bfdaabd766a6f16f26419ee854da)) +- **theme:** fix color of table head row in custom containers ([#2160](https://github.com/vuejs/vitepress/issues/2160)) ([51ecd58](https://github.com/vuejs/vitepress/commit/51ecd580a29d9e2bea73d4d5897154954d750d9f)) +- **theme:** hide outline dropdown scrollbar when it does not overflow ([#2151](https://github.com/vuejs/vitepress/issues/2151)) ([ff26ff1](https://github.com/vuejs/vitepress/commit/ff26ff1e6683def53bfbe6cbd7656740c77f4bcc)) ### Features -* **build:** allow specifying default language for syntax highlighter ([#1296](https://github.com/vuejs/vitepress/issues/1296)) ([f40df31](https://github.com/vuejs/vitepress/commit/f40df319475dba9f3fe1e13ff8d8dc4c0950bf5f)) -* **build:** fence-level config for line-numbers ([#1733](https://github.com/vuejs/vitepress/issues/1733)) ([c048076](https://github.com/vuejs/vitepress/commit/c048076370b081acc69c04754bf5deba2b8f5cd5)) -* **theme:** add `home-hero-image` slot ([#1528](https://github.com/vuejs/vitepress/issues/1528)) ([e72998b](https://github.com/vuejs/vitepress/commit/e72998b68bfcc301d15553033a8b90dee0db65cf)) -* **theme:** add mastodon icon ([#1736](https://github.com/vuejs/vitepress/issues/1736)) ([7a73784](https://github.com/vuejs/vitepress/commit/7a737845e5d81a09151320d373a787d2e5f881af)) -* **theme:** allow adding images as icons in features section ([#1738](https://github.com/vuejs/vitepress/issues/1738)) ([9df598f](https://github.com/vuejs/vitepress/commit/9df598f36e30fdc9d1c7440bf98b45783126c39f)) +- **build:** provide `siteConfig` in `transformPageData` context ([#2163](https://github.com/vuejs/vitepress/issues/2163)) ([3714741](https://github.com/vuejs/vitepress/commit/3714741b409f4e5f8df4cc42c7b59b065c8cc6f6)) +- **theme:** add `page-top/bottom` and `doc-top/bottom` slots ([#2139](https://github.com/vuejs/vitepress/issues/2139)) ([53d0099](https://github.com/vuejs/vitepress/commit/53d0099ffa99582f552d7dff5676734c965ceb05)) +- **theme:** allow moving aside to left ([#2138](https://github.com/vuejs/vitepress/issues/2138)) ([9e3cf0f](https://github.com/vuejs/vitepress/commit/9e3cf0fa7d2c2589d129ef931457ab40f513d187)) +# [1.0.0-alpha.63](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.62...v1.0.0-alpha.63) (2023-03-26) -### Performance Improvements +### Bug Fixes -* **a11y:** make menu traversable only when it is open ([#1491](https://github.com/vuejs/vitepress/issues/1491)) ([257f9e6](https://github.com/vuejs/vitepress/commit/257f9e68e947a603f9c3ef0df4be7b2afa79fbe7)) -* preload css to improve loading speed ([bf1315a](https://github.com/vuejs/vitepress/commit/bf1315ace670df0128682838736371e5381b3f42)) +- **theme:** allow adding html as feature icons ([e5bc1e1](https://github.com/vuejs/vitepress/commit/e5bc1e10862a765f6790f5f08aa2bd76bb258532)) +- **theme:** remove label background of code-group tabs ([#2136](https://github.com/vuejs/vitepress/issues/2136)) ([eac03f2](https://github.com/vuejs/vitepress/commit/eac03f26e2d3ab47158ac2528210e95460f6c302)) +### Features +- more flexible `ignoreDeadLinks` ([#2135](https://github.com/vuejs/vitepress/issues/2135)) ([3235c23](https://github.com/vuejs/vitepress/commit/3235c23313d81f8f95b91779a48db839c02aa952)) -# [1.0.0-alpha.33](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.32...v1.0.0-alpha.33) (2022-12-21) +# [1.0.0-alpha.62](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.61...v1.0.0-alpha.62) (2023-03-25) +### Bug Fixes + +- make md includes work with rewrites ([#1898](https://github.com/vuejs/vitepress/issues/1898)) ([3553f01](https://github.com/vuejs/vitepress/commit/3553f015a9138cb935d57487755d9d5717f79ae3)) +- **theme:** don't show outline when no header is there ([#2117](https://github.com/vuejs/vitepress/issues/2117)) ([42a0ef2](https://github.com/vuejs/vitepress/commit/42a0ef21c17da20c8f22565807578a05a0461df6)) +- **theme:** fix aside position when footer is there ([#2115](https://github.com/vuejs/vitepress/issues/2115)) ([aecdeb9](https://github.com/vuejs/vitepress/commit/aecdeb9b216803f407fe3b48574bf7664262ef01)) +- **theme:** properly align not found icon in algolia ([#2116](https://github.com/vuejs/vitepress/issues/2116)) ([83ce1b8](https://github.com/vuejs/vitepress/commit/83ce1b8c5e95d2e29e733d9312f514d725fe7f0b)) +- **theme:** use locale lang instead of navigator lang for last updated ([#2118](https://github.com/vuejs/vitepress/issues/2118)) ([56a7d9a](https://github.com/vuejs/vitepress/commit/56a7d9aa74bbb1d945c6ca3a3573b5e49ba3ca65)) + +# [1.0.0-alpha.61](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.60...v1.0.0-alpha.61) (2023-03-20) ### Bug Fixes -* **theme:** remove experimental fonts ([#1710](https://github.com/vuejs/vitepress/issues/1710)) ([1ebde66](https://github.com/vuejs/vitepress/commit/1ebde6623ef7f279a77b5a2ddc61e50e322481d1)) +- **build:** skip warning for `txt` language ([#2109](https://github.com/vuejs/vitepress/issues/2109)) ([ac953ce](https://github.com/vuejs/vitepress/commit/ac953ce8bdeecb2854257613c849b82d38a91846)) +- decode when query selecting current hash ([1f2f1ff](https://github.com/vuejs/vitepress/commit/1f2f1ff43dbb3c1598810fe04608678426e4fed5)), closes [#2089](https://github.com/vuejs/vitepress/issues/2089) +- **theme:** prevent code-groups conflict with shiki-twoslash ([#2059](https://github.com/vuejs/vitepress/issues/2059)) ([ee6cda4](https://github.com/vuejs/vitepress/commit/ee6cda42d8631c5f1f6ef47ac1aec0b178a6cbf2)) +# [1.0.0-alpha.60](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.59...v1.0.0-alpha.60) (2023-03-15) ### Features -* **build:** provide a `pathname://` protocol to escape SPA ([#1719](https://github.com/vuejs/vitepress/issues/1719)) ([ae21a3a](https://github.com/vuejs/vitepress/commit/ae21a3a622844af476f8311b1d7eba7ae3d5af36)) -* **theme:** headings anchor should not be selectable ([#1701](https://github.com/vuejs/vitepress/issues/1701)) ([505a4f8](https://github.com/vuejs/vitepress/commit/505a4f8eee254844be98d224d7f0b943a33959e7)) +- support multiple selectors for scrollOffset ([86e2a6f](https://github.com/vuejs/vitepress/commit/86e2a6f97287c0999090d5af0e8362f3e48884db)) +- **theme:** add animation to mobile page outline dropdown ([a6b18a8](https://github.com/vuejs/vitepress/commit/a6b18a8b9aba706aa3a567ee7b2564437a0850aa)) +# [1.0.0-alpha.59](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.58...v1.0.0-alpha.59) (2023-03-15) +### Bug Fixes -# [1.0.0-alpha.32](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.31...v1.0.0-alpha.32) (2022-12-16) +- handle async enhanceApp when extending themes ([52b04f3](https://github.com/vuejs/vitepress/commit/52b04f324cc3a675ed87353d516a6302d282ccfb)) +- **theme:** improve Chinese font handling ([81ae1c7](https://github.com/vuejs/vitepress/commit/81ae1c79cd1c0c9c31f48100f131715efc68efbd)), closes [#2036](https://github.com/vuejs/vitepress/issues/2036) +- **theme:** move doc-footer-before slot into the footer ([b0160bc](https://github.com/vuejs/vitepress/commit/b0160bc2619b50e3bca2bf1bba60d68708a39145)), closes [#2082](https://github.com/vuejs/vitepress/issues/2082) +### Features + +- defineClientComponent helper ([2ad668c](https://github.com/vuejs/vitepress/commit/2ad668cd54174b37a8c68b389a5e31e0aae60828)) + +# [1.0.0-alpha.58](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.57...v1.0.0-alpha.58) (2023-03-14) ### Bug Fixes -* **build:** fix code groups for line numbers mode ([#1700](https://github.com/vuejs/vitepress/issues/1700)) ([135b797](https://github.com/vuejs/vitepress/commit/135b797cfb572659726d9dfbe11ca6045dee9fa3)) +- fix optional component imports from default theme ([7b0f289](https://github.com/vuejs/vitepress/commit/7b0f28915fc15e155fbb27d5153e25d004bdc294)) +# [1.0.0-alpha.57](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.56...v1.0.0-alpha.57) (2023-03-14) + +### Bug Fixes + +- **types:** allow void return in transformHead hook ([32dfaf5](https://github.com/vuejs/vitepress/commit/32dfaf5adc9db5e87995c67a7060169cbf835b09)) ### Features -* add code-group feature ([#728](https://github.com/vuejs/vitepress/issues/728)) ([#1560](https://github.com/vuejs/vitepress/issues/1560)) ([a684b67](https://github.com/vuejs/vitepress/commit/a684b67ec084fdc3b3a300ffbdd21e19fdcf7b1e)), closes [#1242](https://github.com/vuejs/vitepress/issues/1242) -* **build:** support `cacheDir` ([#1355](https://github.com/vuejs/vitepress/issues/1355)) ([f899764](https://github.com/vuejs/vitepress/commit/f899764bad8bfdf4fef91e23901d4af3cda91bcc)) +- expose page and assets on build hooks TransformContext ([468c049](https://github.com/vuejs/vitepress/commit/468c049ccd7648144761def11c88ebf70c0d4226)) +- **theme:** a11y improvements ([3b6a6d1](https://github.com/vuejs/vitepress/commit/3b6a6d1abdc42437d9e659ef598db1d93695db21)) +- **theme:** aria-label for social links ([6ca34c4](https://github.com/vuejs/vitepress/commit/6ca34c4236c076fb40fb0b4fb01c1f9783e2210c)) +- **theme:** page outline for mobile ([7182c42](https://github.com/vuejs/vitepress/commit/7182c4231f3c435f1471dfecacdce99d48270978)) +- **theme:** support extending default theme without importing fonts ([da1691d](https://github.com/vuejs/vitepress/commit/da1691d77e371892cbe566ba45ca24f1fa03dc7c)) +- **theme:** use more accessible header anchors [#2040](https://github.com/vuejs/vitepress/pull/2040) +### Performance Improvements +- **theme:** preload font ([24735db](https://github.com/vuejs/vitepress/commit/24735dbcde15be41bc2697a4ea44001a1a583511)) -# [1.0.0-alpha.31](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.30...v1.0.0-alpha.31) (2022-12-10) +### BREAKING CHANGES +- `markdown.headers` is now disabled by default. This means `PageData` will no longer include extracted headers by default unless this option is explicitly enabled. This is because the default theme now extracts page headers at runtime, so the data is no longer needed by default. -### Features +# [1.0.0-alpha.56](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.55...v1.0.0-alpha.56) (2023-03-13) + +### Bug Fixes + +- do not include head tags in inlined site data ([2f26693](https://github.com/vuejs/vitepress/commit/2f26693a1d78f24d5a62a9b988c457e7c299fc5c)) -* **build:** switch to rollup 3 and vite 4 ([#1591](https://github.com/vuejs/vitepress/issues/1591)) ([ae33896](https://github.com/vuejs/vitepress/commit/ae33896a322b6b4cc944d44398ddba6e60b5d1c7)) +# [1.0.0-alpha.55](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.54...v1.0.0-alpha.55) (2023-03-13) +### Bug Fixes + +- fix scroll to hash on new tab during dev ([9aafc88](https://github.com/vuejs/vitepress/commit/9aafc88d5951684b9b583a7a164840a9b87467b0)), closes [#653](https://github.com/vuejs/vitepress/issues/653) +- gracefully handle config update with syntax error ([470ce3d](https://github.com/vuejs/vitepress/commit/470ce3d3f3272639288cb888dc89d37f041df104)), closes [#2041](https://github.com/vuejs/vitepress/issues/2041) ### Performance Improvements -* **a11y:** add aria-hidden to line numbers wrapper ([#1675](https://github.com/vuejs/vitepress/issues/1675)) ([4c5a892](https://github.com/vuejs/vitepress/commit/4c5a892d7787440faebf061daaaff908680dcd99)) +- inline site data on page ([22ace7b](https://github.com/vuejs/vitepress/commit/22ace7b075276c340d0ae2a1f260d119e82c6470)) +- kickoff main chunk fetch earlier in browsers without modulepreload support ([d64a76e](https://github.com/vuejs/vitepress/commit/d64a76eb366a270c56189096a5e0ae6b8ae23ea7)) +# [1.0.0-alpha.54](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.53...v1.0.0-alpha.54) (2023-03-13) +### Bug Fixes -# [1.0.0-alpha.30](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.29...v1.0.0-alpha.30) (2022-12-05) +- fix chunking logic that causes breakage ([bed202d](https://github.com/vuejs/vitepress/commit/bed202dbcc8f3954c12aaef993369b29ff47211e)), closes [#2072](https://github.com/vuejs/vitepress/issues/2072) [#2073](https://github.com/vuejs/vitepress/issues/2073) [#2074](https://github.com/vuejs/vitepress/issues/2074) [#2075](https://github.com/vuejs/vitepress/issues/2075) +# [1.0.0-alpha.53](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.52...v1.0.0-alpha.53) (2023-03-13) ### Bug Fixes -* **build:** allow importing files having numbers in extension ([#1618](https://github.com/vuejs/vitepress/issues/1618)) ([0565c38](https://github.com/vuejs/vitepress/commit/0565c38fc172cefb9a068882e215ac09dca6636d)) -* **build:** allow serving files in dev from workspace root ([#1647](https://github.com/vuejs/vitepress/issues/1647)) ([dc59662](https://github.com/vuejs/vitepress/commit/dc596621cf5ad11585597423b0a98266949c932a)) -* **theme:** default to vertical align top on badges inside headings ([#1584](https://github.com/vuejs/vitepress/issues/1584)) ([8a488de](https://github.com/vuejs/vitepress/commit/8a488deac111fbc43b8739c8959b8ae60cbedc80)) -* **theme:** ignore removed diff lines while copying code ([f4d5417](https://github.com/vuejs/vitepress/commit/f4d54179306c0ecbc08e4275081e3e169d304e09)) -* **theme:** move background colors to theme-default style ([#1347](https://github.com/vuejs/vitepress/issues/1347)) ([4f0194f](https://github.com/vuejs/vitepress/commit/4f0194f1dceec8c7aff70c490b5e757aca560e8a)) +- avoid circular dependency between siteData virtual module and useData() ([905f58b](https://github.com/vuejs/vitepress/commit/905f58b2a80cd1dd37b645dddde3d54b02cd60d4)), closes [#2072](https://github.com/vuejs/vitepress/issues/2072) [#2073](https://github.com/vuejs/vitepress/issues/2073) [#2074](https://github.com/vuejs/vitepress/issues/2074) + +### Features + +- createContentLoader ([d2838e3](https://github.com/vuejs/vitepress/commit/d2838e3755a8ef5861d1a921a336dfebc6156634)) +- **theme:** editLink can accept function ([#2058](https://github.com/vuejs/vitepress/issues/2058)) ([192708d](https://github.com/vuejs/vitepress/commit/192708de678115116f3477293742c155b8f48e5d)) + +# [1.0.0-alpha.52](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.51...v1.0.0-alpha.52) (2023-03-11) + +### Bug Fixes +- fix line higlighting for empty lines ([9708510](https://github.com/vuejs/vitepress/commit/9708510cbd893f02916c95fabad5a8f07d52dbaf)) +- fix rewrites with non ascii chars ([6ce88da](https://github.com/vuejs/vitepress/commit/6ce88da3baa4bc9e6b8dc3254180ed995766c7ec)), closes [#2017](https://github.com/vuejs/vitepress/issues/2017) +- fix same page hash links with encoded chars ([e05a3f2](https://github.com/vuejs/vitepress/commit/e05a3f2b5aff54ec7e5211c1021c16814eb57e58)), closes [#1749](https://github.com/vuejs/vitepress/issues/1749) +- properly serialize header in outline ([8ab36d0](https://github.com/vuejs/vitepress/commit/8ab36d05fa4aa8b3707c1f89efc1c820ffaf9669)) +- remove @vue/devtools from force include ([9bd940f](https://github.com/vuejs/vitepress/commit/9bd940f22cae0ec88dc1670a31fb9ebc015e1f92)) +- respect user vue alias ([63f33d2](https://github.com/vuejs/vitepress/commit/63f33d2895d21c08903eb4d625c13d8d3721d861)), closes [#1065](https://github.com/vuejs/vitepress/issues/1065) +- **theme:** re-support dynamic headers ([657a7d3](https://github.com/vuejs/vitepress/commit/657a7d38df3c9022a7ef6977fd71a6bde6571cfc)) +- trim spaces from outline headers ([9ceff1d](https://github.com/vuejs/vitepress/commit/9ceff1d587f6b61529806c5eb705fc417b685ad9)) ### Features -* **build:** add preview as an alias for serve in cli ([#1651](https://github.com/vuejs/vitepress/issues/1651)) ([4ba33da](https://github.com/vuejs/vitepress/commit/4ba33dac60b8b091627eb3e9c2347da0aa5efb82)) +- allow disabling markdown.headers ([868a9ff](https://github.com/vuejs/vitepress/commit/868a9ff81ea445556bc7500dfe4210d253da9ceb)) +### Performance Improvements +- improve default theme chunking ([f6cb4c0](https://github.com/vuejs/vitepress/commit/f6cb4c0d44108116c91b28a3fcde820093d94340)) -# [1.0.0-alpha.29](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.28...v1.0.0-alpha.29) (2022-11-15) +### BREAKING CHANGES + +- default theme config option `outlineBadge` has been + removed. Badges in headers are now always excluded when generating + outline text. +# [1.0.0-alpha.51](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.50...v1.0.0-alpha.51) (2023-03-09) ### Bug Fixes -* **build:** explicitly specify asset and entry file names ([#1607](https://github.com/vuejs/vitepress/issues/1607)) ([8601e15](https://github.com/vuejs/vitepress/commit/8601e1596b45e6684b71964d002133fb32d51b9f)) -* **theme:** typo in attribute name ([#1597](https://github.com/vuejs/vitepress/issues/1597)) ([cc91d55](https://github.com/vuejs/vitepress/commit/cc91d555b5bfcbde35f2ba33aedcd79a5cef713b)) +- **theme:** align number to code line ([#2044](https://github.com/vuejs/vitepress/issues/2044)) ([27e3adf](https://github.com/vuejs/vitepress/commit/27e3adf8ed888f03466fec2e10bc7589b0d010e8)) +- **theme:** remove log in VPContent ([747a04d](https://github.com/vuejs/vitepress/commit/747a04d3416a4014e46e41ebfdc734643268bc29)) +### Features +- **theme:** add not-found layout slot ([#2054](https://github.com/vuejs/vitepress/issues/2054)) ([41987b6](https://github.com/vuejs/vitepress/commit/41987b6a880d99e78e48ae3b4a2e6b815e183348)) -# [1.0.0-alpha.28](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.27...v1.0.0-alpha.28) (2022-11-08) +### Performance Improvements +- **a11y:** add aria-label to language button ([#2025](https://github.com/vuejs/vitepress/issues/2025)) ([322c633](https://github.com/vuejs/vitepress/commit/322c633fd0df15b2dfae62b54479d7cdb3255155)) -### Bug Fixes +# [1.0.0-alpha.50](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.49...v1.0.0-alpha.50) (2023-03-07) -* **theme:** use faux italics only with web fonts ([#1581](https://github.com/vuejs/vitepress/issues/1581)) ([124158e](https://github.com/vuejs/vitepress/commit/124158e3a9793fc466b96b51cf7330b8aa3e055b)) +### Bug Fixes +- avoid deprecation warning when using --force ([0c0b6cc](https://github.com/vuejs/vitepress/commit/0c0b6cc5a3a06bb0bee14dc854c7c1102a1b6657)) +- ensure HMR works properly for page outline ([1457681](https://github.com/vuejs/vitepress/commit/1457681484c873a7801729f9a9e11872b60b4868)), closes [#1281](https://github.com/vuejs/vitepress/issues/1281) +- extract all headers by default ([580a8e1](https://github.com/vuejs/vitepress/commit/580a8e1a551089e973745fd224d97aec9d3fa702)) +- respect command line minify and outDir options ([22047f3](https://github.com/vuejs/vitepress/commit/22047f3363af290687cb3077ff617ae550af6e8a)) +- **theme:** make tip box text color darker ([3158115](https://github.com/vuejs/vitepress/commit/3158115afc8f15bee3e35644a33328b02dee6d6d)) +- **theme:** prevent text wrapping in nav dropdown menu ([2a1abbe](https://github.com/vuejs/vitepress/commit/2a1abbe45e10b38f03795357cd52dc4f6cea5dfc)) ### Features -* **theme:** sidebar nav slots ([#1582](https://github.com/vuejs/vitepress/issues/1582)) ([d410d4d](https://github.com/vuejs/vitepress/commit/d410d4dd9f1140b68d140642c1bceaf5419ff304)) -* **theme:** use v-html in VPDocFooter ([#1580](https://github.com/vuejs/vitepress/issues/1580)) ([9d10b1d](https://github.com/vuejs/vitepress/commit/9d10b1d5a1ec8d30689ddad5f2d63d22342cf707)) +- **data-loader:** defineLoader() type helper ([4673bb1](https://github.com/vuejs/vitepress/commit/4673bb187905374896b7a1a3b1a1e5ad3777bdc4)) +- **data-loader:** pass watched files into load() ([e29b6a0](https://github.com/vuejs/vitepress/commit/e29b6a051e89e23945e2acfdfca7057978929715)) +- deprecate Theme.setup ([868a586](https://github.com/vuejs/vitepress/commit/868a58670e747310bba1f0f900a76243c6473da3)) +- export loadEnv from vite ([7609704](https://github.com/vuejs/vitepress/commit/76097048f3570b3f2417ac76ef177ce16afb9116)) +- expose isNotFound on PageData, deperecate Theme.NotFound ([74caccd](https://github.com/vuejs/vitepress/commit/74caccda4342feee3ab980b1a446ef7ec4819e0f)) +- expose params at top level in useData() ([66f94fd](https://github.com/vuejs/vitepress/commit/66f94fd7a0f43882386d32769b6b98014154ffa6)) +- support $params in page components ([a4ac055](https://github.com/vuejs/vitepress/commit/a4ac055dbf42848206683611a8d15e09572441ac)) +- support Theme.extends ([f39b6a9](https://github.com/vuejs/vitepress/commit/f39b6a98d6d2cc9ba405204a4d7a91eadce64a0d)) +- **theme:** add `as` prop to `Content` ([#2011](https://github.com/vuejs/vitepress/issues/2011)) ([254e15b](https://github.com/vuejs/vitepress/commit/254e15beb9b895c081e301eb379cbc2551b3e53c)) +- **theme:** add `home-hero-info` slot ([#1807](https://github.com/vuejs/vitepress/issues/1807)) ([996a5f4](https://github.com/vuejs/vitepress/commit/996a5f47e9064da839aef9e81db22db70fa8d76d)) +- vitepress init command ([#2020](https://github.com/vuejs/vitepress/issues/2020)) ([38bbdad](https://github.com/vuejs/vitepress/commit/38bbdaddb72ec426865d731c2f443e545e5bbbd7)), closes [#1252](https://github.com/vuejs/vitepress/issues/1252) + +# [1.0.0-alpha.49](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.48...v1.0.0-alpha.49) (2023-02-28) +### Bug Fixes +- disable fuzzy link recognition by default ([2450710](https://github.com/vuejs/vitepress/commit/24507105b18362210632543b8a72893832b5940a)) +- dyamic routes w/ srcDir + relative imports ([b075ee5](https://github.com/vuejs/vitepress/commit/b075ee5be6785e671b19ded066c22a1d506ec508)) +- hmr on deps change of data loaders ([5913ebc](https://github.com/vuejs/vitepress/commit/5913ebc34f810e84b4ad482aa835e1a4e8beb404)) +- normalize all paths in config ([8e8fcd9](https://github.com/vuejs/vitepress/commit/8e8fcd9caa4194787c5fc81ad10d17cf82638b8f)) +- **theme:** "copy code" button not readable on hover state ([#819](https://github.com/vuejs/vitepress/issues/819)) ([#1892](https://github.com/vuejs/vitepress/issues/1892)) ([#1998](https://github.com/vuejs/vitepress/issues/1998)) ([c2de4ca](https://github.com/vuejs/vitepress/commit/c2de4caa345bdeda5252a8fc00cfcdbcc18d5d2d)) +- **theme:** tip custom container has wrong bg color for `` block ([d9a2e6e](https://github.com/vuejs/vitepress/commit/d9a2e6e8978f614d70f347be81b9b3b9df03d7a1)) +- update route configs on file add / delete ([bccce98](https://github.com/vuejs/vitepress/commit/bccce98c62d1ea405c55a6f72bab6f2ce27e2e65)) -# [1.0.0-alpha.27](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.26...v1.0.0-alpha.27) (2022-11-03) +### Features +- dynamic routes ([24fa862](https://github.com/vuejs/vitepress/commit/24fa862c39d1b5c2ea6da6faf08cfe95e07f5d2f)) +- **theme:** enhance readability of custom containers ([#1824](https://github.com/vuejs/vitepress/issues/1824)) ([#1989](https://github.com/vuejs/vitepress/issues/1989)) ([472b6ec](https://github.com/vuejs/vitepress/commit/472b6ecf5e404bccc751bcf93b868ac30f43f22b)) -### Bug Fixes +# [1.0.0-alpha.48](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.47...v1.0.0-alpha.48) (2023-02-26) -* **build:** use addClass from shiki-processor ([#1557](https://github.com/vuejs/vitepress/issues/1557)) ([4b0b1ef](https://github.com/vuejs/vitepress/commit/4b0b1ef35f38461514f3e97e0a509029a70d3086)), closes [#1555](https://github.com/vuejs/vitepress/issues/1555) -* **build:** use default slugify from mdit-vue ([#1554](https://github.com/vuejs/vitepress/issues/1554)) ([8cd1f7c](https://github.com/vuejs/vitepress/commit/8cd1f7c4aadb7a911158ac628233b3878a60786a)) -* prevent overlay getting hidden behind navbar ([#1547](https://github.com/vuejs/vitepress/issues/1547)) ([87d6c08](https://github.com/vuejs/vitepress/commit/87d6c085d6ccf084d5435216741e3af408c9897a)) -* remove shell code copy trailing newline ([#1561](https://github.com/vuejs/vitepress/issues/1561)) ([f36cd0d](https://github.com/vuejs/vitepress/commit/f36cd0d62625c3221533b9e1f83a58b2cd4429a2)) -* **theme:** use stored preference to be the value of `userPreference` ([#1543](https://github.com/vuejs/vitepress/issues/1543)) ([a7abf73](https://github.com/vuejs/vitepress/commit/a7abf73e432caa6b06b868e7c8c01c6f31b6cc54)) +### Bug Fixes +- **compat:** remove use of array.at ([fd99590](https://github.com/vuejs/vitepress/commit/fd995906f61e5181ca8e1116dcd93eec65075056)) +- **theme:** add height constraints to hero image ([#1983](https://github.com/vuejs/vitepress/issues/1983)) ([803d5b6](https://github.com/vuejs/vitepress/commit/803d5b6d663b5293c70672ca5526a33f454e4a17)) +- **theme:** allow empty details in home feature ([#1936](https://github.com/vuejs/vitepress/issues/1936)) ([#1963](https://github.com/vuejs/vitepress/issues/1963)) ([b56351c](https://github.com/vuejs/vitepress/commit/b56351c7785b7a3a3413dcf24d7ac63c1f40fd2b)) +- **theme:** show external link icon in navbar ([#1881](https://github.com/vuejs/vitepress/issues/1881)) ([8e6e8d9](https://github.com/vuejs/vitepress/commit/8e6e8d9af534e124cb16552686b460e19d0f894f)), closes [#1948](https://github.com/vuejs/vitepress/issues/1948) +- **theme:** show external link icon on same line ([#1880](https://github.com/vuejs/vitepress/issues/1880)) ([6218b10](https://github.com/vuejs/vitepress/commit/6218b108bc78aed0ec1afd3d1cf4182e611eed90)) ### Features -* **theme:** add built-in global component `Badge` ([#1239](https://github.com/vuejs/vitepress/issues/1239)) ([ac8619f](https://github.com/vuejs/vitepress/commit/ac8619f841862b8629ea0416ba2f188faceebc70)) -* **theme:** add link feature in homepage features ([#984](https://github.com/vuejs/vitepress/issues/984)) ([#1404](https://github.com/vuejs/vitepress/issues/1404)) ([84b4abc](https://github.com/vuejs/vitepress/commit/84b4abc5fa29b353d52162508a31f55a4ea755e5)), closes [#1070](https://github.com/vuejs/vitepress/issues/1070) -* **theme:** sort multiple sidebars ([#1552](https://github.com/vuejs/vitepress/issues/1552)) ([db1c343](https://github.com/vuejs/vitepress/commit/db1c343dfb7011825b18253b4b8a47b5d8f6f817)) +- **build:** add support for custom languages ([#1837](https://github.com/vuejs/vitepress/issues/1837)) ([5a6d384](https://github.com/vuejs/vitepress/commit/5a6d3849527ee1dfd9f4299f5350cfa7641effb7)) +- **theme:** make prev/next links changeable ([#1972](https://github.com/vuejs/vitepress/issues/1972)) ([b8a5e8e](https://github.com/vuejs/vitepress/commit/b8a5e8e5b24b025c9a5e4850b72296f726ae71e5)) +- **theme:** support custom target and rel in navbar links ([#1993](https://github.com/vuejs/vitepress/issues/1993)) ([e2d4edf](https://github.com/vuejs/vitepress/commit/e2d4edf45b5ec890c088d3b0517b21a7b3eab9df)) +# [1.0.0-alpha.47](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.46...v1.0.0-alpha.47) (2023-02-20) + +### Bug Fixes + +- **build:** show error stack in logs ([#1960](https://github.com/vuejs/vitepress/issues/1960)) ([c4d8d72](https://github.com/vuejs/vitepress/commit/c4d8d7225c2d8dd75f1640730e8d1425097e3aa3)) +- custom titles of code snippets inside code groups ([#1834](https://github.com/vuejs/vitepress/issues/1834)) ([bcb8cbf](https://github.com/vuejs/vitepress/commit/bcb8cbf3c839dc17c1eaee7e39edb3ecca236a27)) +- **types:** augment vite user config ([#1946](https://github.com/vuejs/vitepress/issues/1946)) ([5c9b75e](https://github.com/vuejs/vitepress/commit/5c9b75e325c27f63373c969e16035a9df5292cc9)) ### Reverts -* **#1530:** explicitly exit process after build to prevent hangup ([#1572](https://github.com/vuejs/vitepress/issues/1572)) ([01719fa](https://github.com/vuejs/vitepress/commit/01719fa58e245291e640d5b0bc51cac5a4a3085c)), closes [#1530](https://github.com/vuejs/vitepress/issues/1530) +- "docs: add linkage for `code-groups` in `getting-started`" ([#1943](https://github.com/vuejs/vitepress/issues/1943)) ([ed90724](https://github.com/vuejs/vitepress/commit/ed90724022359358de582a3c00e86f381d57eeba)), closes [#1906](https://github.com/vuejs/vitepress/issues/1906) +# [1.0.0-alpha.46](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.45...v1.0.0-alpha.46) (2023-02-12) +### Bug Fixes -# [1.0.0-alpha.26](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.25...v1.0.0-alpha.26) (2022-10-27) +- **build:** prepend base to all internal non-relative links ([#1908](https://github.com/vuejs/vitepress/issues/1908)) ([dcf2941](https://github.com/vuejs/vitepress/commit/dcf29419f24bfb0fe99e424771be931bf77b9961)) +- **theme-default:** avoid preconnect without algolia ([#1902](https://github.com/vuejs/vitepress/issues/1902)) ([616fe5b](https://github.com/vuejs/vitepress/commit/616fe5b636050caa338cabede3794e658baa0ed6)) +- **theme-default:** remove duplicate judgments in `preconnect()` ([#1903](https://github.com/vuejs/vitepress/issues/1903)) ([48c9b11](https://github.com/vuejs/vitepress/commit/48c9b113161823133276198ebeb15131b83a7a75)) +- **theme:** make features support line wrapping ([#1913](https://github.com/vuejs/vitepress/issues/1913)) ([ea43076](https://github.com/vuejs/vitepress/commit/ea430760f507e3ba381c4ab01ec89a2111f35e8c)) +### Features -### Bug Fixes +- **build:** use vite logger ([#1899](https://github.com/vuejs/vitepress/issues/1899)) ([a00bb62](https://github.com/vuejs/vitepress/commit/a00bb621439b2571b3d33da6aa67c74ecd13d3c6)) +- **shiki:** support `ansi` code highlight ([#1878](https://github.com/vuejs/vitepress/issues/1878)) ([f974381](https://github.com/vuejs/vitepress/commit/f9743816a55503c387b9c71793a92eb38817650d)) +- **theme:** support disabling aside globally ([#1925](https://github.com/vuejs/vitepress/issues/1925)) ([dd0c4c6](https://github.com/vuejs/vitepress/commit/dd0c4c698c26d3e249d353c3baff568a8f406e8f)) -* properly apply dark/light classes in code blocks ([#1546](https://github.com/vuejs/vitepress/issues/1546)) ([178895f](https://github.com/vuejs/vitepress/commit/178895f067e0f38e1c76d3efe64a75612cd4ad3a)) +### BREAKING CHANGES +- **build:** `base` is now prepended to all internal (non-relative) links, including any reference to a file present in the public directory. If you want the earlier behavior for such links, use absolute links. +# [1.0.0-alpha.45](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.44...v1.0.0-alpha.45) (2023-01-31) -# [1.0.0-alpha.25](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.24...v1.0.0-alpha.25) (2022-10-25) +### Bug Fixes + +- safari use `window.requestIdleCallback` ([#1871](https://github.com/vuejs/vitepress/issues/1871)) ([507b193](https://github.com/vuejs/vitepress/commit/507b193ef0e09afe667fccbf6de256cbc86de53f)) +# [1.0.0-alpha.44](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.43...v1.0.0-alpha.44) (2023-01-31) ### Bug Fixes -* **banner:** prevent hidden local nav on scroll ([63449ca](https://github.com/vuejs/vitepress/commit/63449caf4cb2c7e8449e4f8aee1d8f504fa949df)) +- take `` in SVG into account ([#1850](https://github.com/vuejs/vitepress/issues/1850)) ([010b3e5](https://github.com/vuejs/vitepress/commit/010b3e5ad99f5e61fd01e27d0c3144896a8f3d86)) +- **theme:** infer collapsible from collapsed ([#1865](https://github.com/vuejs/vitepress/issues/1865)) ([dea6cfa](https://github.com/vuejs/vitepress/commit/dea6cfa9cbccf4c6433295e80571acee9b260f71)) +### Features +- **theme:** preconnect algolia when idle ([#1851](https://github.com/vuejs/vitepress/issues/1851)) ([1f77577](https://github.com/vuejs/vitepress/commit/1f775774da7ef51ae8e690bbd86f94c739611a65)) -# [1.0.0-alpha.24](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.23...v1.0.0-alpha.24) (2022-10-25) +### BREAKING CHANGES +- **theme:** `collapsible` is dropped from sidebar, use `collapsed` instead + +# [1.0.0-alpha.43](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.42...v1.0.0-alpha.43) (2023-01-29) ### Bug Fixes -* **banner:** broken layout on smaller viewports ([#1536](https://github.com/vuejs/vitepress/issues/1536)) ([028cc2c](https://github.com/vuejs/vitepress/commit/028cc2c76e540c595e55a399606701490afd4beb)) +- **build:** hmr with rewrites when base is set ([a05956f](https://github.com/vuejs/vitepress/commit/a05956f38a5295cf038ecfc762c044dbc1cdf040)) +# [1.0.0-alpha.42](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.41...v1.0.0-alpha.42) (2023-01-29) +### Bug Fixes -# [1.0.0-alpha.23](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.22...v1.0.0-alpha.23) (2022-10-25) +- **build:** consider base when checking actual pathname ([#1858](https://github.com/vuejs/vitepress/issues/1858)) ([cf8ad1a](https://github.com/vuejs/vitepress/commit/cf8ad1a29133cc373a1a70720d36e02b38ba6898)) +# [1.0.0-alpha.41](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.40...v1.0.0-alpha.41) (2023-01-28) ### Bug Fixes -* **build:** explicitly exit process after build to prevent hangup ([#1530](https://github.com/vuejs/vitepress/issues/1530)) ([09fcc46](https://github.com/vuejs/vitepress/commit/09fcc460794d515c48c38ccb47a936d58a2582b3)) - +- check document instead of window to detect browser ([#1833](https://github.com/vuejs/vitepress/issues/1833)) ([0f145cb](https://github.com/vuejs/vitepress/commit/0f145cb3c6568760199a9c8eee785aecaf0e0494)) +- **router:** avoid duplicate history entries ([#1827](https://github.com/vuejs/vitepress/issues/1827)) ([1553dbc](https://github.com/vuejs/vitepress/commit/1553dbce8eac9ed4a65312d4590d6b0f9261135c)) +- **theme:** don't show border on navbar when sidebar is there ([#1845](https://github.com/vuejs/vitepress/issues/1845)) ([3db532e](https://github.com/vuejs/vitepress/commit/3db532ed0999c9bddfd6bc90f6b627ae1b9178af)) ### Features -* **build:** add `useWebFonts` option ([#1531](https://github.com/vuejs/vitepress/issues/1531)) ([c9f04e0](https://github.com/vuejs/vitepress/commit/c9f04e045922a6f1e11136bd1ccc824c2e9928f1)) -* support focus, colored diffs, error highlights in code blocks ([#1534](https://github.com/vuejs/vitepress/issues/1534)) ([04ab0eb](https://github.com/vuejs/vitepress/commit/04ab0eb6dcacb065e865332580088891bc2df893)) -* **theme:** add --vp-layout-top-height to adjust banner ([#1521](https://github.com/vuejs/vitepress/issues/1521)) ([a29a4a6](https://github.com/vuejs/vitepress/commit/a29a4a62c682b54ec88c609cb480ddb68b3f4699)) +- **build:** allow ignoring only localhost dead links ([#1821](https://github.com/vuejs/vitepress/issues/1821)) ([fe52fa3](https://github.com/vuejs/vitepress/commit/fe52fa34201dcfa87ac4886fe285331f0ef89ba8)) +- **build:** expose vitepress site config to vite plugins ([#1822](https://github.com/vuejs/vitepress/issues/1822)) ([05430e4](https://github.com/vuejs/vitepress/commit/05430e45c90562b62796caba28c633070934d85f)) +- **build:** support rewrites ([#1798](https://github.com/vuejs/vitepress/issues/1798)) ([00abac6](https://github.com/vuejs/vitepress/commit/00abac611664e12710e5152d0259390b22c0e8ca)) +- stable `cleanUrls` ([#1852](https://github.com/vuejs/vitepress/issues/1852)) ([5ae4fbd](https://github.com/vuejs/vitepress/commit/5ae4fbde3843236e180e63e2cd2b7021efa0fad4)) +- **theme:** allow removing badge text from outline ([#1825](https://github.com/vuejs/vitepress/issues/1825)) ([5d2fc3f](https://github.com/vuejs/vitepress/commit/5d2fc3f9228c9b26dec26264d0951d0f43b3d90d)) +- **theme:** enable multi level sidebar nesting ([#1360](https://github.com/vuejs/vitepress/issues/1360)) ([#1835](https://github.com/vuejs/vitepress/issues/1835)) ([c35a1f0](https://github.com/vuejs/vitepress/commit/c35a1f0faee3702c0494fb22043ce058e7a2954c)), closes [#1361](https://github.com/vuejs/vitepress/issues/1361) [#1680](https://github.com/vuejs/vitepress/issues/1680) +# [1.0.0-alpha.40](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.39...v1.0.0-alpha.40) (2023-01-20) +### Bug Fixes -# [1.0.0-alpha.22](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.21...v1.0.0-alpha.22) (2022-10-22) +- **theme:** nav bg not being applied on some viewport ([39294e0](https://github.com/vuejs/vitepress/commit/39294e0a4ec53b245da4344187de842d0044dac8)) +# [1.0.0-alpha.39](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.38...v1.0.0-alpha.39) (2023-01-20) ### Bug Fixes -* **types:** change ComponentOptions to DefineComponent ([#1499](https://github.com/vuejs/vitepress/issues/1499)) ([5711660](https://github.com/vuejs/vitepress/commit/57116607b83f79e62f399cd6430b0d80524861a3)) +- **theme:** adjust the position of the curtain to avoid block sidebar ([#1816](https://github.com/vuejs/vitepress/issues/1816)) ([48f0b01](https://github.com/vuejs/vitepress/commit/48f0b015694c17767180eb2f75e9eb12c3f2a358)) +- **theme:** sidebar scrollbar is cropped by nav bar ([bd36224](https://github.com/vuejs/vitepress/commit/bd36224b45ee832765afcf4a57c211d362e4e6af)) + +# [1.0.0-alpha.38](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.37...v1.0.0-alpha.38) (2023-01-17) + +### Bug Fixes + +- **theme:** spacing between aside sponsors and ads section is missing ([5c2eb1b](https://github.com/vuejs/vitepress/commit/5c2eb1b3b0988ae98639543e60a740d6b40a17a5)) + +# [1.0.0-alpha.37](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.36...v1.0.0-alpha.37) (2023-01-17) + +### Bug Fixes +- **build:** don't warn on blank lang in fences ([99ad162](https://github.com/vuejs/vitepress/commit/99ad162fb7b11ac80c787131714c9c8bf66fa8c7)) +- **theme:** prevent vertical scrollbar on code group tabs ([#1793](https://github.com/vuejs/vitepress/issues/1793)) ([#1805](https://github.com/vuejs/vitepress/issues/1805)) ([4314b57](https://github.com/vuejs/vitepress/commit/4314b5795918ceaa798dee550b79ff2e8a686b26)) ### Features -* expose isDark ([#1525](https://github.com/vuejs/vitepress/issues/1525)) ([d327811](https://github.com/vuejs/vitepress/commit/d327811fd5b333a73d77730b6b0b347e3d052ebc)) -* **theme:** allow defining dark as the default theme ([#1498](https://github.com/vuejs/vitepress/issues/1498)) ([d404753](https://github.com/vuejs/vitepress/commit/d404753005bf4cc3bb645553ac473d08c6473180)) -* **theme:** support html strings for SidebarGroup headings, SidebarItem text ([#1489](https://github.com/vuejs/vitepress/issues/1489)) ([946c579](https://github.com/vuejs/vitepress/commit/946c579f2b8957839b8e0ef3474bded5ad06de1a)) -* transformPageData hook ([#1492](https://github.com/vuejs/vitepress/issues/1492)) ([afeb06f](https://github.com/vuejs/vitepress/commit/afeb06f17cbd439e3e0151f9571107754fe98b57)) +- add i18n feature ([#1339](https://github.com/vuejs/vitepress/issues/1339)) ([8de2f44](https://github.com/vuejs/vitepress/commit/8de2f4499d9364d85e6070ce4b94651a1902b101)), closes [#291](https://github.com/vuejs/vitepress/issues/291) [#628](https://github.com/vuejs/vitepress/issues/628) [#631](https://github.com/vuejs/vitepress/issues/631) [#902](https://github.com/vuejs/vitepress/issues/902) [#955](https://github.com/vuejs/vitepress/issues/955) [#1253](https://github.com/vuejs/vitepress/issues/1253) [#1381](https://github.com/vuejs/vitepress/issues/1381) +- support for teleports to body ([#1642](https://github.com/vuejs/vitepress/issues/1642)) ([09c2c52](https://github.com/vuejs/vitepress/commit/09c2c52d6c027f6e30fac33c2d11246a4a530c24)) +- **build:** don't hard fail on unknown languages in fences ([#1750](https://github.com/vuejs/vitepress/issues/1750)) ([1ae0596](https://github.com/vuejs/vitepress/commit/1ae05969396ef1651af56c66696ed77f8c4e7e85)) +- **theme:** refine overall styles ([#1049](https://github.com/vuejs/vitepress/issues/1049)) ([#1790](https://github.com/vuejs/vitepress/issues/1790)) ([471f00a](https://github.com/vuejs/vitepress/commit/471f00a68d1e3d8d925ab996f462adaf4f1261a0)) +# [1.0.0-alpha.36](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.35...v1.0.0-alpha.36) (2023-01-11) +### Bug Fixes -# [1.0.0-alpha.21](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.20...v1.0.0-alpha.21) (2022-10-14) +- **build:** handle cleanUrls without trailing slash ([#1772](https://github.com/vuejs/vitepress/issues/1772)) ([2a80fbd](https://github.com/vuejs/vitepress/commit/2a80fbd14ae124eddb05deca71ebffa50de4c2ce)) +- **theme:** `activeMatch` support regexp ([#1754](https://github.com/vuejs/vitepress/issues/1754)) ([0913e0f](https://github.com/vuejs/vitepress/commit/0913e0fe69167c796b0c3c22706b26f4840c6493)), closes [#1771](https://github.com/vuejs/vitepress/issues/1771) +- **theme:** add cursor for summary of custom block details ([#1774](https://github.com/vuejs/vitepress/issues/1774)) ([167a474](https://github.com/vuejs/vitepress/commit/167a474cb8121d758c2aa863016dffbe8d0a1e55)) +- **theme:** wrap long words in `li` ([#1782](https://github.com/vuejs/vitepress/issues/1782)) ([48a42c1](https://github.com/vuejs/vitepress/commit/48a42c19b17417fea384bb0a7004d140b16d9c23)), closes [#1783](https://github.com/vuejs/vitepress/issues/1783) [#1405](https://github.com/vuejs/vitepress/issues/1405) +### Features + +- allow `enhanceApp` to return a `Promise` ([#1760](https://github.com/vuejs/vitepress/issues/1760)) ([01ac579](https://github.com/vuejs/vitepress/commit/01ac57918767f44a0757414316e67072399ffb6d)) +- **build:** support interpolation inside code blocks ([#1759](https://github.com/vuejs/vitepress/issues/1759)) ([3b7ff8d](https://github.com/vuejs/vitepress/commit/3b7ff8d66e9eda3aab1fb126984efc63132bd22d)) + +# [1.0.0-alpha.35](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.34...v1.0.0-alpha.35) (2023-01-03) ### Bug Fixes -* **build:** better align server and client side filename sanitization ([3fd20fe](https://github.com/vuejs/vitepress/commit/3fd20fedb81c88c188cff22b4c03ccc2ad416d2c)) -* **theme:** match switch background transition with page transition ([#1479](https://github.com/vuejs/vitepress/issues/1479)) ([962065a](https://github.com/vuejs/vitepress/commit/962065a46ee1ef34eccbffbde9e65d7f174f8ab1)) -* **theme:** prevent body scrolling when sidebar has opened on small screens ([#1391](https://github.com/vuejs/vitepress/issues/1391)) ([3daabdc](https://github.com/vuejs/vitepress/commit/3daabdc480c0cc10a12a83a08a734f8719d092c5)) +- **theme:** adjust styles for copied button ([#1751](https://github.com/vuejs/vitepress/issues/1751)) ([565ae71](https://github.com/vuejs/vitepress/commit/565ae711b9b90ad2fe820cdbaa04a9d41506ac53)) +- **theme:** adjust styles for diff indicator in code blocks ([#1755](https://github.com/vuejs/vitepress/issues/1755)) ([a642ea2](https://github.com/vuejs/vitepress/commit/a642ea2526f5638243283bd37ef9ba0af350d407)) +- **theme:** prevent layout shift on carbon ads ([f6c5e1f](https://github.com/vuejs/vitepress/commit/f6c5e1f098d1fd4d4f6325a21adbb088c32a0740)) +- **theme:** refresh ads per page navigation ([#1734](https://github.com/vuejs/vitepress/issues/1734)) ([8db20fe](https://github.com/vuejs/vitepress/commit/8db20fe02240bb1d3c02da738740f2433edb1e8b)) + +# [1.0.0-alpha.34](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.33...v1.0.0-alpha.34) (2023-01-01) + +### Bug Fixes +- **build:** dedent of a single-line region ([#1687](https://github.com/vuejs/vitepress/issues/1687)) ([7de7fff](https://github.com/vuejs/vitepress/commit/7de7fff4178251a6173ac67b52de50176830f539)) +- **build:** handle `-` in title of code blocks with line highlighting ([#1743](https://github.com/vuejs/vitepress/issues/1743)) ([ce9467e](https://github.com/vuejs/vitepress/commit/ce9467e389a2776f3230cb31e596cf9e575cc0df)) +- handle cleanUrls with subfolders when using a trailing slash ([#1575](https://github.com/vuejs/vitepress/issues/1575)) ([195d867](https://github.com/vuejs/vitepress/commit/195d867ee9bb51a4c112534b34bda7bcd0c2c3f5)) ### Features -* **theme:** allow specifying common alt for logo ([#1451](https://github.com/vuejs/vitepress/issues/1451)) ([55688a8](https://github.com/vuejs/vitepress/commit/55688a87e3baa38d0e0a37a6eba0039484416875)) +- **build:** allow specifying default language for syntax highlighter ([#1296](https://github.com/vuejs/vitepress/issues/1296)) ([f40df31](https://github.com/vuejs/vitepress/commit/f40df319475dba9f3fe1e13ff8d8dc4c0950bf5f)) +- **build:** fence-level config for line-numbers ([#1733](https://github.com/vuejs/vitepress/issues/1733)) ([c048076](https://github.com/vuejs/vitepress/commit/c048076370b081acc69c04754bf5deba2b8f5cd5)) +- **theme:** add `home-hero-image` slot ([#1528](https://github.com/vuejs/vitepress/issues/1528)) ([e72998b](https://github.com/vuejs/vitepress/commit/e72998b68bfcc301d15553033a8b90dee0db65cf)) +- **theme:** add mastodon icon ([#1736](https://github.com/vuejs/vitepress/issues/1736)) ([7a73784](https://github.com/vuejs/vitepress/commit/7a737845e5d81a09151320d373a787d2e5f881af)) +- **theme:** allow adding images as icons in features section ([#1738](https://github.com/vuejs/vitepress/issues/1738)) ([9df598f](https://github.com/vuejs/vitepress/commit/9df598f36e30fdc9d1c7440bf98b45783126c39f)) +### Performance Improvements +- **a11y:** make menu traversable only when it is open ([#1491](https://github.com/vuejs/vitepress/issues/1491)) ([257f9e6](https://github.com/vuejs/vitepress/commit/257f9e68e947a603f9c3ef0df4be7b2afa79fbe7)) +- preload css to improve loading speed ([bf1315a](https://github.com/vuejs/vitepress/commit/bf1315ace670df0128682838736371e5381b3f42)) -# [1.0.0-alpha.20](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.19...v1.0.0-alpha.20) (2022-10-12) +# [1.0.0-alpha.33](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.32...v1.0.0-alpha.33) (2022-12-21) + +### Bug Fixes + +- **theme:** remove experimental fonts ([#1710](https://github.com/vuejs/vitepress/issues/1710)) ([1ebde66](https://github.com/vuejs/vitepress/commit/1ebde6623ef7f279a77b5a2ddc61e50e322481d1)) + +### Features + +- **build:** provide a `pathname://` protocol to escape SPA ([#1719](https://github.com/vuejs/vitepress/issues/1719)) ([ae21a3a](https://github.com/vuejs/vitepress/commit/ae21a3a622844af476f8311b1d7eba7ae3d5af36)) +- **theme:** headings anchor should not be selectable ([#1701](https://github.com/vuejs/vitepress/issues/1701)) ([505a4f8](https://github.com/vuejs/vitepress/commit/505a4f8eee254844be98d224d7f0b943a33959e7)) +# [1.0.0-alpha.32](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.31...v1.0.0-alpha.32) (2022-12-16) ### Bug Fixes -* **a11y:** add title to copy code button ([#1437](https://github.com/vuejs/vitepress/issues/1437)) ([f79bb78](https://github.com/vuejs/vitepress/commit/f79bb78bf7f472d9bc376a3ec393f731bfe9e7ce)) -* **router:** don't intercept download links ([#1452](https://github.com/vuejs/vitepress/issues/1452)) ([54cf6ce](https://github.com/vuejs/vitepress/commit/54cf6ce51fcf8ce91c0706332e0b51ddcc2b519d)) -* **theme:** disable transitions on theme toggle ([#1447](https://github.com/vuejs/vitepress/issues/1447)) ([067e1a9](https://github.com/vuejs/vitepress/commit/067e1a97434f88835dbfedcf18e2f98d8bfacad9)) -* **theme:** make text prop of VPHero optional ([#1445](https://github.com/vuejs/vitepress/issues/1445)) ([95e4f2a](https://github.com/vuejs/vitepress/commit/95e4f2acc9614360fbfe37450028d2067e5993b8)) +- **build:** fix code groups for line numbers mode ([#1700](https://github.com/vuejs/vitepress/issues/1700)) ([135b797](https://github.com/vuejs/vitepress/commit/135b797cfb572659726d9dfbe11ca6045dee9fa3)) +### Features -### Reverts +- add code-group feature ([#728](https://github.com/vuejs/vitepress/issues/728)) ([#1560](https://github.com/vuejs/vitepress/issues/1560)) ([a684b67](https://github.com/vuejs/vitepress/commit/a684b67ec084fdc3b3a300ffbdd21e19fdcf7b1e)), closes [#1242](https://github.com/vuejs/vitepress/issues/1242) +- **build:** support `cacheDir` ([#1355](https://github.com/vuejs/vitepress/issues/1355)) ([f899764](https://github.com/vuejs/vitepress/commit/f899764bad8bfdf4fef91e23901d4af3cda91bcc)) + +# [1.0.0-alpha.31](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.30...v1.0.0-alpha.31) (2022-12-10) -* "fix(build): remove leading underscore from chunks" ([#1471](https://github.com/vuejs/vitepress/issues/1471)) ([18f0fb4](https://github.com/vuejs/vitepress/commit/18f0fb4e3989192ba95a397476371a945bf84542)) +### Features +- **build:** switch to rollup 3 and vite 4 ([#1591](https://github.com/vuejs/vitepress/issues/1591)) ([ae33896](https://github.com/vuejs/vitepress/commit/ae33896a322b6b4cc944d44398ddba6e60b5d1c7)) +### Performance Improvements -# [1.0.0-alpha.19](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.18...v1.0.0-alpha.19) (2022-10-02) +- **a11y:** add aria-hidden to line numbers wrapper ([#1675](https://github.com/vuejs/vitepress/issues/1675)) ([4c5a892](https://github.com/vuejs/vitepress/commit/4c5a892d7787440faebf061daaaff908680dcd99)) +# [1.0.0-alpha.30](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.29...v1.0.0-alpha.30) (2022-12-05) ### Bug Fixes -* **build:** ignore tsconfig target in dev ([#1428](https://github.com/vuejs/vitepress/issues/1428)) ([a13bc86](https://github.com/vuejs/vitepress/commit/a13bc866d0af911256e0629136f4b48e88c44df1)) - +- **build:** allow importing files having numbers in extension ([#1618](https://github.com/vuejs/vitepress/issues/1618)) ([0565c38](https://github.com/vuejs/vitepress/commit/0565c38fc172cefb9a068882e215ac09dca6636d)) +- **build:** allow serving files in dev from workspace root ([#1647](https://github.com/vuejs/vitepress/issues/1647)) ([dc59662](https://github.com/vuejs/vitepress/commit/dc596621cf5ad11585597423b0a98266949c932a)) +- **theme:** default to vertical align top on badges inside headings ([#1584](https://github.com/vuejs/vitepress/issues/1584)) ([8a488de](https://github.com/vuejs/vitepress/commit/8a488deac111fbc43b8739c8959b8ae60cbedc80)) +- **theme:** ignore removed diff lines while copying code ([f4d5417](https://github.com/vuejs/vitepress/commit/f4d54179306c0ecbc08e4275081e3e169d304e09)) +- **theme:** move background colors to theme-default style ([#1347](https://github.com/vuejs/vitepress/issues/1347)) ([4f0194f](https://github.com/vuejs/vitepress/commit/4f0194f1dceec8c7aff70c490b5e757aca560e8a)) +### Features -# [1.0.0-alpha.18](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.17...v1.0.0-alpha.18) (2022-10-01) +- **build:** add preview as an alias for serve in cli ([#1651](https://github.com/vuejs/vitepress/issues/1651)) ([4ba33da](https://github.com/vuejs/vitepress/commit/4ba33dac60b8b091627eb3e9c2347da0aa5efb82)) +# [1.0.0-alpha.29](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.28...v1.0.0-alpha.29) (2022-11-15) ### Bug Fixes -* **theme:** break long words on overflow ([#1405](https://github.com/vuejs/vitepress/issues/1405)) ([2114d13](https://github.com/vuejs/vitepress/commit/2114d1326a9d3b952ca8a150f1c27c89169629cc)) +- **build:** explicitly specify asset and entry file names ([#1607](https://github.com/vuejs/vitepress/issues/1607)) ([8601e15](https://github.com/vuejs/vitepress/commit/8601e1596b45e6684b71964d002133fb32d51b9f)) +- **theme:** typo in attribute name ([#1597](https://github.com/vuejs/vitepress/issues/1597)) ([cc91d55](https://github.com/vuejs/vitepress/commit/cc91d555b5bfcbde35f2ba33aedcd79a5cef713b)) +# [1.0.0-alpha.28](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.27...v1.0.0-alpha.28) (2022-11-08) +### Bug Fixes -# [1.0.0-alpha.17](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.16...v1.0.0-alpha.17) (2022-09-27) +- **theme:** use faux italics only with web fonts ([#1581](https://github.com/vuejs/vitepress/issues/1581)) ([124158e](https://github.com/vuejs/vitepress/commit/124158e3a9793fc466b96b51cf7330b8aa3e055b)) + +### Features + +- **theme:** sidebar nav slots ([#1582](https://github.com/vuejs/vitepress/issues/1582)) ([d410d4d](https://github.com/vuejs/vitepress/commit/d410d4dd9f1140b68d140642c1bceaf5419ff304)) +- **theme:** use v-html in VPDocFooter ([#1580](https://github.com/vuejs/vitepress/issues/1580)) ([9d10b1d](https://github.com/vuejs/vitepress/commit/9d10b1d5a1ec8d30689ddad5f2d63d22342cf707)) +# [1.0.0-alpha.27](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.26...v1.0.0-alpha.27) (2022-11-03) ### Bug Fixes -* **theme:** add cursor for collapsible sidebar title ([#1397](https://github.com/vuejs/vitepress/issues/1397)) ([ed37b9a](https://github.com/vuejs/vitepress/commit/ed37b9a0e04f85f941131ec9e2ca8b145d89a535)) -* **theme:** remove extra space before docsearch key ([#1396](https://github.com/vuejs/vitepress/issues/1396)) ([6cb79bb](https://github.com/vuejs/vitepress/commit/6cb79bbe6a26f2e8dbd4b07b3fb5b6377f06958d)) +- **build:** use addClass from shiki-processor ([#1557](https://github.com/vuejs/vitepress/issues/1557)) ([4b0b1ef](https://github.com/vuejs/vitepress/commit/4b0b1ef35f38461514f3e97e0a509029a70d3086)), closes [#1555](https://github.com/vuejs/vitepress/issues/1555) +- **build:** use default slugify from mdit-vue ([#1554](https://github.com/vuejs/vitepress/issues/1554)) ([8cd1f7c](https://github.com/vuejs/vitepress/commit/8cd1f7c4aadb7a911158ac628233b3878a60786a)) +- prevent overlay getting hidden behind navbar ([#1547](https://github.com/vuejs/vitepress/issues/1547)) ([87d6c08](https://github.com/vuejs/vitepress/commit/87d6c085d6ccf084d5435216741e3af408c9897a)) +- remove shell code copy trailing newline ([#1561](https://github.com/vuejs/vitepress/issues/1561)) ([f36cd0d](https://github.com/vuejs/vitepress/commit/f36cd0d62625c3221533b9e1f83a58b2cd4429a2)) +- **theme:** use stored preference to be the value of `userPreference` ([#1543](https://github.com/vuejs/vitepress/issues/1543)) ([a7abf73](https://github.com/vuejs/vitepress/commit/a7abf73e432caa6b06b868e7c8c01c6f31b6cc54)) + +### Features +- **theme:** add built-in global component `Badge` ([#1239](https://github.com/vuejs/vitepress/issues/1239)) ([ac8619f](https://github.com/vuejs/vitepress/commit/ac8619f841862b8629ea0416ba2f188faceebc70)) +- **theme:** add link feature in homepage features ([#984](https://github.com/vuejs/vitepress/issues/984)) ([#1404](https://github.com/vuejs/vitepress/issues/1404)) ([84b4abc](https://github.com/vuejs/vitepress/commit/84b4abc5fa29b353d52162508a31f55a4ea755e5)), closes [#1070](https://github.com/vuejs/vitepress/issues/1070) +- **theme:** sort multiple sidebars ([#1552](https://github.com/vuejs/vitepress/issues/1552)) ([db1c343](https://github.com/vuejs/vitepress/commit/db1c343dfb7011825b18253b4b8a47b5d8f6f817)) ### Reverts -* [#1064](https://github.com/vuejs/vitepress/issues/1064) ([9d70ca5](https://github.com/vuejs/vitepress/commit/9d70ca56f147a2ec30d12b03353ea7e4b0850df0)) +- **#1530:** explicitly exit process after build to prevent hangup ([#1572](https://github.com/vuejs/vitepress/issues/1572)) ([01719fa](https://github.com/vuejs/vitepress/commit/01719fa58e245291e640d5b0bc51cac5a4a3085c)), closes [#1530](https://github.com/vuejs/vitepress/issues/1530) +# [1.0.0-alpha.26](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.25...v1.0.0-alpha.26) (2022-10-27) +### Bug Fixes -# [1.0.0-alpha.16](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.15...v1.0.0-alpha.16) (2022-09-24) +- properly apply dark/light classes in code blocks ([#1546](https://github.com/vuejs/vitepress/issues/1546)) ([178895f](https://github.com/vuejs/vitepress/commit/178895f067e0f38e1c76d3efe64a75612cd4ad3a)) +# [1.0.0-alpha.25](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.24...v1.0.0-alpha.25) (2022-10-25) ### Bug Fixes -* **build:** line numbers mode when language specifier has symbol ([#1353](https://github.com/vuejs/vitepress/issues/1353)) ([9c04a10](https://github.com/vuejs/vitepress/commit/9c04a10c4d9fbfc591dc2386b4780a6728f6364a)) -* **build:** remove leading underscore from chunks ([#1394](https://github.com/vuejs/vitepress/issues/1394)) ([66cd164](https://github.com/vuejs/vitepress/commit/66cd1640d16170e0c2d9eb4565ad1ebe81f940e1)) -* **compat:** use default export of dns module ([#1388](https://github.com/vuejs/vitepress/issues/1388)) ([fa6fa56](https://github.com/vuejs/vitepress/commit/fa6fa56af9de78856017f935922e4f2f9376be62)) -* **theme:** always add alt attribute to images ([#1348](https://github.com/vuejs/vitepress/issues/1348)) ([a621c69](https://github.com/vuejs/vitepress/commit/a621c6910c0083adc26dd4b7aaa7d532544cc7fa)) +- **banner:** prevent hidden local nav on scroll ([63449ca](https://github.com/vuejs/vitepress/commit/63449caf4cb2c7e8449e4f8aee1d8f504fa949df)) +# [1.0.0-alpha.24](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.23...v1.0.0-alpha.24) (2022-10-25) -### Features +### Bug Fixes -* **build:** allow using `transformIndexHtml` ([#1380](https://github.com/vuejs/vitepress/issues/1380)) ([ce8d139](https://github.com/vuejs/vitepress/commit/ce8d139a8e70e4d0a8d06711c50119990b041078)) +- **banner:** broken layout on smaller viewports ([#1536](https://github.com/vuejs/vitepress/issues/1536)) ([028cc2c](https://github.com/vuejs/vitepress/commit/028cc2c76e540c595e55a399606701490afd4beb)) +# [1.0.0-alpha.23](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.22...v1.0.0-alpha.23) (2022-10-25) +### Bug Fixes -# [1.0.0-alpha.15](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.14...v1.0.0-alpha.15) (2022-09-15) +- **build:** explicitly exit process after build to prevent hangup ([#1530](https://github.com/vuejs/vitepress/issues/1530)) ([09fcc46](https://github.com/vuejs/vitepress/commit/09fcc460794d515c48c38ccb47a936d58a2582b3)) +### Features -### Bug Fixes +- **build:** add `useWebFonts` option ([#1531](https://github.com/vuejs/vitepress/issues/1531)) ([c9f04e0](https://github.com/vuejs/vitepress/commit/c9f04e045922a6f1e11136bd1ccc824c2e9928f1)) +- support focus, colored diffs, error highlights in code blocks ([#1534](https://github.com/vuejs/vitepress/issues/1534)) ([04ab0eb](https://github.com/vuejs/vitepress/commit/04ab0eb6dcacb065e865332580088891bc2df893)) +- **theme:** add --vp-layout-top-height to adjust banner ([#1521](https://github.com/vuejs/vitepress/issues/1521)) ([a29a4a6](https://github.com/vuejs/vitepress/commit/a29a4a62c682b54ec88c609cb480ddb68b3f4699)) -* **build:** properly resolve node_modules ([#1337](https://github.com/vuejs/vitepress/issues/1337)) ([0672a69](https://github.com/vuejs/vitepress/commit/0672a696a427731851e1ed79fe689c4a2a46fedf)) -* **theme:** hide extra navbar when no content ([#1338](https://github.com/vuejs/vitepress/issues/1338)) ([4482c50](https://github.com/vuejs/vitepress/commit/4482c5019d89129791fe066f011648500d105f41)) -* **theme:** remove trailing `#` from outline ([#1344](https://github.com/vuejs/vitepress/issues/1344)) ([f1cf1e8](https://github.com/vuejs/vitepress/commit/f1cf1e800f0e99fe726bdfa7767180473faaf2c2)) +# [1.0.0-alpha.22](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.21...v1.0.0-alpha.22) (2022-10-22) +### Bug Fixes +- **types:** change ComponentOptions to DefineComponent ([#1499](https://github.com/vuejs/vitepress/issues/1499)) ([5711660](https://github.com/vuejs/vitepress/commit/57116607b83f79e62f399cd6430b0d80524861a3)) -# [1.0.0-alpha.14](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.13...v1.0.0-alpha.14) (2022-09-14) +### Features +- expose isDark ([#1525](https://github.com/vuejs/vitepress/issues/1525)) ([d327811](https://github.com/vuejs/vitepress/commit/d327811fd5b333a73d77730b6b0b347e3d052ebc)) +- **theme:** allow defining dark as the default theme ([#1498](https://github.com/vuejs/vitepress/issues/1498)) ([d404753](https://github.com/vuejs/vitepress/commit/d404753005bf4cc3bb645553ac473d08c6473180)) +- **theme:** support html strings for SidebarGroup headings, SidebarItem text ([#1489](https://github.com/vuejs/vitepress/issues/1489)) ([946c579](https://github.com/vuejs/vitepress/commit/946c579f2b8957839b8e0ef3474bded5ad06de1a)) +- transformPageData hook ([#1492](https://github.com/vuejs/vitepress/issues/1492)) ([afeb06f](https://github.com/vuejs/vitepress/commit/afeb06f17cbd439e3e0151f9571107754fe98b57)) -### Bug Fixes +# [1.0.0-alpha.21](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.20...v1.0.0-alpha.21) (2022-10-14) -* prevent jumping on clicking docsearch action buttons ([#1140](https://github.com/vuejs/vitepress/issues/1140)) ([86413e6](https://github.com/vuejs/vitepress/commit/86413e6739a834f8490c2004a62a27d1f5a59d00)) -* **theme:** break long words ([#1064](https://github.com/vuejs/vitepress/issues/1064)) ([9c739fd](https://github.com/vuejs/vitepress/commit/9c739fd37d15bbf16e8214e20a4bca1c763c4510)) -* **theme:** don't nest sidebar links ([#1279](https://github.com/vuejs/vitepress/issues/1279)) ([f840dbc](https://github.com/vuejs/vitepress/commit/f840dbc58f972492ed4afa9b6b222c4f7d89ade1)) -* **theme:** keep display copied hint when click multiple times ([#1262](https://github.com/vuejs/vitepress/issues/1262)) ([bb11d0f](https://github.com/vuejs/vitepress/commit/bb11d0f17852a3f2a35339f765acffca526a9ee8)) -* **theme:** show progress bar after delay ([#1278](https://github.com/vuejs/vitepress/issues/1278)) ([496bd34](https://github.com/vuejs/vitepress/commit/496bd34ff4143dcef9532f4298ca670bfa34e399)) -* **theme:** use pointer cursor only on enabled buttons ([#1300](https://github.com/vuejs/vitepress/issues/1300)) ([d7eac98](https://github.com/vuejs/vitepress/commit/d7eac980e15510de18dbf1fd675a6c1def5f6697)) -* **theme:** use pointer-events auto instead of all ([#1290](https://github.com/vuejs/vitepress/issues/1290)) ([6fac5b2](https://github.com/vuejs/vitepress/commit/6fac5b2964e77462edc963811ee1714e337fa53e)) -* **types:** allow non async `transformHtml` and `buildEnd` ([#1270](https://github.com/vuejs/vitepress/issues/1270)) ([ee37eaa](https://github.com/vuejs/vitepress/commit/ee37eaa27191faad03c04d60fb3ca8ffbb887fbe)) +### Bug Fixes +- **build:** better align server and client side filename sanitization ([3fd20fe](https://github.com/vuejs/vitepress/commit/3fd20fedb81c88c188cff22b4c03ccc2ad416d2c)) +- **theme:** match switch background transition with page transition ([#1479](https://github.com/vuejs/vitepress/issues/1479)) ([962065a](https://github.com/vuejs/vitepress/commit/962065a46ee1ef34eccbffbde9e65d7f174f8ab1)) +- **theme:** prevent body scrolling when sidebar has opened on small screens ([#1391](https://github.com/vuejs/vitepress/issues/1391)) ([3daabdc](https://github.com/vuejs/vitepress/commit/3daabdc480c0cc10a12a83a08a734f8719d092c5)) ### Features -* add `transformHead` hook ([#1323](https://github.com/vuejs/vitepress/issues/1323)) ([6b16dad](https://github.com/vuejs/vitepress/commit/6b16dad22f944cb173dbf67ef04be5cb0d09279f)) -* add `vp-raw` container ([#1104](https://github.com/vuejs/vitepress/issues/1104)) ([9a6e1ea](https://github.com/vuejs/vitepress/commit/9a6e1ea401c4a44205f96c4786c44061582f675c)) -* bundle type definitions of dev-deps ([#1257](https://github.com/vuejs/vitepress/issues/1257)) ([12591a9](https://github.com/vuejs/vitepress/commit/12591a9487ff7647162051f4b28956f0c1403efb)) -* **theme:** add page load progress bar ([#1264](https://github.com/vuejs/vitepress/issues/1264)) ([ecf5515](https://github.com/vuejs/vitepress/commit/ecf5515bd453eca20946339a56be9180f6dca2c1)) -* **theme:** allow disabling whole layout ([#1268](https://github.com/vuejs/vitepress/issues/1268)) ([8f63033](https://github.com/vuejs/vitepress/commit/8f630339ba95cbaded97f0fcff9323755dd16bcc)) -* **theme:** support dynamic headers and nesting in outline ([#1281](https://github.com/vuejs/vitepress/issues/1281)) ([288aa48](https://github.com/vuejs/vitepress/commit/288aa48b92bc1d4dd74d064148a3b03373cdf1c3)) - +- **theme:** allow specifying common alt for logo ([#1451](https://github.com/vuejs/vitepress/issues/1451)) ([55688a8](https://github.com/vuejs/vitepress/commit/55688a87e3baa38d0e0a37a6eba0039484416875)) -### Performance Improvements +# [1.0.0-alpha.20](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.19...v1.0.0-alpha.20) (2022-10-12) -* **a11y:** add aria-checked attribute to switch ([#644](https://github.com/vuejs/vitepress/issues/644)) ([eb9026d](https://github.com/vuejs/vitepress/commit/eb9026d83ca17c59893e7063e0c64b0bf1b99765)) -* render pages asynchronously ([#1320](https://github.com/vuejs/vitepress/issues/1320)) ([8e4ff4d](https://github.com/vuejs/vitepress/commit/8e4ff4de901d846ac99d37ebf212b12e9687ed5e)) +### Bug Fixes +- **a11y:** add title to copy code button ([#1437](https://github.com/vuejs/vitepress/issues/1437)) ([f79bb78](https://github.com/vuejs/vitepress/commit/f79bb78bf7f472d9bc376a3ec393f731bfe9e7ce)) +- **router:** don't intercept download links ([#1452](https://github.com/vuejs/vitepress/issues/1452)) ([54cf6ce](https://github.com/vuejs/vitepress/commit/54cf6ce51fcf8ce91c0706332e0b51ddcc2b519d)) +- **theme:** disable transitions on theme toggle ([#1447](https://github.com/vuejs/vitepress/issues/1447)) ([067e1a9](https://github.com/vuejs/vitepress/commit/067e1a97434f88835dbfedcf18e2f98d8bfacad9)) +- **theme:** make text prop of VPHero optional ([#1445](https://github.com/vuejs/vitepress/issues/1445)) ([95e4f2a](https://github.com/vuejs/vitepress/commit/95e4f2acc9614360fbfe37450028d2067e5993b8)) ### Reverts -* **#1264:** add page load progress bar ([#1311](https://github.com/vuejs/vitepress/issues/1311)) ([5378a49](https://github.com/vuejs/vitepress/commit/5378a49613ceef591d2cacecbc175921658b22b1)), closes [#1264](https://github.com/vuejs/vitepress/issues/1264) +- "fix(build): remove leading underscore from chunks" ([#1471](https://github.com/vuejs/vitepress/issues/1471)) ([18f0fb4](https://github.com/vuejs/vitepress/commit/18f0fb4e3989192ba95a397476371a945bf84542)) +# [1.0.0-alpha.19](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.18...v1.0.0-alpha.19) (2022-10-02) +### Bug Fixes -# [1.0.0-alpha.13](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.12...v1.0.0-alpha.13) (2022-08-30) +- **build:** ignore tsconfig target in dev ([#1428](https://github.com/vuejs/vitepress/issues/1428)) ([a13bc86](https://github.com/vuejs/vitepress/commit/a13bc866d0af911256e0629136f4b48e88c44df1)) +# [1.0.0-alpha.18](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.17...v1.0.0-alpha.18) (2022-10-01) -### Features +### Bug Fixes -* use global delegation for copy code interaction ([b5bd73f](https://github.com/vuejs/vitepress/commit/b5bd73f6300e458d419d3a7816272d3c7244a4d3)) +- **theme:** break long words on overflow ([#1405](https://github.com/vuejs/vitepress/issues/1405)) ([2114d13](https://github.com/vuejs/vitepress/commit/2114d1326a9d3b952ca8a150f1c27c89169629cc)) +# [1.0.0-alpha.17](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.16...v1.0.0-alpha.17) (2022-09-27) +### Bug Fixes -# [1.0.0-alpha.12](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.11...v1.0.0-alpha.12) (2022-08-26) +- **theme:** add cursor for collapsible sidebar title ([#1397](https://github.com/vuejs/vitepress/issues/1397)) ([ed37b9a](https://github.com/vuejs/vitepress/commit/ed37b9a0e04f85f941131ec9e2ca8b145d89a535)) +- **theme:** remove extra space before docsearch key ([#1396](https://github.com/vuejs/vitepress/issues/1396)) ([6cb79bb](https://github.com/vuejs/vitepress/commit/6cb79bbe6a26f2e8dbd4b07b3fb5b6377f06958d)) +### Reverts +- [#1064](https://github.com/vuejs/vitepress/issues/1064) ([9d70ca5](https://github.com/vuejs/vitepress/commit/9d70ca56f147a2ec30d12b03353ea7e4b0850df0)) -# [1.0.0-alpha.11](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.10...v1.0.0-alpha.11) (2022-08-26) +# [1.0.0-alpha.16](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.15...v1.0.0-alpha.16) (2022-09-24) +### Bug Fixes + +- **build:** line numbers mode when language specifier has symbol ([#1353](https://github.com/vuejs/vitepress/issues/1353)) ([9c04a10](https://github.com/vuejs/vitepress/commit/9c04a10c4d9fbfc591dc2386b4780a6728f6364a)) +- **build:** remove leading underscore from chunks ([#1394](https://github.com/vuejs/vitepress/issues/1394)) ([66cd164](https://github.com/vuejs/vitepress/commit/66cd1640d16170e0c2d9eb4565ad1ebe81f940e1)) +- **compat:** use default export of dns module ([#1388](https://github.com/vuejs/vitepress/issues/1388)) ([fa6fa56](https://github.com/vuejs/vitepress/commit/fa6fa56af9de78856017f935922e4f2f9376be62)) +- **theme:** always add alt attribute to images ([#1348](https://github.com/vuejs/vitepress/issues/1348)) ([a621c69](https://github.com/vuejs/vitepress/commit/a621c6910c0083adc26dd4b7aaa7d532544cc7fa)) ### Features -* support markdown sfc options ([#1238](https://github.com/vuejs/vitepress/issues/1238)) ([d700a66](https://github.com/vuejs/vitepress/commit/d700a66e65c9c457e44c9272362be36a2002eaf7)) +- **build:** allow using `transformIndexHtml` ([#1380](https://github.com/vuejs/vitepress/issues/1380)) ([ce8d139](https://github.com/vuejs/vitepress/commit/ce8d139a8e70e4d0a8d06711c50119990b041078)) +# [1.0.0-alpha.15](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.14...v1.0.0-alpha.15) (2022-09-15) +### Bug Fixes -# [1.0.0-alpha.10](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.9...v1.0.0-alpha.10) (2022-08-22) +- **build:** properly resolve node_modules ([#1337](https://github.com/vuejs/vitepress/issues/1337)) ([0672a69](https://github.com/vuejs/vitepress/commit/0672a696a427731851e1ed79fe689c4a2a46fedf)) +- **theme:** hide extra navbar when no content ([#1338](https://github.com/vuejs/vitepress/issues/1338)) ([4482c50](https://github.com/vuejs/vitepress/commit/4482c5019d89129791fe066f011648500d105f41)) +- **theme:** remove trailing `#` from outline ([#1344](https://github.com/vuejs/vitepress/issues/1344)) ([f1cf1e8](https://github.com/vuejs/vitepress/commit/f1cf1e800f0e99fe726bdfa7767180473faaf2c2)) +# [1.0.0-alpha.14](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.13...v1.0.0-alpha.14) (2022-09-14) ### Bug Fixes -* avoid circular deps when extending default theme + importing feature components ([5fb7948](https://github.com/vuejs/vitepress/commit/5fb794864b20c59729686aa7e19f0e5659c6534f)), closes [#1210](https://github.com/vuejs/vitepress/issues/1210) - +- prevent jumping on clicking docsearch action buttons ([#1140](https://github.com/vuejs/vitepress/issues/1140)) ([86413e6](https://github.com/vuejs/vitepress/commit/86413e6739a834f8490c2004a62a27d1f5a59d00)) +- **theme:** break long words ([#1064](https://github.com/vuejs/vitepress/issues/1064)) ([9c739fd](https://github.com/vuejs/vitepress/commit/9c739fd37d15bbf16e8214e20a4bca1c763c4510)) +- **theme:** don't nest sidebar links ([#1279](https://github.com/vuejs/vitepress/issues/1279)) ([f840dbc](https://github.com/vuejs/vitepress/commit/f840dbc58f972492ed4afa9b6b222c4f7d89ade1)) +- **theme:** keep display copied hint when click multiple times ([#1262](https://github.com/vuejs/vitepress/issues/1262)) ([bb11d0f](https://github.com/vuejs/vitepress/commit/bb11d0f17852a3f2a35339f765acffca526a9ee8)) +- **theme:** show progress bar after delay ([#1278](https://github.com/vuejs/vitepress/issues/1278)) ([496bd34](https://github.com/vuejs/vitepress/commit/496bd34ff4143dcef9532f4298ca670bfa34e399)) +- **theme:** use pointer cursor only on enabled buttons ([#1300](https://github.com/vuejs/vitepress/issues/1300)) ([d7eac98](https://github.com/vuejs/vitepress/commit/d7eac980e15510de18dbf1fd675a6c1def5f6697)) +- **theme:** use pointer-events auto instead of all ([#1290](https://github.com/vuejs/vitepress/issues/1290)) ([6fac5b2](https://github.com/vuejs/vitepress/commit/6fac5b2964e77462edc963811ee1714e337fa53e)) +- **types:** allow non async `transformHtml` and `buildEnd` ([#1270](https://github.com/vuejs/vitepress/issues/1270)) ([ee37eaa](https://github.com/vuejs/vitepress/commit/ee37eaa27191faad03c04d60fb3ca8ffbb887fbe)) ### Features -* **build:** support markdown frontmatter options ([#1218](https://github.com/vuejs/vitepress/issues/1218)) ([bfb0220](https://github.com/vuejs/vitepress/commit/bfb02209896075483b7c9a8c1ca3d36de0a0b731)) +- add `transformHead` hook ([#1323](https://github.com/vuejs/vitepress/issues/1323)) ([6b16dad](https://github.com/vuejs/vitepress/commit/6b16dad22f944cb173dbf67ef04be5cb0d09279f)) +- add `vp-raw` container ([#1104](https://github.com/vuejs/vitepress/issues/1104)) ([9a6e1ea](https://github.com/vuejs/vitepress/commit/9a6e1ea401c4a44205f96c4786c44061582f675c)) +- bundle type definitions of dev-deps ([#1257](https://github.com/vuejs/vitepress/issues/1257)) ([12591a9](https://github.com/vuejs/vitepress/commit/12591a9487ff7647162051f4b28956f0c1403efb)) +- **theme:** add page load progress bar ([#1264](https://github.com/vuejs/vitepress/issues/1264)) ([ecf5515](https://github.com/vuejs/vitepress/commit/ecf5515bd453eca20946339a56be9180f6dca2c1)) +- **theme:** allow disabling whole layout ([#1268](https://github.com/vuejs/vitepress/issues/1268)) ([8f63033](https://github.com/vuejs/vitepress/commit/8f630339ba95cbaded97f0fcff9323755dd16bcc)) +- **theme:** support dynamic headers and nesting in outline ([#1281](https://github.com/vuejs/vitepress/issues/1281)) ([288aa48](https://github.com/vuejs/vitepress/commit/288aa48b92bc1d4dd74d064148a3b03373cdf1c3)) +### Performance Improvements +- **a11y:** add aria-checked attribute to switch ([#644](https://github.com/vuejs/vitepress/issues/644)) ([eb9026d](https://github.com/vuejs/vitepress/commit/eb9026d83ca17c59893e7063e0c64b0bf1b99765)) +- render pages asynchronously ([#1320](https://github.com/vuejs/vitepress/issues/1320)) ([8e4ff4d](https://github.com/vuejs/vitepress/commit/8e4ff4de901d846ac99d37ebf212b12e9687ed5e)) -# [1.0.0-alpha.9](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.8...v1.0.0-alpha.9) (2022-08-20) +### Reverts +- **#1264:** add page load progress bar ([#1311](https://github.com/vuejs/vitepress/issues/1311)) ([5378a49](https://github.com/vuejs/vitepress/commit/5378a49613ceef591d2cacecbc175921658b22b1)), closes [#1264](https://github.com/vuejs/vitepress/issues/1264) -### Bug Fixes +# [1.0.0-alpha.13](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.12...v1.0.0-alpha.13) (2022-08-30) + +### Features -* **theme:** fix typo in carbon ads components ([#1192](https://github.com/vuejs/vitepress/issues/1192)) ([e0932ce](https://github.com/vuejs/vitepress/commit/e0932ce5f49535fb28c6b6e4d17b888dd09187dc)) -* **theme:** show footer message/copyright only if present ([#1191](https://github.com/vuejs/vitepress/issues/1191)) ([da2f8d2](https://github.com/vuejs/vitepress/commit/da2f8d28a6993b099a97b01ab2ff94104e84190c)) -* **theme:** show outline even without sidebar ([#1189](https://github.com/vuejs/vitepress/issues/1189)) ([3714ea3](https://github.com/vuejs/vitepress/commit/3714ea34635e69aa96de3da5f3cbc5b6198fdbc2)) -* **types:** explicitly re-export to resolve ambiguities ([#1193](https://github.com/vuejs/vitepress/issues/1193)) ([eacc18c](https://github.com/vuejs/vitepress/commit/eacc18c993cefa2922c13826c1d0498a9eafc4d1)) -* use junctions in Windows ([#1217](https://github.com/vuejs/vitepress/issues/1217)) ([0e14211](https://github.com/vuejs/vitepress/commit/0e14211b609c4694c7654ce381998ce751230480)) +- use global delegation for copy code interaction ([b5bd73f](https://github.com/vuejs/vitepress/commit/b5bd73f6300e458d419d3a7816272d3c7244a4d3)) +# [1.0.0-alpha.12](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.11...v1.0.0-alpha.12) (2022-08-26) + +# [1.0.0-alpha.11](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.10...v1.0.0-alpha.11) (2022-08-26) ### Features -* **theme:** extend titleTemplate by replacing the title ([#1200](https://github.com/vuejs/vitepress/issues/1200)) ([c7def73](https://github.com/vuejs/vitepress/commit/c7def730c3d9266e7573b91e16e00dd2f3f3350b)) +- support markdown sfc options ([#1238](https://github.com/vuejs/vitepress/issues/1238)) ([d700a66](https://github.com/vuejs/vitepress/commit/d700a66e65c9c457e44c9272362be36a2002eaf7)) +# [1.0.0-alpha.10](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.9...v1.0.0-alpha.10) (2022-08-22) +### Bug Fixes -# [1.0.0-alpha.8](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.7...v1.0.0-alpha.8) (2022-08-17) +- avoid circular deps when extending default theme + importing feature components ([5fb7948](https://github.com/vuejs/vitepress/commit/5fb794864b20c59729686aa7e19f0e5659c6534f)), closes [#1210](https://github.com/vuejs/vitepress/issues/1210) +### Features -### Bug Fixes +- **build:** support markdown frontmatter options ([#1218](https://github.com/vuejs/vitepress/issues/1218)) ([bfb0220](https://github.com/vuejs/vitepress/commit/bfb02209896075483b7c9a8c1ca3d36de0a0b731)) -* fix client build entry ([04c4d0f](https://github.com/vuejs/vitepress/commit/04c4d0f01b6cb67fe842d9a88f8810f6959eb3ca)) +# [1.0.0-alpha.9](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.8...v1.0.0-alpha.9) (2022-08-20) +### Bug Fixes +- **theme:** fix typo in carbon ads components ([#1192](https://github.com/vuejs/vitepress/issues/1192)) ([e0932ce](https://github.com/vuejs/vitepress/commit/e0932ce5f49535fb28c6b6e4d17b888dd09187dc)) +- **theme:** show footer message/copyright only if present ([#1191](https://github.com/vuejs/vitepress/issues/1191)) ([da2f8d2](https://github.com/vuejs/vitepress/commit/da2f8d28a6993b099a97b01ab2ff94104e84190c)) +- **theme:** show outline even without sidebar ([#1189](https://github.com/vuejs/vitepress/issues/1189)) ([3714ea3](https://github.com/vuejs/vitepress/commit/3714ea34635e69aa96de3da5f3cbc5b6198fdbc2)) +- **types:** explicitly re-export to resolve ambiguities ([#1193](https://github.com/vuejs/vitepress/issues/1193)) ([eacc18c](https://github.com/vuejs/vitepress/commit/eacc18c993cefa2922c13826c1d0498a9eafc4d1)) +- use junctions in Windows ([#1217](https://github.com/vuejs/vitepress/issues/1217)) ([0e14211](https://github.com/vuejs/vitepress/commit/0e14211b609c4694c7654ce381998ce751230480)) -# [1.0.0-alpha.7](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.6...v1.0.0-alpha.7) (2022-08-17) +### Features + +- **theme:** extend titleTemplate by replacing the title ([#1200](https://github.com/vuejs/vitepress/issues/1200)) ([c7def73](https://github.com/vuejs/vitepress/commit/c7def730c3d9266e7573b91e16e00dd2f3f3350b)) +# [1.0.0-alpha.8](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.7...v1.0.0-alpha.8) (2022-08-17) ### Bug Fixes -* fix static data file support in vite 3 ([19ec22c](https://github.com/vuejs/vitepress/commit/19ec22cb4055e903b28ee70d606163b49009ef59)) +- fix client build entry ([04c4d0f](https://github.com/vuejs/vitepress/commit/04c4d0f01b6cb67fe842d9a88f8810f6959eb3ca)) +# [1.0.0-alpha.7](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.6...v1.0.0-alpha.7) (2022-08-17) +### Bug Fixes + +- fix static data file support in vite 3 ([19ec22c](https://github.com/vuejs/vitepress/commit/19ec22cb4055e903b28ee70d606163b49009ef59)) # [1.0.0-alpha.6](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.5...v1.0.0-alpha.6) (2022-08-17) ### Breaking Changes -* `/@theme` import alias has been removed. Use `@theme` instead. +- `/@theme` import alias has been removed. Use `@theme` instead. ### Bug Fixes -* **theme:** remove extra padding in code blocks with line numbers ([f6d6c62](https://github.com/vuejs/vitepress/commit/f6d6c6211708d54fb60b89583fe1665aedd9c22f)) -* **theme:** restore styles for code blocks ([#1170](https://github.com/vuejs/vitepress/issues/1170)) ([2c89afb](https://github.com/vuejs/vitepress/commit/2c89afb7ddfeb04f947f95f9ecf636a384492ba8)) -* **theme:** set pointer events all on VPNavScreen ([#1182](https://github.com/vuejs/vitepress/issues/1182)) ([b36656a](https://github.com/vuejs/vitepress/commit/b36656a925b30ce5c85a78d6ae3b686917895822)) - +- **theme:** remove extra padding in code blocks with line numbers ([f6d6c62](https://github.com/vuejs/vitepress/commit/f6d6c6211708d54fb60b89583fe1665aedd9c22f)) +- **theme:** restore styles for code blocks ([#1170](https://github.com/vuejs/vitepress/issues/1170)) ([2c89afb](https://github.com/vuejs/vitepress/commit/2c89afb7ddfeb04f947f95f9ecf636a384492ba8)) +- **theme:** set pointer events all on VPNavScreen ([#1182](https://github.com/vuejs/vitepress/issues/1182)) ([b36656a](https://github.com/vuejs/vitepress/commit/b36656a925b30ce5c85a78d6ae3b686917895822)) ### Features -* **build:** switch to vite 3, support clean urls and esm mode ([#856](https://github.com/vuejs/vitepress/issues/856)) ([0048e2b](https://github.com/vuejs/vitepress/commit/0048e2bf1e7ef0bf0a4b66bcdd49f9dc84074b2d)) - - +- **build:** switch to vite 3, support clean urls and esm mode ([#856](https://github.com/vuejs/vitepress/issues/856)) ([0048e2b](https://github.com/vuejs/vitepress/commit/0048e2bf1e7ef0bf0a4b66bcdd49f9dc84074b2d)) # [1.0.0-alpha.5](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.4...v1.0.0-alpha.5) (2022-08-16) - ### Bug Fixes -* **build:** cache key should consider file path ([#948](https://github.com/vuejs/vitepress/issues/948)) ([1daeaa1](https://github.com/vuejs/vitepress/commit/1daeaa16a038cfa927a24bb970ad62c524aed6cf)) -* **build:** handle vite constants replacement ([#419](https://github.com/vuejs/vitepress/issues/419)) ([#888](https://github.com/vuejs/vitepress/issues/888)) ([9d9db62](https://github.com/vuejs/vitepress/commit/9d9db6227dff40734bf7129abb69f26412424486)) -* **build:** recreate server on config change ([#1132](https://github.com/vuejs/vitepress/issues/1132)) ([93fe820](https://github.com/vuejs/vitepress/commit/93fe8207e7993d62a167af752a8da3c30388f642)) -* **build:** show workaround on encountering dead links ([#822](https://github.com/vuejs/vitepress/issues/822)) ([#868](https://github.com/vuejs/vitepress/issues/868)) ([29d44e7](https://github.com/vuejs/vitepress/commit/29d44e7a2201d43227758745e1e3a14858224736)) -* **build:** strip custom anchor with capital letters in outline ([#1005](https://github.com/vuejs/vitepress/issues/1005)) ([f6d5697](https://github.com/vuejs/vitepress/commit/f6d5697ed7f247e8673614f4e0ff7232e808ef1e)) -* **build:** update language regex for line number class ([#1108](https://github.com/vuejs/vitepress/issues/1108)) ([708c361](https://github.com/vuejs/vitepress/commit/708c36183a925e06c13b9b04ed03af073c315978)) -* can't detect that the page has scrolled to the bottom ([#956](https://github.com/vuejs/vitepress/issues/956)) ([#970](https://github.com/vuejs/vitepress/issues/970)) ([98e45af](https://github.com/vuejs/vitepress/commit/98e45af127a11bfff3577fe5675788e5479f9d79)) -* de-duplicate head tags while merging ([#975](https://github.com/vuejs/vitepress/issues/975)) ([#976](https://github.com/vuejs/vitepress/issues/976)) ([f7e9cfe](https://github.com/vuejs/vitepress/commit/f7e9cfeb3a06ec93726870dd17116a019959d980)) -* decode href before using as query selector ([#951](https://github.com/vuejs/vitepress/issues/951)) ([22006e8](https://github.com/vuejs/vitepress/commit/22006e8d6e3ed45841979d684eb6a4ef999bd707)) -* decode image src so that rollup can process it ([#933](https://github.com/vuejs/vitepress/issues/933)) ([bb41a9f](https://github.com/vuejs/vitepress/commit/bb41a9fed771a5bdfc73b1bbe5200d11c3630367)) -* don't add base to external urls while preloading ([#1045](https://github.com/vuejs/vitepress/issues/1045)) ([7295033](https://github.com/vuejs/vitepress/commit/72950337bc31fd2f8879d6a2f219018a18b29727)) -* don't change url hash while scrolling ([#991](https://github.com/vuejs/vitepress/issues/991)) ([0826944](https://github.com/vuejs/vitepress/commit/082694470a15e50c5d000936572856a574409ea5)) -* layout inconsistencies and remove sidebar from 404 page ([#964](https://github.com/vuejs/vitepress/issues/964)) ([0257ea8](https://github.com/vuejs/vitepress/commit/0257ea88dca09ced9c1dc6e53ba5f133c468df19)) -* line highlighting in custom code block ([#959](https://github.com/vuejs/vitepress/issues/959)) ([#969](https://github.com/vuejs/vitepress/issues/969)) ([7a9e4d9](https://github.com/vuejs/vitepress/commit/7a9e4d9ee02cc677f1b84cc5f2c1f8f385c3a65c)) -* normalize link in VPButton ([#919](https://github.com/vuejs/vitepress/issues/919)) ([bed68f1](https://github.com/vuejs/vitepress/commit/bed68f134186e4fd3c0bca4c6a5871a79e4cd224)) -* only check for duplicate meta tags ([#977](https://github.com/vuejs/vitepress/issues/977)) ([1ef7a18](https://github.com/vuejs/vitepress/commit/1ef7a1857c2a8e2abc7c1859cd54504c144eab3b)), closes [/github.com/vuejs/vitepress/issues/975#issuecomment-1183507200](https://github.com//github.com/vuejs/vitepress/issues/975/issues/issuecomment-1183507200) -* regression caused by [#887](https://github.com/vuejs/vitepress/issues/887) ([30249dc](https://github.com/vuejs/vitepress/commit/30249dc2c3d933dadf6e22e64728a6ffd3647f8e)) -* remove duplicate router logic ([#1087](https://github.com/vuejs/vitepress/issues/1087)) ([63584c2](https://github.com/vuejs/vitepress/commit/63584c2812d2c5172356ef2615ac608684d52681)) -* remove explicit noopener from external links ([#871](https://github.com/vuejs/vitepress/issues/871)) ([e4c60ab](https://github.com/vuejs/vitepress/commit/e4c60ab3c834fe7f730cd7b0d64dd23c6d04dbed)) -* support urls with query during dev ([35b7361](https://github.com/vuejs/vitepress/commit/35b7361ca2c689f0fb464ab9cbab8bb02e4884d5)) -* **theme:** change sponsor link class name to bypass adblock ([#866](https://github.com/vuejs/vitepress/issues/866)) ([#867](https://github.com/vuejs/vitepress/issues/867)) ([e33955e](https://github.com/vuejs/vitepress/commit/e33955e7696af2de2d9ed53d53a06aa5de17f3ce)) -* **theme:** close menu on route change ([#887](https://github.com/vuejs/vitepress/issues/887)) ([fcd7642](https://github.com/vuejs/vitepress/commit/fcd7642924331e81e85ee75a1224a04d1882531c)) -* **theme:** don't let navbar obstruct clicks to top part of scrollbar ([#1168](https://github.com/vuejs/vitepress/issues/1168)) ([44953dc](https://github.com/vuejs/vitepress/commit/44953dcd1e0224bae95666c87e368b9d3fdf17ae)) -* **theme:** fix custom NotFound component rendering ([#1163](https://github.com/vuejs/vitepress/issues/1163)) ([4a6eda4](https://github.com/vuejs/vitepress/commit/4a6eda48704ad34e003d144594bbc56c1b448c6d)) -* **theme:** hide doc footer if empty ([#1126](https://github.com/vuejs/vitepress/issues/1126)) ([70da5f2](https://github.com/vuejs/vitepress/commit/70da5f275bc44ce4e6ed97af40cf30d6971ee378)) -* **theme:** make last updated time reactive ([#879](https://github.com/vuejs/vitepress/issues/879)) ([25a835f](https://github.com/vuejs/vitepress/commit/25a835f0f437a2181f67dbcefa17546dbcb833de)) -* **theme:** navbar menu may exceed the screen ([#988](https://github.com/vuejs/vitepress/issues/988)) ([#989](https://github.com/vuejs/vitepress/issues/989)) ([8a46413](https://github.com/vuejs/vitepress/commit/8a46413d6fa6ff671f780b60c7bc6380d84dc25d)) -* **theme:** prevent docsearch button key from changing ([#986](https://github.com/vuejs/vitepress/issues/986)) ([d65667b](https://github.com/vuejs/vitepress/commit/d65667b8d49a11fccee6bc0cd06a75333a65f22c)) -* **theme:** tweak styles of nav title ([#962](https://github.com/vuejs/vitepress/issues/962)) ([#968](https://github.com/vuejs/vitepress/issues/968)) ([d91f3b1](https://github.com/vuejs/vitepress/commit/d91f3b1b7d46db8009bb459079794b0626488033)) -* **theme:** typo in color name ([#1020](https://github.com/vuejs/vitepress/issues/1020)) ([4b38736](https://github.com/vuejs/vitepress/commit/4b38736adf2853276f573a1980a213a17cf2c740)) -* treat all URI schemes as external ([#945](https://github.com/vuejs/vitepress/issues/945)) ([#946](https://github.com/vuejs/vitepress/issues/946)) ([1e9a7ac](https://github.com/vuejs/vitepress/commit/1e9a7ac6c478c57d7336e2d7b0392f23659080d3)) -* **types:** add client and theme to `exports` field ([#914](https://github.com/vuejs/vitepress/issues/914)) ([1cc087d](https://github.com/vuejs/vitepress/commit/1cc087deeee5f6c8289259bb7a2695ed75f287c3)) -* **types:** fix broken syntax in `theme.d.ts` ([#1101](https://github.com/vuejs/vitepress/issues/1101)) ([70b3060](https://github.com/vuejs/vitepress/commit/70b3060be963ed7a0d2041446d67ac970d6f35e3)) -* use `router.go` if search string is not same ([#1109](https://github.com/vuejs/vitepress/issues/1109)) ([5597165](https://github.com/vuejs/vitepress/commit/55971659a5c4b25cb07968ca4e162abc11fe2e80)) - - -### Features - -* allow adding custom social icons as inline svg ([#738](https://github.com/vuejs/vitepress/issues/738)) ([#953](https://github.com/vuejs/vitepress/issues/953)) ([74e4950](https://github.com/vuejs/vitepress/commit/74e4950c1b83f2e0c8659477c7b2763fa150b349)) -* allow html in footer ([#1034](https://github.com/vuejs/vitepress/issues/1034)) ([ad9af83](https://github.com/vuejs/vitepress/commit/ad9af83278d702a76f674f847b383370b3921256)) -* allow using custom syntax highlighting themes ([#992](https://github.com/vuejs/vitepress/issues/992)) ([d5ed66c](https://github.com/vuejs/vitepress/commit/d5ed66c6d21ec3b5e17469771057132c53220bea)) -* **build:** allow ignoring dead links ([#586](https://github.com/vuejs/vitepress/issues/586)) ([#793](https://github.com/vuejs/vitepress/issues/793)) ([19b0758](https://github.com/vuejs/vitepress/commit/19b0758a04e9fb7863b3a961024dfe1137fbe928)) -* **build:** allow using custom highlighter ([#754](https://github.com/vuejs/vitepress/issues/754)) ([#857](https://github.com/vuejs/vitepress/issues/857)) ([ddf876d](https://github.com/vuejs/vitepress/commit/ddf876d8e90e812a198bb417a5dc60cd443a8273)) -* **build:** handle change of config file dependencies ([#1009](https://github.com/vuejs/vitepress/issues/1009)) ([8e6665b](https://github.com/vuejs/vitepress/commit/8e6665bd8de66a8249fca92fbb1b9a4f6d76a041)) -* **build:** improve code blocks and snippets ([#875](https://github.com/vuejs/vitepress/issues/875)) ([f789932](https://github.com/vuejs/vitepress/commit/f789932ffc79723a90b3b19a59d6f277d9edaaa9)), closes [#861](https://github.com/vuejs/vitepress/issues/861) [#471](https://github.com/vuejs/vitepress/issues/471) [#884](https://github.com/vuejs/vitepress/issues/884) -* **build:** support code highlight in uppercase ([#1082](https://github.com/vuejs/vitepress/issues/1082)) ([867f305](https://github.com/vuejs/vitepress/commit/867f30588687c4f9228c1511bee672074e54c802)), closes [#772](https://github.com/vuejs/vitepress/issues/772) -* provide `transformHtml` hook ([#1022](https://github.com/vuejs/vitepress/issues/1022)) ([2b4b800](https://github.com/vuejs/vitepress/commit/2b4b80061818f1c471aafb23c0572172ef842138)) -* provide build end hook ([#709](https://github.com/vuejs/vitepress/issues/709)) ([e0b730a](https://github.com/vuejs/vitepress/commit/e0b730aa8ee9bec1fe16245c4c1a1a91f62bed42)) -* **theme:** add `doc-footer-before` slot ([#1050](https://github.com/vuejs/vitepress/issues/1050)) ([#1052](https://github.com/vuejs/vitepress/issues/1052)) ([60c515c](https://github.com/vuejs/vitepress/commit/60c515c1255085d73845d2b2cc315823ee18e7b8)) -* **theme:** add navigation slots ([#739](https://github.com/vuejs/vitepress/issues/739)) ([#741](https://github.com/vuejs/vitepress/issues/741)) ([0f0453c](https://github.com/vuejs/vitepress/commit/0f0453c6750c5af9c1ae65abb994813eecf9af27)) -* **theme:** add option to customize search button text ([#713](https://github.com/vuejs/vitepress/issues/713)) ([#747](https://github.com/vuejs/vitepress/issues/747)) ([00fe809](https://github.com/vuejs/vitepress/commit/00fe8092d9e097d2dd24c06787fcb740310bdda7)) -* **theme:** auto open collapsed sidebar on entering ([#1094](https://github.com/vuejs/vitepress/issues/1094)) ([f4f1a6c](https://github.com/vuejs/vitepress/commit/f4f1a6ccd62ea52c03b2c342c649f0f06f466126)) -* **theme:** custom prev/next labels and text ([#897](https://github.com/vuejs/vitepress/issues/897)) ([836a246](https://github.com/vuejs/vitepress/commit/836a24683a19eefbc98d6c448c26e3696a679e7c)) -* **theme:** support hiding aside component from frontmatter ([#980](https://github.com/vuejs/vitepress/issues/980)) ([69ef299](https://github.com/vuejs/vitepress/commit/69ef2998c37453ab9c0147e87dd9a6efb41a24a3)) -* **theme:** support multi-level sidebar ([#851](https://github.com/vuejs/vitepress/issues/851)) ([d1a2c76](https://github.com/vuejs/vitepress/commit/d1a2c76f33ab55ad8d43357b57c9ae3de55e9d0c)) - +- **build:** cache key should consider file path ([#948](https://github.com/vuejs/vitepress/issues/948)) ([1daeaa1](https://github.com/vuejs/vitepress/commit/1daeaa16a038cfa927a24bb970ad62c524aed6cf)) +- **build:** handle vite constants replacement ([#419](https://github.com/vuejs/vitepress/issues/419)) ([#888](https://github.com/vuejs/vitepress/issues/888)) ([9d9db62](https://github.com/vuejs/vitepress/commit/9d9db6227dff40734bf7129abb69f26412424486)) +- **build:** recreate server on config change ([#1132](https://github.com/vuejs/vitepress/issues/1132)) ([93fe820](https://github.com/vuejs/vitepress/commit/93fe8207e7993d62a167af752a8da3c30388f642)) +- **build:** show workaround on encountering dead links ([#822](https://github.com/vuejs/vitepress/issues/822)) ([#868](https://github.com/vuejs/vitepress/issues/868)) ([29d44e7](https://github.com/vuejs/vitepress/commit/29d44e7a2201d43227758745e1e3a14858224736)) +- **build:** strip custom anchor with capital letters in outline ([#1005](https://github.com/vuejs/vitepress/issues/1005)) ([f6d5697](https://github.com/vuejs/vitepress/commit/f6d5697ed7f247e8673614f4e0ff7232e808ef1e)) +- **build:** update language regex for line number class ([#1108](https://github.com/vuejs/vitepress/issues/1108)) ([708c361](https://github.com/vuejs/vitepress/commit/708c36183a925e06c13b9b04ed03af073c315978)) +- can't detect that the page has scrolled to the bottom ([#956](https://github.com/vuejs/vitepress/issues/956)) ([#970](https://github.com/vuejs/vitepress/issues/970)) ([98e45af](https://github.com/vuejs/vitepress/commit/98e45af127a11bfff3577fe5675788e5479f9d79)) +- de-duplicate head tags while merging ([#975](https://github.com/vuejs/vitepress/issues/975)) ([#976](https://github.com/vuejs/vitepress/issues/976)) ([f7e9cfe](https://github.com/vuejs/vitepress/commit/f7e9cfeb3a06ec93726870dd17116a019959d980)) +- decode href before using as query selector ([#951](https://github.com/vuejs/vitepress/issues/951)) ([22006e8](https://github.com/vuejs/vitepress/commit/22006e8d6e3ed45841979d684eb6a4ef999bd707)) +- decode image src so that rollup can process it ([#933](https://github.com/vuejs/vitepress/issues/933)) ([bb41a9f](https://github.com/vuejs/vitepress/commit/bb41a9fed771a5bdfc73b1bbe5200d11c3630367)) +- don't add base to external urls while preloading ([#1045](https://github.com/vuejs/vitepress/issues/1045)) ([7295033](https://github.com/vuejs/vitepress/commit/72950337bc31fd2f8879d6a2f219018a18b29727)) +- don't change url hash while scrolling ([#991](https://github.com/vuejs/vitepress/issues/991)) ([0826944](https://github.com/vuejs/vitepress/commit/082694470a15e50c5d000936572856a574409ea5)) +- layout inconsistencies and remove sidebar from 404 page ([#964](https://github.com/vuejs/vitepress/issues/964)) ([0257ea8](https://github.com/vuejs/vitepress/commit/0257ea88dca09ced9c1dc6e53ba5f133c468df19)) +- line highlighting in custom code block ([#959](https://github.com/vuejs/vitepress/issues/959)) ([#969](https://github.com/vuejs/vitepress/issues/969)) ([7a9e4d9](https://github.com/vuejs/vitepress/commit/7a9e4d9ee02cc677f1b84cc5f2c1f8f385c3a65c)) +- normalize link in VPButton ([#919](https://github.com/vuejs/vitepress/issues/919)) ([bed68f1](https://github.com/vuejs/vitepress/commit/bed68f134186e4fd3c0bca4c6a5871a79e4cd224)) +- only check for duplicate meta tags ([#977](https://github.com/vuejs/vitepress/issues/977)) ([1ef7a18](https://github.com/vuejs/vitepress/commit/1ef7a1857c2a8e2abc7c1859cd54504c144eab3b)), closes [/github.com/vuejs/vitepress/issues/975#issuecomment-1183507200](https://github.com//github.com/vuejs/vitepress/issues/975/issues/issuecomment-1183507200) +- regression caused by [#887](https://github.com/vuejs/vitepress/issues/887) ([30249dc](https://github.com/vuejs/vitepress/commit/30249dc2c3d933dadf6e22e64728a6ffd3647f8e)) +- remove duplicate router logic ([#1087](https://github.com/vuejs/vitepress/issues/1087)) ([63584c2](https://github.com/vuejs/vitepress/commit/63584c2812d2c5172356ef2615ac608684d52681)) +- remove explicit noopener from external links ([#871](https://github.com/vuejs/vitepress/issues/871)) ([e4c60ab](https://github.com/vuejs/vitepress/commit/e4c60ab3c834fe7f730cd7b0d64dd23c6d04dbed)) +- support urls with query during dev ([35b7361](https://github.com/vuejs/vitepress/commit/35b7361ca2c689f0fb464ab9cbab8bb02e4884d5)) +- **theme:** change sponsor link class name to bypass adblock ([#866](https://github.com/vuejs/vitepress/issues/866)) ([#867](https://github.com/vuejs/vitepress/issues/867)) ([e33955e](https://github.com/vuejs/vitepress/commit/e33955e7696af2de2d9ed53d53a06aa5de17f3ce)) +- **theme:** close menu on route change ([#887](https://github.com/vuejs/vitepress/issues/887)) ([fcd7642](https://github.com/vuejs/vitepress/commit/fcd7642924331e81e85ee75a1224a04d1882531c)) +- **theme:** don't let navbar obstruct clicks to top part of scrollbar ([#1168](https://github.com/vuejs/vitepress/issues/1168)) ([44953dc](https://github.com/vuejs/vitepress/commit/44953dcd1e0224bae95666c87e368b9d3fdf17ae)) +- **theme:** fix custom NotFound component rendering ([#1163](https://github.com/vuejs/vitepress/issues/1163)) ([4a6eda4](https://github.com/vuejs/vitepress/commit/4a6eda48704ad34e003d144594bbc56c1b448c6d)) +- **theme:** hide doc footer if empty ([#1126](https://github.com/vuejs/vitepress/issues/1126)) ([70da5f2](https://github.com/vuejs/vitepress/commit/70da5f275bc44ce4e6ed97af40cf30d6971ee378)) +- **theme:** make last updated time reactive ([#879](https://github.com/vuejs/vitepress/issues/879)) ([25a835f](https://github.com/vuejs/vitepress/commit/25a835f0f437a2181f67dbcefa17546dbcb833de)) +- **theme:** navbar menu may exceed the screen ([#988](https://github.com/vuejs/vitepress/issues/988)) ([#989](https://github.com/vuejs/vitepress/issues/989)) ([8a46413](https://github.com/vuejs/vitepress/commit/8a46413d6fa6ff671f780b60c7bc6380d84dc25d)) +- **theme:** prevent docsearch button key from changing ([#986](https://github.com/vuejs/vitepress/issues/986)) ([d65667b](https://github.com/vuejs/vitepress/commit/d65667b8d49a11fccee6bc0cd06a75333a65f22c)) +- **theme:** tweak styles of nav title ([#962](https://github.com/vuejs/vitepress/issues/962)) ([#968](https://github.com/vuejs/vitepress/issues/968)) ([d91f3b1](https://github.com/vuejs/vitepress/commit/d91f3b1b7d46db8009bb459079794b0626488033)) +- **theme:** typo in color name ([#1020](https://github.com/vuejs/vitepress/issues/1020)) ([4b38736](https://github.com/vuejs/vitepress/commit/4b38736adf2853276f573a1980a213a17cf2c740)) +- treat all URI schemes as external ([#945](https://github.com/vuejs/vitepress/issues/945)) ([#946](https://github.com/vuejs/vitepress/issues/946)) ([1e9a7ac](https://github.com/vuejs/vitepress/commit/1e9a7ac6c478c57d7336e2d7b0392f23659080d3)) +- **types:** add client and theme to `exports` field ([#914](https://github.com/vuejs/vitepress/issues/914)) ([1cc087d](https://github.com/vuejs/vitepress/commit/1cc087deeee5f6c8289259bb7a2695ed75f287c3)) +- **types:** fix broken syntax in `theme.d.ts` ([#1101](https://github.com/vuejs/vitepress/issues/1101)) ([70b3060](https://github.com/vuejs/vitepress/commit/70b3060be963ed7a0d2041446d67ac970d6f35e3)) +- use `router.go` if search string is not same ([#1109](https://github.com/vuejs/vitepress/issues/1109)) ([5597165](https://github.com/vuejs/vitepress/commit/55971659a5c4b25cb07968ca4e162abc11fe2e80)) + +### Features + +- allow adding custom social icons as inline svg ([#738](https://github.com/vuejs/vitepress/issues/738)) ([#953](https://github.com/vuejs/vitepress/issues/953)) ([74e4950](https://github.com/vuejs/vitepress/commit/74e4950c1b83f2e0c8659477c7b2763fa150b349)) +- allow html in footer ([#1034](https://github.com/vuejs/vitepress/issues/1034)) ([ad9af83](https://github.com/vuejs/vitepress/commit/ad9af83278d702a76f674f847b383370b3921256)) +- allow using custom syntax highlighting themes ([#992](https://github.com/vuejs/vitepress/issues/992)) ([d5ed66c](https://github.com/vuejs/vitepress/commit/d5ed66c6d21ec3b5e17469771057132c53220bea)) +- **build:** allow ignoring dead links ([#586](https://github.com/vuejs/vitepress/issues/586)) ([#793](https://github.com/vuejs/vitepress/issues/793)) ([19b0758](https://github.com/vuejs/vitepress/commit/19b0758a04e9fb7863b3a961024dfe1137fbe928)) +- **build:** allow using custom highlighter ([#754](https://github.com/vuejs/vitepress/issues/754)) ([#857](https://github.com/vuejs/vitepress/issues/857)) ([ddf876d](https://github.com/vuejs/vitepress/commit/ddf876d8e90e812a198bb417a5dc60cd443a8273)) +- **build:** handle change of config file dependencies ([#1009](https://github.com/vuejs/vitepress/issues/1009)) ([8e6665b](https://github.com/vuejs/vitepress/commit/8e6665bd8de66a8249fca92fbb1b9a4f6d76a041)) +- **build:** improve code blocks and snippets ([#875](https://github.com/vuejs/vitepress/issues/875)) ([f789932](https://github.com/vuejs/vitepress/commit/f789932ffc79723a90b3b19a59d6f277d9edaaa9)), closes [#861](https://github.com/vuejs/vitepress/issues/861) [#471](https://github.com/vuejs/vitepress/issues/471) [#884](https://github.com/vuejs/vitepress/issues/884) +- **build:** support code highlight in uppercase ([#1082](https://github.com/vuejs/vitepress/issues/1082)) ([867f305](https://github.com/vuejs/vitepress/commit/867f30588687c4f9228c1511bee672074e54c802)), closes [#772](https://github.com/vuejs/vitepress/issues/772) +- provide `transformHtml` hook ([#1022](https://github.com/vuejs/vitepress/issues/1022)) ([2b4b800](https://github.com/vuejs/vitepress/commit/2b4b80061818f1c471aafb23c0572172ef842138)) +- provide build end hook ([#709](https://github.com/vuejs/vitepress/issues/709)) ([e0b730a](https://github.com/vuejs/vitepress/commit/e0b730aa8ee9bec1fe16245c4c1a1a91f62bed42)) +- **theme:** add `doc-footer-before` slot ([#1050](https://github.com/vuejs/vitepress/issues/1050)) ([#1052](https://github.com/vuejs/vitepress/issues/1052)) ([60c515c](https://github.com/vuejs/vitepress/commit/60c515c1255085d73845d2b2cc315823ee18e7b8)) +- **theme:** add navigation slots ([#739](https://github.com/vuejs/vitepress/issues/739)) ([#741](https://github.com/vuejs/vitepress/issues/741)) ([0f0453c](https://github.com/vuejs/vitepress/commit/0f0453c6750c5af9c1ae65abb994813eecf9af27)) +- **theme:** add option to customize search button text ([#713](https://github.com/vuejs/vitepress/issues/713)) ([#747](https://github.com/vuejs/vitepress/issues/747)) ([00fe809](https://github.com/vuejs/vitepress/commit/00fe8092d9e097d2dd24c06787fcb740310bdda7)) +- **theme:** auto open collapsed sidebar on entering ([#1094](https://github.com/vuejs/vitepress/issues/1094)) ([f4f1a6c](https://github.com/vuejs/vitepress/commit/f4f1a6ccd62ea52c03b2c342c649f0f06f466126)) +- **theme:** custom prev/next labels and text ([#897](https://github.com/vuejs/vitepress/issues/897)) ([836a246](https://github.com/vuejs/vitepress/commit/836a24683a19eefbc98d6c448c26e3696a679e7c)) +- **theme:** support hiding aside component from frontmatter ([#980](https://github.com/vuejs/vitepress/issues/980)) ([69ef299](https://github.com/vuejs/vitepress/commit/69ef2998c37453ab9c0147e87dd9a6efb41a24a3)) +- **theme:** support multi-level sidebar ([#851](https://github.com/vuejs/vitepress/issues/851)) ([d1a2c76](https://github.com/vuejs/vitepress/commit/d1a2c76f33ab55ad8d43357b57c9ae3de55e9d0c)) ### Performance Improvements -* **a11y:** change copy code span to button ([#1056](https://github.com/vuejs/vitepress/issues/1056)) ([fb9cee9](https://github.com/vuejs/vitepress/commit/fb9cee95b95bf5989599deb1c4fbb1a448d67952)) - +- **a11y:** change copy code span to button ([#1056](https://github.com/vuejs/vitepress/issues/1056)) ([fb9cee9](https://github.com/vuejs/vitepress/commit/fb9cee95b95bf5989599deb1c4fbb1a448d67952)) ### Reverts -* vuejs/vitepress[#889](https://github.com/vuejs/vitepress/issues/889) ([#896](https://github.com/vuejs/vitepress/issues/896)) ([e1339fd](https://github.com/vuejs/vitepress/commit/e1339fdc4fc9736fc31d69393ca4289a1f245013)) - - +- vuejs/vitepress[#889](https://github.com/vuejs/vitepress/issues/889) ([#896](https://github.com/vuejs/vitepress/issues/896)) ([e1339fd](https://github.com/vuejs/vitepress/commit/e1339fdc4fc9736fc31d69393ca4289a1f245013)) ## [1.0.0-alpha.4](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.3...v1.0.0-alpha.4) (2022-06-22) ### Bug Fixes -* **theme:** home image style is broken in big view port ([2bd960d](https://github.com/vuejs/vitepress/commit/2bd960d5f5a84df614035a4fb941331fdf9d84f2)) +- **theme:** home image style is broken in big view port ([2bd960d](https://github.com/vuejs/vitepress/commit/2bd960d5f5a84df614035a4fb941331fdf9d84f2)) ## [1.0.0-alpha.3](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.2...v1.0.0-alpha.3) (2022-06-22) ### Bug Fixes -* **theme:** italic fonts are missing ([#759](https://github.com/vuejs/vitepress/issues/759)) ([#777](https://github.com/vuejs/vitepress/issues/777)) ([fa00c83](https://github.com/vuejs/vitepress/commit/fa00c83af4aa5fa619cf2e3da8d5aab77984ba7c)) -* **theme:** copy code in non-secure contexts ([#792](https://github.com/vuejs/vitepress/issues/792)) ([2935ed2](https://github.com/vuejs/vitepress/commit/2935ed22954010fa0d48d0625e5f2b0136991e0b)) -* **theme:** copy code button has wrong tag closing syntax ([#816](https://github.com/vuejs/vitepress/issues/816)) ([75ca9e4](https://github.com/vuejs/vitepress/commit/75ca9e4302c65e3bcc9518f7df928318380f6cf6)) -* **theme:** edit link gets hidden when a page don't have siblings ([#751](https://github.com/vuejs/vitepress/issues/751)) ([9bc4330](https://github.com/vuejs/vitepress/commit/9bc43306a1fe7bfd54b738642fd1737917a3af41)) -* **theme:** nav close icon not working correctly ([#744](https://github.com/vuejs/vitepress/issues/744)) ([75c9d80](https://github.com/vuejs/vitepress/commit/75c9d809d21c0484c0ae8ce691d598cf229c9525)) -* **theme:** sidebar is shown on home layout ([#825](https://github.com/vuejs/vitepress/issues/825)) ([#829](https://github.com/vuejs/vitepress/issues/829)) ([42cbd31](https://github.com/vuejs/vitepress/commit/42cbd31327b789ff9525919afb39b3092f1d445b)) -* **theme:** sidebar collapsed option not working on layout change ([#809](https://github.com/vuejs/vitepress/issues/809)) ([#811](https://github.com/vuejs/vitepress/issues/811)) ([7737699](https://github.com/vuejs/vitepress/commit/773769926b74cabfbb3577d6c6e654fe976c0b76)) -* **theme:** `DefaultTheme` type causes error in some cases ([#804](https://github.com/vuejs/vitepress/issues/804)) ([107724a](https://github.com/vuejs/vitepress/commit/107724ac6f24e5272964d3bdbff54169fa4d91ae)) +- **theme:** italic fonts are missing ([#759](https://github.com/vuejs/vitepress/issues/759)) ([#777](https://github.com/vuejs/vitepress/issues/777)) ([fa00c83](https://github.com/vuejs/vitepress/commit/fa00c83af4aa5fa619cf2e3da8d5aab77984ba7c)) +- **theme:** copy code in non-secure contexts ([#792](https://github.com/vuejs/vitepress/issues/792)) ([2935ed2](https://github.com/vuejs/vitepress/commit/2935ed22954010fa0d48d0625e5f2b0136991e0b)) +- **theme:** copy code button has wrong tag closing syntax ([#816](https://github.com/vuejs/vitepress/issues/816)) ([75ca9e4](https://github.com/vuejs/vitepress/commit/75ca9e4302c65e3bcc9518f7df928318380f6cf6)) +- **theme:** edit link gets hidden when a page don't have siblings ([#751](https://github.com/vuejs/vitepress/issues/751)) ([9bc4330](https://github.com/vuejs/vitepress/commit/9bc43306a1fe7bfd54b738642fd1737917a3af41)) +- **theme:** nav close icon not working correctly ([#744](https://github.com/vuejs/vitepress/issues/744)) ([75c9d80](https://github.com/vuejs/vitepress/commit/75c9d809d21c0484c0ae8ce691d598cf229c9525)) +- **theme:** sidebar is shown on home layout ([#825](https://github.com/vuejs/vitepress/issues/825)) ([#829](https://github.com/vuejs/vitepress/issues/829)) ([42cbd31](https://github.com/vuejs/vitepress/commit/42cbd31327b789ff9525919afb39b3092f1d445b)) +- **theme:** sidebar collapsed option not working on layout change ([#809](https://github.com/vuejs/vitepress/issues/809)) ([#811](https://github.com/vuejs/vitepress/issues/811)) ([7737699](https://github.com/vuejs/vitepress/commit/773769926b74cabfbb3577d6c6e654fe976c0b76)) +- **theme:** `DefaultTheme` type causes error in some cases ([#804](https://github.com/vuejs/vitepress/issues/804)) ([107724a](https://github.com/vuejs/vitepress/commit/107724ac6f24e5272964d3bdbff54169fa4d91ae)) ### Features -* **build:** allow setting `base` from command line ([2952638](https://github.com/vuejs/vitepress/commit/295263807df5a0cdff3b04d5131a3cebc76ec491)) -* **theme:** add active status to nav menu group ([#820](https://github.com/vuejs/vitepress/issues/820)) ([fdb5720](https://github.com/vuejs/vitepress/commit/fdb5720acda9f8f2dd1e4f33d0810a6e9ca9e7de)) -* **theme:** add global layout slots ([#760](https://github.com/vuejs/vitepress/issues/760)) ([#812](https://github.com/vuejs/vitepress/issues/812)) ([1f1e298](https://github.com/vuejs/vitepress/commit/1f1e298864f7b8af9672b55251958ba766678e0b)) -* **theme:** support themeable images for logo and hero ([#745](https://github.com/vuejs/vitepress/issues/745)) ([42813ce](https://github.com/vuejs/vitepress/commit/42813ce936d9fb141241969651cb0e3a02345442)) -* **theme:** add team page feature ([#828](https://github.com/vuejs/vitepress/issues/828)) ([7cfe0f0](https://github.com/vuejs/vitepress/commit/7cfe0f05ab013904c66c48d8529d2ba4747869cb)) +- **build:** allow setting `base` from command line ([2952638](https://github.com/vuejs/vitepress/commit/295263807df5a0cdff3b04d5131a3cebc76ec491)) +- **theme:** add active status to nav menu group ([#820](https://github.com/vuejs/vitepress/issues/820)) ([fdb5720](https://github.com/vuejs/vitepress/commit/fdb5720acda9f8f2dd1e4f33d0810a6e9ca9e7de)) +- **theme:** add global layout slots ([#760](https://github.com/vuejs/vitepress/issues/760)) ([#812](https://github.com/vuejs/vitepress/issues/812)) ([1f1e298](https://github.com/vuejs/vitepress/commit/1f1e298864f7b8af9672b55251958ba766678e0b)) +- **theme:** support themeable images for logo and hero ([#745](https://github.com/vuejs/vitepress/issues/745)) ([42813ce](https://github.com/vuejs/vitepress/commit/42813ce936d9fb141241969651cb0e3a02345442)) +- **theme:** add team page feature ([#828](https://github.com/vuejs/vitepress/issues/828)) ([7cfe0f0](https://github.com/vuejs/vitepress/commit/7cfe0f05ab013904c66c48d8529d2ba4747869cb)) ## [1.0.0-alpha.2](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.1...v1.0.0-alpha.2) (2022-06-14) ### Bug Fixes -* use h1 for title in hero instead of p ([#776](https://github.com/vuejs/vitepress/issues/776)) ([919d230](https://github.com/vuejs/vitepress/commit/919d23079b636c188ea2049039461b88e0c02fc2)) -* add background color in navbar to avoid contrast issues ([#695](https://github.com/vuejs/vitepress/issues/695)) ([305bcc0](https://github.com/vuejs/vitepress/commit/305bcc02e68f8f9aea0000e6950e78455cf572f5)) -* add default value for base in `createMarkdownRenderer` ([#555](https://github.com/vuejs/vitepress/issues/555)) ([#556](https://github.com/vuejs/vitepress/issues/556)) ([78a2e84](https://github.com/vuejs/vitepress/commit/78a2e84e7bb7acfda50e686bbd404961babb91e8)) -* allow lang='ts' on scripts in markdown ([#693](https://github.com/vuejs/vitepress/issues/693)) ([#701](https://github.com/vuejs/vitepress/issues/701)) ([59df105](https://github.com/vuejs/vitepress/commit/59df10590b958bbc39cc2e8c81a2209eda9d431b)) -* better nav item types ([#714](https://github.com/vuejs/vitepress/issues/714)) ([263607b](https://github.com/vuejs/vitepress/commit/263607b279cbfd3db80bbe0ea66000560d24993a)) -* double base in sidebar links ([#756](https://github.com/vuejs/vitepress/issues/756)) ([aa65cb5](https://github.com/vuejs/vitepress/commit/aa65cb58f508bb8e79c20b6370bdfe1b7e470abf)) -* use `pre-wrap` for text and tagline ([#746](https://github.com/vuejs/vitepress/issues/746)) ([94704c9](https://github.com/vuejs/vitepress/commit/94704c95637f1cc844d526d4743818d38d1cbae0)) -* nav nested items type error ([#710](https://github.com/vuejs/vitepress/issues/710)) ([#711](https://github.com/vuejs/vitepress/issues/711)) ([e5bf15a](https://github.com/vuejs/vitepress/commit/e5bf15a21ee777b4e56ad86ec5ebb5b0e161b721)) -* page layout breaks when page name matches the css class name ([#696](https://github.com/vuejs/vitepress/issues/696)) ([#699](https://github.com/vuejs/vitepress/issues/699)) ([9c0ed93](https://github.com/vuejs/vitepress/commit/9c0ed9397f35827a261d45c789d23ce7faa7ecee)) -* remove title bg transition to avoid flush on sidebar on/off ([1942418](https://github.com/vuejs/vitepress/commit/1942418f9570feb81d8066a2413d70b0f36fb8ce)) -* sidebar right blur notch ([#712](https://github.com/vuejs/vitepress/issues/712)) ([64c3654](https://github.com/vuejs/vitepress/commit/64c3654b4ba82c16fefdf396106f3077d066c67b)) -* typo ([#708](https://github.com/vuejs/vitepress/issues/708)) ([#716](https://github.com/vuejs/vitepress/issues/716)) ([1fe5153](https://github.com/vuejs/vitepress/commit/1fe5153f47465efed05e087119c93d50da6e92a3)) -* title in containers not working with markdown content ([#765](https://github.com/vuejs/vitepress/issues/765)) ([#768](https://github.com/vuejs/vitepress/issues/768)) ([c5c3c64](https://github.com/vuejs/vitepress/commit/c5c3c64851b240279a304198fd97e3dc8b5f2fd0)) -* use base in links ([#717](https://github.com/vuejs/vitepress/issues/717)) ([#718](https://github.com/vuejs/vitepress/issues/718)) ([8e50154](https://github.com/vuejs/vitepress/commit/8e5015462c8f42c5404525ac8de33af8862c204d)) -* use h2 for feature headers ([#774](https://github.com/vuejs/vitepress/issues/774)) ([b1ff725](https://github.com/vuejs/vitepress/commit/b1ff72561182c91b4912ebef44204a53ee3aca5e)) - -### Features - -* add `lastUpdated` option to frontmatter ([b31fbf3](https://github.com/vuejs/vitepress/commit/b31fbf3621bbd7f627a1b80c581b7a8444bc6b0d)) -* add doc before and after slot ([#762](https://github.com/vuejs/vitepress/issues/762)) ([#786](https://github.com/vuejs/vitepress/issues/786)) ([9c2a36f](https://github.com/vuejs/vitepress/commit/9c2a36f5428bd98eafb6e2e9bc63f5e532b596b7)) -* allow custom edit links ([#698](https://github.com/vuejs/vitepress/issues/698)) ([535e176](https://github.com/vuejs/vitepress/commit/535e176b9a230f692f58a79813a12d2ffbe90be3)), closes [#694](https://github.com/vuejs/vitepress/issues/694) [#697](https://github.com/vuejs/vitepress/issues/697) -* allow custom outline title ([#689](https://github.com/vuejs/vitepress/issues/689)) ([#690](https://github.com/vuejs/vitepress/issues/690)) ([a8a1623](https://github.com/vuejs/vitepress/commit/a8a16237cd8e3e4bb180fbd523a4668a4555b732)) -* allow external links in sidebar ([#205](https://github.com/vuejs/vitepress/issues/205)) ([#686](https://github.com/vuejs/vitepress/issues/686)) ([ce17f50](https://github.com/vuejs/vitepress/commit/ce17f5035cbbd1e07373ce0f44913f25269bd80b)) -* support custom content in home layout ([#702](https://github.com/vuejs/vitepress/issues/702)) ([92659a2](https://github.com/vuejs/vitepress/commit/92659a2e9dde13e35fadf2d2dca157d648bc9013)) -* emit 404.html on build ([#729](https://github.com/vuejs/vitepress/issues/729)) ([#740](https://github.com/vuejs/vitepress/issues/740)) ([23276ba](https://github.com/vuejs/vitepress/commit/23276bae050190b6c1d57347424360fe2c3a57be)) -* setup devtools and remove debug component ([#721](https://github.com/vuejs/vitepress/issues/721)) ([421f641](https://github.com/vuejs/vitepress/commit/421f641a76ddc0e8b0f23ab7ad711833fc98c245)) +- use h1 for title in hero instead of p ([#776](https://github.com/vuejs/vitepress/issues/776)) ([919d230](https://github.com/vuejs/vitepress/commit/919d23079b636c188ea2049039461b88e0c02fc2)) +- add background color in navbar to avoid contrast issues ([#695](https://github.com/vuejs/vitepress/issues/695)) ([305bcc0](https://github.com/vuejs/vitepress/commit/305bcc02e68f8f9aea0000e6950e78455cf572f5)) +- add default value for base in `createMarkdownRenderer` ([#555](https://github.com/vuejs/vitepress/issues/555)) ([#556](https://github.com/vuejs/vitepress/issues/556)) ([78a2e84](https://github.com/vuejs/vitepress/commit/78a2e84e7bb7acfda50e686bbd404961babb91e8)) +- allow lang='ts' on scripts in markdown ([#693](https://github.com/vuejs/vitepress/issues/693)) ([#701](https://github.com/vuejs/vitepress/issues/701)) ([59df105](https://github.com/vuejs/vitepress/commit/59df10590b958bbc39cc2e8c81a2209eda9d431b)) +- better nav item types ([#714](https://github.com/vuejs/vitepress/issues/714)) ([263607b](https://github.com/vuejs/vitepress/commit/263607b279cbfd3db80bbe0ea66000560d24993a)) +- double base in sidebar links ([#756](https://github.com/vuejs/vitepress/issues/756)) ([aa65cb5](https://github.com/vuejs/vitepress/commit/aa65cb58f508bb8e79c20b6370bdfe1b7e470abf)) +- use `pre-wrap` for text and tagline ([#746](https://github.com/vuejs/vitepress/issues/746)) ([94704c9](https://github.com/vuejs/vitepress/commit/94704c95637f1cc844d526d4743818d38d1cbae0)) +- nav nested items type error ([#710](https://github.com/vuejs/vitepress/issues/710)) ([#711](https://github.com/vuejs/vitepress/issues/711)) ([e5bf15a](https://github.com/vuejs/vitepress/commit/e5bf15a21ee777b4e56ad86ec5ebb5b0e161b721)) +- page layout breaks when page name matches the css class name ([#696](https://github.com/vuejs/vitepress/issues/696)) ([#699](https://github.com/vuejs/vitepress/issues/699)) ([9c0ed93](https://github.com/vuejs/vitepress/commit/9c0ed9397f35827a261d45c789d23ce7faa7ecee)) +- remove title bg transition to avoid flush on sidebar on/off ([1942418](https://github.com/vuejs/vitepress/commit/1942418f9570feb81d8066a2413d70b0f36fb8ce)) +- sidebar right blur notch ([#712](https://github.com/vuejs/vitepress/issues/712)) ([64c3654](https://github.com/vuejs/vitepress/commit/64c3654b4ba82c16fefdf396106f3077d066c67b)) +- typo ([#708](https://github.com/vuejs/vitepress/issues/708)) ([#716](https://github.com/vuejs/vitepress/issues/716)) ([1fe5153](https://github.com/vuejs/vitepress/commit/1fe5153f47465efed05e087119c93d50da6e92a3)) +- title in containers not working with markdown content ([#765](https://github.com/vuejs/vitepress/issues/765)) ([#768](https://github.com/vuejs/vitepress/issues/768)) ([c5c3c64](https://github.com/vuejs/vitepress/commit/c5c3c64851b240279a304198fd97e3dc8b5f2fd0)) +- use base in links ([#717](https://github.com/vuejs/vitepress/issues/717)) ([#718](https://github.com/vuejs/vitepress/issues/718)) ([8e50154](https://github.com/vuejs/vitepress/commit/8e5015462c8f42c5404525ac8de33af8862c204d)) +- use h2 for feature headers ([#774](https://github.com/vuejs/vitepress/issues/774)) ([b1ff725](https://github.com/vuejs/vitepress/commit/b1ff72561182c91b4912ebef44204a53ee3aca5e)) + +### Features + +- add `lastUpdated` option to frontmatter ([b31fbf3](https://github.com/vuejs/vitepress/commit/b31fbf3621bbd7f627a1b80c581b7a8444bc6b0d)) +- add doc before and after slot ([#762](https://github.com/vuejs/vitepress/issues/762)) ([#786](https://github.com/vuejs/vitepress/issues/786)) ([9c2a36f](https://github.com/vuejs/vitepress/commit/9c2a36f5428bd98eafb6e2e9bc63f5e532b596b7)) +- allow custom edit links ([#698](https://github.com/vuejs/vitepress/issues/698)) ([535e176](https://github.com/vuejs/vitepress/commit/535e176b9a230f692f58a79813a12d2ffbe90be3)), closes [#694](https://github.com/vuejs/vitepress/issues/694) [#697](https://github.com/vuejs/vitepress/issues/697) +- allow custom outline title ([#689](https://github.com/vuejs/vitepress/issues/689)) ([#690](https://github.com/vuejs/vitepress/issues/690)) ([a8a1623](https://github.com/vuejs/vitepress/commit/a8a16237cd8e3e4bb180fbd523a4668a4555b732)) +- allow external links in sidebar ([#205](https://github.com/vuejs/vitepress/issues/205)) ([#686](https://github.com/vuejs/vitepress/issues/686)) ([ce17f50](https://github.com/vuejs/vitepress/commit/ce17f5035cbbd1e07373ce0f44913f25269bd80b)) +- support custom content in home layout ([#702](https://github.com/vuejs/vitepress/issues/702)) ([92659a2](https://github.com/vuejs/vitepress/commit/92659a2e9dde13e35fadf2d2dca157d648bc9013)) +- emit 404.html on build ([#729](https://github.com/vuejs/vitepress/issues/729)) ([#740](https://github.com/vuejs/vitepress/issues/740)) ([23276ba](https://github.com/vuejs/vitepress/commit/23276bae050190b6c1d57347424360fe2c3a57be)) +- setup devtools and remove debug component ([#721](https://github.com/vuejs/vitepress/issues/721)) ([421f641](https://github.com/vuejs/vitepress/commit/421f641a76ddc0e8b0f23ab7ad711833fc98c245)) ## [1.0.0-alpha.1](https://github.com/vuejs/vitepress/compare/v0.22.4...v1.0.0-alpha.1) (2022-06-01) diff --git a/README.md b/README.md index d8ff0b85..aedcd487 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,13 @@ -# VitePress (beta) 📝💨 +# VitePress 📝💨 -[![Test](https://github.com/vuejs/vitepress/workflows/Test/badge.svg)](https://github.com/vuejs/vitepress/actions) +[![test](https://github.com/vuejs/vitepress/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/vuejs/vitepress/actions/workflows/test.yml) [![npm](https://img.shields.io/npm/v/vitepress)](https://www.npmjs.com/package/vitepress) +[![nightly releases](https://img.shields.io/badge/nightly-releases-orange)](https://nightly.akryum.dev/vuejs/vitepress) [![chat](https://img.shields.io/badge/chat-discord-blue?logo=discord)](https://chat.vuejs.org) --- -VitePress is [VuePress](https://vuepress.vuejs.org)' spiritual successor, built on top of [vite](https://github.com/vitejs/vite). - -Currently, it is in the `beta` stage. It is already suitable for out-of-the-box documentation use. There still might be issues, however, we do not plan to introduce any breaking changes from here on until the stable release. +VitePress is a Vue-powered static site generator and a spiritual successor to [VuePress](https://vuepress.vuejs.org), built on top of [Vite](https://github.com/vitejs/vite). ## Documentation diff --git a/__tests__/e2e/.vitepress/config.ts b/__tests__/e2e/.vitepress/config.ts index 9a40532f..121761e7 100644 --- a/__tests__/e2e/.vitepress/config.ts +++ b/__tests__/e2e/.vitepress/config.ts @@ -1,5 +1,73 @@ import { defineConfig, type DefaultTheme } from 'vitepress' +const nav: DefaultTheme.Config['nav'] = [ + { + text: 'Home', + link: '/' + }, + { + text: 'API Reference', + items: [ + { + text: 'Example', + link: '/home.html' + }, + { + component: 'ApiPreference', + props: { + options: ['JavaScript', 'TypeScript', 'Flow'], + defaultOption: 'TypeScript' + } + }, + { + component: 'ApiPreference', + props: { + options: ['Options', 'Composition'], + defaultOption: 'Composition' + } + } + ] + }, + { + component: 'NavVersion', + props: { + versions: [ + { + text: 'v1.x', + link: '/' + }, + { + text: 'v0.x', + link: '/v0.x/' + } + ] + } + }, + { + text: 'Nested', + items: [ + { + text: 'Level 1 - 1', + items: [ + { + text: 'Level 2 - 1', + link: '/nested/level1-1/level2-1' + } + ] + }, + { + text: 'Level 1 - 2', + items: [ + { + text: 'Level 2 - 2', + link: '/nested/level1-2/level2-2' + } + ] + } + ] + } +] + const sidebar: DefaultTheme.Config['sidebar'] = { '/': [ { @@ -86,7 +154,32 @@ const sidebar: DefaultTheme.Config['sidebar'] = { export default defineConfig({ title: 'Example', description: 'An example app using VitePress.', + markdown: { + image: { + lazyLoading: true + } + }, themeConfig: { - sidebar + nav, + sidebar, + search: { + provider: 'local', + options: { + async _render(src, env, md) { + const html = await md.renderAsync(src, env) + if (env.frontmatter?.search === false) return '' + if (env.relativePath.startsWith('local-search/excluded')) return '' + return html + } + } + } + }, + vite: { + server: { + watch: { + usePolling: true, + interval: 100 + } + } } }) diff --git a/__tests__/e2e/.vitepress/theme/components/ApiPreference.vue b/__tests__/e2e/.vitepress/theme/components/ApiPreference.vue new file mode 100644 index 00000000..c286640b --- /dev/null +++ b/__tests__/e2e/.vitepress/theme/components/ApiPreference.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/__tests__/e2e/.vitepress/theme/components/NavVersion.vue b/__tests__/e2e/.vitepress/theme/components/NavVersion.vue new file mode 100644 index 00000000..d256e3d2 --- /dev/null +++ b/__tests__/e2e/.vitepress/theme/components/NavVersion.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/__tests__/e2e/.vitepress/theme/index.ts b/__tests__/e2e/.vitepress/theme/index.ts new file mode 100644 index 00000000..d2629777 --- /dev/null +++ b/__tests__/e2e/.vitepress/theme/index.ts @@ -0,0 +1,12 @@ +import type { Theme } from 'vitepress' +import DefaultTheme from 'vitepress/theme' +import ApiPreference from './components/ApiPreference.vue' +import NavVersion from './components/NavVersion.vue' + +export default { + extends: DefaultTheme, + enhanceApp({ app }) { + app.component('ApiPreference', ApiPreference) + app.component('NavVersion', NavVersion) + } +} satisfies Theme diff --git a/__tests__/e2e/__snapshots__/home.test.ts.snap b/__tests__/e2e/__snapshots__/home.test.ts.snap index 0c5972fc..50f16ad8 100644 --- a/__tests__/e2e/__snapshots__/home.test.ts.snap +++ b/__tests__/e2e/__snapshots__/home.test.ts.snap @@ -4,8 +4,8 @@ exports[`render correct content > main content 1`] = ` [ "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.", - "Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of \\"de Finibus Bonorum et Malorum\\" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, \\"Lorem ipsum dolor sit amet..\\", comes from a line in section 1.10.32.", - "The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from \\"de Finibus Bonorum et Malorum\\" by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.", + "Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32.", + "The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from "de Finibus Bonorum et Malorum" by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.", "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).", "There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn't anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.", ] diff --git a/__tests__/e2e/data-loading/basic.data.mts b/__tests__/e2e/data-loading/basic.data.mts new file mode 100644 index 00000000..56aab77e --- /dev/null +++ b/__tests__/e2e/data-loading/basic.data.mts @@ -0,0 +1,16 @@ +import fs from 'node:fs' +import { defineLoader } from 'vitepress' + +type Data = Record[] +export declare const data: Data + +export default defineLoader({ + watch: ['./data/*'], + async load(files: string[]): Promise { + const data: Data = [] + for (const file of files.sort().filter((file) => file.endsWith('.json'))) { + data.push(JSON.parse(fs.readFileSync(file, 'utf-8'))) + } + return data + } +}) diff --git a/__tests__/e2e/data-loading/basic.data.ts b/__tests__/e2e/data-loading/basic.data.ts deleted file mode 100644 index 1a70d74a..00000000 --- a/__tests__/e2e/data-loading/basic.data.ts +++ /dev/null @@ -1,20 +0,0 @@ -import fs from 'fs' -import { defineLoader } from 'vitepress' - -type Data = Record[] -export declare const data: Data - -export default defineLoader({ - watch: ['./data/*'], - async load(files: string[]): Promise { - const foo = fs.readFileSync( - files.find((f) => f.endsWith('foo.json'))!, - 'utf-8' - ) - const bar = fs.readFileSync( - files.find((f) => f.endsWith('bar.json'))!, - 'utf-8' - ) - return [JSON.parse(foo), JSON.parse(bar)] - } -}) diff --git a/__tests__/e2e/data-loading/data.md b/__tests__/e2e/data-loading/data.md index 69ded9df..e78a1aca 100644 --- a/__tests__/e2e/data-loading/data.md +++ b/__tests__/e2e/data-loading/data.md @@ -1,7 +1,7 @@ # Static Data diff --git a/__tests__/e2e/data-loading/data.test.ts b/__tests__/e2e/data-loading/data.test.ts index 642bb28f..fafc403a 100644 --- a/__tests__/e2e/data-loading/data.test.ts +++ b/__tests__/e2e/data-loading/data.test.ts @@ -1,3 +1,6 @@ +import fs from 'node:fs/promises' +import { fileURLToPath } from 'node:url' + describe('static data file support in vite 3', () => { beforeAll(async () => { await goto('/data-loading/data') @@ -7,36 +10,99 @@ describe('static data file support in vite 3', () => { expect(await page.textContent('pre#basic')).toMatchInlineSnapshot(` "[ { - \\"foo\\": true + "a": true }, { - \\"bar\\": true + "b": true } ]" `) expect(await page.textContent('pre#content')).toMatchInlineSnapshot(` "[ { - \\"src\\": \\"---\\\\ntitle: bar\\\\n---\\\\n\\\\nHello\\\\n\\\\n---\\\\n\\\\nworld\\\\n\\", - \\"html\\": \\"

Hello

\\\\n
\\\\n

world

\\\\n\\", - \\"frontmatter\\": { - \\"title\\": \\"bar\\" + "src": "---\\ntitle: bar\\n---\\n\\nHello\\n\\n---\\n\\nworld\\n", + "html": "

Hello

\\n
\\n

world

\\n", + "frontmatter": { + "title": "bar" }, - \\"excerpt\\": \\"

Hello

\\\\n\\", - \\"url\\": \\"/data-loading/content/bar.html\\", - \\"transformed\\": true + "excerpt": "

Hello

\\n", + "url": "/data-loading/content/bar.html", + "transformed": true }, { - \\"src\\": \\"---\\\\ntitle: foo\\\\n---\\\\n\\\\nHello\\\\n\\\\n---\\\\n\\\\nworld\\\\n\\", - \\"html\\": \\"

Hello

\\\\n
\\\\n

world

\\\\n\\", - \\"frontmatter\\": { - \\"title\\": \\"foo\\" + "src": "---\\ntitle: foo\\n---\\n\\nHello\\n\\n---\\n\\nworld\\n", + "html": "

Hello

\\n
\\n

world

\\n", + "frontmatter": { + "title": "foo" }, - \\"excerpt\\": \\"

Hello

\\\\n\\", - \\"url\\": \\"/data-loading/content/foo.html\\", - \\"transformed\\": true + "excerpt": "

Hello

\\n", + "url": "/data-loading/content/foo.html", + "transformed": true } ]" `) }) + + test.runIf(!process.env.VITE_TEST_BUILD)('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 + */ }) diff --git a/__tests__/e2e/data-loading/data/a.json b/__tests__/e2e/data-loading/data/a.json new file mode 100644 index 00000000..eb174f2f --- /dev/null +++ b/__tests__/e2e/data-loading/data/a.json @@ -0,0 +1,3 @@ +{ + "a": true +} diff --git a/__tests__/e2e/data-loading/data/b.json b/__tests__/e2e/data-loading/data/b.json new file mode 100644 index 00000000..d44f4ab8 --- /dev/null +++ b/__tests__/e2e/data-loading/data/b.json @@ -0,0 +1,3 @@ +{ + "b": true +} diff --git a/__tests__/e2e/data-loading/data/bar.json b/__tests__/e2e/data-loading/data/bar.json deleted file mode 100644 index 01309803..00000000 --- a/__tests__/e2e/data-loading/data/bar.json +++ /dev/null @@ -1 +0,0 @@ -{ "bar": true } diff --git a/__tests__/e2e/data-loading/data/foo.json b/__tests__/e2e/data-loading/data/foo.json deleted file mode 100644 index 46a10aa7..00000000 --- a/__tests__/e2e/data-loading/data/foo.json +++ /dev/null @@ -1 +0,0 @@ -{ "foo": true } diff --git a/__tests__/e2e/dynamic-routes/[id].paths.ts b/__tests__/e2e/dynamic-routes/[id].paths.ts index 3eca4d91..12a8bc32 100644 --- a/__tests__/e2e/dynamic-routes/[id].paths.ts +++ b/__tests__/e2e/dynamic-routes/[id].paths.ts @@ -1,8 +1,14 @@ -export default { - async paths() { - return [ - { params: { id: 'foo' }, content: `# Foo` }, - { params: { id: 'bar' }, content: `# Bar` } - ] +import { defineRoutes } from 'vitepress' +import paths from './paths' + +export default defineRoutes({ + async paths(watchedFiles: string[]) { + // console.log('watchedFiles', watchedFiles) + return paths + }, + watch: ['**/data-loading/**/*.json'], + async transformPageData(pageData) { + // console.log('transformPageData', pageData.filePath) + pageData.title += ' - transformed' } -} +}) diff --git a/__tests__/e2e/dynamic-routes/paths.ts b/__tests__/e2e/dynamic-routes/paths.ts new file mode 100644 index 00000000..5adb0ed4 --- /dev/null +++ b/__tests__/e2e/dynamic-routes/paths.ts @@ -0,0 +1,4 @@ +export default [ + { params: { id: 'foo' }, content: `# Foo` }, + { params: { id: 'bar' }, content: `# Bar` } +] diff --git a/__tests__/e2e/frontmatter/multiple-levels-outline.md b/__tests__/e2e/frontmatter/multiple-levels-outline.md index 332a7cda..09a17406 100644 --- a/__tests__/e2e/frontmatter/multiple-levels-outline.md +++ b/__tests__/e2e/frontmatter/multiple-levels-outline.md @@ -1,7 +1,7 @@ --- title: Multiple Levels Outline editLink: true -outline: 'deep' +outline: deep --- # h1 - 1 diff --git a/__tests__/e2e/local-search/excluded.md b/__tests__/e2e/local-search/excluded.md new file mode 100644 index 00000000..eb9e7c01 --- /dev/null +++ b/__tests__/e2e/local-search/excluded.md @@ -0,0 +1 @@ +# Local search config excluded \ No newline at end of file diff --git a/__tests__/e2e/local-search/frontmatter-excluded.md b/__tests__/e2e/local-search/frontmatter-excluded.md new file mode 100644 index 00000000..afc32512 --- /dev/null +++ b/__tests__/e2e/local-search/frontmatter-excluded.md @@ -0,0 +1,5 @@ +--- +search: false +--- + +# Local search frontmatter excluded \ No newline at end of file diff --git a/__tests__/e2e/local-search/index.md b/__tests__/e2e/local-search/index.md new file mode 100644 index 00000000..08d8b31a --- /dev/null +++ b/__tests__/e2e/local-search/index.md @@ -0,0 +1 @@ +# Local search included \ No newline at end of file diff --git a/__tests__/e2e/local-search/local-search.test.ts b/__tests__/e2e/local-search/local-search.test.ts new file mode 100644 index 00000000..492136b6 --- /dev/null +++ b/__tests__/e2e/local-search/local-search.test.ts @@ -0,0 +1,31 @@ +describe('local search', () => { + beforeEach(async () => { + await goto('/') + }) + + test('exclude content from search results', async () => { + await page.locator('#local-search button').click() + + const input = await page.waitForSelector('input#localsearch-input') + await input.type('local') + + await page.waitForSelector('ul#localsearch-list', { state: 'visible' }) + + const searchResults = page.locator('#localsearch-list') + expect(await searchResults.locator('li[role=option]').count()).toBe(1) + + expect( + await searchResults.filter({ hasText: 'Local search included' }).count() + ).toBe(1) + + expect( + await searchResults.filter({ hasText: 'Local search excluded' }).count() + ).toBe(0) + + expect( + await searchResults + .filter({ hasText: 'Local search frontmatter excluded' }) + .count() + ).toBe(0) + }) +}) diff --git a/__tests__/e2e/markdown-extensions/foo.md b/__tests__/e2e/markdown-extensions/foo.md index c601f247..bd93e61f 100644 --- a/__tests__/e2e/markdown-extensions/foo.md +++ b/__tests__/e2e/markdown-extensions/foo.md @@ -1,7 +1,11 @@ # Foo +This is before region + ## Region -this is region - \ No newline at end of file +This is a region + + +This is after region diff --git a/__tests__/e2e/markdown-extensions/header-include.md b/__tests__/e2e/markdown-extensions/header-include.md new file mode 100644 index 00000000..70fac23b --- /dev/null +++ b/__tests__/e2e/markdown-extensions/header-include.md @@ -0,0 +1,27 @@ +# header 1 + +header 1 content + +## header 1.1 + +header 1.1 content + +### header 1.1.1 + +header 1.1.1 content + +### header 1.1.2 + +header 1.1.2 content + +## header 1.2 + +header 1.2 content + +### header 1.2.1 + +header 1.2.1 content + +### header 1.2.2 + +header 1.2.2 content diff --git a/__tests__/e2e/markdown-extensions/index.md b/__tests__/e2e/markdown-extensions/index.md index 348bdca9..3446b4ef 100644 --- a/__tests__/e2e/markdown-extensions/index.md +++ b/__tests__/e2e/markdown-extensions/index.md @@ -180,3 +180,43 @@ export default config ## Markdown At File Inclusion + +## Markdown Nested File Inclusion + + + +## Markdown File Inclusion with Range + + + +## Markdown File Inclusion with Range without Start + + + +## Markdown File Inclusion with Range without End + + + +## Markdown At File Region Snippet + + + +## Markdown At File Range Region Snippet + + + +## Markdown At File Range Region Snippet without start + + + +## Markdown At File Range Region Snippet without end + + + +## Markdown File Inclusion with Header + + + +## Image Lazy Loading + +![vitepress logo](/vitepress.png) diff --git a/__tests__/e2e/markdown-extensions/markdown-extensions.test.ts b/__tests__/e2e/markdown-extensions/markdown-extensions.test.ts index b844647b..839f953c 100644 --- a/__tests__/e2e/markdown-extensions/markdown-extensions.test.ts +++ b/__tests__/e2e/markdown-extensions/markdown-extensions.test.ts @@ -5,6 +5,8 @@ const getClassList = async (locator: Locator) => { return className?.split(' ').filter(Boolean) ?? [] } +const trim = (str?: string | null) => str?.replace(/\u200B/g, '').trim() + beforeEach(async () => { await goto('/markdown-extensions/') }) @@ -62,8 +64,61 @@ describe('Emoji', () => { describe('Table of Contents', () => { test('render toc', async () => { const items = page.locator('#table-of-contents + nav ul li') - const count = await items.count() - expect(count).toBe(24) + expect( + await items.evaluateAll((elements) => + elements.map((el) => el.childNodes[0].textContent) + ) + ).toMatchInlineSnapshot(` + [ + "Links", + "Internal Links", + "External Links", + "GitHub-Style Tables", + "Emoji", + "Table of Contents", + "Custom Containers", + "Default Title", + "Custom Title", + "Line Highlighting in Code Blocks", + "Single Line", + "Multiple single lines, ranges", + "Comment Highlight", + "Line Numbers", + "Import Code Snippets", + "Basic Code Snippet", + "Specify Region", + "With Other Features", + "Code Groups", + "Basic Code Group", + "With Other Features", + "Markdown File Inclusion", + "Region", + "Markdown At File Inclusion", + "Markdown Nested File Inclusion", + "Region", + "After Foo", + "Sub sub", + "Sub sub sub", + "Markdown File Inclusion with Range", + "Region", + "Markdown File Inclusion with Range without Start", + "Region", + "Markdown File Inclusion with Range without End", + "Region", + "Markdown At File Region Snippet", + "Region Snippet", + "Markdown At File Range Region Snippet", + "Range Region Line 2", + "Markdown At File Range Region Snippet without start", + "Range Region Line 1", + "Markdown At File Range Region Snippet without end", + "Range Region Line 3", + "Markdown File Inclusion with Header", + "header 1.1.1", + "header 1.1.2", + "Image Lazy Loading", + ] + `) }) }) @@ -161,7 +216,7 @@ describe('Line Numbers', () => { describe('Import Code Snippets', () => { test('basic', async () => { const lines = page.locator('#basic-code-snippet + div code > span') - expect(await lines.count()).toBe(7) + expect(await lines.count()).toBe(11) }) test('specify region', async () => { @@ -214,7 +269,7 @@ describe('Code Groups', () => { // blocks const blocks = div.locator('.blocks > div') - expect(await blocks.nth(0).locator('code > span').count()).toBe(7) + expect(await blocks.nth(0).locator('code > span').count()).toBe(11) expect(await getClassList(blocks.nth(1))).toContain('line-numbers-mode') expect(await getClassList(blocks.nth(1))).toContain('language-ts') expect(await blocks.nth(1).locator('code > span').count()).toBe(3) @@ -229,8 +284,79 @@ describe('Markdown File Inclusion', () => { const h1 = page.locator('#markdown-file-inclusion + h1') expect(await h1.getAttribute('id')).toBe('foo') }) + test('render markdown using @', async () => { const h1 = page.locator('#markdown-at-file-inclusion + h1') expect(await h1.getAttribute('id')).toBe('bar') }) + + test('render markdown using nested inclusion', async () => { + const h1 = page.locator('#markdown-nested-file-inclusion + h1') + expect(await h1.getAttribute('id')).toBe('foo-1') + }) + + test('render markdown using nested inclusion inside sub folder', async () => { + const h1 = page.locator('#after-foo + h1') + expect(await h1.getAttribute('id')).toBe('inside-sub-folder') + const h2 = page.locator('#after-foo + h1 + h2') + expect(await h2.getAttribute('id')).toBe('sub-sub') + const h3 = page.locator('#after-foo + h1 + h2 + h3') + expect(await h3.getAttribute('id')).toBe('sub-sub-sub') + }) + + test('support selecting range', async () => { + const h2 = page.locator('#markdown-file-inclusion-with-range + h2') + expect(trim(await h2.textContent())).toBe('Region') + + const p = page.locator('#markdown-file-inclusion-with-range + h2 + p') + expect(trim(await p.textContent())).toBe('This is a region') + }) + + test('support selecting range without specifying start', async () => { + const p = page.locator( + '#markdown-file-inclusion-with-range-without-start ~ p' + ) + expect(trim(await p.nth(0).textContent())).toBe('This is before region') + expect(trim(await p.nth(1).textContent())).toBe('This is a region') + }) + + test('support selecting range without specifying end', async () => { + const p = page.locator( + '#markdown-file-inclusion-with-range-without-end ~ p' + ) + expect(trim(await p.nth(0).textContent())).toBe('This is a region') + expect(trim(await p.nth(1).textContent())).toBe('This is after region') + }) + + test('support markdown region snippet', async () => { + const h2 = page.locator('#markdown-at-file-region-snippet + h2') + expect(await h2.getAttribute('id')).toBe('region-snippet') + + const line = page.locator('#markdown-at-file-range-region-snippet + h2') + expect(await line.getAttribute('id')).toBe('range-region-line-2') + + const lineWithoutStart = page.locator( + '#markdown-at-file-range-region-snippet-without-start + h2' + ) + expect(await lineWithoutStart.getAttribute('id')).toBe( + 'range-region-line-1' + ) + + const lineWithoutEnd = page.locator( + '#markdown-at-file-range-region-snippet-without-end + h2' + ) + expect(await lineWithoutEnd.getAttribute('id')).toBe('range-region-line-3') + }) + + test('ignore frontmatter if range is not specified', async () => { + const p = page.locator('.vp-doc') + expect(await p.textContent()).not.toContain('title') + }) +}) + +describe('Image Lazy Loading', () => { + test('render loading="lazy" in the tag', async () => { + const img = page.locator('#image-lazy-loading + p img') + expect(await img.getAttribute('loading')).toBe('lazy') + }) }) diff --git a/__tests__/e2e/markdown-extensions/nested-include.md b/__tests__/e2e/markdown-extensions/nested-include.md new file mode 100644 index 00000000..8b876c78 --- /dev/null +++ b/__tests__/e2e/markdown-extensions/nested-include.md @@ -0,0 +1,9 @@ +--- +title: Nested Include +--- + + + +### After Foo + + diff --git a/__tests__/e2e/markdown-extensions/region-include.md b/__tests__/e2e/markdown-extensions/region-include.md new file mode 100644 index 00000000..4daeb7ff --- /dev/null +++ b/__tests__/e2e/markdown-extensions/region-include.md @@ -0,0 +1,13 @@ + + + +## Range Region Line 1 + +## Range Region Line 2 + +## Range Region Line 3 + + + +## Region Snippet + diff --git a/__tests__/e2e/markdown-extensions/subfolder/inside-subfolder.md b/__tests__/e2e/markdown-extensions/subfolder/inside-subfolder.md new file mode 100644 index 00000000..8477113a --- /dev/null +++ b/__tests__/e2e/markdown-extensions/subfolder/inside-subfolder.md @@ -0,0 +1,3 @@ +# Inside sub folder + + diff --git a/__tests__/e2e/markdown-extensions/subfolder/subsub/subsub.md b/__tests__/e2e/markdown-extensions/subfolder/subsub/subsub.md new file mode 100644 index 00000000..70d0332e --- /dev/null +++ b/__tests__/e2e/markdown-extensions/subfolder/subsub/subsub.md @@ -0,0 +1,3 @@ +## Sub sub + + diff --git a/__tests__/e2e/markdown-extensions/subfolder/subsub/subsubsub/subsubsub.md b/__tests__/e2e/markdown-extensions/subfolder/subsub/subsubsub/subsubsub.md new file mode 100644 index 00000000..9b4e5e69 --- /dev/null +++ b/__tests__/e2e/markdown-extensions/subfolder/subsub/subsubsub/subsubsub.md @@ -0,0 +1 @@ +### Sub sub sub diff --git a/__tests__/e2e/package.json b/__tests__/e2e/package.json index 0aea6117..1d558ff7 100644 --- a/__tests__/e2e/package.json +++ b/__tests__/e2e/package.json @@ -1,6 +1,14 @@ { + "name": "tests-e2e", "private": true, "type": "module", + "scripts": { + "test": "vitest run", + "watch": "DEBUG=1 vitest", + "site:dev": "vitepress", + "site:build": "vitepress build", + "site:preview": "vitepress preview" + }, "devDependencies": { "vitepress": "workspace:*" } diff --git a/__tests__/e2e/vitest.config.ts b/__tests__/e2e/vitest.config.ts index d94a39b9..04aa9475 100644 --- a/__tests__/e2e/vitest.config.ts +++ b/__tests__/e2e/vitest.config.ts @@ -5,7 +5,7 @@ const timeout = 60_000 export default defineConfig({ test: { setupFiles: ['vitestSetup.ts'], - globalSetup: ['__tests__/e2e/vitestGlobalSetup.ts'], + globalSetup: ['vitestGlobalSetup.ts'], testTimeout: timeout, hookTimeout: timeout, teardownTimeout: timeout, diff --git a/__tests__/e2e/vitestGlobalSetup.ts b/__tests__/e2e/vitestGlobalSetup.ts index 0ee9455f..74596801 100644 --- a/__tests__/e2e/vitestGlobalSetup.ts +++ b/__tests__/e2e/vitestGlobalSetup.ts @@ -1,13 +1,13 @@ import getPort from 'get-port' +import type { Server } from 'node:net' import { chromium, type BrowserServer } from 'playwright-chromium' -import { build, createServer, serve } from 'vitepress' import type { ViteDevServer } from 'vite' -import type { Server } from 'net' +import { build, createServer, serve } from 'vitepress' let browserServer: BrowserServer let server: ViteDevServer | Server -const root = '__tests__/e2e' +const root = '.' export async function setup() { browserServer = await chromium.launchServer({ diff --git a/__tests__/init/init.test.ts b/__tests__/init/init.test.ts index a05bd820..7766b060 100644 --- a/__tests__/init/init.test.ts +++ b/__tests__/init/init.test.ts @@ -1,98 +1,72 @@ -import { chromium, type Browser, type Page } from 'playwright-chromium' -import { fileURLToPath } from 'url' -import path from 'path' import fs from 'fs-extra' -import { - scaffold, - build, - createServer, - serve, - ScaffoldThemeType, - type ScaffoldOptions -} from 'vitepress' -import type { ViteDevServer } from 'vite' -import type { Server } from 'net' import getPort from 'get-port' +import { nanoid } from 'nanoid' +import path from 'node:path' +import { fileURLToPath, URL } from 'node:url' +import { chromium } from 'playwright-chromium' +import { createServer, scaffold, ScaffoldThemeType } from 'vitepress' -let browser: Browser -let page: Page +const tempDir = fileURLToPath(new URL('./.temp', import.meta.url)) +const getTempRoot = () => path.join(tempDir, nanoid()) -beforeAll(async () => { - browser = await chromium.connect(process.env['WS_ENDPOINT']!) - page = await browser.newPage() +const browser = await chromium.launch({ + headless: !process.env.DEBUG, + args: process.env.CI + ? ['--no-sandbox', '--disable-setuid-sandbox'] + : undefined }) +const page = await browser.newPage() + +const themes = [ + ScaffoldThemeType.Default, + ScaffoldThemeType.DefaultCustom, + ScaffoldThemeType.Custom +] +const usingTs = [false, true] +const variations = themes.flatMap((theme) => + usingTs.map( + (useTs) => [`${theme}${useTs ? ' + ts' : ''}`, { theme, useTs }] as const + ) +) + afterAll(async () => { await page.close() await browser.close() + await fs.remove(tempDir) }) -const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), 'temp') - -async function testVariation(options: ScaffoldOptions) { - fs.removeSync(root) - scaffold({ - ...options, - root - }) +test.each(variations)('init %s', async (_, { theme, useTs }) => { + const root = getTempRoot() + await fs.remove(root) + scaffold({ root, theme, useTs, injectNpmScripts: false }) - let server: ViteDevServer | Server const port = await getPort() + const server = await createServer(root, { port }) + await server.listen() async function goto(path: string) { await page.goto(`http://localhost:${port}${path}`) await page.waitForSelector('#app div') } - if (process.env['VITE_TEST_BUILD']) { - await build(root) - server = (await serve({ root, port })).server - } else { - server = await createServer(root, { port }) - await server!.listen() - } - try { await goto('/') expect(await page.textContent('h1')).toMatch('My Awesome Project') await page.click('a[href="/markdown-examples.html"]') - await page.waitForSelector('pre code') + await page.waitForFunction('document.querySelector("pre code")') expect(await page.textContent('h1')).toMatch('Markdown Extension Examples') await goto('/') expect(await page.textContent('h1')).toMatch('My Awesome Project') await page.click('a[href="/api-examples.html"]') - await page.waitForSelector('pre code') + await page.waitForFunction('document.querySelector("pre code")') expect(await page.textContent('h1')).toMatch('Runtime API Examples') - } finally { - fs.removeSync(root) - if ('ws' in server) { - await server.close() - } else { - await new Promise((resolve, reject) => { - server.close((error) => (error ? reject(error) : resolve())) - }) - } - } -} -const themes = [ - ScaffoldThemeType.Default, - ScaffoldThemeType.DefaultCustom, - ScaffoldThemeType.Custom -] -const usingTs = [false, true] - -for (const theme of themes) { - for (const useTs of usingTs) { - test(`${theme}${useTs ? ` + TypeScript` : ``}`, () => - testVariation({ - root: '.', - theme, - useTs, - injectNpmScripts: false - })) + // teardown + } finally { + await server.close() } -} +}) diff --git a/__tests__/init/package.json b/__tests__/init/package.json index 0aea6117..a3f14021 100644 --- a/__tests__/init/package.json +++ b/__tests__/init/package.json @@ -1,6 +1,11 @@ { + "name": "tests-init", "private": true, "type": "module", + "scripts": { + "test": "vitest run", + "watch": "DEBUG=1 vitest" + }, "devDependencies": { "vitepress": "workspace:*" } diff --git a/__tests__/init/vitest.config.ts b/__tests__/init/vitest.config.ts index 789ba16d..abd62c34 100644 --- a/__tests__/init/vitest.config.ts +++ b/__tests__/init/vitest.config.ts @@ -1,20 +1,9 @@ -import { dirname, resolve } from 'path' -import { fileURLToPath } from 'url' import { defineConfig } from 'vitest/config' -const dir = dirname(fileURLToPath(import.meta.url)) - const timeout = 60_000 export default defineConfig({ - resolve: { - alias: { - node: resolve(dir, '../../src/node') - } - }, test: { - watchExclude: ['**/node_modules/**', '**/temp/**'], - globalSetup: ['__tests__/init/vitestGlobalSetup.ts'], testTimeout: timeout, hookTimeout: timeout, teardownTimeout: timeout, diff --git a/__tests__/init/vitestGlobalSetup.ts b/__tests__/init/vitestGlobalSetup.ts deleted file mode 100644 index 3f2c2508..00000000 --- a/__tests__/init/vitestGlobalSetup.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { chromium, type BrowserServer } from 'playwright-chromium' - -let browserServer: BrowserServer - -export async function setup() { - browserServer = await chromium.launchServer({ - headless: !process.env.DEBUG, - args: process.env.CI - ? ['--no-sandbox', '--disable-setuid-sandbox'] - : undefined - }) - process.env['WS_ENDPOINT'] = browserServer.wsEndpoint() -} - -export async function teardown() { - await browserServer.close() -} diff --git a/__tests__/unit/client/theme-default/composables/outline.test.ts b/__tests__/unit/client/theme-default/composables/outline.test.ts index 06180f1a..af659c9f 100644 --- a/__tests__/unit/client/theme-default/composables/outline.test.ts +++ b/__tests__/unit/client/theme-default/composables/outline.test.ts @@ -1,5 +1,11 @@ import { resolveHeaders } from 'client/theme-default/composables/outline' +const element = { + classList: { + contains: () => false + } +} as unknown as HTMLHeadElement + describe('client/theme-default/composables/outline', () => { describe('resolveHeader', () => { test('levels range', () => { @@ -9,12 +15,14 @@ describe('client/theme-default/composables/outline', () => { { level: 2, title: 'h2 - 1', - link: '#h2-1' + link: '#h2-1', + element }, { level: 3, title: 'h3 - 1', - link: '#h3-1' + link: '#h3-1', + element } ], [2, 3] @@ -28,9 +36,12 @@ describe('client/theme-default/composables/outline', () => { { level: 3, title: 'h3 - 1', - link: '#h3-1' + link: '#h3-1', + children: [], + element } - ] + ], + element } ]) }) @@ -42,12 +53,14 @@ describe('client/theme-default/composables/outline', () => { { level: 2, title: 'h2 - 1', - link: '#h2-1' + link: '#h2-1', + element }, { level: 3, title: 'h3 - 1', - link: '#h3-1' + link: '#h3-1', + element } ], 2 @@ -56,7 +69,9 @@ describe('client/theme-default/composables/outline', () => { { level: 2, title: 'h2 - 1', - link: '#h2-1' + link: '#h2-1', + children: [], + element } ]) }) @@ -68,42 +83,50 @@ describe('client/theme-default/composables/outline', () => { { level: 2, title: 'h2 - 1', - link: '#h2-1' + link: '#h2-1', + element }, { level: 3, title: 'h3 - 1', - link: '#h3-1' + link: '#h3-1', + element }, { level: 4, title: 'h4 - 1', - link: '#h4-1' + link: '#h4-1', + element }, { level: 3, title: 'h3 - 2', - link: '#h3-2' + link: '#h3-2', + element }, { level: 4, title: 'h4 - 2', - link: '#h4-2' + link: '#h4-2', + element }, { level: 2, title: 'h2 - 2', - link: '#h2-2' + link: '#h2-2', + element }, { level: 3, title: 'h3 - 3', - link: '#h3-3' + link: '#h3-3', + element }, { level: 4, title: 'h4 - 3', - link: '#h4-3' + link: '#h4-3', + element } ], 'deep' @@ -122,9 +145,12 @@ describe('client/theme-default/composables/outline', () => { { level: 4, title: 'h4 - 1', - link: '#h4-1' + link: '#h4-1', + children: [], + element } - ] + ], + element }, { level: 3, @@ -134,11 +160,15 @@ describe('client/theme-default/composables/outline', () => { { level: 4, title: 'h4 - 2', - link: '#h4-2' + link: '#h4-2', + children: [], + element } - ] + ], + element } - ] + ], + element }, { level: 2, @@ -153,11 +183,15 @@ describe('client/theme-default/composables/outline', () => { { level: 4, title: 'h4 - 3', - link: '#h4-3' + link: '#h4-3', + children: [], + element } - ] + ], + element } - ] + ], + element } ]) }) diff --git a/__tests__/unit/client/theme-default/support/sidebar.test.ts b/__tests__/unit/client/theme-default/support/sidebar.test.ts index 5afdb95e..f33dcbd9 100644 --- a/__tests__/unit/client/theme-default/support/sidebar.test.ts +++ b/__tests__/unit/client/theme-default/support/sidebar.test.ts @@ -28,15 +28,19 @@ describe('client/theme-default/support/sidebar', () => { } test('gets `/` sidebar', () => { - expect(getSidebar(normalSidebar, '/')).toBe(root) + expect(getSidebar(normalSidebar, '/')).toStrictEqual(root) }) test('gets `/multi-sidebar/` sidebar', () => { - expect(getSidebar(normalSidebar, '/multi-sidebar/')).toBe(another) + expect(getSidebar(normalSidebar, '/multi-sidebar/')).toStrictEqual( + another + ) }) test('gets `/` sidebar again', () => { - expect(getSidebar(normalSidebar, '/some-entry.html')).toBe(root) + expect(getSidebar(normalSidebar, '/some-entry.html')).toStrictEqual( + root + ) }) }) @@ -47,15 +51,19 @@ describe('client/theme-default/support/sidebar', () => { } test('gets `/` sidebar', () => { - expect(getSidebar(reversedSidebar, '/')).toBe(root) + expect(getSidebar(reversedSidebar, '/')).toStrictEqual(root) }) test('gets `/multi-sidebar/` sidebar', () => { - expect(getSidebar(reversedSidebar, '/multi-sidebar/')).toBe(another) + expect(getSidebar(reversedSidebar, '/multi-sidebar/')).toStrictEqual( + another + ) }) test('gets `/` sidebar again', () => { - expect(getSidebar(reversedSidebar, '/some-entry.html')).toBe(root) + expect(getSidebar(reversedSidebar, '/some-entry.html')).toStrictEqual( + root + ) }) }) @@ -74,19 +82,25 @@ describe('client/theme-default/support/sidebar', () => { } test('gets `/` sidebar', () => { - expect(getSidebar(nestedSidebar, '/')).toBe(root) + expect(getSidebar(nestedSidebar, '/')).toStrictEqual(root) }) test('gets `/multi-sidebar/` sidebar', () => { - expect(getSidebar(nestedSidebar, '/multi-sidebar/')).toBe(another) + expect(getSidebar(nestedSidebar, '/multi-sidebar/')).toStrictEqual( + another + ) }) test('gets `/multi-sidebar/nested/` sidebar', () => { - expect(getSidebar(nestedSidebar, '/multi-sidebar/nested/')).toBe(nested) + expect( + getSidebar(nestedSidebar, '/multi-sidebar/nested/') + ).toStrictEqual(nested) }) test('gets `/` sidebar again', () => { - expect(getSidebar(nestedSidebar, '/some-entry.html')).toBe(root) + expect(getSidebar(nestedSidebar, '/some-entry.html')).toStrictEqual( + root + ) }) }) }) diff --git a/__tests__/unit/node/markdown/plugins/snippet.test.ts b/__tests__/unit/node/markdown/plugins/snippet.test.ts index ce50d42b..aa940784 100644 --- a/__tests__/unit/node/markdown/plugins/snippet.test.ts +++ b/__tests__/unit/node/markdown/plugins/snippet.test.ts @@ -1,4 +1,45 @@ -import { dedent } from 'node/markdown/plugins/snippet' +import { + dedent, + findRegion, + rawPathToToken +} from 'node/markdown/plugins/snippet' +import { expect } from 'vitest' + +const removeEmptyKeys = >(obj: T) => { + return Object.fromEntries( + Object.entries(obj).filter(([, value]) => value !== '') + ) as T +} + +/* prettier-ignore */ +const rawPathTokenMap: [string, Partial<{ filepath: string, extension: string, title: string, region: string, lines: string, lang: string }>][] = [ + ['/path/to/file.extension', { filepath: '/path/to/file.extension', extension: 'extension', title: 'file.extension' }], + ['./path/to/file.extension', { filepath: './path/to/file.extension', extension: 'extension', title: 'file.extension' }], + ['/path to/file.extension', { filepath: '/path to/file.extension', extension: 'extension', title: 'file.extension' }], + ['./path to/file.extension', { filepath: './path to/file.extension', extension: 'extension', title: 'file.extension' }], + ['/path.to/file.extension', { filepath: '/path.to/file.extension', extension: 'extension', title: 'file.extension' }], + ['./path.to/file.extension', { filepath: './path.to/file.extension', extension: 'extension', title: 'file.extension' }], + ['/path .to/file.extension', { filepath: '/path .to/file.extension', extension: 'extension', title: 'file.extension' }], + ['./path .to/file.extension', { filepath: './path .to/file.extension', extension: 'extension', title: 'file.extension' }], + ['/path/to/file', { filepath: '/path/to/file', title: 'file' }], + ['./path/to/file', { filepath: './path/to/file', title: 'file' }], + ['/path to/file', { filepath: '/path to/file', title: 'file' }], + ['./path to/file', { filepath: './path to/file', title: 'file' }], + ['/path.to/file', { filepath: '/path.to/file', title: 'file' }], + ['./path.to/file', { filepath: './path.to/file', title: 'file' }], + ['/path .to/file', { filepath: '/path .to/file', title: 'file' }], + ['./path .to/file', { filepath: './path .to/file', title: 'file' }], + ['/path/to/file.extension#region', { filepath: '/path/to/file.extension', extension: 'extension', title: 'file.extension', region: '#region' }], + ['./path/to/file.extension {c#}', { filepath: './path/to/file.extension', extension: 'extension', title: 'file.extension', lang: 'c#' }], + ['/path to/file.extension {1,2,4-6}', { filepath: '/path to/file.extension', extension: 'extension', title: 'file.extension', lines: '1,2,4-6' }], + ['/path to/file.extension {1,2,4-6 c#}', { filepath: '/path to/file.extension', extension: 'extension', title: 'file.extension', lines: '1,2,4-6', lang: 'c#' }], + ['/path.to/file.extension [title]', { filepath: '/path.to/file.extension', extension: 'extension', title: 'title' }], + ['./path.to/file.extension#region {c#}', { filepath: './path.to/file.extension', extension: 'extension', title: 'file.extension', region: '#region', lang: 'c#' }], + ['/path/to/file#region {1,2,4-6}', { filepath: '/path/to/file', title: 'file', region: '#region', lines: '1,2,4-6' }], + ['./path/to/file#region {1,2,4-6 c#}', { filepath: './path/to/file', title: 'file', region: '#region', lines: '1,2,4-6', lang: 'c#' }], + ['/path to/file {1,2,4-6 c#} [title]', { filepath: '/path to/file', title: 'title', lines: '1,2,4-6', lang: 'c#' }], + ['./path to/file#region {1,2,4-6 c#} [title]', { filepath: './path to/file', title: 'title', region: '#region', lines: '1,2,4-6', lang: 'c#' }], +] describe('node/markdown/plugins/snippet', () => { describe('dedent', () => { @@ -14,7 +55,7 @@ describe('node/markdown/plugins/snippet', () => { ) ).toMatchInlineSnapshot(` "fn main() { - println!(\\"Hello\\"); + println!("Hello"); }" `) }) @@ -57,4 +98,229 @@ describe('node/markdown/plugins/snippet', () => { `) }) }) + + describe('rawPathToToken', () => { + test.each(rawPathTokenMap)('%s', (rawPath, token) => { + expect(removeEmptyKeys(rawPathToToken(rawPath))).toEqual(token) + }) + }) + + describe('findRegion', () => { + it('returns null when no region markers are present', () => { + const lines = ['function foo() {', ' console.log("hello");', '}'] + expect(findRegion(lines, 'foo')).toBeNull() + }) + + it('ignores non-matching region names', () => { + const lines = [ + '// #region regionA', + 'some code here', + '// #endregion regionA' + ] + expect(findRegion(lines, 'regionC')).toBeNull() + }) + + it('returns null if a region start marker exists without a matching end marker', () => { + const lines = [ + '// #region missingEnd', + 'console.log("inside region");', + 'console.log("still inside");' + ] + expect(findRegion(lines, 'missingEnd')).toBeNull() + }) + + it('returns null if an end marker exists without a preceding start marker', () => { + const lines = [ + '// #endregion ghostRegion', + 'console.log("stray end marker");' + ] + expect(findRegion(lines, 'ghostRegion')).toBeNull() + }) + + it('detects C#/JavaScript style region markers with matching tags', () => { + const lines = [ + 'Console.WriteLine("Before region");', + '#region hello', + 'Console.WriteLine("Hello, World!");', + '#endregion hello', + 'Console.WriteLine("After region");' + ] + const result = findRegion(lines, 'hello') + expect(result).not.toBeNull() + if (result) { + expect(lines.slice(result.start, result.end).join('\n')).toBe( + 'Console.WriteLine("Hello, World!");' + ) + } + }) + + it('detects region markers even when the end marker omits the region name', () => { + const lines = [ + 'Console.WriteLine("Before region");', + '#region hello', + 'Console.WriteLine("Hello, World!");', + '#endregion', + 'Console.WriteLine("After region");' + ] + const result = findRegion(lines, 'hello') + expect(result).not.toBeNull() + if (result) { + expect(lines.slice(result.start, result.end).join('\n')).toBe( + 'Console.WriteLine("Hello, World!");' + ) + } + }) + + it('handles indented region markers correctly', () => { + const lines = [ + ' Console.WriteLine("Before region");', + ' #region hello', + ' Console.WriteLine("Hello, World!");', + ' #endregion hello', + ' Console.WriteLine("After region");' + ] + const result = findRegion(lines, 'hello') + expect(result).not.toBeNull() + if (result) { + expect(lines.slice(result.start, result.end).join('\n')).toBe( + ' Console.WriteLine("Hello, World!");' + ) + } + }) + + it('detects TypeScript style region markers', () => { + const lines = [ + 'let regexp: RegExp[] = [];', + '// #region foo', + 'let start = -1;', + '// #endregion foo' + ] + const result = findRegion(lines, 'foo') + expect(result).not.toBeNull() + if (result) { + expect(lines.slice(result.start, result.end).join('\n')).toBe( + 'let start = -1;' + ) + } + }) + + it('detects CSS style region markers', () => { + const lines = [ + '.body-content {', + '/* #region foo */', + ' padding-left: 15px;', + '/* #endregion foo */', + ' padding-right: 15px;', + '}' + ] + const result = findRegion(lines, 'foo') + expect(result).not.toBeNull() + if (result) { + expect(lines.slice(result.start, result.end).join('\n')).toBe( + ' padding-left: 15px;' + ) + } + }) + + it('detects HTML style region markers', () => { + const lines = [ + '
Some content
', + '', + '

Hello world

', + '', + '
Other content
' + ] + const result = findRegion(lines, 'foo') + expect(result).not.toBeNull() + if (result) { + expect(lines.slice(result.start, result.end).join('\n')).toBe( + '

Hello world

' + ) + } + }) + + it('detects Visual Basic style region markers (with case-insensitive "End")', () => { + const lines = [ + 'Console.WriteLine("VB")', + '#Region VBRegion', + ' Console.WriteLine("Inside region")', + '#End Region VBRegion', + 'Console.WriteLine("Done")' + ] + const result = findRegion(lines, 'VBRegion') + expect(result).not.toBeNull() + if (result) { + expect(lines.slice(result.start, result.end).join('\n')).toBe( + ' Console.WriteLine("Inside region")' + ) + } + }) + + it('detects Bat style region markers', () => { + const lines = ['::#region foo', 'echo off', '::#endregion foo'] + const result = findRegion(lines, 'foo') + expect(result).not.toBeNull() + if (result) { + expect(lines.slice(result.start, result.end).join('\n')).toBe( + 'echo off' + ) + } + }) + + it('detects C/C++ style region markers using #pragma', () => { + const lines = [ + '#pragma region foo', + 'int a = 1;', + '#pragma endregion foo' + ] + const result = findRegion(lines, 'foo') + expect(result).not.toBeNull() + if (result) { + expect(lines.slice(result.start, result.end).join('\n')).toBe( + 'int a = 1;' + ) + } + }) + + it('returns the first complete region when multiple regions exist', () => { + const lines = [ + '// #region foo', + 'first region content', + '// #endregion foo', + '// #region foo', + 'second region content', + '// #endregion foo' + ] + const result = findRegion(lines, 'foo') + expect(result).not.toBeNull() + if (result) { + expect(lines.slice(result.start, result.end).join('\n')).toBe( + 'first region content' + ) + } + }) + + it('handles nested regions with different names properly', () => { + const lines = [ + '// #region foo', + "console.log('line before nested');", + '// #region bar', + "console.log('nested content');", + '// #endregion bar', + '// #endregion foo' + ] + const result = findRegion(lines, 'foo') + expect(result).not.toBeNull() + if (result) { + const extracted = lines.slice(result.start, result.end).join('\n') + const expected = [ + "console.log('line before nested');", + '// #region bar', + "console.log('nested content');", + '// #endregion bar' + ].join('\n') + expect(extracted).toBe(expected) + } + }) + }) }) diff --git a/__tests__/unit/node/utils/moduleGraph.test.ts b/__tests__/unit/node/utils/moduleGraph.test.ts new file mode 100644 index 00000000..9b3db9e5 --- /dev/null +++ b/__tests__/unit/node/utils/moduleGraph.test.ts @@ -0,0 +1,72 @@ +import { ModuleGraph } from 'node/utils/moduleGraph' + +describe('node/utils/moduleGraph', () => { + let graph: ModuleGraph + + beforeEach(() => { + graph = new ModuleGraph() + }) + + it('should correctly delete a module and its dependents', () => { + graph.add('A', ['B', 'C']) + graph.add('B', ['D']) + graph.add('C', []) + graph.add('D', []) + + expect(graph.delete('D')).toEqual(new Set(['D', 'B', 'A'])) + }) + + it('should handle shared dependencies correctly', () => { + graph.add('A', ['B', 'C']) + graph.add('B', ['D']) + graph.add('C', ['D']) // Shared dependency + graph.add('D', []) + + expect(graph.delete('D')).toEqual(new Set(['A', 'B', 'C', 'D'])) + }) + + it('merges dependencies correctly', () => { + // Add module A with dependency B + graph.add('A', ['B']) + // Merge new dependency C into module A (B should remain) + graph.add('A', ['C']) + + // Deleting B should remove A as well, since A depends on B. + expect(graph.delete('B')).toEqual(new Set(['B', 'A'])) + }) + + it('handles cycles gracefully', () => { + // Create a cycle: A -> B, B -> C, C -> A. + graph.add('A', ['B']) + graph.add('B', ['C']) + graph.add('C', ['A']) + + // Deleting any module in the cycle should delete all modules in the cycle. + expect(graph.delete('A')).toEqual(new Set(['A', 'B', 'C'])) + }) + + it('cleans up dependencies when deletion', () => { + // Setup A -> B relationship. + graph.add('A', ['B']) + graph.add('B', []) + + // Deleting B should remove both B and A from the graph. + expect(graph.delete('B')).toEqual(new Set(['B', 'A'])) + + // After deletion, add modules again. + graph.add('C', []) + graph.add('A', ['C']) // Now A depends only on C. + + expect(graph.delete('C')).toEqual(new Set(['C', 'A'])) + }) + + it('handles independent modules', () => { + // Modules with no dependencies. + graph.add('X', []) + graph.add('Y', []) + + // Deletion of one should only remove that module. + expect(graph.delete('X')).toEqual(new Set(['X'])) + expect(graph.delete('Y')).toEqual(new Set(['Y'])) + }) +}) diff --git a/__tests__/unit/vitest.config.ts b/__tests__/unit/vitest.config.ts index 88d82e51..b028d4ee 100644 --- a/__tests__/unit/vitest.config.ts +++ b/__tests__/unit/vitest.config.ts @@ -1,17 +1,26 @@ -import { dirname, resolve } from 'path' -import { fileURLToPath } from 'url' +import vue from '@vitejs/plugin-vue' +import { dirname, resolve } from 'node:path' +import { fileURLToPath } from 'node:url' import { defineConfig } from 'vitest/config' const dir = dirname(fileURLToPath(import.meta.url)) export default defineConfig({ + plugins: [vue()], resolve: { - alias: { - '@siteData': resolve(dir, './shims.ts'), - client: resolve(dir, '../../src/client'), - node: resolve(dir, '../../src/node'), - vitepress: resolve(dir, '../../src/client') - } + alias: [ + { find: '@siteData', replacement: resolve(dir, './shims.ts') }, + { find: 'client', replacement: resolve(dir, '../../src/client') }, + { find: 'node', replacement: resolve(dir, '../../src/node') }, + { + find: /^vitepress$/, + replacement: resolve(dir, '../../src/client/index.js') + }, + { + find: /^vitepress\/theme$/, + replacement: resolve(dir, '../../src/client/theme-default/index.js') + } + ] }, test: { globals: true diff --git a/art/vitepress-logo-mini.svg b/art/vitepress-logo-mini.svg new file mode 100644 index 00000000..47756f7a --- /dev/null +++ b/art/vitepress-logo-mini.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/art/vitepress-logo.svg b/art/vitepress-logo.svg new file mode 100644 index 00000000..0805ed51 --- /dev/null +++ b/art/vitepress-logo.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bin/vitepress.js b/bin/vitepress.js index 7c50ec90..9cf31ae0 100755 --- a/bin/vitepress.js +++ b/bin/vitepress.js @@ -1,2 +1,16 @@ #!/usr/bin/env node +// @ts-check + +import module from 'node:module' + +// https://github.com/vitejs/vite/blob/6c8a5a27e645a182f5b03a4ed6aa726eab85993f/packages/vite/bin/vite.js#L48-L63 +try { + module.enableCompileCache?.() + setTimeout(() => { + try { + module.flushCompileCache?.() + } catch {} + }, 10 * 1000).unref() +} catch {} + import('../dist/node/cli.js') diff --git a/docs/.postcssrc.json b/docs/.postcssrc.json new file mode 100644 index 00000000..edc6a490 --- /dev/null +++ b/docs/.postcssrc.json @@ -0,0 +1,8 @@ +{ + "plugins": { + "postcss-rtlcss": { + "ltrPrefix": ":where([dir=\"ltr\"])", + "rtlPrefix": ":where([dir=\"rtl\"])" + } + } +} diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 265e8f0c..575d114d 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -1,227 +1,148 @@ -import { createRequire } from 'module' -import { defineConfig } from 'vitepress' +import { + defineConfig, + resolveSiteDataByRoute, + type HeadConfig +} from 'vitepress' +import { + groupIconMdPlugin, + groupIconVitePlugin, + localIconLoader +} from 'vitepress-plugin-group-icons' +import llmstxt from 'vitepress-plugin-llms' -const require = createRequire(import.meta.url) -const pkg = require('vitepress/package.json') +const prod = !!process.env.NETLIFY export default defineConfig({ - lang: 'en-US', title: 'VitePress', - description: 'Vite & Vue powered static site generator.', + + rewrites: { + 'en/:rest*': ':rest*' + }, lastUpdated: true, cleanUrls: true, + metaChunk: true, - head: [ - ['meta', { name: 'theme-color', content: '#3c8772' }], - [ - 'script', + markdown: { + math: true, + codeTransformers: [ + // We use `[!!code` in demo to prevent transformation, here we revert it back. { - src: 'https://cdn.usefathom.com/script.js', - 'data-site': 'AZBRSFGG', - 'data-spa': 'auto', - defer: '' + postprocess(code) { + return code.replace(/\[\!\!code/g, '[!code') + } } - ] - ], + ], + config(md) { + // TODO: remove when https://github.com/vuejs/vitepress/issues/4431 is fixed + const fence = md.renderer.rules.fence! + md.renderer.rules.fence = function (tokens, idx, options, env, self) { + const { localeIndex = 'root' } = env + const codeCopyButtonTitle = (() => { + switch (localeIndex) { + case 'es': + return 'Copiar código' + case 'fa': + return 'کپی کد' + case 'ko': + return '코드 복사' + case 'pt': + return 'Copiar código' + case 'ru': + return 'Скопировать код' + case 'zh': + return '复制代码' + default: + return 'Copy code' + } + })() + return fence(tokens, idx, options, env, self).replace( + '', + `` + ) + } + md.use(groupIconMdPlugin) + } + }, - themeConfig: { - nav: nav(), + sitemap: { + hostname: 'https://vitepress.dev', + transformItems(items) { + return items.filter((item) => !item.url.includes('migration')) + } + }, - sidebar: { - '/guide/': sidebarGuide(), - '/reference/': sidebarReference() - }, + /* prettier-ignore */ + head: [ + ['link', { rel: 'icon', type: 'image/svg+xml', href: '/vitepress-logo-mini.svg' }], + ['link', { rel: 'icon', type: 'image/png', href: '/vitepress-logo-mini.png' }], + ['meta', { name: 'theme-color', content: '#5f67ee' }], + ['meta', { property: 'og:type', content: 'website' }], + ['meta', { property: 'og:site_name', content: 'VitePress' }], + ['meta', { property: 'og:image', content: 'https://vitepress.dev/vitepress-og.jpg' }], + ['meta', { property: 'og:url', content: 'https://vitepress.dev/' }], + ['script', { src: 'https://cdn.usefathom.com/script.js', 'data-site': 'AZBRSFGG', 'data-spa': 'auto', defer: '' }] + ], - editLink: { - pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', - text: 'Edit this page on GitHub' - }, + themeConfig: { + logo: { src: '/vitepress-logo-mini.svg', width: 24, height: 24 }, socialLinks: [ { icon: 'github', link: 'https://github.com/vuejs/vitepress' } ], - footer: { - message: 'Released under the MIT License.', - copyright: 'Copyright © 2019-present Evan You' - }, - search: { provider: 'algolia', options: { appId: '8J64VVRP8K', - apiKey: 'a18e2f4cc5665f6602c5631fd868adfd', + apiKey: '52f578a92b88ad6abde815aae2b0ad7c', indexName: 'vitepress' } }, - carbonAds: { - code: 'CEBDT27Y', - placement: 'vuejsorg' - } - } -}) + carbonAds: { code: 'CEBDT27Y', placement: 'vuejsorg' } + }, -function nav() { - return [ - { text: 'Guide', link: '/guide/what-is-vitepress', activeMatch: '/guide/' }, - { - text: 'Reference', - link: '/reference/site-config', - activeMatch: '/reference/' - }, - { - text: pkg.version, - items: [ - { - text: 'Changelog', - link: 'https://github.com/vuejs/vitepress/blob/main/CHANGELOG.md' - }, - { - text: 'Contributing', - link: 'https://github.com/vuejs/vitepress/blob/main/.github/contributing.md' - } - ] - } - ] -} + locales: { + root: { label: 'English' }, + zh: { label: '简体中文' }, + pt: { label: 'Português' }, + ru: { label: 'Русский' }, + es: { label: 'Español' }, + ko: { label: '한국어' }, + fa: { label: 'فارسی' } + }, -function sidebarGuide() { - return [ - { - text: 'Introduction', - collapsed: false, - items: [ - { text: 'What is VitePress?', link: '/guide/what-is-vitepress' }, - { text: 'Getting Started', link: '/guide/getting-started' }, - { text: 'Routing', link: '/guide/routing' }, - { text: 'Deploy', link: '/guide/deploy' } - ] - }, - { - text: 'Writing', - collapsed: false, - items: [ - { text: 'Markdown Extensions', link: '/guide/markdown' }, - { text: 'Asset Handling', link: '/guide/asset-handling' }, - { text: 'Frontmatter', link: '/guide/frontmatter' }, - { text: 'Using Vue in Markdown', link: '/guide/using-vue' }, - { text: 'Internationalization', link: '/guide/i18n' } - ] - }, - { - text: 'Customization', - collapsed: false, - items: [ - { text: 'Using a Custom Theme', link: '/guide/custom-theme' }, - { - text: 'Extending the Default Theme', - link: '/guide/extending-default-theme' - }, - { text: 'Build-Time Data Loading', link: '/guide/data-loading' }, - { text: 'SSR Compatibility', link: '/guide/ssr-compat' }, - { text: 'Connecting to a CMS', link: '/guide/cms' } - ] - }, - { - text: 'Experimental', - collapsed: false, - items: [ - { - text: 'MPA Mode', - link: '/guide/mpa-mode' + vite: { + plugins: [ + groupIconVitePlugin({ + customIcon: { + vitepress: localIconLoader( + import.meta.url, + '../public/vitepress-logo-mini.svg' + ), + firebase: 'logos:firebase' } - ] - }, - // { - // text: 'Migrations', - // collapsed: false, - // items: [ - // { - // text: 'Migration from VuePress', - // link: '/guide/migration-from-vuepress' - // }, - // { - // text: 'Migration from VitePress 0.x', - // link: '/guide/migration-from-vitepress-0' - // } - // ] - // }, - { - text: 'Config & API Reference', - link: '/reference/site-config' - } - ] -} + }), + prod && + llmstxt({ + workDir: 'en', + ignoreFiles: ['index.md'] + }) + ] + }, -function sidebarReference() { - return [ - { - text: 'Reference', - items: [ - { text: 'Site Config', link: '/reference/site-config' }, - { text: 'Frontmatter Config', link: '/reference/frontmatter-config' }, - { text: 'Runtime API', link: '/reference/runtime-api' }, - { text: 'CLI', link: '/reference/cli' }, - { - text: 'Default Theme', - items: [ - { - text: 'Overview', - link: '/reference/default-theme-config' - }, - { - text: 'Nav', - link: '/reference/default-theme-nav' - }, - { - text: 'Sidebar', - link: '/reference/default-theme-sidebar' - }, - { - text: 'Home Page', - link: '/reference/default-theme-home-page' - }, - { - text: 'Footer', - link: '/reference/default-theme-footer' - }, - { - text: 'Layout', - link: '/reference/default-theme-layout' - }, - { - text: 'Badge', - link: '/reference/default-theme-badge' - }, - { - text: 'Team Page', - link: '/reference/default-theme-team-page' - }, - { - text: 'Prev / Next Links', - link: '/reference/default-theme-prev-next-links' - }, - { - text: 'Edit Link', - link: '/reference/default-theme-edit-link' - }, - { - text: 'Last Updated Timestamp', - link: '/reference/default-theme-last-updated' - }, - { - text: 'Search', - link: '/reference/default-theme-search' - }, - { - text: 'Carbon Ads', - link: '/reference/default-theme-carbon-ads' - } - ] - } - ] - } - ] -} + transformPageData: prod + ? (pageData, ctx) => { + const site = resolveSiteDataByRoute( + ctx.siteConfig.site, + pageData.relativePath + ) + const title = `${pageData.title || site.title} | ${pageData.description || site.description}` + ;((pageData.frontmatter.head ??= []) as HeadConfig[]).push( + ['meta', { property: 'og:locale', content: site.lang }], + ['meta', { property: 'og:title', content: title }] + ) + } + : undefined +}) diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts new file mode 100644 index 00000000..0e7ba37f --- /dev/null +++ b/docs/.vitepress/theme/index.ts @@ -0,0 +1,5 @@ +import Theme from 'vitepress/theme' +import 'virtual:group-icons.css' +import './styles.css' + +export default Theme diff --git a/docs/.vitepress/theme/styles.css b/docs/.vitepress/theme/styles.css new file mode 100644 index 00000000..2635e80d --- /dev/null +++ b/docs/.vitepress/theme/styles.css @@ -0,0 +1,43 @@ +:root:where(:lang(fa)) { + --vp-font-family-base: + 'Vazirmatn', 'Inter', ui-sans-serif, system-ui, sans-serif, + 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; +} + +:root { + --vp-home-hero-name-color: transparent; + --vp-home-hero-name-background: -webkit-linear-gradient( + 120deg, + #bd34fe 30%, + #41d1ff + ); + --vp-home-hero-image-background-image: linear-gradient( + -45deg, + #bd34fe 50%, + #47caff 50% + ); + --vp-home-hero-image-filter: blur(44px); +} + +@media (min-width: 640px) { + :root { + --vp-home-hero-image-filter: blur(56px); + } +} + +@media (min-width: 960px) { + :root { + --vp-home-hero-image-filter: blur(68px); + } +} + +.VPHero .VPImage { + filter: drop-shadow(-2px 4px 6px rgba(0, 0, 0, 0.2)); + padding: 18px; +} + +/* used in reference/default-theme-search */ +img[src='/search.png'] { + width: 100%; + aspect-ratio: 1 / 1; +} diff --git a/docs/config.ts b/docs/config.ts new file mode 100644 index 00000000..a09a3a67 --- /dev/null +++ b/docs/config.ts @@ -0,0 +1,139 @@ +import { createRequire } from 'module' +import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' + +const require = createRequire(import.meta.url) +const pkg = require('vitepress/package.json') + +export default defineAdditionalConfig({ + lang: 'en-US', + description: 'Vite & Vue powered static site generator.', + + themeConfig: { + nav: nav(), + + sidebar: { + '/guide/': { base: '/guide/', items: sidebarGuide() }, + '/reference/': { base: '/reference/', items: sidebarReference() } + }, + + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + text: 'Edit this page on GitHub' + }, + + footer: { + message: 'Released under the MIT License.', + copyright: 'Copyright © 2019-present Evan You' + } + } +}) + +function nav(): DefaultTheme.NavItem[] { + return [ + { + text: 'Guide', + link: '/guide/what-is-vitepress', + activeMatch: '/guide/' + }, + { + text: 'Reference', + link: '/reference/site-config', + activeMatch: '/reference/' + }, + { + text: pkg.version, + items: [ + { + text: 'Changelog', + link: 'https://github.com/vuejs/vitepress/blob/main/CHANGELOG.md' + }, + { + text: 'Contributing', + link: 'https://github.com/vuejs/vitepress/blob/main/.github/contributing.md' + } + ] + } + ] +} + +function sidebarGuide(): DefaultTheme.SidebarItem[] { + return [ + { + text: 'Introduction', + collapsed: false, + items: [ + { text: 'What is VitePress?', link: 'what-is-vitepress' }, + { text: 'Getting Started', link: 'getting-started' }, + { text: 'Routing', link: 'routing' }, + { text: 'Deploy', link: 'deploy' } + ] + }, + { + text: 'Writing', + collapsed: false, + items: [ + { text: 'Markdown Extensions', link: 'markdown' }, + { text: 'Asset Handling', link: 'asset-handling' }, + { text: 'Frontmatter', link: 'frontmatter' }, + { text: 'Using Vue in Markdown', link: 'using-vue' }, + { text: 'Internationalization', link: 'i18n' } + ] + }, + { + text: 'Customization', + collapsed: false, + items: [ + { text: 'Using a Custom Theme', link: 'custom-theme' }, + { + text: 'Extending the Default Theme', + link: 'extending-default-theme' + }, + { text: 'Build-Time Data Loading', link: 'data-loading' }, + { text: 'SSR Compatibility', link: 'ssr-compat' }, + { text: 'Connecting to a CMS', link: 'cms' } + ] + }, + { + text: 'Experimental', + collapsed: false, + items: [ + { text: 'MPA Mode', link: 'mpa-mode' }, + { text: 'Sitemap Generation', link: 'sitemap-generation' } + ] + }, + { text: 'Config & API Reference', base: '/reference/', link: 'site-config' } + ] +} + +function sidebarReference(): DefaultTheme.SidebarItem[] { + return [ + { + text: 'Reference', + items: [ + { text: 'Site Config', link: 'site-config' }, + { text: 'Frontmatter Config', link: 'frontmatter-config' }, + { text: 'Runtime API', link: 'runtime-api' }, + { text: 'CLI', link: 'cli' }, + { + text: 'Default Theme', + base: '/reference/default-theme-', + items: [ + { text: 'Overview', link: 'config' }, + { text: 'Nav', link: 'nav' }, + { text: 'Sidebar', link: 'sidebar' }, + { text: 'Home Page', link: 'home-page' }, + { text: 'Footer', link: 'footer' }, + { text: 'Layout', link: 'layout' }, + { text: 'Badge', link: 'badge' }, + { text: 'Team Page', link: 'team-page' }, + { text: 'Prev / Next Links', link: 'prev-next-links' }, + { text: 'Edit Link', link: 'edit-link' }, + { text: 'Last Updated Timestamp', link: 'last-updated' }, + { text: 'Search', link: 'search' }, + { text: 'Carbon Ads', link: 'carbon-ads' } + ] + } + ] + } + ] +} diff --git a/docs/guide/asset-handling.md b/docs/en/guide/asset-handling.md similarity index 89% rename from docs/guide/asset-handling.md rename to docs/en/guide/asset-handling.md index d8260687..eeedc8c0 100644 --- a/docs/guide/asset-handling.md +++ b/docs/en/guide/asset-handling.md @@ -12,6 +12,10 @@ You can reference static assets in your markdown files, your `*.vue` components Common image, media, and font filetypes are detected and included as assets automatically. +::: tip Linked files are not treated as assets +PDFs or other documents referenced by links within markdown files are not automatically treated as assets. To make linked files accessible, you must manually place them within the [`public`](#the-public-directory) directory of your project. +::: + All referenced assets, including those using absolute paths, will be copied to the output directory with a hashed file name in the production build. Never-referenced assets will not be copied. Image assets smaller than 4kb will be base64 inlined - this can be configured via the [`vite`](../reference/site-config#vite) config option. All **static** path references, including absolute paths, should be based on your working directory structure. @@ -26,11 +30,6 @@ Assets placed in `public` will be copied to the root of the output directory as- Note that you should reference files placed in `public` using root absolute path - for example, `public/icon.png` should always be referenced in source code as `/icon.png`. -There is one exception to this: if you have an HTML page in `public` and link to it from the main site, the router will yield a 404 by default. To get around this, VitePress provides a `pathname://` protocol which allows you to link to another page in the same domain as if the link is external. Compare these two links: - -- [/pure.html](/pure.html) -- - ## Base URL If your site is deployed to a non-root URL, you will need to set the `base` option in `.vitepress/config.js`. For example, if you plan to deploy your site to `https://foo.github.io/bar/`, then `base` should be set to `'/bar/'` (it should always start and end with a slash). diff --git a/docs/guide/cms.md b/docs/en/guide/cms.md similarity index 100% rename from docs/guide/cms.md rename to docs/en/guide/cms.md diff --git a/docs/guide/custom-theme.md b/docs/en/guide/custom-theme.md similarity index 96% rename from docs/guide/custom-theme.md rename to docs/en/guide/custom-theme.md index 83625a23..96943c9f 100644 --- a/docs/guide/custom-theme.md +++ b/docs/en/guide/custom-theme.md @@ -49,8 +49,7 @@ interface EnhanceAppContext { The theme entry file should export the theme as its default export: -```js -// .vitepress/theme/index.js +```js [.vitepress/theme/index.js] // You can directly import Vue files in the theme entry // VitePress is pre-configured with @vitejs/plugin-vue. @@ -72,8 +71,7 @@ Inside your layout component, it works just like a normal Vite + Vue 3 applicati The most basic layout component needs to contain a [``](../reference/runtime-api#content) component: -```vue - +```vue [.vitepress/theme/Layout.vue] - + ``` @@ -212,6 +210,9 @@ interface TeamMember { // URL for the sponsor page for the member. sponsor?: string + + // Text for the sponsor link. Defaults to 'Sponsor'. + actionText?: string } ``` diff --git a/docs/reference/frontmatter-config.md b/docs/en/reference/frontmatter-config.md similarity index 65% rename from docs/reference/frontmatter-config.md rename to docs/en/reference/frontmatter-config.md index 9008e2b9..4d6f86c0 100644 --- a/docs/reference/frontmatter-config.md +++ b/docs/en/reference/frontmatter-config.md @@ -86,7 +86,7 @@ type HeadConfig = The following frontmatter options are only applicable when using the default theme. -### layout +### layout - Type: `doc | home | page` - Default: `doc` @@ -103,15 +103,41 @@ layout: doc --- ``` -### hero +### hero Defines contents of home hero section when `layout` is set to `home`. More details in [Default Theme: Home Page](./default-theme-home-page). -### features +### features Defines items to display in features section when `layout` is set to `home`. More details in [Default Theme: Home Page](./default-theme-home-page). -### aside +### navbar + +- Type: `boolean` +- Default: `true` + +Whether to display [navbar](./default-theme-nav). + +```yaml +--- +navbar: false +--- +``` + +### sidebar + +- Type: `boolean` +- Default: `true` + +Whether to display [sidebar](./default-theme-sidebar). + +```yaml +--- +sidebar: false +--- +``` + +### aside - Type: `boolean | 'left'` - Default: `true` @@ -128,19 +154,25 @@ aside: false --- ``` -### outline +### outline - Type: `number | [number, number] | 'deep' | false` - Default: `2` -The levels of header in the outline to display for the page. It's same as [config.themeConfig.outline](./default-theme-config#outline), and it overrides the theme 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` +- Type: `boolean | Date` - Default: `true` -Whether to display [Last Updated](./default-theme-last-updated) text in the footer of the current page. +Whether to display [last updated](./default-theme-last-updated) text in the footer of the current page. If a datetime is specified, it will be displayed instead of the last git modified timestamp. ```yaml --- @@ -148,15 +180,61 @@ lastUpdated: false --- ``` -### editLink +### editLink - Type: `boolean` - Default: `true` -Whether to display [Edit Link](./default-theme-edit-link) in the footer of the current page. +Whether to display [edit link](./default-theme-edit-link) in the footer of the current page. ```yaml --- editLink: false --- ``` + +### footer + +- Type: `boolean` +- Default: `true` + +Whether to display [footer](./default-theme-footer). + +```yaml +--- +footer: false +--- +``` + +### pageClass + +- Type: `string` + +Add extra class name to a specific page. + +```yaml +--- +pageClass: custom-page-class +--- +``` + +Then you can customize styles of this specific page in `.vitepress/theme/custom.css` file: + +```css +.custom-page-class { + /* page-specific styles */ +} +``` + +### isHome + +- Type: `boolean` + +The default theme relies on checks like `frontmatter.layout === 'home'` to determine if the current page is the home page.\ +This is useful when you want to force show the home page elements in a custom layout. + +```yaml +--- +isHome: true +--- +``` diff --git a/docs/reference/runtime-api.md b/docs/en/reference/runtime-api.md similarity index 81% rename from docs/reference/runtime-api.md rename to docs/en/reference/runtime-api.md index 416a8217..d55165f5 100644 --- a/docs/reference/runtime-api.md +++ b/docs/en/reference/runtime-api.md @@ -38,6 +38,10 @@ interface VitePressData { isDark: Ref dir: Ref localeIndex: Ref + /** + * Current location hash + */ + hash: Ref } interface PageData { @@ -86,8 +90,31 @@ Returns the VitePress router instance so you can programmatically navigate to an ```ts interface Router { + /** + * Current route. + */ route: Route - go: (href?: string) => Promise + /** + * Navigate to a new URL. + */ + go: (to?: string) => Promise + /** + * Called before the route changes. Return `false` to cancel the navigation. + */ + onBeforeRouteChange?: (to: string) => Awaitable + /** + * Called before the page component is loaded (after the history state is updated). + * Return `false` to cancel the navigation. + */ + onBeforePageLoad?: (to: string) => Awaitable + /** + * Called after the page component is loaded (before the page component is updated). + */ + onAfterPageLoad?: (to: string) => Awaitable + /** + * Called after the route changes. + */ + onAfterRouteChange?: (to: string) => Awaitable } ``` @@ -122,7 +149,7 @@ If you are using or demoing components that are not SSR-friendly (for example, c ``` -- Related: [SSR Compatibility](/guide/ssr-compat) +- Related: [SSR Compatibility](../guide/ssr-compat) ## `$frontmatter` diff --git a/docs/reference/site-config.md b/docs/en/reference/site-config.md similarity index 67% rename from docs/reference/site-config.md rename to docs/en/reference/site-config.md index 0f020e8a..8cf5e264 100644 --- a/docs/reference/site-config.md +++ b/docs/en/reference/site-config.md @@ -10,7 +10,7 @@ Site config is where you can define the global settings of the site. App config ### Config Resolution -The config file is always resolved from `/.vitepress/config.[ext]`, where `` is your VitePress [project root](../guide/routing#root-and-source-directory), and `[ext]` is one of the supported file extensions. TypeScript is supported out of the box. Supported extensions include `.js`, `.ts`, `.cjs`, `.mjs`, `.cts`, and `.mts`. +The config file is always resolved from `/.vitepress/config.[ext]`, where `` is your VitePress [project root](../guide/routing#root-and-source-directory), and `[ext]` is one of the supported file extensions. TypeScript is supported out of the box. Supported extensions include `.js`, `.ts`, `.mjs`, and `.mts`. It is recommended to use ES modules syntax in config files. The config file should default export an object: @@ -24,6 +24,62 @@ export default { } ``` +:::details Dynamic (Async) Config + +If you need to dynamically generate the config, you can also default export a function. For example: + +```ts +import { defineConfig } from 'vitepress' + +export default async () => { + const posts = await (await fetch('https://my-cms.com/blog-posts')).json() + + return defineConfig({ + // app level config options + lang: 'en-US', + title: 'VitePress', + description: 'Vite & Vue powered static site generator.', + + // theme level config options + themeConfig: { + sidebar: [ + ...posts.map((post) => ({ + text: post.name, + link: `/posts/${post.name}` + })) + ] + } + }) +} +``` + +You can also use top-level `await`. For example: + +```ts +import { defineConfig } from 'vitepress' + +const posts = await (await fetch('https://my-cms.com/blog-posts')).json() + +export default defineConfig({ + // app level config options + lang: 'en-US', + title: 'VitePress', + description: 'Vite & Vue powered static site generator.', + + // theme level config options + themeConfig: { + sidebar: [ + ...posts.map((post) => ({ + text: post.name, + link: `/posts/${post.name}` + })) + ] + } +}) +``` + +::: + ### Config Intellisense Using the `defineConfig` helper will provide TypeScript-powered intellisense for config options. Assuming your IDE supports it, this should work in both JavaScript and TypeScript. @@ -155,17 +211,56 @@ export default { Additional elements to render in the `` tag in the page HTML. The user-added tags are rendered before the closing `head` tag, after VitePress tags. +```ts +type HeadConfig = + | [string, Record] + | [string, Record, string] +``` + +#### Example: Adding a favicon + +```ts +export default { + head: [['link', { rel: 'icon', href: '/favicon.ico' }]] +} // put favicon.ico in public directory, if base is set, use /base/favicon.ico + +/* Would render: + +*/ +``` + +#### Example: Adding Google Fonts + ```ts export default { head: [ + [ + 'link', + { rel: 'preconnect', href: 'https://fonts.googleapis.com' } + ], [ 'link', { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: '' } - // would render: - // - // ], + [ + 'link', + { href: 'https://fonts.googleapis.com/css2?family=Roboto&display=swap', rel: 'stylesheet' } + ] + ] +} + +/* Would render: + + + +*/ +``` +#### Example: Registering a service worker + +```ts +export default { + head: [ [ 'script', { id: 'register-sw' }, @@ -174,24 +269,50 @@ export default { navigator.serviceWorker.register('/sw.js') } })()` - // would render: - // - // ] ] } + +/* Would render: + +*/ ``` +#### Example: Using Google Analytics + ```ts -type HeadConfig = - | [string, Record] - | [string, Record, string] +export default { + head: [ + [ + 'script', + { async: '', src: 'https://www.googletagmanager.com/gtag/js?id=TAG_ID' } + ], + [ + 'script', + {}, + `window.dataLayer = window.dataLayer || []; + function gtag(){dataLayer.push(arguments);} + gtag('js', new Date()); + gtag('config', 'TAG_ID');` + ] + ] +} + +/* Would render: + + +*/ ``` ### lang @@ -239,7 +360,7 @@ Enabling this may require additional configuration on your hosting platform. For - Type: `Record` -Defines custom directory <-> URL mappings. See [Routing: Route Rewrites](../guide/routing#route-rewrites) for more details. +Defines custom directory <-> URL mappings. See [Routing: Route Rewrites](../guide/routing#route-rewrites) for more details. ```ts export default { @@ -266,7 +387,7 @@ export default { ### srcExclude -- Type: `string` +- Type: `string[]` - Default: `undefined` A [glob pattern](https://github.com/mrmlnc/fast-glob#pattern-syntax) for matching markdown files that should be excluded as source content. @@ -290,6 +411,19 @@ export default { } ``` +### assetsDir + +- Type: `string` +- Default: `assets` + +Specify the directory to nest generated assets under. The path should be inside [`outDir`](#outdir) and is resolved relative to it. + +```ts +export default { + assetsDir: 'static' +} +``` + ### cacheDir - Type: `string` @@ -337,6 +471,13 @@ export default { } ``` +### metaChunk + +- Type: `boolean` +- Default: `false` + +When set to `true`, extract pages metadata to a separate JavaScript chunk instead of inlining it in the initial HTML. This makes each page's HTML payload smaller and makes the pages metadata cacheable, thus reducing server bandwidth when you have many pages in the site. + ### mpa - Type: `boolean` @@ -348,7 +489,7 @@ When set to `true`, the production app will be built in [MPA Mode](../guide/mpa- ### appearance -- Type: `boolean | 'dark'` +- Type: `boolean | 'dark' | 'force-dark' | 'force-auto' | import('@vueuse/core').UseDarkOptions` - Default: `true` Whether to enable dark mode (by adding the `.dark` class to the `` element). @@ -356,9 +497,13 @@ Whether to enable dark mode (by adding the `.dark` class to the `` element - If the option is set to `true`, the default theme will be determined by the user's preferred color scheme. - If the option is set to `dark`, the theme will be dark by default, unless the user manually toggles it. - If the option is set to `false`, users will not be able to toggle the theme. +- If the option is set to `'force-dark'`, the theme will always be dark and users will not be able to toggle it. +- If the option is set to `'force-auto'`, the theme will always be determined by the user's preferred color scheme and users will not be able to toggle it. This option injects an inline script that restores users settings from local storage using the `vitepress-theme-appearance` key. This ensures the `.dark` class is applied before the page is rendered to avoid flickering. +`appearance.initialValue` can only be `'dark' | undefined`. Refs or getters are not supported. + ### lastUpdated - Type: `boolean` @@ -374,81 +519,15 @@ When using the default theme, enabling this option will display each page's last - Type: `MarkdownOption` -Configure Markdown parser options. VitePress uses [Markdown-it](https://github.com/markdown-it/markdown-it) as the parser, and [Shiki](https://shiki.matsu.io/) to highlight language syntax. Inside this option, you may pass various Markdown related options to fit your needs. +Configure Markdown parser options. VitePress uses [Markdown-it](https://github.com/markdown-it/markdown-it) as the parser, and [Shiki](https://github.com/shikijs/shiki) to highlight language syntax. Inside this option, you may pass various Markdown related options to fit your needs. ```js export default { - markdown: { - theme: 'material-theme-palenight', - lineNumbers: true, - - // adjust how header anchors are generated, - // useful for integrating with tools that use different conventions - anchor: { - slugify(str) { - return encodeURIComponent(str) - } - } - } + markdown: {...} } ``` -Below are all the options that you can have in this object: - -```ts -interface MarkdownOptions extends MarkdownIt.Options { - // Custom theme for syntax highlighting. - // You can use an existing theme. - // See: https://github.com/shikijs/shiki/blob/main/docs/themes.md#all-themes - // Or add your own theme. - // See: https://github.com/shikijs/shiki/blob/main/docs/themes.md#loading-theme - theme?: - | Shiki.IThemeRegistration - | { light: Shiki.IThemeRegistration; dark: Shiki.IThemeRegistration } - - // Enable line numbers in code block. - lineNumbers?: boolean - - // Add support for your own languages. - // https://github.com/shikijs/shiki/blob/main/docs/languages.md#supporting-your-own-languages-with-shiki - languages?: Shiki.ILanguageRegistration - - // markdown-it-anchor plugin options. - // See: https://github.com/valeriangalliat/markdown-it-anchor#usage - anchor?: anchorPlugin.AnchorOptions - - // markdown-it-attrs plugin options. - // See: https://github.com/arve0/markdown-it-attrs - attrs?: { - leftDelimiter?: string - rightDelimiter?: string - allowedAttributes?: string[] - disable?: boolean - } - - // specify default language for syntax highlighter - defaultHighlightLang?: string - - // @mdit-vue/plugin-frontmatter plugin options. - // See: https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-frontmatter#options - frontmatter?: FrontmatterPluginOptions - - // @mdit-vue/plugin-headers plugin options. - // See: https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-headers#options - headers?: HeadersPluginOptions - - // @mdit-vue/plugin-sfc plugin options. - // See: https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-sfc#options - sfc?: SfcPluginOptions - - // @mdit-vue/plugin-toc plugin options. - // See: https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-toc#options - toc?: TocPluginOptions - - // Configure the Markdown-it instance. - config?: (md: MarkdownIt) => void -} -``` +Check the [type declaration and jsdocs](https://github.com/vuejs/vitepress/blob/main/src/node/markdown/markdown.ts) for all the options available. ### vite @@ -530,7 +609,7 @@ interface SSGContext { `transformHead` is a build hook to transform the head before generating each page. It will allow you to add head entries that cannot be statically added to your VitePress config. You only need to return extra entries, they will be merged automatically with the existing ones. ::: warning -Don't mutate anything inside the `ctx`. +Don't mutate anything inside the `context`. ::: ```ts @@ -555,14 +634,52 @@ interface TransformContext { } ``` +Note that this hook is only called when generating the site statically. It is not called during dev. If you need to add dynamic head entries during dev, you can use the [`transformPageData`](#transformpagedata) hook instead: + +```ts +export default { + transformPageData(pageData) { + pageData.frontmatter.head ??= [] + pageData.frontmatter.head.push([ + 'meta', + { + name: 'og:title', + content: + pageData.frontmatter.layout === 'home' + ? `VitePress` + : `${pageData.title} | VitePress` + } + ]) + } +} +``` + +#### Example: Adding a canonical URL `` + +```ts +export default { + transformPageData(pageData) { + const canonicalUrl = `https://example.com/${pageData.relativePath}` + .replace(/index\.md$/, '') + .replace(/\.md$/, '.html') + + pageData.frontmatter.head ??= [] + pageData.frontmatter.head.push([ + 'link', + { rel: 'canonical', href: canonicalUrl } + ]) + } +} +``` + ### transformHtml -- Type: `(code: string, id: string, ctx: TransformContext) => Awaitable` +- Type: `(code: string, id: string, context: TransformContext) => Awaitable` `transformHtml` is a build hook to transform the content of each page before saving to disk. ::: warning -Don't mutate anything inside the `ctx`. Also, modifying the html content may cause hydration problems in runtime. +Don't mutate anything inside the `context`. Also, modifying the html content may cause hydration problems in runtime. ::: ```ts @@ -575,12 +692,12 @@ export default { ### transformPageData -- Type: `(pageData: PageData, ctx: TransformPageContext) => Awaitable | { [key: string]: any } | void>` +- Type: `(pageData: PageData, context: TransformPageContext) => Awaitable | { [key: string]: any } | void>` -`transformPageData` is a hook to transform the `pageData` of each page. You can directly mutate `pageData` or return changed values which will be merged into PageData. +`transformPageData` is a hook to transform the `pageData` of each page. You can directly mutate `pageData` or return changed values which will be merged into the page data. ::: warning -Don't mutate anything inside the `ctx`. +Don't mutate anything inside the `context` and be careful that this might impact the performance of dev server, especially if you have some network requests or heavy computations (like generating images) in the hook. You can check for `process.env.NODE_ENV === 'production'` for conditional logic. ::: ```ts diff --git a/docs/es/config.ts b/docs/es/config.ts new file mode 100644 index 00000000..099edba6 --- /dev/null +++ b/docs/es/config.ts @@ -0,0 +1,222 @@ +import { createRequire } from 'module' +import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' + +const require = createRequire(import.meta.url) +const pkg = require('vitepress/package.json') + +export default defineAdditionalConfig({ + lang: 'es-CO', + description: 'Generador de Sitios Estaticos desarrollado con Vite y Vue.', + + themeConfig: { + nav: nav(), + + search: { options: searchOptions() }, + + sidebar: { + '/es/guide/': { base: '/es/guide/', items: sidebarGuide() }, + '/es/reference/': { base: '/es/reference/', items: sidebarReference() } + }, + + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + text: 'Editar esta página en GitHub' + }, + + footer: { + message: 'Liberado bajo la licencia MIT', + copyright: `Derechos reservados © 2019-${new Date().getFullYear()} Evan You` + }, + + docFooter: { + prev: 'Anterior', + next: 'Siguiente' + }, + + outline: { + label: 'En esta página' + }, + + lastUpdated: { + text: 'Actualizado en' + }, + + notFound: { + title: 'PÁGINA NO ENCONTRADA', + quote: + 'Pero si no cambias de dirección y sigues buscando, podrías terminar donde te diriges.', + linkLabel: 'ir a inicio', + linkText: 'Llévame a casa' + }, + + langMenuLabel: 'Cambiar Idioma', + returnToTopLabel: 'Volver arriba', + sidebarMenuLabel: 'Menu Lateral', + darkModeSwitchLabel: 'Tema Oscuro', + lightModeSwitchTitle: 'Cambiar a modo claro', + darkModeSwitchTitle: 'Cambiar a modo oscuro', + skipToContentLabel: 'Saltar al contenido' + } +}) + +function nav(): DefaultTheme.NavItem[] { + return [ + { + text: 'Guia', + link: '/es/guide/what-is-vitepress', + activeMatch: '/es/guide/' + }, + { + text: 'Referencia', + link: '/es/reference/site-config', + activeMatch: '/es/reference/' + }, + { + text: pkg.version, + items: [ + { + text: 'Registro de cambios', + link: 'https://github.com/vuejs/vitepress/blob/main/CHANGELOG.md' + }, + { + text: 'Contribuir', + link: 'https://github.com/vuejs/vitepress/blob/main/.github/contributing.md' + } + ] + } + ] +} + +function sidebarGuide(): DefaultTheme.SidebarItem[] { + return [ + { + text: 'Introducción', + collapsed: false, + items: [ + { text: 'Qué es VitePress?', link: 'what-is-vitepress' }, + { text: 'Iniciando', link: 'getting-started' }, + { text: 'Enrutamiento', link: 'routing' }, + { text: 'Despliegue', link: 'deploy' } + ] + }, + { + text: 'Escribiendo', + collapsed: false, + items: [ + { text: 'Extensiones Markdown', link: 'markdown' }, + { text: 'Manejo de assets', link: 'asset-handling' }, + { text: 'Frontmatter', link: 'frontmatter' }, + { text: 'Usando Vue en Markdown', link: 'using-vue' }, + { text: 'Internacionalización', link: 'i18n' } + ] + }, + { + text: 'Pesonalización', + collapsed: false, + items: [ + { text: 'Usando un tema personalizado', link: 'custom-theme' }, + { + text: 'Extendiendo el tema por defecto', + link: 'extending-default-theme' + }, + { + text: 'Carga de datos en tiempo de compilación', + link: 'data-loading' + }, + { text: 'Compatibilidad SSR', link: 'ssr-compat' }, + { text: 'Conectando a un CMS', link: 'cms' } + ] + }, + { + text: 'Experimental', + collapsed: false, + items: [ + { text: 'Modo MPA', link: 'mpa-mode' }, + { text: 'Generación de Sitemap', link: 'sitemap-generation' } + ] + }, + { + text: 'Configuración y Referencia del API', + base: '/es/reference/', + link: 'site-config' + } + ] +} + +function sidebarReference(): DefaultTheme.SidebarItem[] { + return [ + { + text: 'Referencia', + items: [ + { text: 'Configuración del sitio', link: 'site-config' }, + { text: 'Configuración Frontmatter', link: 'frontmatter-config' }, + { text: 'API de tiempo de ejecución', link: 'runtime-api' }, + { text: 'CLI', link: 'cli' }, + { + text: 'Tema por defecto', + base: '/es/reference/default-theme-', + items: [ + { text: 'Visión general', link: 'config' }, + { text: 'Navegación', link: 'nav' }, + { text: 'Barra Lateral', link: 'sidebar' }, + { text: 'Página Inicial', link: 'home-page' }, + { text: 'Pie de página', link: 'footer' }, + { text: 'Layout', link: 'layout' }, + { text: 'Distintivo', link: 'badge' }, + { text: 'Página del equipo', link: 'team-page' }, + { text: 'Links Anterior / Siguiente', link: 'prev-next-links' }, + { text: 'Editar Link', link: 'edit-link' }, + { text: 'Sello temporal de actualización', link: 'last-updated' }, + { text: 'Busqueda', link: 'search' }, + { text: 'Carbon Ads', link: 'carbon-ads' } + ] + } + ] + } + ] +} + +function searchOptions(): Partial { + return { + placeholder: 'Buscar documentos', + translations: { + button: { + buttonText: 'Buscar', + buttonAriaLabel: 'Buscar' + }, + modal: { + searchBox: { + resetButtonTitle: 'Limpiar búsqueda', + resetButtonAriaLabel: 'Limpiar búsqueda', + cancelButtonText: 'Cancelar', + cancelButtonAriaLabel: 'Cancelar' + }, + startScreen: { + recentSearchesTitle: 'Historial de búsqueda', + noRecentSearchesText: 'Ninguna búsqueda reciente', + saveRecentSearchButtonTitle: 'Guardar en el historial de búsqueda', + removeRecentSearchButtonTitle: 'Borrar del historial de búsqueda', + favoriteSearchesTitle: 'Favoritos', + removeFavoriteSearchButtonTitle: 'Borrar de favoritos' + }, + errorScreen: { + titleText: 'No fue posible obtener resultados', + helpText: 'Verifique su conexión de red' + }, + footer: { + selectText: 'Seleccionar', + navigateText: 'Navegar', + closeText: 'Cerrar', + searchByText: 'Busqueda por' + }, + noResultsScreen: { + noResultsText: 'No fue posible encontrar resultados', + suggestedQueryText: 'Puede intentar una nueva búsqueda', + reportMissingResultsText: + 'Deberian haber resultados para esa consulta?', + reportMissingResultsLinkText: 'Click para enviar feedback' + } + } + } + } +} diff --git a/docs/es/guide/asset-handling.md b/docs/es/guide/asset-handling.md new file mode 100644 index 00000000..18c07d26 --- /dev/null +++ b/docs/es/guide/asset-handling.md @@ -0,0 +1,59 @@ +# Manejo de Assets {#asset-handling} + +## Referenciando Assets Estáticos {#referencing-static-assets} + +Todos los archivos Markdown son compilados en componentes Vue y procesados por [Vite](https://vitejs.dev/guide/assets.html). Usted puede **y debe** referenciar cualquier asset usando URLs relativas: + +```md +![Una imagen](./imagen.png) +``` + +Puede referenciar assets estáticos en sus archivos markdown, sus componentes `*.vue` en el tema, estilos y simples archivos `.css`, usando paths públicos absolutos (com base en la raiz del projeto) o paths relativos (con base en su sistema de arhivos). Este último es semejante al comportamiento que está acostumbrado se ya usó Vite, Vue CLI o el `file-loader` de webpack. + +Tipos comunes de archivos de imagen, media y fuente son detectados e incluidos automaticamente como assets. + +Todos los assets referenciados, incluyendo aquellos usando paths absolutos, serán copiados al directorio de salida con un nombre de archivo hash en la compilación de producción. Assets nunca referenciados no serán copiados. Assets de imagen menores que 4KB serán incorporados en base64 - esto puede ser configurado por la opción [`vite`](../reference/site-config#vite) en configuración. + +Todas las referencias de path **estáticas**, incluyendo paths absolutos, deben ser basadas en la estructura de su directorio de trabajo. + +## El directorio público {#the-public-directory} + +A veces, puede ser necesario proveer assets estáticos que no son referenciados directamente en ninguno de sus componentes del tema o Markdown, o usted puede querer servir ciertos archivos con el nombre del archivo original. Ejemplos de tales archivos incluyen `robots.txt`, favicons e iconos PWA. + +Puede colocar esos archivos en el directorio `public` sobre el [directorio de origen](./routing#source-directory). Por ejemplo, se la raiz de su proyecto fuera `./docs` y estuviera usando localización por defecto del directorio fuente, entonces el directorio público será `./docs/public`. + +Los assets colocados en `public` serán copiados a la raiz del directorio de salida tal como son. + +Observe que usted debe referenciar archivos colocados en `public` usando e path absoluto de la raiz - por ejemplo, `public/icon.png` debe siempre ser referenciado en el código fuente como `/icon.png`. + +## URL Base {#base-url} + +Si su sitio estuviera implantado en una URL que no sea la raiz, será necesario definir la opción `base` en `.vitepress/config.js`. Por ejemplo, se planea implantar su sitio en `https://foo.github.io/bar/`, entonces `base` debe ser definido como `'/bar/'` (siempre debe comenzar y terminar con una barra). + +Todos los paths de sus assets estáticos son procesados automáticamente para ajustarse a los diferentes valores de configuración `base`. Por ejemplo, se tuviera una referencia absoluta a un asset sobre `public` en su Markdown: + +```md +![Una imagen](/imagen-dentro-de-public.png) +``` + +**No** necesita actualizarlo cuando altere el valor de configuración `base` en ese caso. + +Sin embargo, se estuviera creando un componente de tema que vincula assets dinámicamente, por ejemplo, una imagen cuyo `src` esta basado en un valor de configuración del tema: + +```vue + +``` + +En este caso, es recomendable complementar el path con el [`auxiliar withBase`](../reference/runtime-api#withbase) proporcionado por VitePress: + +```vue + + + +``` diff --git a/docs/es/guide/cms.md b/docs/es/guide/cms.md new file mode 100644 index 00000000..88020297 --- /dev/null +++ b/docs/es/guide/cms.md @@ -0,0 +1,56 @@ +--- +outline: deep +--- + +# Conectando a un CMS {#connecting-to-a-cms} + +## Flujo de Trabajo general {#general-workflow} + +Conectar VitePress a un CMS girará mayormente en torno a [Rutas dinámicas](./routing#dynamic-routes). Asegurese de entender cómo funcionan antes de proceder. + +Como cada CMS funcionará de forma diferente, aqui podemos proveer apenas un flujo de trabajo genérico que requiere ser adaptado para cada escenario específico. + +1. Si su CMS exige autenticación, cree un archivo `.env` para almacenar los tokens del API y cargarlos como: + + ```js + // posts/[id].paths.js + import { loadEnv } from 'vitepress' + + const env = loadEnv('', process.cwd()) + ``` + +2. Obtenga los datos necesarios del CMS y aplique formato en paths de datos apropiados: + + ```js + export default { + async paths() { + // use la biblioteca del cliente CMS respectiva si es necesario + const data = await (await fetch('https://my-cms-api', { + headers: { + // token caso necesario + } + })).json() + + return data.map(entry => { + return { + params: { id: entry.id, /* título, autores, data, etc. */ }, + content: entry.content + } + }) + } + } + ``` + +3. Presente el contenido en la página: + + ```md + # {{ $params.title }} + + - por {{ $params.author }} en {{ $params.date }} + + + ``` + +## Guias de Integración {#integration-guides} + +Se usted escribió una guía sobre cómo integrar VitePress con un CMS específico, por favor use el link "Edite esta página" abajo para enviarlo hacia aqui! diff --git a/docs/es/guide/custom-theme.md b/docs/es/guide/custom-theme.md new file mode 100644 index 00000000..4b13b77b --- /dev/null +++ b/docs/es/guide/custom-theme.md @@ -0,0 +1,218 @@ +# Usando un Tema Personalizado {#using-a-custom-theme} + +## Carga de Tema {#theme-resolving} + +Puede habilitar un tema personalizado creando un archivo `.vitepress/theme/index.js` o `.vitepress/theme/index.ts` (o "archivo de entrada de tema"): + +``` +. +├─ docs # raiz del proyecto +│ ├─ .vitepress +│ │ ├─ theme +│ │ │ └─ index.js # entrada de tema +│ │ └─ config.js # archivo de configuración +│ └─ index.md +└─ package.json +``` + +VitePress siempre usará el tema personalizado en vez del tema por defecto cuando detecte la precencia de un archivo de entrada de tema. Sin embargo, puede [extender el tema por defecto](./extending-default-theme) para realizar personalizaciones avanzadas sobre el. + +## Interfaz del Tema {#theme-interface} + +Un tema personalizado de VitePress es definifo como un objeto con la siguiente interfaz: + +```ts +interface Theme { + /** + * Componente raiz de layout para todas las páginas + * @required + */ + Layout: Component + /** + * Mejora la instancia de la aplicación Vue + * @optional + */ + enhanceApp?: (ctx: EnhanceAppContext) => Awaitable + /** + * Extiende otro tema, llamando su `enhanceApp` antes de nuestro + * @optional + */ + extends?: Theme +} + +interface EnhanceAppContext { + app: App // instancia de la aplicación Vue + router: Router // instancia del enrutador VitePress + siteData: Ref // Metadata a nivel del sitio +} +``` + +El archivo de entrada del tema debe exportar el tema como su exportación por defecto: + +```js [.vitepress/theme/index.js] + +// Puede importar archivos Vue directamente en el archivo de entrada del tema +// VitePress ya está preconfigurado con @vitejs/plugin-vue. +import Layout from './Layout.vue' + +export default { + Layout, + enhanceApp({ app, router, siteData }) { + // ... + } +} +``` + +La exportación por defecto es el único contrato para un tema personalizado, y apenas la propiedad `Layout` es exigida. Tecnicamente, un tema de VitePress puede ser tan simple como un único componente Vue. + +Dentro de su componente de layout, el funciona como una aplicación Vite + Vue 3 normal. Note que el tema también necesita ser [compatible con SSR](./ssr-compat). + +## Construyendo un Layout {#building-a-layout} + +El componente de layout más básico necesita un componente [``](../reference/runtime-api#content): + +```vue [.vitepress/theme/Layout.vue] + +``` + +El layout encima simplemente renderiza el markdown de todas las páginas cómo HTML. La primera mejora que podemos adicionar es lidiar con errores 404: + +```vue{1-4,9-12} + + + +``` + +El auxiliar [`useData()`](../reference/runtime-api#usedata) proporciona todos los datos en tiempo de ejecución que necesitamos para mostrar layouts diferentes. Uno de los otros datos que podemos accesar es el frontmatter de la página actual. Podemos aprovechar esto para permitir que el usuario final controle el layout en cada página. Por ejemplo, el usuario puede indicar que la página debe usar un layout especial de la pagina inicial con: + +```md +--- +layout: home +--- +``` + +Y podemos ajustar nuestro tema para lidiar con esto: + +```vue{3,12-14} + + + +``` + +Puede, claro está, dividir el layout en más componentes: + +```vue{3-5,12-15} + + + +``` + +Consulte la [Referencia del API en tiempo de Ejecución](../reference/runtime-api) para todo lo que está disponible en componentes de tema. Además, puede aprovechar la [Carga de datos en Tiempo de Compilación](./data-loading) para generar layouts orientados por datos - por ejemplo, una página que lista todos los posts del blog en el proyecto actual. + +## Distribuyendo un Tema Personalizado {#distributing-a-custom-theme} + +La manera más facil de distribuir un tema personalizado es proporcionarlo como un [repositorio de template en GitHub](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-template-repository). + +Si desea distribuir su tema como un paquete npm, siga estos pasos: + +1. Exporte el objeto del tema como la exportación por defecto en su archivo de paquete. + +2. Si aplica, exporte la definición de configuración del tipo de tema como `ThemeConfig`. + +3. Si su tema exige ajustes en la configuración de VitePress, exporte esa configuración en un subdirectorio del paquete (por ejemplo, `mi-tema/config`) para que el usuario pueda extenderlo. + +4. Documente las opciones de configuración del tema (Ambos, via archivo y frontmatter). + +5. Proporcione instrucciones claras sobre cómo consumir su tema(vea abajo). + +## Consumiendo un Tema Personalizado {#consuming-a-custom-theme} + +Para consumir un tema extereno, importelo e reexportelo a partir del archivo de entrada del tema personalizado: + +```js [.vitepress/theme/index.js] +import Theme from 'awesome-vitepress-theme' + +export default Theme +``` + +Si el tema necesita ser extendido: + +```js [.vitepress/theme/index.js] +import Theme from 'awesome-vitepress-theme' + +export default { + extends: Theme, + enhanceApp(ctx) { + // ... + } +} +``` + +Si el tema exige una configuración especial de VitePress, también necesitará extenderlo en su propia configuración: + +```ts +// .vitepress/theme/config.ts +import baseConfig from 'awesome-vitepress-theme/config' + +export default { + // extienda la configuración base del tema (de ser necesario) + extends: baseConfig +} +``` + +Finalmente, si el tema proporciona tipos para la configuración del tema: + +```ts +// .vitepress/theme/config.ts +import baseConfig from 'awesome-vitepress-theme/config' +import { defineConfigWithTheme } from 'vitepress' +import type { ThemeConfig } from 'awesome-vitepress-theme' + +export default defineConfigWithTheme({ + extends: baseConfig, + themeConfig: { + // El tipo es `ThemeConfig` + } +}) +``` diff --git a/docs/es/guide/data-loading.md b/docs/es/guide/data-loading.md new file mode 100644 index 00000000..eadafadd --- /dev/null +++ b/docs/es/guide/data-loading.md @@ -0,0 +1,243 @@ +# Carga de Datos en Tiempo de Compilacion {#build-time-data-loading} + +VitePress proporciona un recurso llamado **cargadores de dato** que permite cargar datos arbitrarios e importarlos desde páginas o componentes. La carga de datos es ejecutada **apenas en el tiempo del build** los datos resultantes serán serializados como JSON en el paquete de JavaScript final. + +Los cargadores de datos pueden ser usados para buscar datos remotos o generar metadatos con base en archivos locales. Por ejemplo, puede usar cargadores de datos para procesar todas sus pagínas API locales y generar automáticamente un indice de todas las entradas del API. + +## Uso Básico {#basic-usage} + +Un archivo de cargados de datos debe terminar con `.data.js` o `.data.ts`. El archivo debe proporcionar una exportación por defecto de un objeto con el método `load()`: + +```js [example.data.js] +export default { + load() { + return { + hello: 'world' + } + } +} +``` + +El módulo del cargador es validado apenas en Node.js, entonces puede importar APIs Node y dependencias npm caso necesario. +Puede importar entonces datos de este archivo en páginas `.md` y componentes `.vue` usando la exportación llamada `data`: + +```vue + + +
{{ data }}
+``` + +Salida: + +```json +{ + "hello": "world" +} +``` + +Notará que el propio cargados de datos no exporta `data`. Es VitePress llamando el método `load()` entre bastidores y exponiendo implicitamente el resultado por medio de la exportación llamada `data`. + +Esto funciona incluso si el cargador fuera asíncrono: + +```js +export default { + async load() { + // buscar datos remotos + return (await fetch('...')).json() + } +} +``` + +## Datos de Archivos Locales {#data-from-local-files} + +Cuando necesita generar datos con base en archivos locales, debe usar la opción `watch` en el cargador de datos para que los cambios hechos en esos archivos puedan accionar actualizaciones rápidas. + +La opción `watch` tabién es conveniente porque puede usar [patrones glob](https://github.com/mrmlnc/fast-glob#pattern-syntax) para corresponder a vários archivos. Los patrones pueden ser relativos al propio archivo del cargador, y la función `load()` recibirá los archivos correspondientes como paths absolutos. + +El siguiente ejemplo muestra el cargamento de archivos CSV y la transformación de estos en JSON usando [csv-parse](https://github.com/adaltas/node-csv/tree/master/packages/csv-parse/). Como este archivo solo es ejecutado en el tiempo del build, usted no enviará el procesador de CSV para el cliente! + +```js +import fs from 'node:fs' +import { parse } from 'csv-parse/sync' + +export default { + watch: ['./data/*.csv'], + load(watchedFiles) { + // watchedFiles será un array de paths absolutos de los archivos um array de caminhos absolutos dos arquivos correspondientes. + // generar un array de metadatos de post que puede ser usado para mostrar + // una lista en el layout del tema + return watchedFiles.map((file) => { + return parse(fs.readFileSync(file, 'utf-8'), { + columns: true, + skip_empty_lines: true + }) + }) + } +} +``` + +## `createContentLoader` + +Al construir un sitio enfocado en contenido, frecuentemente necesitamos crear una página de "archivo" o "índice": una página donde listamos todas las entradas disponibles en nuestra colección de contenido, por ejemplo, articulos de blog o páginas de API. Nosotros **podemos** implementar esto directamente con el API de cargador de datos, pero como este es un caso de uso tan común, VitePress también proporciona un auxiliar `createContentLoader` para simplificar esto: + +```js [posts.data.js] +import { createContentLoader } from 'vitepress' + +export default createContentLoader('posts/*.md', /* opciones */) +``` + +El auxiliar acepta un patrón glob relativo al [diretório fuente](./routing#source-directory) y retorna un objeto de cargador de datos `{ watch, load }` que puede ser usado como exportación por defecto en un archivo de cargador de datos. El también implementa cache con base en los sellos se datos del archivo para mejorar el desempeño en el desarrollo. + +Note que el cargador solo funciona con archivos Markdown - archivos no Markdown encontrados serán ignorados. + +Los datos cargados serán un _array_ con el tipo `ContentData[]`: + +```ts +interface ContentData { + // URL mapeada para la página. Ex: /posts/hello.html (no incluye la base) + // itere manualmente o use `transform` personalizado para normalizar los paths + url: string + // datos frontmatter de la página + frontmatter: Record + + // los siguientes están presentes si las opciones relevantes están habilitadas + // discutiremos sobre eso abajo + src: string | undefined + html: string | undefined + excerpt: string | undefined +} +``` + +Por defecto, apenas `url` y `frontmatter` son proporcionados. Esto ocurre porque los datos cargados serán incorporados como JSON en el paquete del cliente, entonces necesitamos ser cautelosos con su tamaño. Aqui está un ejemplo de cómo usar los datos para construir una página de índice de blog mínima: + +```vue + + + +``` + +### Opciones {#options} + +Los datos por defecto pueden no atender todas las necesidades - puede optar por transformar los datos usando opciones: + +```js [posts.data.js] +import { createContentLoader } from 'vitepress' + +export default createContentLoader('posts/*.md', { + includeSrc: true, // incluir fuente markdown en crudo? + render: true, // incluir HTML completo de la página presentada? + excerpt: true, // incluir extracto? + transform(rawData) { + // mapee, ordene o filtre los datos en crudo como desee. + // el resultado final es lo que será enviado al cliente. + return rawData.sort((a, b) => { + return +new Date(b.frontmatter.date) - +new Date(a.frontmatter.date) + }).map((page) => { + page.src // fuente markdown en crudo + page.html // HTML completo de la página presentada + page.excerpt // HTML del extracto presentado (contenido encima del primer `---`) + return {/* ... */} + }) + } +}) +``` + +Vea cómo es usado en el [blog Vue.js](https://github.com/vuejs/blog/blob/main/.vitepress/theme/posts.data.ts). + +El API `createContentLoader` también puede ser usada dentro de los [build hooks](../reference/site-config#build-hooks): + +```js [.vitepress/config.js] +export default { + async buildEnd() { + const posts = await createContentLoader('posts/*.md').load() + // generar archivos con base en los metadatos de los posts, por ejemplo, feed RSS + } +} +``` + +**Tipos** + +```ts +interface ContentOptions { + /** + * Incluir src? + * @default false + */ + includeSrc?: boolean + + /** + * Renderizar src para HTML e incluir en los datos? + * @default false + */ + render?: boolean + + /** + * Si `boolean`, debe procesarse e incluir el resumen? (presentado como HTML) + * + * Si `function`, controla como el extracto es extraido del contenido. + * + * Si `string`, define un separador personalizado usado para extraer el + * extracto. El separados por defecto es `---` si `excerpt` fuera `true`. + * + * @see https://github.com/jonschlinkert/gray-matter#optionsexcerpt + * @see https://github.com/jonschlinkert/gray-matter#optionsexcerpt_separator + * + * @default false + */ + excerpt?: + | boolean + | ((file: { data: { [key: string]: any }; content: string; excerpt?: string }, options?: any) => void) + | string + + /** + * Transforma los datos. Observe que los datos serán incorporados como JSON en el paquete del cliente + * caso sean importados de componentes o archivos markdown. + */ + transform?: (data: ContentData[]) => T | Promise +} +``` + +## Cargadores de datos con Tipos {#typed-data-loaders} + +Al usar TypeScript, puede tipar su cargador de datos y exportar `data` de la siguiente forma: + +```ts +import { defineLoader } from 'vitepress' + +export interface Data { + // tipo de dato +} + +declare const data: Data +export { data } + +export default defineLoader({ + // opciones del cargador verificadas por el tipo + watch: ['...'], + async load(): Promise { + // ... + } +}) +``` + +## Configuración {#configuration} + +Para obtener información de configuración dentro de un cargador, puede usar un código como este: + +```ts +import type { SiteConfig } from 'vitepress' + +const config: SiteConfig = (globalThis as any).VITEPRESS_CONFIG +``` diff --git a/docs/es/guide/deploy.md b/docs/es/guide/deploy.md new file mode 100644 index 00000000..5d2c9c06 --- /dev/null +++ b/docs/es/guide/deploy.md @@ -0,0 +1,292 @@ +--- +outline: deep +--- + +# Despliegue su Sitio VitePress {#deploy-your-vitepress-site} + +Las siguientes orientaciones están basadas en algunos supuestos: + +- El sitio VitePress está dentro del directorio `docs` de su proyecto. +- Está usando la directorio por defecto para el build (`.vitepress/dist`). +- VitePress está instalado como una dependencia local en su proyecto, y usted configuró los siguientes scripts en su `package.json`: + + ```json [package.json] + { + "scripts": { + "docs:build": "vitepress build docs", + "docs:preview": "vitepress preview docs" + } + } + ``` + +## Compilar y Testear Localmente {#build-and-test-locally} + +1. Ejecute este comando para compilar la documentación: + + ```sh + $ npm run docs:build + ``` + +2. Después de la compilación, vea la vista previa ejecutando: + + ```sh + $ npm run docs:preview + ``` + + El comando `preview` inicializará un servidor web estático local que servirá la directorio de salida `.vitepress/dist` en `http://localhost:4173`. Puede usar eso para garantizar que todo esté correcto antes de enviar a producción. + +3. Puede configurar el puerto del servidor pasando `--port` como argumento. + + ```json + { + "scripts": { + "docs:preview": "vitepress preview docs --port 8080" + } + } + ``` + + Ahora el método `docs:preview` implantará el servidor en `http://localhost:8080`. + +## Configurando un Path Base Publico {#setting-a-public-base-path} + +Por defecto, asumimos que el sitio será implantado en el path raiz de un dominio (`/`). Si su sitio fuera servido en un subpath, por ejemplo, `https://meusite.com/blog/`, necesitará entonces configurar la opción [`base`](../reference/site-config#base) para `'/blog/'` en la configuración VitePress. + +**Ejemplo:** Al usar GitHub Pages (ou GitLab Pages) e implantar en `user.github.io/repo/`, defina su `base` como `/repo/`. + +## Headers de Cache HTTP {#http-cache-headers} + +Si tiene control sobre los headers HTTP de su servidor en producción, se puede configurar headers `cache-control` para obtener mejor desempeño en vistar repetidas. + +La compilación de producción usa nombres de archivos con hash para assets estáticos (JavaScript, CSS e otros assets que no están en `public`). Se inspecciona la previa de producción usando las herramientas de desarrollador de su navegador en la pestaña red, verá archivos como `app.4f283b18.js`. + +Este hash `4f283b18` es generado a partir del contenido de este archivo. La misma URL con hash es garantizada para servir el mismo contenido del archivo - se el contenido cambia, las URLs también cambian. Esto significa que puede utilizar con seguridad los headers de cahe más fuertespara esos archivos. Todos esos archivos serán colocados en `assets/` en la directorio de salida, entonces puede configurar el siguiente header para ellos: + +``` +Cache-Control: max-age=31536000,immutable +``` + +::: details Ejemplo de archivo `_headers` do Netlify + +``` +/assets/* + cache-control: max-age=31536000 + cache-control: immutable +``` + +Nota: el archivo `_headers` debe ser colocado en [diretório public](./asset-handling#the-public-directory) - en nuestro caso, `docs/public/_headers` - para que el sea copiado exactamente para la directorio de salida. + +[Documentación de headers personalizados de Netlify](https://docs.netlify.com/routing/headers/) + +::: + +::: details de Ejemplo de configuración Vercel em `vercel.json` + +```json +{ + "headers": [ + { + "source": "/assets/(.*)", + "headers": [ + { + "key": "Cache-Control", + "value": "max-age=31536000, immutable" + } + ] + } + ] +} +``` + +Nota: el archivo `vercel.json` debe ser colocado en la raiz de su **repositório**. + +[Documentación Vercel sobre configuración de headers ](https://vercel.com/docs/concepts/projects/project-configuration#headers) + +::: + +## Guias de Plataforma {#platform-guides} + +### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render + +Configure un nuevo proyecto y altere estas configuraciones usando su panel: + +- **Comando de Compilación:** `npm run docs:build` +- **directorio de Salida:** `docs/.vitepress/dist` +- **Versión de Node:** `18` (o superior) + +::: warning +No active opciones como _Auto Minify_ para código HTML. Eso removera comentarios de salida que tiene significado para Vue. Habrán errores de incompatibilidad de hidratación se fueran removidos. +::: + +### GitHub Pages + +1. Cree un archivo llamado `deploy.yml` dentro del directorio `.github/workflows` do seu projeto com algum conteúdo como este: + + ```yaml [.github/workflows/deploy.yml] + # Ejemplo de flujo de trabajo para compilar e implantar un sitio VitePress en GitHub Pages + # + name: Implante el sitio VitePress en Pages + + on: + # Ejecute en push direccionados a la branch `main`. + # Cambie para `master` si estuviera usando la branch `master` por defecto. + push: + branches: [main] + + # Permite ejecutar manualmente este flujo de trabajo en la guia Actions + workflow_dispatch: + + # Define permisos GITHUB_TOKEN para la implementación en GitHub Pages + permissions: + contents: read + pages: write + id-token: write + + # Permite apenas una implantación simultánea, omitiendo ejecuciones en fila entre la ejecución en progreso y la última de la fila. + # Sin embargo, NO cancela ejecuciones en progreso, pues queremos permitir que esas implantaciones de producción sean concuidas. + concurrency: + group: pages + cancel-in-progress: false + + jobs: + # Trabajo de compilación + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 # No necesario se lastUpdated no estuviera habilitado + # - uses: pnpm/action-setup@v3 # Desconecte eso si estuviera usando pnpm + # with: + # version: 9 + # - uses: oven-sh/setup-bun@v1 # Desconecte eso se estuviera usando Bun + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm # o pnpm / yarn + - name: Setup Pages + uses: actions/configure-pages@v4 + - name: Install dependencies + run: npm ci # o pnpm install / yarn install / bun install + - name: Build with VitePress + run: | + npm run docs:build # o pnpm docs:build / yarn docs:build / bun run docs:build + touch docs/.vitepress/dist/.nojekyll + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: docs/.vitepress/dist + + # Trabajo de implantación + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + needs: build + runs-on: ubuntu-latest + name: Deploy + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 + ``` + + Asegurese de que la opción `base` en su VitePress esté configurada correctamentse. Vea [Configuranco un Path base Público](#setting-a-public-base-path) para más detalles. + ::: + +2. En las configuraciones de su repositorio sobre el item del menú "Pages", seleccione "GitHub Actions" en "Build and deployment > Source". + +3. Envie sus modificaciones para el branch `main` y espere la conclusión del flujo de trabajo de GitHub Actions. Verá su sitio implantado en `https://.github.io/[repository]/` o `https:///` dependiendo de sus configuraciones. Su sitio será implantado automáticamente en cada push para la branch `main`. + +### GitLab Pages + +1. Defina `outDir` en la configuración VitePress como `../public`. Configure la opción `base` para `'//'` se desea implantar en `https://.gitlab.io//`. + +2. Cree un archivo llamado `.gitlab-ci.yml` en la raiz del proyecto con el contenido abajo. Esto construirá e implantará su sitio siempre que haga alteraciones en el contenido. + + ```yaml [.gitlab-ci.yml] + image: node:18 + pages: + cache: + paths: + - node_modules/ + script: + # - apk add git # Desconecte eso se estuviera usando imagenes pequeñas de Docker como Alpine y tuviera lastUpdated habilitado + - npm install + - npm run docs:build + artifacts: + paths: + - public + only: + - main + ``` + +### Azure Static Web Apps {#azure-static-web-apps} + +1. Siga la [documentación oficial](https://docs.microsoft.com/en-us/azure/static-web-apps/build-configuration). + +2. Configure esos valores en su archivo de configuración (y remueva aquellos que no necesita, como `api_location`): + + - **`app_location`**: `/` + - **`output_location`**: `docs/.vitepress/dist` + - **`app_build_command`**: `npm run docs:build` + +### Firebase {#firebase} + +1. Cree `firebase.json` y `.firebaserc` en la raiz de su proyecto: + + `firebase.json`: + + ```json [firebase.json] + { + "hosting": { + "public": "docs/.vitepress/dist", + "ignore": [] + } + } + ``` + + `.firebaserc`: + + ```json [.firebaserc] + { + "projects": { + "default": "" + } + } + ``` + +2. Después de ejecutar `npm run docs:build`, ejecute este comando para implantar: + + ```sh + firebase deploy + ``` + +### Surge + +1. Después de ejecutar `npm run docs:build`, ejecute este comando para implantar: + + ```sh + npx surge docs/.vitepress/dist + ``` + +### Heroku + +1. Siga la documentación y el guia proporcionados por [`heroku-buildpack-static`](https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-static). + +2. Cree un archivo llamado `static.json` en la raiz de su proyecto con el contenido abajo: + + ```json [static.json] + { + "root": "docs/.vitepress/dist" + } + ``` + +### Edgio + +Consulte [Crear e Implantar una Aplicación VitePress en Edgio](https://docs.edg.io/guides/vitepress). + +### Kinsta Static Site Hosting {#kinsta-static-site-hosting} + +Puede implantar su sitio VitePress em [Kinsta](https://kinsta.com/static-site-hosting/) siguiendo estas [instrucciones](https://kinsta.com/docs/vitepress-static-site-example/). diff --git a/docs/es/guide/extending-default-theme.md b/docs/es/guide/extending-default-theme.md new file mode 100644 index 00000000..85bf8de8 --- /dev/null +++ b/docs/es/guide/extending-default-theme.md @@ -0,0 +1,330 @@ +--- +outline: deep +--- + +# Extendiendo el Tema por defecto {#extending-the-default-theme} + +El tema por defecto de VitePress es optimizado para documentación y puede ser personalizado. Consulte la [Visión General de Configuración del Tema por Defecto](../reference/default-theme-config) para una lista completa de opciones. + +Sin embargo, hay casos en que apenas la configuración no será suficiente. Por ejemplo: + +1. Es necesario ajustar los estilos CSS; +2. Es necesario modificar la instancia de la aplicación Vue, por ejemplo para registrar componentes globales; +3. Es necesario inyectar contenido personalizado en el tema por medio de _slots_ en el layout. + +Esas personalizaciones avanzadas exigirán el uso de un tema personalizado que "extiende" el tema por defecto. + +::: tip +Antes de seguir, asegurese de leer primero [Usando un Tema Personalizado](./custom-theme) para entender como funcionan los temas personalizados. +::: + +## Personalizando el CSS {#customizing-css} + +El CSS del tema por defecto puede ser personalizado substuyendo las variables CSS a nivel de la raiz: + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme' +import './custom.css' + +export default DefaultTheme +``` + +```css +/* .vitepress/theme/custom.css */ +:root { + --vp-c-brand-1: #646cff; + --vp-c-brand-2: #747bff; +} +``` + +Vea las [variables CSS del tema por defecto](https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css) que pueden ser substituídas. + +## Usando Fuentes Diferentes {#using-different-fonts} + +VitePress usa [Inter](https://rsms.me/inter/) como fuente por defecto e incluirá las fuentes en la salida de compilación. La fuente también es pre-cargada automaticamente en producción. Sin embargo, eso puede no ser deseable se quiere usar una fuente principal diferente. + +Para evitar la inclusión de Inter en la salida de compilación, importe el tema de `vitepress/theme-without-fonts`: + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme-without-fonts' +import './my-fonts.css' + +export default DefaultTheme +``` + +```css +/* .vitepress/theme/my-fonts.css */ +:root { + --vp-font-family-base: /* fuente de texto normal */ + --vp-font-family-mono: /* fuente de código */ +} +``` + +::: warning +Si está usando componentes opcionales como los componentes de la [Página del equipo](../reference/default-theme-team-page), asegurese de también importarlos de `vitepress/theme-without-fonts`! +::: + +Si su fuente es un archivo local referenciado via `@font-face`, ella será procesada como un asset e incluida en `.vitepress/dist/assets` con un nombre de archivo hash. Para pre-cargar ese archivo, use el hook de construcción [transformHead](../reference/site-config#transformhead): + +```js [.vitepress/config.js] +export default { + transformHead({ assets }) { + // ajuste el regex para corresponder a su fuente + const myFontFile = assets.find(file => /font-name\.[\w-]+\.woff2/.test(file)) + if (myFontFile) { + return [ + [ + 'link', + { + rel: 'preload', + href: myFontFile, + as: 'font', + type: 'font/woff2', + crossorigin: '' + } + ] + ] + } + } +} +``` + +## Registrando Componentes Globales {#registering-global-components} + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme' + +/** @type {import('vitepress').Theme} */ +export default { + extends: DefaultTheme, + enhanceApp({ app }) { + // registre sus componentes globales personalizados + app.component('MyGlobalComponent' /* ... */) + } +} +``` + +Si está usando TypeScript: +```ts [.vitepress/theme/index.ts] +import type { Theme } from 'vitepress' +import DefaultTheme from 'vitepress/theme' + +export default { + extends: DefaultTheme, + enhanceApp({ app }) { + // registre sus componentes globales personalizados + app.component('MyGlobalComponent' /* ... */) + } +} satisfies Theme +``` + +Como estamos usando Vite, puede también aprovechar la [funcionalidad de importación glob](https://vitejs.dev/guide/features.html#glob-import) de Vite para registrar automaticamente un directorio de componetes. + +## _Slots_ en el Layout {#layout-slots} + +El componente `` del tema por defecto posee algunos _slots_ que pueden ser usados para inyectar contenido en lugares específicos de la página. Aqui un ejemplo de como inyectar un componente antes del esquema: + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme' +import MyLayout from './MyLayout.vue' + +export default { + extends: DefaultTheme, + // substituya el Layout por un componente wrapper que + // inyecta los slots + Layout: MyLayout +} +``` + +```vue [.vitepress/theme/MyLayout.vue] + + + +``` + +O puede también usar la función _render_. + +```js [.vitepress/theme/index.js] +import { h } from 'vue' +import DefaultTheme from 'vitepress/theme' +import MyComponent from './MyComponent.vue' + +export default { + extends: DefaultTheme, + Layout() { + return h(DefaultTheme.Layout, null, { + 'aside-outline-before': () => h(MyComponent) + }) + } +} +``` + +Lista completa de _slots_ disponibles en el layout del tema por defecto: + +- Cuando `layout: 'doc'` (por defecto) está habilitado via frontmatter: + - `doc-top` + - `doc-bottom` + - `doc-footer-before` + - `doc-before` + - `doc-after` + - `sidebar-nav-before` + - `sidebar-nav-after` + - `aside-top` + - `aside-bottom` + - `aside-outline-before` + - `aside-outline-after` + - `aside-ads-before` + - `aside-ads-after` +- Cuando `layout: 'home'` está habilitado via frontmatter: + - `home-hero-before` + - `home-hero-info-before` + - `home-hero-info` + - `home-hero-actions-after` + - `home-hero-image` + - `home-hero-after` + - `home-features-before` + - `home-features-after` +- Cuando `layout: 'page'` está habilitado via frontmatter: + - `page-top` + - `page-bottom` +- En la página no encontrada (404): + - `not-found` +- Siempre: + - `layout-top` + - `layout-bottom` + - `nav-bar-title-before` + - `nav-bar-title-after` + - `nav-bar-content-before` + - `nav-bar-content-after` + - `nav-screen-content-before` + - `nav-screen-content-after` + +## Usando el API View Transitions + +### En la Alternancia de Apariencia {#on-appearance-toggle} + +Puede extender el tema por defecto para proporcionar una transición personalizada cuando el modo de color es alternado. Un ejemplo: + +```vue [.vitepress/theme/Layout.vue] + + + + + +``` + +Resultado (**atención!**: colores destellantes, movimientos súbitos, luces brillantes): + +
+Demo + +![Demo de Transición de Alternancia de Apariencia](/appearance-toggle-transition.webp) + +
+ +Consulte [Chrome Docs](https://developer.chrome.com/docs/web-platform/view-transitions/) para mas detalles sobre _view transitions_. + +### En el Cambio de Ruta {#on-route-change} + +En breve. + +## Substituyendo Componentes Internos {#overriding-internal-components} + +Puede usar los [aliases](https://vitejs.dev/config/shared-options.html#resolve-alias) Vite para substituir los componentes del tema por defecto por los suyos personalizados: + +```ts +import { fileURLToPath, URL } from 'node:url' +import { defineConfig } from 'vitepress' + +export default defineConfig({ + vite: { + resolve: { + alias: [ + { + find: /^.*\/VPNavBar\.vue$/, + replacement: fileURLToPath( + new URL('./components/CustomNavBar.vue', import.meta.url) + ) + } + ] + } + } +}) +``` + +Para saber el nombre exacto del componente consulte [nuestro código fuente](https://github.com/vuejs/vitepress/tree/main/src/client/theme-default/components). Como los componentes son internos, hay una pequeña chance de que el nombre sea actualizado entre lanzamientos secundarios. diff --git a/docs/es/guide/frontmatter.md b/docs/es/guide/frontmatter.md new file mode 100644 index 00000000..84736639 --- /dev/null +++ b/docs/es/guide/frontmatter.md @@ -0,0 +1,48 @@ +# Frontmatter + +## Uso {#usage} + +VitePress soporta frontmatter YAML en todos los archivos Markdown, procesandolos con [gray-matter](https://github.com/jonschlinkert/gray-matter). El frontmatter debe estar en la parte superior del archivo Markdown (antes de cualquier elemento, incluyendo tags ` + + +``` + +## Soporte a RTL (Experimental) {#rtl-support-experimental} + +Para soporte a RTL (Right to Left), especifique `dir: 'rtl'` en la configuración y use algún plugin RTLCSS PostCSS como , o . Necesitará configurar su plugin PostCSS para usar `:where([dir="ltr"])` y `:where([dir="rtl"])` como prefijos para evitar problemas de especificidad CSS. diff --git a/docs/es/guide/markdown.md b/docs/es/guide/markdown.md new file mode 100644 index 00000000..00f973ed --- /dev/null +++ b/docs/es/guide/markdown.md @@ -0,0 +1,929 @@ +# Extensiones Markdown {#markdown-extensions} + +VitePress viene con Extensiones embutidas. + +## Anchors de Header {#header-anchors} + +Los Header reciben la aplicación automáticamente de links anchor. La presentación de los anchor puede ser configurada usando la opción `markdown.anchor`. + +### Anchor personalizados {#custom-anchors} + +Para especificar un _tag_ anchor personalizado para um header en vex de usar la generada automáticamente, adicione un sufijo al header: + +``` +# Usando anchors personalizados {#mi-anchor} +``` + +Esto permite que tenga un link del header como `#mi-anchor` en vez del default `#usando-anchors-personalizados`. + +## Links {#links} + +Ambos links internos y externos reciben tratamiento especial. + +### Links Internos {#internal-links} + +Los links internos son convertidos en links de enrutador para navegación SPA. Además de eso , todo archivo `index.md` contenido en cada subdirectorio será automáticamente convertido en `index.html`, con la URL correspondiente `/`. + +Por ejemplo, dada la siguiente estructura de directorios: + +``` +. +├─ index.md +├─ foo +│ ├─ index.md +│ ├─ one.md +│ └─ two.md +└─ bar + ├─ index.md + ├─ three.md + └─ four.md +``` + +Y suponiendo que está en `foo/one.md`: + +```md +[Página Inicial](/) +[foo](/foo/) +[foo heading](./#heading) +[bar - three](../bar/three) +[bar - three](../bar/three.md) +[bar - four](../bar/four.html) +``` + +### Sufijo de Página {#page-suffix} + +Páginas y links internos son generados con el sufijo `.html` por defecto. + +### Links Externos {#external-links} + +Links externos reciben automáticamente `target="_blank" rel="noreferrer"`: + +- [vuejs.org](https://vuejs.org) +- [VitePress no GitHub](https://github.com/vuejs/vitepress) + +## Frontmatter {#frontmatter} + +[YAML frontmatter](https://jekyllrb.com/docs/front-matter/) es soportado por defecto: + +```yaml +--- +título: Escribiendo como un Hacker +idioma: es-CO +--- +``` + +Esos datos estarán disponibles para el resto de la página, junto con todos los componentes personalizados y de temas. + +Para más detalles, vea [Frontmatter](../reference/frontmatter-config). + +## Tablas al Estilo GitHub {#github-style-tables} + +**Entrada** + +```md +| Tablas | Son | Geniales| +| ------------- | :-----------: | ----: | +| col 3 está | à direita | $1600 | +| col 2 está | centralizada | $12 | +| listras | são legais | $1 | +``` + +**Salida** + +| Tablas | Son | Geniales | +| ------------- | :-----------: | -----: | +| col 3 está | à direita | \$1600 | +| col 2 está | centralizada | \$12 | +| listras | são legais | \$1 | + +## Emoji :tada: + +**Entrada** + +``` +:tada: :100: +``` + +**Salida** + +:tada: :100: + +Una [lista de todos los emojis](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.mjs) está disponible. + +## Tabla de Contenido (TOC) + +**Entrada** + +``` +[[toc]] +``` + +**Salida** + +[[toc]] + +La presentación de TOC (Table of Contents) puede ser configurada usando la opción `markdown.toc`. + +## Contenedores Personalizados {#custom-containers} + +Contenedores personalizados pueden ser definidos por sus tipos, títulos y contenidos. + +### Título por Defecto {#default-title} + +**Entrada** + +```md +::: info +Este es un bloque de información. +::: + +::: tip +Este es un aviso. +::: + +::: warning +Esto es una advertencia. +::: + +::: danger +Este es un aviso de peligro. +::: + +::: details +Este es un bloque de detalles. +::: +``` + +**Salida** + +::: info +Este es un bloque de información. +::: + +::: tip +Este es un aviso. +::: + +::: warning +Esto es una advertencia. +::: + +::: danger +Este es un aviso de peligro. +::: + +::: details +Este es un bloque de detalles. +::: + +### Título Personalizado {#custom-title} + +Puede definir un título personalizado adicionando el texto inmediatamente después del "tipo" del recipiente. + +**Entrada** + +```md +::: danger STOP +Zona de peligro, no siga +::: + +::: details Click para ver el código +```js +console.log('Hola, VitePress!') +``` +::: +``` +``` + +**Salida** + +::: danger STOP +Zona de peligro, no siga +::: + +::: details Click para ver el código +```js +console.log('Hola, VitePress!') +``` +::: + +Además de eso, puede definir títulos personalizados globalmente adicionando el siguiente contenifo en el archivo de configuración del sitio, útil si no estuviera escribiendo en ingles: + +```ts +// config.ts +export default defineConfig({ + // ... + markdown: { + container: { + tipLabel: '提示', + warningLabel: '警告', + dangerLabel: '危险', + infoLabel: '信息', + detailsLabel: '详细信息' + } + } + // ... +}) +``` + +### `raw` + +Este es un recipiente especial que puee ser usado para evitar conflictos de estilo y enrutador con VitePress. Esto es especialmente útil al documentar bibliotecas de componentes. Puede tambien verificar [whyframe](https://whyframe.dev/docs/integrations/vitepress) para mejor aislamiento. + +**Sintaxis** + +```md +::: raw +Envuelve en un `
` +::: +``` + +La clase `vp-raw` también puede ser usada directamente en elementos. El aislamiento de estilo es actualmente opcional: + +- Instale `postcss` con su gestor de paquetes preferido: + + ```sh + $ npm add -D postcss + ``` + +- Cree un archivo llamado `docs/postcss.config.mjs` y adicione lo siguiente: + + ```js + import { postcssIsolateStyles } from 'vitepress' + + export default { + plugins: [postcssIsolateStyles()] + } + ``` + + El utiliza [`postcss-prefix-selector`](https://github.com/postcss/postcss-load-config) internamente. Puede pasar opciones así: + + ```js + postcssIsolateStyles({ + includeFiles: [/vp-doc\.css/] // o padrão é /base\.css/ + }) + ``` + +## Alertas en estilo GitHub {#github-flavored-alerts} + +VitePress también soporta [alertas en estilo 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) para presentar como un bloque de llamada. Ellos serán presentados de la misma forma que [elementos personalizados](#custom-containers). + +```md +> [!NOTE] +> Destaca informaciones que los usuarios deben tener en consideración, incluso leyendo rapidamente. + +> [!TIP] +> Informaciones opcionales para ayudar al usuario a tener más éxito. + +> [!IMPORTANT] +> Informaciones cruciales necesarias par que los usuarios tengan éxito. + +> [!WARNING] +> Contenido critico exigiendo atención inmediata del usuario debido a riesgos potenciales. + +> [!CAUTION] +> Potenciales consecuencias negativas de una acción. +``` + +> [!NOTE] +> Destaca informaciones que los usuarios deben tener en consideración, incluso leyendo rapidamente. + +> [!TIP] +> Informaciones opcionales para ayudar al usuario a tener más éxito. + +> [!IMPORTANT] +> Informaciones cruciales necesarias par que los usuarios tengan éxito. + +> [!WARNING] +> Contenido critico exigiendo atención inmediata del usuario debido a riesgos potenciales. + +> [!CAUTION] +> Potenciales consecuencias negativas de una acción. + +## Destaque de Sintaxis en Bloques de Código {#syntax-highlighting-in-code-blocks} + +VitePress utiliza [Shiki](https://github.com/shikijs/shiki) para destacar la sintaxis del lenguaje en bloques de código Markdown, usando texto coloreado. Shiki soporta una amplia variedad de lenguajes de programación. Todo lo que necesita es adicionar un _alias_ de lenguaje válido después de los backticks iniciales del bloque de código: + +**Entrada** + +```` +```js +export default { + name: 'MyComponent', + // ... +} +``` +```` + +```` +```html +
    +
  • + {{ todo.text }} +
  • +
+``` +```` + +**Salida** + +```js +export default { + name: 'MyComponent' + // ... +} +``` + +```html +
    +
  • + {{ todo.text }} +
  • +
+``` + +Una [lista de lenguajes válidas](https://shiki.style/languages) está disponible en el repositório Shiki. + +También puede personalizar el tema de destaque de sintaxis en la configuración de la aplicación. Consulte las [opciones `markdown`](../reference/site-config#markdown) para más detalles. + +## Destaque de Linea en Bloques de Código {#line-highlighting-in-code-blocks} + +**Entrada** + +```` +```js{4} +export default { + data () { + return { + msg: 'Destacado!' + } + } +} +``` +```` + +**Salida** + +```js{4} +export default { + data () { + return { + msg: 'Destacado!' + } + } +} +``` + +Además de una única linea, puede también especificar múltiples lineas únicas, intervalos, o ambos: + +- Intervalos de linea: por ejemplo, `{5-8}`, `{3-10}`, `{10-17}` +- Múltiples lineas únicas: por ejemplo, `{4,7,9}` +- Intervalos de linea y lineas únicas: por ejemplo, `{4,7-13,16,23-27,40}` + +**Entrada** + +```` +```js{1,4,6-8} +export default { // Destacado + data () { + return { + msg: `Destacado! + Esta linea no está destacada, + pero esta y las próximas están.`, + motd: 'VitePress es increible', + lorem: 'ipsum' + } + } +} +``` +```` + +**Salida** + +```js{1,4,6-8} +export default { // Destacado + data () { + return { + msg: `Destacado! + Esta linea no está destacada, + pero esta y las próximas están.`, + motd: 'VitePress es increible', + lorem: 'ipsum', + } + } +} +``` + +Alternativamente, es posible destacar directamente en la linea usando el comentario `// [!code highlight]`. + +**Entrada** + +```` +```js +export default { + data () { + return { + msg: 'Destacado!' // [!!code highlight] + } + } +} +``` +```` + +**Saída** + +```js +export default { + data() { + return { + msg: 'Destacado!' // [!code highlight] + } + } +} +``` + +## Enfoque en Bloques de Código {#focus-in-code-blocks} + +Adicionando el comentario `// [!code focus]` en una linea, esta será destacada y desenfocará las otras partes del código. + +Además, puede definir el número de lineas para enfocar usando `// [!code focus:]`. + +**Entrada** + +```` +```js +export default { + data () { + return { + msg: 'Enfocado!' // [!!code focus] + } + } +} +``` +```` + +**Salida** + +```js +export default { + data() { + return { + msg: 'Enfocado!' // [!code focus] + } + } +} +``` + +## Diferencias Coloreadas en Bloques de Código {#colored-diffs-in-code-blocks} + +Adicionar los comentarios `// [!code --]` o `// [!code ++]` en una linea creará una diferencia en esa linea, manteniendo los colores del bloque de código. + +**Entrada** + +```` +```js +export default { + data () { + return { + msg: 'Borrado' // [!!code --] + msg: 'Adicionado' // [!!code ++] + } + } +} +``` +```` + +**Salida** + +```js +export default { + data () { + return { + msg: 'Borrado' // [!code --] + msg: 'Adicionado' // [!code ++] + } + } +} +``` + +## Errores y Avisos en Bloques de Código {#errors-and-warnings-in-code-blocks} + +Adicionar los comentarios `// [!code warning]` o `// [!code error]` en una linea coloreará los bloques conforme necesário. + +**Entrada** + +```` +```js +export default { + data () { + return { + msg: 'Error', // [!!code error] + msg: 'Aviso' // [!!code warning] + } + } +} +``` +```` + +**Salida** + +```js +export default { + data() { + return { + msg: 'Error', // [!code error] + msg: 'Aviso' // [!code warning] + } + } +} +``` + +## Números de Linea {#line-numbers} + +Puede habilitar números de linea para cada bloque de código a través del archivo de configuración: + +```js +export default { + markdown: { + lineNumbers: true + } +} +``` + +Consulte las [opciones markdown](../reference/site-config#markdown) para más detalles. + +Puede adicionar la marca `:line-numbers` / `:no-line-numbers` en sus bloques de código para substituir el valor definido en la configuración. + +También puede personalizar el número inicial de linea adicionando `=` después `:line-numbers`. Por ejemplo, `:line-numbers=2` significa que los números de las lineas en los bloques de código comenzarán a partir de `2`. + +**Entrada** + +````md +```ts {1} +// números de linea desactivados por defecto +const line2 = 'Esta es la linea 2' +const line3 = 'Esta es la linea 3' +``` + +```ts:line-numbers {1} +// números de linea activados +const line2 = 'Esta es la linea 2' +const line3 = 'Esta es la linea 3' +``` + +```ts:line-numbers=2 {1} +// números de linea activados y comienzan en 2 +const line3 = 'Esta es la linea 3' +const line4 = 'Esta es la linea 4' +``` +```` + +**Salida** + +```ts {1} +// números de linea desactivados por defecto +const line2 = 'Esta es la linea 2' +const line3 = 'Esta es la linea 3' +``` + +```ts:line-numbers {1} +// números de linea activados +const line2 = 'Esta es la linea 2' +const line3 = 'Esta es la linea 3' +``` + +```ts:line-numbers=2 {1} +// números de linea activados y comienzan en 2 +const line3 = 'Esta es la linea 3' +const line4 = 'Esta es la linea 4' +``` + +## Importar _Snippets_ de Código {#import-code-snippets} + +Puede importar pedazos de código de archivos existentes usando la siguiente sintaxis: + +```md +<<< @/filepath +``` + +También soporta [destaque de linea](#line-highlighting-in-code-blocks): + +```md +<<< @/filepath{highlightLines} +``` + +**Entrada** + +```md +<<< @/snippets/snippet.js{2} +``` + +**Archivo de Código** + +<<< @/snippets/snippet.js + +**Salida** + +<<< @/snippets/snippet.js{2} + +::: tip + +El valor de `@` corresponde a la raiz del código fuente. Por defecto, es la raiz del proyecto VitePress, a menos que `srcDir` sea configurado. Alternativamente, puede también importar de paths relativos: + +```md +<<< ../snippets/snippet.js +``` + +::: + +También puede usar una [región VS Code](https://code.visualstudio.com/docs/editor/codebasics#_folding) para incluir apenas la parte correspondiente del archivo de código. Puede proporcionar un nombre de región personalizado después de `#` siguiendo el path del archivo: + +**Entrada** + +```md +<<< @/snippets/snippet-with-region.js#snippet{1} +``` + +**Archivo de Código** + +<<< @/snippets/snippet-with-region.js + +**Salida** + +<<< @/snippets/snippet-with-region.js#snippet{1} + +También puede especificar el idioma dentro de llaves (`{}`), así: + +```md +<<< @/snippets/snippet.cs{c#} + + + +<<< @/snippets/snippet.cs{1,2,4-6 c#} + + + +<<< @/snippets/snippet.cs{1,2,4-6 c#:line-numbers} +``` + +Esto es útil si el lenguaje original no puede ser inferida por la extensión de archivo. + +## Grupos de Código {#code-groups} + +Puede agrupar varios bloques de código así: + +**Entrada** + +````md +::: code-group + +```js [config.js] +/** + * @type {import('vitepress').UserConfig} + */ +const config = { + // ... +} + +export default config +``` + +```ts [config.ts] +import type { UserConfig } from 'vitepress' + +const config: UserConfig = { + // ... +} + +export default config +``` + +::: +```` + +**Salída** + +::: code-group + +```js [config.js] +/** + * @type {import('vitepress').UserConfig} + */ +const config = { + // ... +} + +export default config +``` + +```ts [config.ts] +import type { UserConfig } from 'vitepress' + +const config: UserConfig = { + // ... +} + +export default config +``` + +::: + +También puede [importar _snippets_ de código](#import-code-snippets) en grupos de código: + +**Entrada** + +```md +::: code-group + + + +<<< @/snippets/snippet.js + + + +<<< @/snippets/snippet-with-region.js#snippet{1,2 ts:line-numbers} [snippet with region] + +::: +``` + +**Output** + +::: code-group + +<<< @/snippets/snippet.js + +<<< @/snippets/snippet-with-region.js#snippet{1,2 ts:line-numbers} [snippet with region] + +::: + +## Inclusión de Archivo Markdown {#markdown-file-inclusion} + +Puede incluir un archivo markdown en otro archvo markdown, incluso anidado. + +::: tip +Puede prefijar el path del markdown con `@`, el actuará como la raiz de origen. Por defecto, es la raiz del projecto VitePress, a menos que `srcDir` sea configurado. +::: + +Por ejemplo, puede incluir un archivo markdown relativo usando esto: + +**Entrada** + +```md +# Documentación + +## Conceptos Básicos + + +``` + +**Archivo de Parte** (`parts/basics.md`) + +```md +Algunas cosas básicas. + +### Configuración + +Puede ser creada usando `.foorc.json`. +``` + +**Código Equivalente** + +```md +# Documentación + +## Conceptos básicos + +Algunas cosas básicas + +### Configuración + +Puede ser creada usando `.foorc.json`. +``` + +También soporta la selección de un intervalo de lineas: + +**Entrada** + +```md +# Documentación + +## Conceptos Básicos + + +``` + +**Archivo de Parte** (`parts/basics.md`) + +```md +Algunas cosas básicas. + +### Configuración + +Puede ser creada usando `.foorc.json`. +``` + +**Código Equivalente** + +```md +# Documentación + +## Conceptos Básicos + +### Configuración + +Puede ser creada usando `.foorc.json`. +``` + +El formato del intervalo de lineas seleccionado puede ser: `{3,}`, `{,10}`, `{1,10}` + +::: warning +Observe que esto no genera errores si el archivo no está presente. Por lo tanto, al usar este recurso, asegurese de que el contenido está siendo mostrado como se espera.::: + +## Ecuaciones Matemáticas {#math-equations} + +Esto es actualmente opcional. Para activarlo, necesita instalar `markdown-it-mathjax3` y definir `markdown.math` como `true` en su archivo de configuración: + +```sh +npm add -D markdown-it-mathjax3 +``` + +```ts [.vitepress/config.ts] +export default { + markdown: { + math: true + } +} +``` + +**Entrada** + +```md +Cuando $a \ne 0$, existen dos soluciones para $(ax^2 + bx + c = 0)$ y ellas son +$$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ + +**Ecuaciones de Maxwell:** + +| ecuación | descripción | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | +| $\nabla \cdot \vec{\mathbf{B}} = 0$ | la divergencia de $\vec{\mathbf{B}}$ es cero | +| $\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | la rotacional de $\vec{\mathbf{E}}$ es proporcional a la tasa de variación de $\vec{\mathbf{B}}$ | +| $\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | _hã?_ | + +**Salída** + +Cuando $a \ne 0$, existen dos soluciones para $(ax^2 + bx + c = 0)$ y ellas son +$$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ + +**Ecuaciones de Maxwell:** + +| ecuación | descripción | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | +| $\nabla \cdot \vec{\mathbf{B}} = 0$ | la divergencia de $\vec{\mathbf{B}}$ es cero | +| $\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | la rotacional de $\vec{\mathbf{E}}$ es proporcional a la tasa de variación de $\vec{\mathbf{B}}$ | +| $\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | _hã?_ | + +## _Lazy Loading_ de Imagenes {#image-lazy-loading} + +Puede activar la "carga perezosa" para cada imagen adicionada via markdown definiendo `lazyLoading` como `true` en su archivo de configuración: + +```js +export default { + markdown: { + image: { + // la carga perezosa de imagenes está desactivada por defecto + lazyLoading: true + } + } +} +``` + +## Configuración Avanzada {#advanced-configuration} + +VitePress usa [markdown-it](https://github.com/markdown-it/markdown-it) como interprete Markdown. Muchas de las extensiones arriba son implementadas por medio de _plugins_ personalizados. Puede personalizar más la instancia `markdown-it` usando la opción `markdown` en `.vitepress/config.js`: + +```js +import { defineConfig } from 'vitepress' +import markdownItAnchor from 'markdown-it-anchor' +import markdownItFoo from 'markdown-it-foo' + +export default defineConfig({ + markdown: { + // opciones para markdown-it-anchor + // https://github.com/valeriangalliat/markdown-it-anchor#usage + anchor: { + permalink: markdownItAnchor.permalink.headerLink() + }, + + // opciones para @mdit-vue/plugin-toc + // https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-toc#options + toc: { level: [1, 2] }, + + config: (md) => { + // use más plugins markdown-it! + md.use(markdownItFoo) + } + } +}) +``` + +Consulte la lista completa de propiedades configurables en [Referencia de Configuración: Configuración de la Aplicación](../reference/site-config#markdown). diff --git a/docs/es/guide/mpa-mode.md b/docs/es/guide/mpa-mode.md new file mode 100644 index 00000000..1e8a7d26 --- /dev/null +++ b/docs/es/guide/mpa-mode.md @@ -0,0 +1,23 @@ +# Modo MPA {#mpa-mode} + +El modo MPA (Aplicación de multiples páginas) puede ser habilitado por la linea de comandos con `vitepress build --mpa`, o a través de la configuración por la opción `mpa: true`. + +En el modo MPA, todas las páginas son presentadas por defecto sin JavaScript incluído. Como resultado, el sitio en producción probablemente tendrá una marca de desempeño de visita inicial superior con herramientas de auditoría. + +Sin embargo, debido a la ausencia de navegación SPA, los links entre páginas resultan en recargas de página completos. Navegaciones después de la carga en el modo MPA no parecerán tan instantáneos en comparación con el modo SPA. + +También note que no tener JavaScript por defecto significa que está esencialmente utilizando Vue como modelo de lenguaje en el lado del servidor. Nungun manipulador de eventos será embutido en el navegador, entonces no habrá interactividad. Para cargar JavaScript en el lado del cliente, necesitará usar el tag especial ` + +# Hola +``` + +` +``` + +### Presentando Contenido Crudo {#rendering-raw-content} + +Parámetros pasados para una página serán serializados en la carga JavaScript del cliente, por lo tanto, evite pasar datos pesados en los parámetros, como Markdown crudo o contenido HTML obtenido de un CSS remoto. + +En lugar de eso, puede pasar tal contenido para cada página usando la propiedad `content` en cada objeto de path: + +```js +export default { + async paths() { + const posts = await (await fetch('https://my-cms.com/blog-posts')).json() + + return posts.map((post) => { + return { + params: { id: post.id }, + content: post.content // Markdown o HTML crudo + } + }) + } +} +``` + +En seguida, use la siguiente sintaxis especial para presentar el contenido como parte del propio archivo Markdown: + +```md + +``` diff --git a/docs/es/guide/sitemap-generation.md b/docs/es/guide/sitemap-generation.md new file mode 100644 index 00000000..09f10aea --- /dev/null +++ b/docs/es/guide/sitemap-generation.md @@ -0,0 +1,53 @@ +# Generación de Sitemap {#sitemap-generation} + +VitePress viene con soporte embutido para generar un archivo `sitemap.xml` para su sitio. Para habilitar, adicione lo siguiente a su `.vitepress/config.js`: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + sitemap: { + hostname: 'https://example.com' + } +}) +``` + +Para tener tags `` en su `sitemap.xml`, puede habilitar la opción [`lastUpdated`](../reference/default-theme-last-updated). + +## Opciones {#options} + +El soporte de Sitemap es alimentado por el módulo [`sitemap`](https://www.npmjs.com/package/sitemap). Puede pasar cualquiera de las opciones soportadas por el en la opción `sitemap` de su archivo de configuración. Estos serán pasados directamente al constructor `SitemapStream`. Consulte la [documentación `sitemap`](https://www.npmjs.com/package/sitemap#options-you-can-pass) para más detalles. Ejemplo: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + sitemap: { + hostname: 'https://example.com', + lastmodDateOnly: false + } +}) +``` + +## Hook `transformItems` + +Puede usar el hook `sitemap.transformItems` para modificar los items del sitemap antes de ser escritos en el archivo `sitemap.xml`. Este hook es llamado como un _array_ de items sitemap y espera un _array_ de items sitemap como retorno. Ejemplo: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + sitemap: { + hostname: 'https://example.com', + transformItems: (items) => { + // adiciona nuevos items o modifica/filtra items existentes + items.push({ + url: '/extra-page', + changefreq: 'monthly', + priority: 0.8 + }) + return items + } + } +}) +``` diff --git a/docs/es/guide/ssr-compat.md b/docs/es/guide/ssr-compat.md new file mode 100644 index 00000000..7f701eb8 --- /dev/null +++ b/docs/es/guide/ssr-compat.md @@ -0,0 +1,135 @@ +--- +outline: deep +--- + +# Compatibilidad SSR {#ssr-compatibility} + +VitePress pre-interpreta la aplicación en Node.js durante la compilación del producción, utilizando las capacidades de Interpretación del lado del servidor (SSR) de Vue. Esto significa que todo el código personalizado en los componentes del tema está sujeto a la compatibilidad SSR. + +La [sección SSR en la documentación Vue oficial](https://vuejs.org/guide/scaling-up/ssr.html) proporciona más contexto sobre lo que es SSR, la relación entre SSR / SSG y notas comunes sobre escribir código amigable con SSR. La regla general es acceder apenas APIs deln navegador / DOM en los hooks `beforeMount` o `mounted` de los componentes Vue. + +## `` + +Se está usando o demostrando componentes que no son compatibles con SSR (por ejemplo, contienen directivas personalizadas), puede envolverlos en el componente embutido ``: + +```md + + + +``` + +## Bibliotecas que Acceden el API del Navegador en la Importación {#libraries-that-access-browser-api-on-import} + +Algunos componentes o bibliotecas acceden APIs del navegador **en la Importación**. Para usar código que asume un ambiente de navegador en la importación, necesita importarlo dinámicamente. + +### Importando en el Hook `mounted` {#importing-in-mounted-hook} + +```vue + +``` + +### Importación Condicional {#conditional-import} + +Puede también importar condicionalmente usando el flag `import.meta.env.SSR` (parte de las [variables de entorno Vite](https://vitejs.dev/guide/env-and-mode.html#env-variables)): + +```js +if (!import.meta.env.SSR) { + import('./lib-que-accede-window-en-la-importacion').then((module) => { + // usar código + }) +} +``` + +Como [`Theme.enhanceApp`](./custom-theme#theme-interface) puede ser asíncrono, puede importar condicionalmente y registrar plugins Vue que acceden APIs del navegador en la importación: + +```js [.vitepress/theme/index.js] +/** @type {import('vitepress').Theme} */ +export default { + // ... + async enhanceApp({ app }) { + if (!import.meta.env.SSR) { + const plugin = await import('plugin-que-accede-window-en-la-importacion') + app.use(plugin.default) + } + } +} +``` + +Si está usando TypeScript: +```ts [.vitepress/theme/index.ts] +import type { Theme } from 'vitepress' + +export default { + // ... + async enhanceApp({ app }) { + if (!import.meta.env.SSR) { + const plugin = await import('plugin-que-accede-window-en-la-importacion') + app.use(plugin.default) + } + } +} satisfies Theme +``` + +### `defineClientComponent` + +VitePress proporciona un auxiliar de conveniencia para importar componentes Vue que acceden APIs del navegador en la importación. + +```vue + + + +``` + +Puede también pasar propiedades/hijos/_slots_ para el componente objetivo: + +```vue + + + +``` + +El componente objetivo solo será importado en el hook `mounted` del componente que lo envuelve. diff --git a/docs/es/guide/using-vue.md b/docs/es/guide/using-vue.md new file mode 100644 index 00000000..0131cc76 --- /dev/null +++ b/docs/es/guide/using-vue.md @@ -0,0 +1,289 @@ +# Usando Vue en Markdown {#using-vue-in-markdown} + +En VitePress, cada archivo Markdown es compilado para HTML y entonces procesado como un [Componente de Archivo Único de Vue](https://vuejs.org/guide/scaling-up/sfc.html). Esto significa que puede usar cualquier funcionalidad de Vue dentro del Markdown, incluyendo la interpolación dinámica, usar componentes Vue o lógica arbitrária de componentes Vue dentro de la página adicionando una tag ` + +## Contenido Markdown + +El conteo es: {{ count }} + + + + +``` + +::: warning Evite ` +``` + +## Usando _Teleports_ {#using-teleports} + +VitePress actualmente ofrece soporte a SSG para _teleports_ apenas para el cuerpo. Para otros objetivos, puede envolverlos dentro del componente embutido `` o inyectar la marcación de _teleport_ en la localización correcta en su página final HTML por medio del [hook `postRender`](../reference/site-config#postrender). + + + +::: details +<<< @/components/ModalDemo.vue +::: + +```md + + +
+ // ... +
+
+
+``` + + + + + +## Soporte de IntelliSense en VS Code + + + +Vue ofrece soporte para IntelliSense de forma predeterminada mediante el [Plugin oficial de Vue para VS Code](https://marketplace.visualstudio.com/items?itemName=Vue.volar). Sin embargo, para habilitarlo en archivos `.md`, es necesario realizar algunos ajustes en los archivos de configuración. + +1. Agrega el patrón `.md` a las opciones `include` y `vueCompilerOptions.vitePressExtensions` en el archivo tsconfig/jsconfig: + +::: code-group +```json [tsconfig.json] +{ + "include": [ + "docs/**/*.ts", + "docs/**/*.vue", + "docs/**/*.md", + ], + "vueCompilerOptions": { + "vitePressExtensions": [".md"], + }, +} +``` +::: + +2. Agrega `markdown` a la opción `vue.server.includeLanguages` en el archivo de configuración de VS Code + +::: code-group +```json [.vscode/settings.json] +{ + "vue.server.includeLanguages": ["vue", "markdown"] +} +``` +::: diff --git a/docs/es/guide/what-is-vitepress.md b/docs/es/guide/what-is-vitepress.md new file mode 100644 index 00000000..21512356 --- /dev/null +++ b/docs/es/guide/what-is-vitepress.md @@ -0,0 +1,57 @@ +# Qué es VitePress? {#what-is-vitepress} + +VitePress es un [Generador de Sitios Estáticos](https://en.wikipedia.org/wiki/Static_site_generator) (SSG) proyectado para crear sitios rápidos y centrados en contenido. En suma, VitePress utiliza su contenido fuente escrito en [Markdown](https://en.wikipedia.org/wiki/Markdown), aplica un tema a el y genera páginas HTML estáticas que pueden ser facilmente implantadas en cualquier lugar. + +
+ +Quiere apenas experimentar? Valla al [Início Rápido](./getting-started). + +
+ +## Casos de Uso {#use-cases} + +- **Documentación** + + VitePress viene con un tema por defecto proyectado para documentación técnica. El alimenta esta página que está leyendo ahora, juntamente con la documentación [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/) e [muchos otros](https://www.vuetelescope.com/explore?framework.slug=vitepress). + + La [documentación oficial Vue.js](https://vuejs.org/) también está basada en VitePress, pero usa un tema personalizado compartido entre varias traducciones. + +- **Blogs, Portfólios y sitios de Marketing** + + VitePress soporta [temas totalmente personalizables](./custom-theme), con la experiencia de desarrollador por defecto de una aplicaciónn Vite + Vue. La construcción con Vite significa que puede aprovechar directamente plugins Vite de su rico ecosistema. Adicionalmente, VitePress proporciona APIs flexibles para[cargar datos](./data-loading) (locales o remotos) y [generar rutas dinámicamente](./routing#dynamic-routes). Puede usarlo para construir practicamente cualquier cosa desde que los datos puedan ser determinados en el momento del build. + + El [blog oficial Vue.js](https://blog.vuejs.org/) es un blog simple que genera su página inicial basada en contenido local. + +## Experiencia de Desarrollador {#developer-experience} + +VitePress visa proporcionar excelente Experiencia de Desarrollador (DX) al trabajar con contenido en Markdown. + +- **[Alimentado por Vite:](https://vitejs.dev/)** inicialización instantánea del servidor, con ediciones siempre reflejadas instantáneamente (<100ms) sin recarga de página. + +- **[Extensiones Markdown Integradas:](./markdown)** Frontmatter, tablas, destaque de sintaxis... usted escoje. Especificamente, VitePress proporciona muchos recursos para trabajar con bloques de código, tornandolo ideal para documentación altamente técnica. + +- **[Markdown Mejorado por Vue:](./using-vue)** cada página Markdown es también un [Componente de Archivo único](https://pt.vuejs.org/guide/scaling-up/sfc.html), gracias a la compatibilidad de sintaxis de 100% del template Vue con HTML. Puede también incorporar iteractividad con su contenido estático usando recursos de template Vue o componentes Vue importados. + +## Desempeño {#performance} + +Al contrario de muchos SSGs tradicionales, un sitio generado por VitePress es la verdad una [Single Page Application](https://en.wikipedia.org/wiki/Single-page_application) (SPA). + +- **Carga Inicial Rápida** + + La visita inicial a cualquier página será servida con el HTML estático pré-renderizado para velocidad de carga rápida y SEO optimizado. La página entonces carga un paquete JavaScript que transforma la página en una SPA Vue ("hidratación"). El proceso de hidratación es extremadamente rápido: en [PageSpeed Insights](https://pagespeed.web.dev/report?url=https%3A%2F%2Fvitepress.dev%2F), sitios típicos VitePress alcanzan puntuaciones de desempeño casi perfectas, incluso en dispositivos móbiles de bajo desempeño con una red lenta. + +- **Navegación Rápida pos-carga** + + Más importante todavía, el modelo SPA lleva a una mejor experiencia del usuario **después** de la carga inicial. La navegación subsequente dentro del sitio no causará una recarga adicional completa de la página. En vez de eso, el contenido de la página de entrada será buscado y actualizado dinámicamente. VitePress también pre-carga automáticamente pedazos de página para links que están dentro del viewport. En la mayoría de los casos, la navegación pos-carga parecerá instantánea. + +- **Interactividad Sin Penalidades** + + Para ser capaz de hidratar las partes dinámicas Vue incorporadas dentro del Markdown estático, cada página Markdown es procesada como un componente Vue y compilada en JavaScript. Esto puede parecer ineficiente, pero el compilador Vue es suficientemente inteligente para separar las partes estáticas y dinámicas, minimizando tanto el costo de hidratación así como el tamaño de carga. Para la carga inicial de la página, las partes estáticas son automáticamente eliminadas de la carga JavaScript y omitidas durante la hidratación. + +## Y VuePress? {#what-about-vuepress} + +VitePress es el sucesor espiritual de VuePress. VuePress era orginalmente basado en Vue 2 y webpack. Con Vue 3 y Vite, VitePress ofrece una experiencia de desarrollador significamente mejor, mejor desempeño en producción, un tema por defecto más pulido y un API de personalización más flexible. + +A diferencia del API entre VitePress y VuePress reside principalmente en temas y personalización. Si estuviera usando VuePress 1 con el tema por defecto, la migración para VitePress debe ser relativamente simple. + +También hubo esfuerzo invertido en VuePress 2, que también soporta Vue 3 y Vite con mejor compatibilidad que con VuePress 1. Sin embargo, mantener dos SSGs en paralelo no es sustentable, entonces el equipo Vue decidió enfocarse en VitePress como el principal SSG recomendado a largo plazo. diff --git a/docs/es/index.md b/docs/es/index.md new file mode 100644 index 00000000..24b5034c --- /dev/null +++ b/docs/es/index.md @@ -0,0 +1,35 @@ +--- +layout: home + +hero: + name: VitePress + text: Generador de Sitios Estáticos Vite y Vue + tagline: Markdown para obtener lindos documentos en minutos + actions: + - theme: brand + text: Qué es VitePress? + link: /es/guide/what-is-vitepress + - theme: alt + text: Iniciar + link: /es/guide/getting-started + - theme: alt + text: GitHub + link: https://github.com/vuejs/vitepress + image: + src: /vitepress-logo-large.svg + alt: VitePress + +features: + - icon: 📝 + title: Concéntrese en su contenido + details: Cree lindos sitios de documentación apenas con markdown. + - icon: + title: Disfruta de la experiencia Vite + details: Inicio instantaneo de servidor, actualizaciones ultrarrápidas, y plugins del ecosistema Vite. + - icon: + title: Personaliza con Vue + details: Usa la sintaxis y componentes Vue directamente en markdown, o construye temas personalizados con Vue. + - icon: 🚀 + title: Entrega rápida de sitios + details: Carga inicial rápida con HTML estático, navegación rápida con enrutamiento del lado del cliente. +--- diff --git a/docs/es/reference/cli.md b/docs/es/reference/cli.md new file mode 100644 index 00000000..f5a5583c --- /dev/null +++ b/docs/es/reference/cli.md @@ -0,0 +1,74 @@ +# Intefaz de Linea de Comando {#command-line-interface} + +## `vitepress dev` + + Inicia el servidor de desarrollo VitePress con el directorio designado como raíz. Por defecto, utiliza el director actual. el comando `dev` también se puede omitir cuando se ejecuta el directorio actual. + +### Uso + +```sh +# Comienza en el directorio actual, omite el `dev` +vitepress + +# iniciar en un subdirectorio +vitepress dev [root] +``` + +### Opciones {#options} + +| Opciones | Descripción | +| --------------- | ----------------------------------------------------------------- | +| `--open [path]` | Abre el navegador en el inicio (`boolean \| string`) | +| `--port ` | Especifica el puerto (`number`) | +| `--base ` | Ruta de base pública (por defecto: `/`) (`string`) | +| `--cors` | Habilitar CORS | +| `--strictPort` | Salir si el puerto especificado ya esta en uso (`boolean`) | +| `--force` | Obligar al optimizador a ignorar el cache y volver a empaquetar (`boolean`) | + +## `vitepress build` + +Compilar el sitio web de VitePress para producción. + +### Uso + +```sh +vitepress build [root] +``` + +### Opciones + +| Opción | Descripción | +| ------------------------------ | ------------------------------------------------------------------------------------------------------------------- | +| `--mpa` (experimental) | Compilar en [Modo MPA](../guide/mpa-mode) Sin hidratación del lado del cliente (`boolean`) | +| `--base ` | Ruta de base pública (por defecto: `/`) (`string`) | +| `--target ` | Transpilar objetivo (por defecto: `"modules"`) (`string`) | +| `--outDir
` | Directorio de salida relativo a **cwd** (por defecto: `/.vitepress/dist`) (`string`) | +| `--minify [minifier]` | Habilitar/desabilitar la minificación, o especifica un minero para usar (por defecto: `"esbuild"`) (`boolean \| "terser" \| "esbuild"`) | +| `--assetsInlineLimit ` | Limitar los bytes para alinear los activos en base 64 (por defecto: `4096`) (`number`) | + +## `vitepress preview` + +Proporciona localmente la compilación de la producción. + +### Uso + +```sh +vitepress preview [root] +``` + +### Opciones + +| Opción | Descripción | +| --------------- | ------------------------------------------ | +| `--base ` | Ruta de base pública (por defecto: `/`) (`string`) | +| `--port ` | Especifica el puerto (`number`) | + +## `vitepress init` + +Inicia el [Asistente de Instalación](../guide/getting-started#setup-wizard) en el directorio actual. + +### Uso + +```sh +vitepress init +``` diff --git a/docs/es/reference/default-theme-badge.md b/docs/es/reference/default-theme-badge.md new file mode 100644 index 00000000..4c5e57eb --- /dev/null +++ b/docs/es/reference/default-theme-badge.md @@ -0,0 +1,69 @@ +# Badge {#badge} + +Los Badge te permite agregar estados a tus encabezados. Por ejemplo, podría resultar útil especificar el tipo de sección o la version compatible. + +## Uso {#usage} + +Puedes usar el componente `Badge` que está disponible globalmente. + +```html +### Title +### Title +### Title +### Title +``` + +el código anterior se representa como: + +### Title +### Title +### Title +### Title + +## Personalizar hijos {#custom-children} + +`` acepta `children` (hijos), que se mostrará en el badge. + +```html +### Title custom element +``` + +### Title custom element + +## Personalizar Tipo de Color {#customize-type-color} + +Puedes personalizar el estilo del badge anulando las variables CSS. los siguiente son los valores predeterminados: + +```css +:root { + --vp-badge-info-border: transparent; + --vp-badge-info-text: var(--vp-c-text-2); + --vp-badge-info-bg: var(--vp-c-default-soft); + + --vp-badge-tip-border: transparent; + --vp-badge-tip-text: var(--vp-c-brand-1); + --vp-badge-tip-bg: var(--vp-c-brand-soft); + + --vp-badge-warning-border: transparent; + --vp-badge-warning-text: var(--vp-c-warning-1); + --vp-badge-warning-bg: var(--vp-c-warning-soft); + + --vp-badge-danger-border: transparent; + --vp-badge-danger-text: var(--vp-c-danger-1); + --vp-badge-danger-bg: var(--vp-c-danger-soft); +} +``` + +## `` + +El componente `` acepta las siguiente propiedades: + +```ts +interface Props { + // Cuando se pasa `` ese valor es ignorado. + text?: string + + // El valor predeterminado es `tip`. + type?: 'info' | 'tip' | 'warning' | 'danger' +} +``` diff --git a/docs/es/reference/default-theme-carbon-ads.md b/docs/es/reference/default-theme-carbon-ads.md new file mode 100644 index 00000000..4ca016c5 --- /dev/null +++ b/docs/es/reference/default-theme-carbon-ads.md @@ -0,0 +1,22 @@ +# Carbon Ads {#carbon-ads} + +VitePress ha incorporado soporte nativo para [Carbon Ads](https://www.carbonads.net/). Al definir las credenciales de Carbon Ads en la configuración, VitePress mostrará anuncios en la página. + +```js +export default { + themeConfig: { + carbonAds: { + code: 'tu-código-carbon', + placement: 'tu-vinculación-carbon' + } + } +} +``` + +Estos valores se utilizan para llamar al script en CDN de carbon como se muestra a continuación. + +```js +`//cdn.carbonads.com/carbon.js?serve=${code}&placement=${placement}` +``` + +Para obtener más información de la configuración de Carbono Ads, por favor visite [Site Carbon Ads](https://www.carbonads.net/). diff --git a/docs/es/reference/default-theme-config.md b/docs/es/reference/default-theme-config.md new file mode 100644 index 00000000..129f16f6 --- /dev/null +++ b/docs/es/reference/default-theme-config.md @@ -0,0 +1,438 @@ +# Configuración del Tema Predeterminado {#default-theme-config} + +La configuración del tema te permite personalizar tu tema. puedes definir la configuración del tema a través de la opción `themeConfig` en el archivo de configuración: + +```ts +export default { + lang: 'pt-BR', + title: 'VitePress', + description: 'Generador de site estático Vite & Vue.', + + // Configuraciones relacionadas con el tema. + themeConfig: { + logo: '/logo.svg', + nav: [...], + sidebar: { ... } + } +} +``` + +**Las opciones documentadas de esta página se aplican unicamente al tema por defecto.** Diferentes temas esperan configuraciones diferentes de tema. Cuando se utiliza un tema personalizado, el objeto de configuración del tema se pasará al tema para que se puedan definir comportamientos condicionales. + +## i18nRouting + +- Tipo: `boolean` + +Cambie la configuración a, por ejemplo, `zh` será alterado para URL `/foo` (ou `/en/foo/`) para `/zh/foo`. Puedes desactivar este comportamiento configurado `themeConfig.i18nRouting` como `false`. + +## logo + +- Tipo: `ThemeableImage` + +Archivo de logotipo que se mostrará en la barra de navegación, justo antes del título del sitio. Acepta una ruta de cadena o un objeto para definir un logotipo diferente para los modos claro/oscuro. + +```ts +export default { + themeConfig: { + logo: '/logo.svg' + } +} +``` + +```ts +type ThemeableImage = + | string + | { src: string; alt?: string } + | { light: string; dark: string; alt?: string } +``` + +## siteTitle + +- Tipo: `string | false` + +Puedes personalizar este elemento para reemplazar el título del sitio predeterminado (`title` en configuración de la aplicación) en navegación. Cuando se establece como `false`, el título en la navegación quedará deshabilitado. Útil cuando tienes un `logo` que ya contiene el título del sitio. + +```ts +export default { + themeConfig: { + siteTitle: 'Hola mundo' + } +} +``` + +## nav + +- Tipo: `NavItem` + +La configuración del elemento del menú de navegación. Más detalles en [Tema Predeterminado: Navegación](./default-theme-nav#navigation-links). + +```ts +export default { + themeConfig: { + nav: [ + { text: 'Guia', link: '/guide' }, + { + text: 'Menú Dropdown', + items: [ + { text: 'Item A', link: '/item-1' }, + { text: 'Item B', link: '/item-2' }, + { text: 'Item C', link: '/item-3' } + ] + } + ] + } +} +``` + +```ts +type NavItem = NavItemWithLink | NavItemWithChildren + +interface NavItemWithLink { + text: string + link: string + activeMatch?: string + target?: string + rel?: string + noIcon?: boolean +} + +interface NavItemChildren { + text?: string + items: NavItemWithLink[] +} + +interface NavItemWithChildren { + text?: string + items: (NavItemChildren | NavItemWithLink)[] + activeMatch?: string +} +``` + +## sidebar + +- Tipo: `Sidebar` + +La configuración del elemento del menú de la barra lateral. Más detalles en [Tema Predeterminado: Barra Lateral](./default-theme-sidebar). + +```ts +export default { + themeConfig: { + sidebar: [ + { + text: 'Guia', + items: [ + { text: 'Introducción', link: '/introduction' }, + { text: 'A partir de', link: '/getting-started' }, + ... + ] + } + ] + } +} +``` + +```ts +export type Sidebar = SidebarItem[] | SidebarMulti + +export interface SidebarMulti { + [path: string]: SidebarItem[] +} + +export type SidebarItem = { + /** + * El rotulo del item. + */ + text?: string + + /** + * El link del item. + */ + link?: string + + /** + * Los hijos del item. + */ + items?: SidebarItem[] + + /** + * Si no se especifica, el grupo no es retráctil. + * + * Si es 'true', el grupo se puede contraer y está contraído de forma predeterminada. + * + * Si es 'false', el grupo se puede contraer pero se expande de forma predeterminada. + */ + collapsed?: boolean +} +``` + +## aside + +- Tipo: `boolean | 'left'` +- Estandar: `true` +- Puede ser anulado por la página a través de [frontmatter](./frontmatter-config#aside) + +Definir este valor como `false` evita que se muestre el elemento lateral.\ +Definir este valor como `true` presenta el lado de la derecha.\ +Definir este valor como `left` presenta el lado de la izquierda. + +Si desea deshabilitarlo para todas las vistas, debe usar `outline: false` en vez de eso. + +## outline + +- Tipo: `Outline | Outline['level'] | false` +- El nivel se puede superponer por página mediante [frontmatter](./frontmatter-config#outline) + +Definir este valor como `false` evita que el elemento se muestre _outline_. Consulte la interfaz para más detalles: + +```ts +interface Outline { + /** + * Los niveles de título que se mostrarán en el esquema. + * Un solo número significa que solo se mostrarán los títulos de ese nivel. + * Si se pasa una tupla, el primer número es el nivel mínimo y el segundo número es el nivel máximo. + * `'deep'` es lo mismo que `[2, 6]`, lo que significa que todos los titulos `

` a `

` serán mostrados. + * + * @default 2 + */ + level?: number | [number, number] | 'deep' + + /** + * El titulo que se mostrará en el equema. + * + * @default 'On this page' + */ + label?: string +} +``` + +## socialLinks + +- Tipo: `SocialLink[]` + +Puedes configurar esta opción para mostrar enlaces de redes sociales con íconos en la navegación. + +```ts +export default { + themeConfig: { + socialLinks: [ + { icon: 'github', link: 'https://github.com/vuejs/vitepress' }, + { icon: 'twitter', link: '...' }, + // También puedes agregar íconos personalizados pasando SVG como string: + { + icon: { + svg: 'Dribbble' + }, + link: '...', + // También puedes incluir una etiqueta personalizada de accesibilidad (opcional pero recomendada): + ariaLabel: 'cool link' + } + ] + } +} +``` + +```ts +interface SocialLink { + icon: string | { svg: string } + link: string + ariaLabel?: string +} +``` + +## footer + +- Tipo: `Footer` +- Se puede superponer por página mediante [frontmatter](./frontmatter-config#footer) + +Configuración de pie de página. Puede agregar un mensaje o texto de derechos de autor en el pie de página; sin embargo, solo se mostrará cuando la página no contenga una barra lateral. Esto se debe a preocupaciones de diseño. + +```ts +export default { + themeConfig: { + footer: { + message: 'Publicado bajo la licencia MIT.', + copyright: 'Derechos de autor © 2019-presente Evan You' + } + } +} +``` + +```ts +export interface Footer { + message?: string + copyright?: string +} +``` + +## editLink + +- Tipo: `EditLink` +- Se puede superponer por página mediante [frontmatter](./frontmatter-config#editlink) + +_EditLink_ le permite mostrar un enlace para editar la página en los servicios de administración Git, como GitHub o GitLab. Consulte [Tema por defecto: Editar Link](./default-theme-edit-link) para más detalles. + +```ts +export default { + themeConfig: { + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + text: 'Editar esta página en GitHub' + } + } +} +``` + +```ts +export interface EditLink { + pattern: string + text?: string +} +``` + +## lastUpdated + +- Tipo: `LastUpdatedOptions` + +Permite la personalización del formato de fecha y texto actualizado por ultima vez. + +```ts +export default { + themeConfig: { + lastUpdated: { + text: 'Actualizado en', + formatOptions: { + dateStyle: 'full', + timeStyle: 'medium' + } + } + } +} +``` + +```ts +export interface LastUpdatedOptions { + /** + * @default 'Last updated' + */ + text?: string + + /** + * @default + * { dateStyle: 'short', timeStyle: 'short' } + */ + formatOptions?: Intl.DateTimeFormatOptions & { forceLocale?: boolean } +} +``` + +## algolia + +- Tipo: `AlgoliaSearch` + +Una opción para dar soporte para buscar en su sitio de documentación usando [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch). Obtenga más información en [Tema predeterminado: Buscar](./default-theme-search). + +```ts +export interface AlgoliaSearchOptions extends DocSearchProps { + locales?: Record> +} +``` + +Ver todas las opciones [aquí](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts). + +## carbonAds {#carbon-ads} + +- Tipo: `CarbonAdsOptions` + +Una opción para mostrar [Carbon Ads](https://www.carbonads.net/). + +```ts +export default { + themeConfig: { + carbonAds: { + code: 'su-código-carbon', + placement: 'su-colocación-carbon' + } + } +} +``` + +```ts +export interface CarbonAdsOptions { + code: string + placement: string +} +``` + +Obtenga más información en [Tema Predeterminado: Carbon Ads](./default-theme-carbon-ads). + +## docFooter + +- Tipo: `DocFooter` + +Se puede utilizar para personalizar el texto que aparece encima de los enlaces anterior y siguiente. Útil si no estás escribiendo documentación en inglés. También se puede utilizar para desactivar globalmente los enlaces anteriores/siguientes. Si desea habilitar/deshabilitar selectivamente enlaces anteriores/siguientes, puede usar [frontmatter](./default-theme-prev-next-links). + +```ts +export default { + themeConfig: { + docFooter: { + prev: 'Página anterior', + next: 'Próxima página' + } + } +} +``` + +```ts +export interface DocFooter { + prev?: string | false + next?: string | false +} +``` + +## darkModeSwitchLabel + +- Tipo: `string` +- Estandar: `Appearance` + +Se puede utilizar para personalizar la etiqueta del botón del modo oscuro. Esta etiqueta solo se muestra en la vista móvil. + +## lightModeSwitchTitle + +- Tipo: `string` +- Estandar: `Switch to light theme` + +Se puede utilizar para personalizar el título del botón borrar que aparece al pasar el mouse. + +## darkModeSwitchTitle + +- Tipo: `string` +- Estandar: `Switch to dark theme` + +Se puede utilizar para personalizar el título del botón del modo oscuro que aparece al pasar el mouse. + +## sidebarMenuLabel + +- Tipo: `string` +- Estandar: `Menu` + +Se puede utilizar para personalizar la etiqueta del menú de la barra lateral. Esta etiqueta solo se muestra en la vista móvil. + +## returnToTopLabel + +- Tipo: `string` +- Estandar: `Return to top` + +Se puede utilizar para personalizar la etiqueta del botón Volver al principio. Esta etiqueta solo se muestra en la vista móvil. + +## langMenuLabel + +- Tipo: `string` +- Estandar: `Change language` + +Se puede utilizar para personalizar la etiqueta aria del botón de idioma en la barra de navegación. Esto sólo se usa si estás usando [i18n](../guide/i18n). + +## externalLinkIcon + +- Tipo: `boolean` +- Estandar: `false` + +Se debe mostrar um ícono de link externo junto a los enlaces externos en markdown. diff --git a/docs/es/reference/default-theme-edit-link.md b/docs/es/reference/default-theme-edit-link.md new file mode 100644 index 00000000..fc26f3d6 --- /dev/null +++ b/docs/es/reference/default-theme-edit-link.md @@ -0,0 +1,60 @@ +# Editar Link {#edit-link} + +## Configuración a nivel de sitio {#site-level-config} + +Editar enlace le permite mostrar un enlace para editar la página con servicios de administración de Git como GitHub o GitLab. Para habilitar, agregue la opción `themeConfig.editLink` en su configuración. + +```js +export default { + themeConfig: { + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path' + } + } +} +``` + +La opción `pattern` define una estructura de URL para el enlace, y `:path` se reemplaza con la misma ruta de la página + +También puedes poner una función pura que acepte [`PageData`](./runtime-api#usedata) como argumento y retorna una URL en string. + +```js +export default { + themeConfig: { + editLink: { + pattern: ({ filePath }) => { + if (filePath.startsWith('packages/')) { + return `https://github.com/acme/monorepo/edit/main/${filePath}` + } else { + return `https://github.com/acme/monorepo/edit/main/docs/${filePath}` + } + } + } + } +} +``` + +Esto no debería generar efectos secundarios ni acceder a nada fuera de su alcance, ya que será serializado y ejecutado en el navegador. + +De forma predeterminada, esto agregará el enlace con el texto 'Editar esta página' al final de la página de documentación. Puedes personalizar este texto configurando la opción `text`. + +```js +export default { + themeConfig: { + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + text: 'Edite la página en GitHub' + } + } +} +``` + +## Configuración Frontmatter {#frontmatter-config} + +La funcionalidad se puede desactivar por página utilizando la opción `editLink` en frontmatter: + +```yaml +--- +editLink: false +--- +``` diff --git a/docs/es/reference/default-theme-footer.md b/docs/es/reference/default-theme-footer.md new file mode 100644 index 00000000..538a039e --- /dev/null +++ b/docs/es/reference/default-theme-footer.md @@ -0,0 +1,53 @@ +# Pie de página {#footer} + +VitePress mostrará un pie de página global en la parte inferior de la página cuando `themeConfig.footer` está presente. + +```ts +export default { + themeConfig: { + footer: { + message: 'Publicado bajo la licencia MIT.', + copyright: 'Derechos de autor © 2019-present Evan You' + } + } +} +``` + +```ts +export interface Footer { + // El mensaje mostrado justo antes del copyright. + message?: string + + // El texto real de copyright. + copyright?: string +} +``` + +La configuración anterior también admite cadenas HTML. Entonces, por ejemplo, si desea configurar el texto de su pie de página para que tenga algunos enlaces, puede ajustar la configuración de la siguiente manera: + +```ts +export default { + themeConfig: { + footer: { + message: 'Publicado bajo Licencia MIT.', + copyright: 'Derechos de autor © 2019-present Evan You' + } + } +} +``` + +::: warning +Solo se utilizan elementos _inline_ será utilizado en `message` y `copyright` tal como se presenta dentro del elemento `

`. Si desea agregar elementos de tipo _block_, considere usar un _slot_ [`layout-bottom`](../guide/extending-default-theme#layout-slots). +::: + +Tenga en cuenta que el pie de página no se mostrará cuando la [Barra Lateral](./default-theme-sidebar) es visible. + +## Configuración Frontmatter {#frontmatter-config} + +Esto se puede desactivar por página usando la opción `footer` en frontmatter: + +```yaml +--- +footer: false +--- +``` diff --git a/docs/es/reference/default-theme-home-page.md b/docs/es/reference/default-theme-home-page.md new file mode 100644 index 00000000..70dbdfcd --- /dev/null +++ b/docs/es/reference/default-theme-home-page.md @@ -0,0 +1,168 @@ +# Página Inicial {#home-page} + +El tema predeterminado de VitePress proporciona un diseño de página de inicio, que también puedes ver en uso [en la página de inicio de este sitio web](../). Puedes usarlo en cualquiera de sus páginas especificando `layout: home` en [frontmatter](./frontmatter-config). + +```yaml +--- +layout: home +--- +``` + +Sin embargo, esta opción por sí sola no sirve de mucho. Puede agregar varias "secciones" predefinidas diferentes a la página de inicio configurando opciones adicionales como `hero` y `features`. + +## Sección Hero {#hero-section} + +La sección _Hero_ queda en la parte superior de la página de inicio. Asi es como se puede configurar la sección _Hero_. + +```yaml +--- +layout: home + +hero: + name: VitePress + text: Generador de sitios web estáticos con Vite & Vue. + tagline: Lorem ipsum... + image: + src: /logo.png + alt: VitePress + actions: + - theme: brand + text: Iniciar + link: /guide/what-is-vitepress + - theme: alt + text: Ver en GitHub + link: https://github.com/vuejs/vitepress +--- +``` + +```ts +interface Hero { + // El string que se muestra encima del `text`. Viene con el color de la marca + // y se espera que sea breve, como el nombre del producto. + name?: string + + // El texto principal de la sección de hero. + // Esto se definirá como un tag `h1`. + text: string + + // Eslogan que se muestra abajo del `text`. + tagline?: string + + // La imagen se muestra junto al área de texto y eslogan. + image?: ThemeableImage + + // Botones accionables para mostrar en la sección principal de la página de inicio. + actions?: HeroAction[] +} + +type ThemeableImage = + | string + | { src: string; alt?: string } + | { light: string; dark: string; alt?: string } + +interface HeroAction { + // Tema de color de botón. Estándar: `brand`. + theme?: 'brand' | 'alt' + + // Etiqueta del botón. + text: string + + // Destino del enlace del botón. + link: string + + // Atributo target del link. + target?: string + + // Atributo rel del link. + rel?: string +} +``` + +### Personalizando el color del nombre {#customizing-the-name-color} + +VitePress usa el color de la marca (`--vp-c-brand-1`) para `name`. Sin embargo, puedes personalizar este color anulando la variable `--vp-home-hero-name-color`. + +```css +:root { + --vp-home-hero-name-color: blue; +} +``` + +También puedes personalizarlo aún más combinando `--vp-home-hero-name-background` para dar al `name` un color degradado. + +```css +:root { + --vp-home-hero-name-color: transparent; + --vp-home-hero-name-background: -webkit-linear-gradient(120deg, #bd34fe, #41d1ff); +} +``` + +## Sección de caracteristicas {#features-section} + +En la sección de funciones, puede enumerar cualquier cantidad de funciones que desee mostrar inmediatamente después de la sección. _Hero_. Para configurarlo seleccione la opción `features` para el frontmatter. + +Puede proporcionar un icono para cada función, que puede ser un emoji o cualquier tipo de imagen. Cuando el icono configurado es una imagen (svg, png, jpeg...), debes proporcionar al ícono el ancho y alto apropiados; También puedes proporcionar la descripción, su tamaño intrínseco y sus variantes para temas oscuros y claros cuando sea necesario. + +```yaml +--- +layout: home + +features: + - icon: 🛠️ + title: Sencillo y minimalista, siempre + details: Lorem ipsum... + - icon: + src: /cool-feature-icon.svg + title: Otra caracteristica interesante + details: Lorem ipsum... + - icon: + dark: /dark-feature-icon.svg + light: /light-feature-icon.svg + title: Otra caracteristica interesante + details: Lorem ipsum... +--- +``` + +```ts +interface Feature { + // Muestra el icono en cada cuadro de función. + icon?: FeatureIcon + + // Título de la caracteristica. + title: string + + // Detalles de la caracteristicas. + details: string + + // Enlace al hacer clic en el componente de funcionalidad + // El vínculo puede ser interno o externo. + // + // ej. `guide/reference/default-theme-home-page` ou `https://example.com` + link?: string + + // Texto del enlace que se mostrará dentro del componente de funcionalidad. + // Mejor usado con opción `link`. + // + // ej. `Sepa más`, `Visitar página`, etc. + linkText?: string + + // Atributo rel de enlace para la opción `link`. + // + // ej. `external` + rel?: string + + // Atributo de destino del enlace para la opción `link`. + target?: string +} + +type FeatureIcon = + | string + | { src: string; alt?: string; width?: string; height: string } + | { + light: string + dark: string + alt?: string + width?: string + height: string + } +``` diff --git a/docs/es/reference/default-theme-last-updated.md b/docs/es/reference/default-theme-last-updated.md new file mode 100644 index 00000000..e1ac4022 --- /dev/null +++ b/docs/es/reference/default-theme-last-updated.md @@ -0,0 +1,27 @@ +# Última Actualización {#last-updated} + +La hora en que se actualizó el contenido por última vez se mostrará en la esquina inferior derecha de la página. Para habilitar, agregue la opción `lastUpdated` en su confirguración. + +::: tip +Necesitas hacer un _commit_ en el archivo markdown para ver el clima actualizado. +::: + +## Configuración a nivel de sitio {#site-level-config} + +```js +export default { + lastUpdated: true +} +``` + +## Configuración Frontmatter {#frontmatter-config} + +Esto se puede desactivar por página usando la opción `lastUpdated` en frontmatter: + +```yaml +--- +lastUpdated: false +--- +``` + +Consulte [Tema Personalizado: Última Actualización](./default-theme-config#lastupdated) para obtener más. Cualquier valor positivo a nivel de tema también habilitará la funcionalidad a menos que esté explícitamente deshabilitado a nivel de página o sitio. diff --git a/docs/es/reference/default-theme-layout.md b/docs/es/reference/default-theme-layout.md new file mode 100644 index 00000000..10e910c0 --- /dev/null +++ b/docs/es/reference/default-theme-layout.md @@ -0,0 +1,62 @@ +# Layout {#layout} + +Puedes elegir el layout de la página definiendo una opción de `layout` para el [frontmatter](./frontmatter-config) De la página. Hay tres opciones de layout: `doc`, `page` y `home`. Si no se especifica nada, la página será tratada como una página. `doc`. + +```yaml +--- +layout: doc +--- +``` + +## Layout del documento {#doc-layout} + +La opción `doc` es el layout predeterminado y aplica estilo a todo el contenido de Markdown el aspecto de "documentación". Funciona agrupando todo el contenido en la clase CSS `vp-doc`, y aplicando estilos a los elementos debajo de ella. + +Casi todos los elementos genéricos como `p` o `h2`, recibirá un estilo especial. Por tanto, recuerda que si añades algún HTML contenido personalizado dentro del contenido Markdown, también se verá afectado por estos estilos. + +También proporciona recursos de documentación específicos que se enumeran a continuación. Estas funciones solo están habilitadas en este layout. + +- Editar link +- Links Anterior y próximo. +- _Outline_ +- [Carbon Ads](./default-theme-carbon-ads) + +## Layout de la Página {#page-layout} + +La opción `page` se trata como una 'página en blanco'. Markdown aún se procesará y todo [Extensiones Markdown](../guide/markdown) funcionará de la misma manera que el layout `doc`, pero esto no recibirá ningún estilo predeterminado. + +El layout de la página le permitirá diseñar todo sin que el tema de VitePress afecte el marcado. Esto es útil cuando desea crear su propia página personalizada. + +Tenga en cuenta que incluso en este mismo layout, la barra lateral seguirá apareciendo si la página tiene una configuración de barra lateral correspondiente. + +## Layout de Home {#home-layout} + +La opción `home` gerará un modelo de _"Homepage"_. En este layout podrás definir opciones extras, como `hero` y `features`, para personalizar todavá más el contenido. Visite [Tema predeterminado: Página Inicial](./default-theme-home-page) para obter más detalles. + +## Sin Layout {#no-layout} + +Si no quieres ningún diseño, puedes pasar `layout: false` a través del frontmatter. Esta opción es útil si deseas una página de destino completamente personalizable (sin barra lateral, barra de navegacón o pie de página por defecto). + +## Layout Personalizado {#custom-layout} + +También puedes usar un layout personalizado: + +```md +--- +layout: foo +--- +``` + +Esto buscará un componente llamado `foo` registrado en contexto. Por ejemplo, puede registrar su componente globalmente en `.vitepress/theme/index.ts`: + +```ts +import DefaultTheme from 'vitepress/theme' +import Foo from './Foo.vue' + +export default { + extends: DefaultTheme, + enhanceApp({ app }) { + app.component('foo', Foo) + } +} +``` diff --git a/docs/es/reference/default-theme-nav.md b/docs/es/reference/default-theme-nav.md new file mode 100644 index 00000000..d244cba5 --- /dev/null +++ b/docs/es/reference/default-theme-nav.md @@ -0,0 +1,162 @@ +# Navegación {#nav} + +Refiriéndose a la barra de navegación que se muestra en la parte superior de la página. Contiene el título del sitio, enlaces del menú global, etc. + +## Título y logotipo del sitio {#site-title-and-logo} + +Por defecto, la navegación muestra el título del sitio que hace referencia al valor de [`config.title`](./site-config#title). Si desea cambiar lo que se muestra en la navegación, puede configurar un texto personalizado en el `themeConfig.siteTitle`. + +```js +export default { + themeConfig: { + siteTitle: 'Mi Título Personalizado' + } +} +``` + +Si tiene un logotipo para su sitio web, puede mostrarlo pasando la ruta a la imagen. Debes colocar el logo directamente dentro de la carpeta. `public`, y establezca la ruta absoluta hacia él. + +```js +export default { + themeConfig: { + logo: '/my-logo.svg' + } +} +``` + +Cuando agrega un logotipo, se muestra junto con el título del sitio. Si su logotipo tiene todo lo que necesita y desea ocultar el texto del título, configure `false` en la opción `siteTitle`. + +```js +export default { + themeConfig: { + logo: '/my-logo.svg', + siteTitle: false + } +} +``` + +También puedes pasar un objeto como logotipo si quieres agregar un atributo. `alt` o personalizarlo según el modo claro/oscuro. Consultar [`themeConfig.logo`](./default-theme-config#logo) para obtener más detalles. + +## Links de Navegación {#navigation-links} + +Puedes configurar la opción `themeConfig.nav` para añadir enlaces a tu navegación. + +```js +export default { + themeConfig: { + nav: [ + { text: 'Guia', link: '/guide' }, + { text: 'Configuración', link: '/config' }, + { text: 'Registro de Cambios', link: 'https://github.com/...' } + ] + } +} +``` + +`text` es el texto que se muestra en la navegación, y el `link` es el link al que será navegando cuando se hace click en el texto. Para el enlace, establezca la ruta al archivo sin el prefijo `.md` y siempre comenzar por `/`. + +Links de navegación también pueden ser menus _dropdown_. Para hacer eso, establezca la clave de `items` en la opción del link. + +```js +export default { + themeConfig: { + nav: [ + { text: 'Guia', link: '/guide' }, + { + text: 'Menú Dropdown', + items: [ + { text: 'Item A', link: '/item-1' }, + { text: 'Item B', link: '/item-2' }, + { text: 'Item C', link: '/item-3' } + ] + } + ] + } +} +``` + +Tenga en cuenta que el titulo del menú _dropdown_ (`Menu Dropdown` en el ejemplo anterior) no puede tener una propiedad `link`, ya que se convierte en un botón para abrir el cuadro del dialogo dropdown. + +También puedes agregar "secciones" a los elementos del menú _dropdown_ pasando más elementos anidados. + +```js +export default { + themeConfig: { + nav: [ + { text: 'Guia', link: '/guia' }, + { + text: 'Menú Dropdown', + items: [ + { + // Título da seção. + text: 'Título de la sección A', + items: [ + { text: 'Item A de la sección A', link: '...' }, + { text: 'Item B de la sección B', link: '...' } + ] + } + ] + }, + { + text: 'Menú Dropdown', + items: [ + { + // También puedes omitir el título + items: [ + { text: 'Item A da Seção A', link: '...' }, + { text: 'Item B da Seção B', link: '...' } + ] + } + ] + } + ] + } +} +``` + +### Personaliza el estado "activo" del link {#customize-link-s-active-state} + +Los elementos del menú de navegación se resaltarán cuando la página actual esté en la ruta correspondiente. Si desea personalizar la ruta que debe coincidir, establezca la propiedad `activeMatch` el regex como um valor en string. + +```js +export default { + themeConfig: { + nav: [ + // Este link esta en estado activo cuando + // el usuario esta en el camino `/config/`. + { + text: 'Guia', + link: '/guide', + activeMatch: '/config/' + } + ] + } +} +``` + +::: warning +`activeMatch` Debería ser un string regex, pero deberías definirla como un string. No podemos usar un objeto RegExp real aquí porque no es serializable durante el tiempo de construcción. +::: + +### Personalizar los atributos "target" y "rel" de links {#customize-link-s-target-and-rel-attributes} + +Por defecto, VitePress determina automáticamente lod atributos `target` y `rel` en función de si existe un enlace externo o no. Pero si quieres, también puedes personalizarlos. + +```js +export default { + themeConfig: { + nav: [ + { + text: 'Merchandise', + link: 'https://www.thegithubshop.com/', + target: '_self', + rel: 'sponsored' + } + ] + } +} +``` + +## Links Scociales {#social-links} + +Consulte [`socialLinks`](./default-theme-config#sociallinks). diff --git a/docs/es/reference/default-theme-prev-next-links.md b/docs/es/reference/default-theme-prev-next-links.md new file mode 100644 index 00000000..6c10c7bc --- /dev/null +++ b/docs/es/reference/default-theme-prev-next-links.md @@ -0,0 +1,43 @@ +# Links Anterior y Próximo {#prev-next-links} + +Puede personalizar el texto y el enlace de los botones Anterior y Siguiente que se muestran en la parte inferior de la página. Esto es útil cuando desea mostrar un texto diferente al que tiene en la barra lateral. Además, puede resultarle útil desactivar el pie de página o el enlace a la página para que no se incluya en la barra lateral. + +## prev + +- Tipo: `string | false | { text?: string; link?: string }` + +- Detalles: + + Especifica el text/enlace que se mostrará en el enlace a la página anterior. Si no ve esto al principio, el text/enlace se deducirá de la configuración de la barra lateral. + +- Ejemplos: + + - Para personalizar solo texto: + + ```yaml + --- + prev: 'Iniciar | Markdown' + --- + ``` + + - Para personalizar ambos texto y link: + + ```yaml + --- + prev: + text: 'Markdown' + link: '/guide/markdown' + --- + ``` + + - Para esconder la página anterior: + + ```yaml + --- + prev: false + --- + ``` + +## next + +Igual que el `prev` pero para la página siguiente. diff --git a/docs/es/reference/default-theme-search.md b/docs/es/reference/default-theme-search.md new file mode 100644 index 00000000..3059b0ba --- /dev/null +++ b/docs/es/reference/default-theme-search.md @@ -0,0 +1,372 @@ +--- +outline: deep +--- + +# Buscar {#search} + +## Busqueda local {#local-search} + +VitePress admite la búsqueda de texto completo utilizando un índice en el navegador gracias a [minisearch](https://github.com/lucaong/minisearch/). Para habilitar esta función, simplemente configure la opción `themeConfig.search.provider` como `'local'` en el archivo `.vitepress/config.ts`: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local' + } + } +}) +``` + +Resultado de ejemplo: + +![captura de pantalla del modo de búsqueda](/search.png) + +Alternativamente, puedes usar [Algolia DocSearch](#algolia-search) o algunos complementos comunitarios como o . + +### i18n {#local-search-i18n} + +Puede utilizar una configuración como esta para utilizar la búsqueda multilingüe: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + locales: { + zh: { + translations: { + button: { + buttonText: '搜索文档', + buttonAriaLabel: '搜索文档' + }, + modal: { + noResultsText: '无法找到相关结果', + resetButtonTitle: '清除查询条件', + footer: { + selectText: '选择', + navigateText: '切换' + } + } + } + } + } + } + } + } +}) +``` + +### Opciones MiniSearch {#mini-search-options} + +Puedes configurar MiniSearch de esta manera: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + miniSearch: { + /** + * @type {Pick} + */ + options: { + /* ... */ + }, + /** + * @type {import('minisearch').SearchOptions} + * @default + * { fuzzy: 0.2, prefix: true, boost: { title: 4, text: 2, titles: 1 } } + */ + searchOptions: { + /* ... */ + } + } + } + } + } +}) +``` + +Obtenga más información en [documentación de MiniSearch](https://lucaong.github.io/minisearch/classes/MiniSearch.MiniSearch.html). + +### Presentador de contenido personalizado {#custom-content-renderer} + +Puedes personalizar la función utilizada para presentar el contenido de rebajas antes de indexarlo: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + /** + * @param {string} src + * @param {import('vitepress').MarkdownEnv} env + * @param {import('markdown-it-async')} md + */ + async _render(src, env, md) { + // retorne un string HTML + } + } + } + } +}) +``` + +Esta función se eliminará de los datos del sitio web en el lado del cliente, por lo que podrá utilizar las API de Node.js en ella. + +#### Ejemplo: Excluir páginas de la busqueda {#example-excluding-pages-from-search} + +Puedes excluir páginas de la busqueda adicionando `search: false` al principio de la página. Alternativamente: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + async _render(src, env, md) { + const html = await md.renderAsync(src, env) + if (env.frontmatter?.search === false) return '' + if (env.relativePath.startsWith('algum/caminho')) return '' + return html + } + } + } + } +}) +``` + +::: warning Nota +En este caso, una función `_render` se proporciona, es necesario manipular el `search: false` desde el frente por su cuenta. Además, el objeto `env` no estará completamente poblado antes que `md.renderAsync` se llama, luego verifica las propiedades opcionales `env`, como `frontmatter`, debe hacerse después de eso. +::: + +#### Ejemplo: Transformar contenido - agregar anclajes {#example-transforming-content-adding-anchors} + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + async _render(src, env, md) { + const html = await md.renderAsync(src, env) + if (env.frontmatter?.title) + return await md.renderAsync(`# ${env.frontmatter.title}`) + html + return html + } + } + } + } +}) +``` + +## Busqueda de Algolia {#algolia-search} + +VitePress admite la búsqueda en su sitio de documentación utilizando [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch). Consulte su guía de introducción. en tu archivo `.vitepress/config.ts`, Deberá proporcionar al menos lo siguiente para que funcione: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'algolia', + options: { + appId: '...', + apiKey: '...', + indexName: '...' + } + } + } +}) +``` + +### i18n {#algolia-search-i18n} {#algolia-search-i18n} + +Puedes utilizar una configuración como esta para utilizar la búsqueda multilingüe: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'algolia', + options: { + appId: '...', + apiKey: '...', + indexName: '...', + locales: { + zh: { + placeholder: '搜索文档', + translations: { + button: { + buttonText: '搜索文档', + buttonAriaLabel: '搜索文档' + }, + modal: { + searchBox: { + resetButtonTitle: '清除查询条件', + resetButtonAriaLabel: '清除查询条件', + cancelButtonText: '取消', + cancelButtonAriaLabel: '取消' + }, + startScreen: { + recentSearchesTitle: '搜索历史', + noRecentSearchesText: '没有搜索历史', + saveRecentSearchButtonTitle: '保存至搜索历史', + removeRecentSearchButtonTitle: '从搜索历史中移除', + favoriteSearchesTitle: '收藏', + removeFavoriteSearchButtonTitle: '从收藏中移除' + }, + errorScreen: { + titleText: '无法获取结果', + helpText: '你可能需要检查你的网络连接' + }, + footer: { + selectText: '选择', + navigateText: '切换', + closeText: '关闭', + searchByText: '搜索提供者' + }, + noResultsScreen: { + noResultsText: '无法找到相关结果', + suggestedQueryText: '你可以尝试查询', + reportMissingResultsText: '你认为该查询应该有结果?', + reportMissingResultsLinkText: '点击反馈' + } + } + } + } + } + } + } + } +}) +``` + +[Estas opciones](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts) se pueden superponer. Consulte la documentación oficial de Algolia para obtener más información sobre ellos. + +### Configuración _Crawler_ {#crawler-config} + +A continuación se muestra un ejemplo de la configuración que utiliza este sitio: + +```ts +new Crawler({ + appId: '...', + apiKey: '...', + rateLimit: 8, + startUrls: ['https://vitepress.dev/'], + renderJavaScript: false, + sitemaps: [], + exclusionPatterns: [], + ignoreCanonicalTo: false, + discoveryPatterns: ['https://vitepress.dev/**'], + schedule: 'at 05:10 on Saturday', + actions: [ + { + indexName: 'vitepress', + pathsToMatch: ['https://vitepress.dev/**'], + recordExtractor: ({ $, helpers }) => { + return helpers.docsearch({ + recordProps: { + lvl1: '.content h1', + content: '.content p, .content li', + lvl0: { + selectors: 'section.has-active div h2', + defaultValue: 'Documentation' + }, + lvl2: '.content h2', + lvl3: '.content h3', + lvl4: '.content h4', + lvl5: '.content h5' + }, + indexHeadings: true + }) + } + } + ], + initialIndexSettings: { + vitepress: { + attributesForFaceting: ['type', 'lang'], + attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'], + attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'], + attributesToSnippet: ['content:10'], + camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'], + searchableAttributes: [ + 'unordered(hierarchy_radio_camel.lvl0)', + 'unordered(hierarchy_radio.lvl0)', + 'unordered(hierarchy_radio_camel.lvl1)', + 'unordered(hierarchy_radio.lvl1)', + 'unordered(hierarchy_radio_camel.lvl2)', + 'unordered(hierarchy_radio.lvl2)', + 'unordered(hierarchy_radio_camel.lvl3)', + 'unordered(hierarchy_radio.lvl3)', + 'unordered(hierarchy_radio_camel.lvl4)', + 'unordered(hierarchy_radio.lvl4)', + 'unordered(hierarchy_radio_camel.lvl5)', + 'unordered(hierarchy_radio.lvl5)', + 'unordered(hierarchy_radio_camel.lvl6)', + 'unordered(hierarchy_radio.lvl6)', + 'unordered(hierarchy_camel.lvl0)', + 'unordered(hierarchy.lvl0)', + 'unordered(hierarchy_camel.lvl1)', + 'unordered(hierarchy.lvl1)', + 'unordered(hierarchy_camel.lvl2)', + 'unordered(hierarchy.lvl2)', + 'unordered(hierarchy_camel.lvl3)', + 'unordered(hierarchy.lvl3)', + 'unordered(hierarchy_camel.lvl4)', + 'unordered(hierarchy.lvl4)', + 'unordered(hierarchy_camel.lvl5)', + 'unordered(hierarchy.lvl5)', + 'unordered(hierarchy_camel.lvl6)', + 'unordered(hierarchy.lvl6)', + 'content' + ], + distinct: true, + attributeForDistinct: 'url', + customRanking: [ + 'desc(weight.pageRank)', + 'desc(weight.level)', + 'asc(weight.position)' + ], + ranking: [ + 'words', + 'filters', + 'typo', + 'attribute', + 'proximity', + 'exact', + 'custom' + ], + highlightPreTag: '', + highlightPostTag: '', + minWordSizefor1Typo: 3, + minWordSizefor2Typos: 7, + allowTyposOnNumericTokens: false, + minProximity: 1, + ignorePlurals: true, + advancedSyntax: true, + attributeCriteriaComputedByMinProximity: true, + removeWordsIfNoResults: 'allOptional' + } + } +}) +``` diff --git a/docs/es/reference/default-theme-sidebar.md b/docs/es/reference/default-theme-sidebar.md new file mode 100644 index 00000000..41cd5cac --- /dev/null +++ b/docs/es/reference/default-theme-sidebar.md @@ -0,0 +1,183 @@ +# Barra Lateral {#sidebar} + +La barra lateral es el bloque de navegación principal de su documentación. Puede configurar el menú de la barra lateral en [`themeConfig.sidebar`](./default-theme-config#sidebar). + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Guia', + items: [ + { text: 'Introducción', link: '/introduction' }, + { text: 'Iniciando', link: '/getting-started' }, + ... + ] + } + ] + } +} +``` + +## Conceptos básicos {#the-basics} + +La forma más sencilla del menú de la barra lateral es pasar una único _array_ de links. El elemento de primer nivel define la "sección" de la barra latera. debe contener `text`, cuál es el título de la sección, y `items` que son los propios enlaces de navegación. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Título de la sección A', + items: [ + { text: 'Item A', link: '/item-a' }, + { text: 'Item B', link: '/item-b' }, + ... + ] + }, + { + text: 'Título de la sección B', + items: [ + { text: 'Item C', link: '/item-c' }, + { text: 'Item D', link: '/item-d' }, + ... + ] + } + ] + } +} +``` + +Cada `link` debe especificar la ruta al archivo en sí comenzando con `/`. +Si agrega una barra al final del enlace, mostrará el `index.md` del directorio correspondiente. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Guia', + items: [ + // Esto muestra la página `/guide/index.md`. + { text: 'Introducción', link: '/guide/' } + ] + } + ] + } +} +``` + +Puede anidar aún más elementos de la barra lateral hasta 6 niveles de profundidad contando desde el nivel raíz. Tenga en cuenta que los niveles superiores a 6 se ignorarán y no se mostrarán en la barra lateral. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Nivel 1', + items: [ + { + text: 'Nivel 2', + items: [ + { + text: 'Nivel 3', + items: [ + ... + ] + } + ] + } + ] + } + ] + } +} +``` + +## Varias Barras Laterales {#multiple-sidebars} + +Puedes mostrar una barra lateral diferente según la ruta de la página. Por ejemplo, como se muestra en este sitio, es posible que desee crear secciones separadas de contenido en su documentación, como la página "Guía" y la página "Configuración". + +Para hacer esto, primero organice sus páginas en directorios para cada sección deseada: + +``` +. +├─ guide/ +│ ├─ index.md +│ ├─ one.md +│ └─ two.md +└─ config/ + ├─ index.md + ├─ three.md + └─ four.md +``` + +Luego actualice su configuración para definir su barra lateral para cada sección. Esta vez debes pasar un objeto en lugar de un array. + +```js +export default { + themeConfig: { + sidebar: { + // Esta barra lateral se muestra cuando un usuario + // está en el directorio `guide`. + '/guide/': [ + { + text: 'Guia', + items: [ + { text: 'Índice', link: '/guide/' }, + { text: 'Um', link: '/guide/one' }, + { text: 'Dois', link: '/guide/two' } + ] + } + ], + + // Esta barra lateral se muestra cuando un usuario + // está en el directorio `config`. + '/config/': [ + { + text: 'Configuración', + items: [ + { text: 'Índice', link: '/config/' }, + { text: 'Tres', link: '/config/three' }, + { text: 'Cuatro', link: '/config/four' } + ] + } + ] + } + } +} +``` + +## Grupos Retráctiles en la Barra Lateral {#collapsible-sidebar-groups} + +Adicionando una opción `collapsed` al grupo de la barra lateral, muestra un botón para ocultar/mostrar cada sección + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Título de la sección A', + collapsed: false, + items: [...] + } + ] + } +} +``` + +Todas las secciones están 'abiertas' de forma predeterminada. Si desea que estén 'cerrados' al cargar la página inicial, configure la opción `collapsed` como `true`. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Título de la sección A', + collapsed: true, + items: [...] + } + ] + } +} +``` diff --git a/docs/es/reference/default-theme-team-page.md b/docs/es/reference/default-theme-team-page.md new file mode 100644 index 00000000..996e8f18 --- /dev/null +++ b/docs/es/reference/default-theme-team-page.md @@ -0,0 +1,256 @@ + + +# Página de Equipo {#team-page} + +Si deseas presentar a tu equipo, puedes utilizar componentes del equipo para crear la página del equipo. Hay dos formas de utilizar estos componentes. Una es incrustarlo en la página del documento y otra es crear una página de equipo completa. + +## Mostrar miembros del equipo en una página {#show-team-members-in-a-page} + +Puedes usar el componente `` expuesto en `vitepress/theme` para mostrar una lista de los miembros del equipo en cualquier página. + +```html + + +# Nuestro equipo + +Saluda a nuestro increible equipo. + + +``` + +El código anterior mostrará a un miembro del equipo en un elemento similar a una tarjeta. Debería mostrar algo similar a lo siguiente. + + + +El componente `` viene en dos tamaños diferentes, pequeño `small` y médio `medium`. Si bien es una cuestión de preferencia, generalmente el tamaño `small` debería encajar mejor cuando se use en la página del documento. Además, puede agregar más propiedades a cada miembro, como agregar el botón "descripción" o "patrocinador". Obtenga más información sobre en [``](#vpteammembers). + +Incrustar miembros del equipo en la página del documento es bueno para equipos pequeños donde tener una página de equipo dedicada completa puede ser demasiado, o introducir miembros parciales como referencia al contexto de la documentación. + +Si tienes una gran cantidad de miembros o simplemente deseas más espacio para exhibir a los miembros del equipo, considere [crear una página de equipo completa.](#create-a-full-team-page) + +## Creando una página de equipo completa {#create-a-full-team-page} + +En lugar de agregar miembros del equipo a la página del documento, también puede crear una página de equipo completa, del mismo modo que puede crear una [Página Inicial](./default-theme-home-page) personalizada. + +Para crear una página de equipo, primero cree un nuevo md. El nombre del archivo no importa, pero aquí lo llamaremos `team.md`. En este archivo, configure la opción `layout: page` desde frontmatter, y luego puedes componer la estructura de tu página usando componentes `TeamPage`. + +```html +--- +layout: page +--- + + + + + + + + + +``` + +Al crear una página de equipo completa, recuerde agrupar todos los componentes con el componente ``. Este componente garantizará que todos los componentes anidados relacionados con el equipo obtengan la estructura de diseño adecuada, como los espacios. + +El componente `` adiciona la sección de título de la página. El título es `

`. Use los _slots_ `#title` y `#lead` para poder documentar sobre su equipo. + +`` funciona igual que cuando se usa en una página de documento. Mostrará la lista de miembros. + +### Agregar secciones para dividir a los miembros del equipo {#add-sections-to-divide-team-members} + +Puede agregar "secciones" a la página de su equipo. Por ejemplo, puede tener diferentes tipos de miembros del equipo, como miembros del equipo central y socios de la comunidad. Puede dividir a estos miembros en secciones para explicar mejor las funciones de cada grupo. + +Para poder hacerlo, agregue al componente `` al archivo `team.md` que creamos anteriormente. + +```html +--- +layout: page +--- + + + + + + + + + + + + + + +``` + +El componente `` Puede tener los _slots_ `#title` y `#lead` similares al componente `VPTeamPageTitle`, y también al _slot_ `#members` para mostrar a los miembros del equipo. + +Recuerde colocar el componente `` dentro del _slot_ `#members`. + +## `` + +El componente `` muestra una determinada lista de miembros. + +```html + +``` + +```ts +interface Props { + // Tamaño de cada miembro. El valor predeterminado es `medium`. + size?: 'small' | 'medium' + + // Lista de miembros que se mostrará. + members: TeamMember[] +} + +interface TeamMember { + // Imagen de avatar de miembro. + avatar: string + + // Nombre del miembro. + name: string + + // Título a ser mostrado a bajo del nombre del miembro. + // Ej.: Desarrollador, Ingeniero de Software, etc. + title?: string + + // Organización a la que pertenece al miembro. + org?: string + + // URL de la organización. + orgLink?: string + + // Descripción del miembro. + desc?: string + + // Links sociales, por ejemplo, GitHub, Twitter, etc. + // Puedes pasar un objeto de Links Sociales aquí. + // Vea: https://vitepress.dev/reference/default-theme-config.html#sociallinks + links?: SocialLink[] + + // URL de la página del patrocinador del miembro. + sponsor?: string + + // Texto para enlace del patrocinador. El valor predeterminado es 'Sponsor'. + actionText?: string +} +``` + +## `` + +El componente raíz al crear una página de equipo completa. Sólo acepta una _slot_. Aplicará estilo a todos los componentes anteriores relacionados con el equipo. + +## `` + +Agrega la sección "título" a la página. Es mejor usarlo desde el principio debajo ``. Acepta los _slots_ `#title` y `#lead`. + +```html + + + + + + +``` + +## `` + +Crea una 'sección' en la página del equipo. Aceptar los _slots_ `#title`, `#lead` y `#members`. Puedes agregar tantas secciones como quieras dentro ``. + +```html + + ... + + + + + + +``` diff --git a/docs/es/reference/frontmatter-config.md b/docs/es/reference/frontmatter-config.md new file mode 100644 index 00000000..9032f42e --- /dev/null +++ b/docs/es/reference/frontmatter-config.md @@ -0,0 +1,221 @@ +--- +outline: deep +--- + +# Configuración Frontmatter {#frontmatter-config} + +Frontmatter permite la configuración basada en páginas. En cada archivo markdown, puede utilizar la configuración de frontmatter para anular las opciones de configuración a nivel de sitio o tema. Además, hay opciones de configuración que sólo se pueden establecer en frontmatter. + +Ejemplo de uso: + +```md +--- +title: Documentación con VitePress +editLink: true +--- +``` + +Puede acceder a los datos del frontmatter a través de la variable global `$frontmatter` en expresiones Vue: + +```md +{{ $frontmatter.title }} +``` + +## title + +- Tipo: `string` + +Título de la página. Es lo mismo que [config.title](./site-config#title), y anula la configuración a nivel de sitio. + +```yaml +--- +title: VitePress +--- +``` + +## titleTemplate + +- Tipo: `string | boolean` + +El sufijo del título. Es lo mismo que [config.titleTemplate](./site-config#titletemplate), y anula la configuración a nivel de sitio. + +```yaml +--- +title: VitePress +titleTemplate: Generador de sitios web estáticos con Vite & Vue +--- +``` + +## descripción + +- Tipo: `string` + +Descripción de la página. Es lo mismo que [config.description](./site-config#description), y anula la configuración a nivel de sitio. + +```yaml +--- +description: VitePress +--- +``` + +## head + +- Tipo: `HeadConfig[]` + +Especifica etiquetas de encabezado adicionales que se inyectarán en la página actual. Se agregarán después de las etiquetas principales inyectadas por la configuración a nivel de sitio. + +```yaml +--- +head: + - - meta + - name: description + content: hello + - - meta + - name: keywords + content: super duper SEO +--- +``` + +```ts +type HeadConfig = + | [string, Record] + | [string, Record, string] +``` + +## Solo Tema Predeterminado {#default-theme-only} + +Las siguientes opciones de frontmatter solo se aplican cuando se usa el tema predeterminado. + +### layout + +- Tipo: `doc | home | page` +- Predeterminado: `doc` + +Determina el layout de la página. + +- `doc` - Aplica estilos de documentación por defecto al contenido markdown. +- `home` - Layout especial para la "Página Inicial". Puedes agregar opciones extras como `hero` y `features` para crear rapidamente una hermosa página inicial. +- `page` - Se comporta de manera similar a `doc`, pero no aplica estilos al contenido. Útil cuando desea crear una página totalmente personalizada. + +```yaml +--- +layout: doc +--- +``` + +### hero + +Define el contenido de la sección _hero_ en la página inicial cuando `layout` está definido como `home`. Más detalles en [Tema Predeterminado: Página Inicial](./default-theme-home-page). + +### features + +Define los elementos que se mostrarán en la sección de características cuando `layout` está definido como `home`. Más detalles en [Tema Predeterminado: Página Inicial](./default-theme-home-page). + +### navbar + +- Tipo: `boolean` +- Predeterminado: `true` + +Se debe mostrar una [barra de navegación](./default-theme-nav). + +```yaml +--- +navbar: false +--- +``` + +### sidebar + +- Tipo: `boolean` +- Predeterminado: `true` + +Se debe mostrar una [barra lateral](./default-theme-sidebar). + +```yaml +--- +sidebar: false +--- +``` + +### aside + +- Tipo: `boolean | 'left'` +- Predeterminado: `true` + +Define la localización del componente aside en el layout `doc`. + +Configurar este valor como `false` evita que se muestre el elemento lateral.\ +Configurar este valor como `true` presenta el lado de la derecha.\ +Configurar este valor como `'left'` presenta el lado de la izquierda. + +```yaml +--- +aside: false +--- +``` + +### outline + +- Tipo: `number | [number, number] | 'deep' | false` +- Predeterminado: `2` + +Los niveles del encabezado en _outline_ que se mostrará para la página. Es lo mismo que [config.themeConfig.outline.level](./default-theme-config#outline), y anula el valor establecido en la configuración a nivel de sitio. + +### lastUpdated + +- Tipo: `boolean | Date` +- Predeterminado: `true` + +Se debe mostrar el texto de [última actualización](./default-theme-last-updated) en el pie de página de la página actual. Si se especifica una fecha y hora específicas, se mostrarán en lugar de la hora de la última modificación de git. + +```yaml +--- +lastUpdated: false +--- +``` + +### editLink + +- Tipo: `boolean` +- Predeterminado: `true` + +Se debe mostrar el [link de edición](./default-theme-edit-link) en el pie de página de la página actual. + +```yaml +--- +editLink: false +--- +``` + +### footer + +- Tipo: `boolean` +- Predeterminado: `true` + +Se debe mostrar el [pie de página](./default-theme-footer). + +```yaml +--- +footer: false +--- +``` + +### pageClass + +- Tipo: `string` + +Agrega un nombre de clase adicional a una página específica. + +```yaml +--- +pageClass: custom-page-class +--- +``` + +Luego puede personalizar los estilos para esta página específica en el archivo. `.vitepress/theme/custom.css`: + +```css +.custom-page-class { + /* estilos especificos de la página */ +} +``` diff --git a/docs/es/reference/runtime-api.md b/docs/es/reference/runtime-api.md new file mode 100644 index 00000000..1446df4c --- /dev/null +++ b/docs/es/reference/runtime-api.md @@ -0,0 +1,165 @@ +# API en Tiempo de Ejecución {#runtime-api} + +VitePress ofrece varias API integradas para permitir el acceso a los datos de la aplicación. VitePress también viene con algunos componentes integrados que se pueden utilizar globalmente. + +Los métodos auxiliares son importaciones globales de `vitepress` y se utilizan a menudo en componentes Vue de temas personalizados. Sin embargo, también se pueden utilizar dentro de páginas `.md` porque los archivos de rebajas se compilan en [Componentes de Archivo Único Vue (SFC)](https://vuejs.org/guide/scaling-up/sfc.html). + +Métodos que comienzan con `use*` indican que es una función de [API de Composición Vue 3](https://vuejs.org/guide/introduction.html#composition-api) ("Composable") que solo puede ser utilizada dentro de `setup()` o ` + + +``` + +## `useRoute` + +Devuelve el objeto de ruta actual con el siguiente tipo: + +```ts +interface Route { + path: string + data: PageData + component: Component | null +} +``` + +## `useRouter` + +Devuelve la instancia del enrutador VitePress para que pueda navegar mediante programación a otra página. + +```ts +interface Router { + /** + * Ruta atual. + */ + route: Route + /** + * Navegar para una nueva URL. + */ + go: (to?: string) => Promise + /** + * Llamado antes del cambio de ruta. Devuelve 'falso' para cancelar la navegación. + */ + onBeforeRouteChange?: (to: string) => Awaitable + /** + * Se llama antes de que se cargue el componente de la página (después de que se haya actualizado el estado del historial). + * atualizado). Retorne `false` para cancelar la navegación. + */ + onBeforePageLoad?: (to: string) => Awaitable + /** + * Llamado después del cambio de ruta. + */ + onAfterRouteChange?: (to: string) => Awaitable +} +``` + +## `withBase` + +- **Tipo**: `(path: string) => string` + +agrega la [`base`](./site-config#base) configurada a una ruta URL determinada. Consulte también [Base URL](../guide/asset-handling#base-url). + +## `` + +El componente `` muestra el contenido de markdown renderizado. Útil [al crear tu propio tema](../guide/custom-theme). + +```vue + +``` + +## `` + +El componente `` muestra tu _slot_ solo del lado del cliente. + +Debido a que las aplicaciones VitePress se interpretan en el lado del servidor en Node.js cuando generan compilaciones estáticas, cualquier uso de Vue debe seguir los requisitos del código universal. En resumen, asegúrese de acceder solo a las API del navegador/DOM en ganchos `beforeMount` o `mounted`. + +Si está utilizando o demostrando componentes que no son compatibles con SSR (por ejemplo, contienen directivas personalizadas), puede incluirlos dentro del componente. `ClientOnly`. + +```vue-html + + + +``` + +- Relacionado: [Compatibilidad SSR](../guide/ssr-compat) + +## `$frontmatter` + +Accede directamente a los datos [frontmatter](../guide/frontmatter) de la página actual en expresiones Vue. + +```md +--- +title: Olá +--- + +# {{ $frontmatter.title }} +``` + +## `$params` + +Accede directamente a los [parámetros de ruta dinámica](../guide/routing#dynamic-routes) de la página actual en expresiones Vue. + +```md +- nombre del paquete: {{ $params.pkg }} +- versión: {{ $params.version }} +``` diff --git a/docs/es/reference/site-config.md b/docs/es/reference/site-config.md new file mode 100644 index 00000000..d46fe4c5 --- /dev/null +++ b/docs/es/reference/site-config.md @@ -0,0 +1,705 @@ +--- +outline: deep +--- + +# Configuración de site {#site-config} + +La configuración del site es donde puede configurar los ajustes globales del site. Las opciones de configuración de la aplicación definen las configuraciones que se aplican a todos los sites de VitePress, independientemente del tema que estén utilizando. Por ejemplo, el directorio base o el título del site. + +## Vista general {#overview} + +### Resolución de configuración {#config-resolution} + +El archivo de configuración siempre se resuelve desde `/.vitepress/config.[ext]`, donde `` es la [raiz del proyecto](../guide/routing#root-and-source-directory) VitePress y `[ext]` es una de las extensiones de archivo compatibles. TypeScript es compatible desde el primer momento. Las extensiones compatibles incluyen `.js`, `.ts`, `.mjs` y `.mts`. + +Recuerde usar la sintaxis de módulos ES en los archivos de configuración. El archivo de configuración debe exportar por defecto un objeto: + +```ts +export default { + // opciones de configuración a nivel de aplicación + lang: 'pt-BR', + title: 'VitePress', + description: 'Generador de site estático Vite & Vue.', + ... +} +``` + +:::details Configuración dinámica (Assíncrona) + +Si necesitas generar dinamicamente la configuración, también puedes exportar por defecto una función. Por ejemplo: + +```ts +import { defineConfig } from 'vitepress' + +export default async () => { + const posts = await (await fetch('https://my-cms.com/blog-posts')).json() + + return defineConfig({ + // opciones de configuración a nivel de aplicación + lang: 'pt-BR', + title: 'VitePress', + description: 'Generador de site estático Vite & Vue.', + + // opciones de configuración a nivel de tema + themeConfig: { + sidebar: [ + ...posts.map((post) => ({ + text: post.name, + link: `/posts/${post.name}` + })) + ] + } + }) +} +``` + +También puedes utilizar `await` en el nivel superior. Como: + +```ts +import { defineConfig } from 'vitepress' + +const posts = await (await fetch('https://my-cms.com/blog-posts')).json() + +export default defineConfig({ + // opciones de configuración a nivel de aplicación + lang: 'pt-BR', + title: 'VitePress', + description: 'Generador de site estático Vite & Vue.', + + // opciones de configuración a nivel de tema + themeConfig: { + sidebar: [ + ...posts.map((post) => ({ + text: post.name, + link: `/posts/${post.name}` + })) + ] + } +}) +``` + +::: + +### Configuración Intellisense {#config-intellisense} + +Usar el auxiliar `defineConfig` proporcionará Intellisense con tecnología TypeScript para las opciones de configuración. Suponiendo que su IDE lo admita, esto debería funcionar tanto en JavaScript como en TypeScript. + +```js +import { defineConfig } from 'vitepress' + +export default defineConfig({ + // ... +}) +``` + +### Configuración de Tema Escrito {#typed-theme-config} + +Por defecto, el auxiliar `defineConfig` espera el tipo de configuración del tema por defecto: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + // El tipo es `DefaultTheme.Config` + } +}) +``` + +Si usa un tema personalizado y desea realizar comprobaciones de tipo para la configuración del tema, deberá usar `defineConfigWithTheme` en su lugar, y pase el tipo de configuración para su tema personalizado a través de un argumento genérico: + +```ts +import { defineConfigWithTheme } from 'vitepress' +import type { ThemeConfig } from 'your-theme' + +export default defineConfigWithTheme({ + themeConfig: { + // El tipo es `ThemeConfig` + } +}) +``` + +### Configuración Vite, Vue & Markdown + +- **Vite** + + Puede configurar la instancia de Vite subyacente usando la opción [vite](#vite) en su configuración de VitePress. No es necesario crear un archivo de configuración de Vite por separado. + +- **Vue** + + VitePress ya incluye el plugin oficial de Vue para Vite ([@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue)). Puede configurar sus opciones usando la opción [vue](#vue) en su configuración VitePress. + +- **Markdown** + + Puede configurar la instancia subyacente de [Markdown-It](https://github.com/markdown-it/markdown-it) usando la opción [markdown](#markdown) en su configuración VitePress. + +## Metadatos de Site {#site-metadata} + +### title + +- Tipo: `string` +- Predeterminado: `VitePress` +- Puede ser reemplazado por página a través de [frontmatter](./frontmatter-config#title) + +Título de site. Al usar el tema por defecto, este será mostrado en la barra de navegación. + +También se utilizará como sufijo predeterminado para todos los títulos de páginas individuales a menos que [`titleTemplate`](#titletemplate) definirse. El título final de una página individual será el contenido textual de su primer encabezado. `

`, combinado con el título global como sufijo. Por ejemplo, con la siguiente configuración y contenido de página: + +```ts +export default { + title: 'Mi increible sitio web' +} +``` + +```md +# Hola +``` + +El título de la página será `Hola | Mi increible sitio web`. + +### titleTemplate + +- Tipo: `string | boolean` +- Puede ser reemplazado por página a través de [frontmatter](./frontmatter-config#titletemplate) + +Le permite personalizar el sufijo del título de cada página o el título completo. Por ejemplo: + +```ts +export default { + title: 'Mi increible sitio web', + titleTemplate: 'Sufijo Personalizado' +} +``` + +```md +# Hola +``` + +El título de la página será `Hola | Sufijo Personalizado`. + +Para personalizar completamente cómo se debe representar el título, puedes usar el símbolo `:title` en `titleTemplate`: + +```ts +export default { + titleTemplate: ':title - Sufijo Personalizado' +} +``` + +Aqui, `:title` será reemplazado por el texto que se deduce del primer título `

` de la página. El título del ejemplo de la página anterior será `Hola - Sufijo Personalizado`. + +Una opción puede ser definida como `false` para desactivar sufijos del título. + +### description + +- Tipo: `string` +- Predeterminado: `Um site VitePress` +- Puede ser sustituído por página a través de [frontmatter](./frontmatter-config#descrição) + +Descripción del sitio web. Esto se presentará como una etiqueta. `` en la página HTML. + +```ts +export default { + descripción: 'Un site VitePress' +} +``` + +### head + +- Tipo: `HeadConfig[]` +- Predeterminado: `[]` +- Se puede agregar por página a través de [frontmatter](./frontmatter-config#head) + +Elementos adicionales para agregar a la etiqueta `` de la página HTML. Las etiquetas agregadas por los usuarios son mostradas antes de la etiqueta `head` de cierre, despues de las etiquetas VitePress. + +```ts +type HeadConfig = + | [string, Record] + | [string, Record, string] +``` + +#### Ejemplo: Agregando un favicon {#example-adding-a-favicon} + +```ts +export default { + cabecera: [['link', { rel: 'icon', href: '/favicon.ico' }]] +} // coloque favicon.ico en el directorio público, si la base está definida, use /base/favicon.ico + +/* Mostraría: + +*/ +``` + +#### Ejemplo: Agregando Fuentes de Google {#example-adding-google-fonts} + +```ts +export default { + head: [ + [ + 'link', + { rel: 'preconnect', href: 'https://fonts.googleapis.com' } + ], + [ + 'link', + { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: '' } + ], + [ + 'link', + { href: 'https://fonts.googleapis.com/css2?family=Roboto&display=swap', rel: 'stylesheet' } + ] + ] +} + +/* Mostraría: + + + +*/ +``` + +#### Ejemplo: Registrando un _service worker_ {#example-registering-a-service-worker} + +```ts +export default { + head: [ + [ + 'script', + { id: 'register-sw' }, + `;(() => { + if ('serviceWorker' in navigator) { + navigator.serviceWorker.register('/sw.js') + } + })()` + ] + ] +} + +/* Mostraría: + +*/ +``` + +#### Ejemplo: Usando Google Analytics {#example-using-google-analytics} + +```ts +export default { + head: [ + [ + 'script', + { async: '', src: 'https://www.googletagmanager.com/gtag/js?id=TAG_ID' } + ], + [ + 'script', + {}, + `window.dataLayer = window.dataLayer || []; + function gtag(){dataLayer.push(arguments);} + gtag('js', new Date()); + gtag('config', 'TAG_ID');` + ] + ] +} + +/* Mostraría: + + +*/ +``` + +### lang + +- Tipo: `string` +- Predeterminado: `en-US` + +El atributo de idioma del sitio. Esto se mostrará como una etiqueta. `` en la página HTML. + +```ts +export default { + lang: 'en-US' +} +``` + +### base + +- Tipo: `string` +- Predeterminado: `/` + +La URL base donde se implementará el sitio. Deberá configurar esto si planea implementar su sitio en un subdirectorio, por ejemplo, en páginas de GitHub. Si planea implementar su sitio web en `https://foo.github.io/bar/` entonces deberías definir la base como `'/bar/'`. Siempre debe comenzar y terminar con una barra. + +La base se agrega automáticamente a todas las URL que comienzan con / en otras opciones, por lo que solo necesitas especificarla una vez. + +```ts +export default { + base: '/base/' +} +``` + +## Roteamento {#routing} + +### cleanUrls + +- Tipo: `boolean` +- Predeterminado: `false` + +Cuando se establece en `true`, VitePress eliminará el `.html` al final de las URLs. Consulte también [Generar URL Limpia](../guide/routing#generating-clean-url). + +::: warning Soporte de Servidor Requerido +Habilitar esto puede requerir configurar adicional en su plataforma de alojamiento. Para funcionar, su servidor debe poder servir `/foo.html` cuando visite `/foo` **sin redirección**. +::: + +### rewrites + +- Tipo: `Record` + +Define asignaciones de directorios personalizados <-> URL. Visite [Rutas: Reescribir Rutas](../guide/routing#route-rewrites) para obtener más detalles. + +```ts +export default { + rewrites: { + 'source/:page': 'destination/:page' + } +} +``` + +## Construcción {#build} + +### srcDir + +- Tipo: `string` +- Predeterminado: `.` + +El directorio donde se almacenan tus páginas de rebajas, en relación con la raíz del proyecto. vea también [Directorio Raiz y de origen](../guide/routing#root-and-source-directory). + +```ts +export default { + srcDir: './src' +} +``` + +### srcExclude + +- Tipo: `string` +- Predeterminado: `undefined` + +Un [patrón glob](https://github.com/mrmlnc/fast-glob#pattern-syntax) para hacer coincidir los archivos de rebajas que deben exluirse como contenido de origen. + +```ts +export default { + srcExclude: ['**/README.md', '**/TODO.md'] +} +``` + +### outDir + +- Tipo: `string` +- Predeterminado: `./.vitepress/dist` + +La ubicación de la salida de compilación para el sitio, en relación con el [raiz del proyecto](../guide/routing#root-and-source-directory). + +```ts +export default { + outDir: '../public' +} +``` + +### assetsDir + +- Tipo: `string` +- Predeterminado: `assets` + +Especifica el directorio para anidar los activos generados. El camino debe estar dentro [`outDir`](#outdir) y se resuelve en relación con el mismo. + +```ts +export default { + assetsDir: 'static' +} +``` + +### cacheDir + +- Tipo: `string` +- Predeterminado: `./.vitepress/cache` + +El directorio para los archivos de caché, en relación con el [raiz del proyecto](../guide/routing#root-and-source-directory). Vea también: [cacheDir](https://vitejs.dev/config/shared-options.html#cachedir). + +```ts +export default { + cacheDir: './.vitepress/.vite' +} +``` + +### ignoreDeadLinks + +- Tipo: `boolean | 'localhostLinks' | (string | RegExp | ((link: string) => boolean))[]` +- Predeterminado: `false` + +Cuando se establece en `true`, VitePress no dejará de compilarse debido a links rotos. + +Cuando se establece en `'localhostLinks'`, la compilación fallará en links rotos, per no verificará los links `localhost`. + +```ts +export default { + ignoreDeadLinks: true +} +``` + +También puede ser un _array_ de una exacta URL en string, patrones regex, o funciones de filtro personalizadas. + +```ts +export default { + ignoreDeadLinks: [ + // ignora URL exacta "/playground" + '/playground', + // ignora todos los links localhost + /^https?:\/\/localhost/, + // ignora todos los links incluyendo "/repl/"" + /\/repl\//, + // función personalizada, ignora todos los links incluyendo "ignore" + (url) => { + return url.toLowerCase().includes('ignore') + } + ] +} +``` + +### mpa + +- Tipo: `boolean` +- Predeterminado: `false` + +Cuando se define como `true`, la aplicación de producción se compilará en [Modo MPA](../guide/mpa-mode). El modo MPA envía 0 kb de JavaScript de forma predeterminada, a expensas de deshabilitar la navegación del lado del cliente y requerir permiso explícito para la interactividad. + +## Tematización {#theming} + +### appearance + +- Tipo: `boolean | 'dark' | 'force-dark' | import('@vueuse/core').UseDarkOptions` +- Predeterminado: `true` + +Se habilitará el modo oscuro (agregando una classe `.dark` al elemento ``). + +- Si la opción está configurada en `true` El tema predeterminado está determinado por la combinación de colores preferida del usuario. +- Si la opción está configurada en `dark` El tema es oscuro de forma predeterminada a menos que el usuario lo cambie manualmente. +- Si la opción está configurada en `false` los usuarios no podrán cambiar el tema. + +Esta opción inyecta un script en línea que restaura la configuración de los usuarios desde el almacenamiento local. (_local storage_) usando una llave `vitepress-theme-appearance`. Eso asegurará que la clase `.dark` se aplicará antes de que se muestre la página para evitar el parpadeo. + +`appearance.initialValue` puede ser `'dark' | undefined`. Refs o getters no son soportados. + +### lastUpdated + +- Tipo: `boolean` +- Predeterminado: `false` + +Para obtener la marca de tiempo de la última actualización para cada página usando Git. El sello de fecha se incluirá en los datos de cada página, accesible a través de [`useData`](./runtime-api#usedata). + +Cuando se utiliza el tema predeterminado, al habilitar esta opción se mostrará la última hora de actualización de cada página. Puedes personalizar el texto mediante la opción [`themeConfig.lastUpdatedText`](./default-theme-config#lastupdatedtext). + +## Personalización {#customization} + +### markdown + +- Tipo: `MarkdownOption` + +Configure las opciones de procesador Markdown. VitePress usa [Markdown-it](https://github.com/markdown-it/markdown-it) como procesador y [Shiki](https://github.com/shikijs/shiki) para resaltar la sintaxis del idioma. Dentro de esta opción, puede pasar varias opciones de Markdown relacionadas para satisfacer sus necesidades. + +```js +export default { + markdown: {...} +} +``` + +Consulte la [declaración de tipo y jsdocs](https://github.com/vuejs/vitepress/blob/main/src/node/markdown/markdown.ts) para conocer todas las opciones disponibles. + +### vite + +- Tipo: `import('vite').UserConfig` + +Pase la [Configuración Vite](https://vitejs.dev/config/) sin procesar al servidor interno / empaquetador Vite. + +```js +export default { + vite: { + // Opciones de configuración Vite + } +} +``` + +### vue + +- Tipo: `import('@vitejs/plugin-vue').Options` + +Pase las opciones [`@vitejs/plugin-vue`](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue#options) sin formato a la instancia del complemento interno. + +```js +export default { + vue: { + // Opciones @vitejs/plugin-vue + } +} +``` + +## Construir Ganchos {#build-hooks} + +Los enlaces de compilación VitePress permiten agregar nuevas funciones al su sitio web: + +- Sitemap +- Indexación de busqueda +- PWA +- _Teleports_ + +## buildEnd +- Tipo: `(siteConfig: SiteConfig) => Awaitable` +`buildEnd` es un enlace de compilación CLI (Interfaz de línea de comando), se ejecutará después de que se complete la compilación (SSG) pero antes de que finalice el proceso CLI de VitePress. + +```ts +export default { + async buildEnd(siteConfig) { + // ... + } +} +``` + +## postRender +- Tipo: `(context: SSGContext) => Awaitable` +- `postRender` es un gancho de compilación, llamado cuando se completa la interpretación de SSG. Le permitirá manipular el contenido de los _teleports_ durante la generación de sitios estáticos. + + ```ts + export default { + async postRender(context) { + // ... + } + } + ``` + + ```ts + interface SSGContext { + content: string + teleports?: Record + [key: string]: any + } + ``` + +## transformHead +- Tipo: `(context: TransformContext) => Awaitable` + +`transformHead` es un enlace de compilación para transformar el encabezado antes de generar cada página. Esto le permite agregar entradas de encabezado que no se pueden agregar estáticamente a la configuración de VitePress. Sólo necesita devolver entradas adicionales, que se fusionarán automáticamente con las existentes. + +:::warning +No mutes ningún elemento dentro `context`. +::: + +```ts +export default { + async transformHead(context) { + // ... + } +} +``` + +```ts +interface TransformContext { + page: string // e.g. index.md (relativo a srcDir) + assets: string[] // todos los activos no-js/css con URL pública completamente resuelta + siteConfig: SiteConfig + siteData: SiteData + pageData: PageData + title: string + description: string + head: HeadConfig[] + content: string +} +``` + +Tenga en cuenta que este enlace solo se llama cuando se genera el sitio de forma estática. No se llama durante el desarrollo. Si necesita agregar entradas de encabezado dinámicas durante el desarrollo, puede usar el enlace [`transformPageData`](#transformpagedata) en su lugar. + + ```ts + export default { + transformPageData(pageData) { + pageData.frontmatter.head ??= [] + pageData.frontmatter.head.push([ + 'meta', + { + name: 'og:title', + content: + pageData.frontmatter.layout === 'home' + ? `VitePress` + : `${pageData.title} | VitePress` + } + ]) + } + } + ``` + +#### Ejemplo: Agregando una URL canónica `` {#example-adding-a-canonical-url-link} + +```ts +export default { + transformPageData(pageData) { + const canonicalUrl = `https://example.com/${pageData.relativePath}` + .replace(/index\.md$/, '') + .replace(/\.md$/, '.html') + + pageData.frontmatter.head ??= [] + pageData.frontmatter.head.push([ + 'link', + { rel: 'canonical', href: canonicalUrl } + ]) + } +} +``` + +### transformHtml +- Tipo: `(code: string, id: string, context: TransformContext) => Awaitable` +`transformHtml` es un gancho de compilación para transformar el contenido de cada página antes de guardarla en el disco. + +:::warning +No mute ningún elemento dentro del `context`. Además, modificar el contenido HTML puede provocar problemas de hidratación en tiempo de ejecución. +::: + +```ts +export default { + async transformHtml(code, id, context) { + // ... + } +} +``` + +### transformPageData +- Tipo: `(pageData: PageData, context: TransformPageContext) => Awaitable | { [key: string]: any } | void>` + +`transformPageData` es un gancho para transformar los datos de cada página. Puedes hacer mutaciones directamente en `pageData` o devolver valores modificados que se fusionarán con los datos de la página. + +:::warning +No mute ningún elemento dentro del `context` y tenga cuidado ya que esto puede afectar el rendimiento del servidor de desarrollo, especialmente si tiene algunas solicitudes de red o cálculos pesados (como generar imágenes) en el gancho. Puede consultar `process.env.NODE_ENV === 'production'` para ver la lógica condicional. +::: + +```ts +export default { + async transformPageData(pageData, { siteConfig }) { + pageData.contributors = await getPageContributors(pageData.relativePath) + } + + // o devolver datos para fusionar + async transformPageData(pageData, { siteConfig }) { + return { + contributors: await getPageContributors(pageData.relativePath) + } + } +} +``` + +```ts +interface TransformPageContext { + siteConfig: SiteConfig +} +``` diff --git a/docs/fa/config.ts b/docs/fa/config.ts new file mode 100644 index 00000000..606366f6 --- /dev/null +++ b/docs/fa/config.ts @@ -0,0 +1,220 @@ +import { createRequire } from 'module' +import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' + +const require = createRequire(import.meta.url) +const pkg = require('vitepress/package.json') + +export default defineAdditionalConfig({ + lang: 'fa-IR', + description: 'ژنراتور استاتیک وب‌سایت با Vite و Vue', + dir: 'rtl', + + // prettier-ignore + head: [ + ['link', { rel: 'preconnect', href: 'https://fonts.googleapis.com' }], + ['link', { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: '' }], + ['link', { href: 'https://fonts.googleapis.com/css2?family=Vazirmatn:wght@100..900&display=swap', rel: 'stylesheet' }], + ], + + themeConfig: { + nav: nav(), + + search: { options: searchOptions() }, + + sidebar: { + '/fa/guide/': { base: '/fa/guide/', items: sidebarGuide() }, + '/fa/reference/': { base: '/fa/reference/', items: sidebarReference() } + }, + + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + text: 'ویرایش این صفحه در گیت‌هاب' + }, + + footer: { + message: 'انتشار یافته تحت لایسنس MIT', + copyright: 'حق نسخه‌برداری © 2019-کنون Evan You' + }, + + docFooter: { + prev: 'قبلی', + next: 'بعدی' + }, + + outline: { + label: 'در این صفحه' + }, + + lastUpdated: { + text: 'آخرین به‌روزرسانی‌' + }, + + notFound: { + title: 'صفحه پیدا نشد', + quote: + 'اما اگر جهت خود را تغییر ندهید و همچنان به جستجو ادامه دهید، ممکن است در نهایت به جایی برسید که در حال رفتن به آن هستید.', + linkLabel: 'برو به خانه', + linkText: 'من را به خانه ببر' + }, + + langMenuLabel: 'تغییر زبان', + returnToTopLabel: 'بازگشت به بالا', + sidebarMenuLabel: 'منوی جانبی', + darkModeSwitchLabel: 'تم تاریک', + lightModeSwitchTitle: 'رفتن به حالت روشن', + darkModeSwitchTitle: 'رفتن به حالت تاریک', + siteTitle: 'ویت‌پرس' + } +}) + +function nav(): DefaultTheme.NavItem[] { + return [ + { + text: 'راهنما', + link: 'fa/guide/what-is-vitepress', + activeMatch: '/guide/' + }, + { + text: 'مرجع', + link: 'fa/reference/site-config', + activeMatch: '/reference/' + }, + { + text: pkg.version, + items: [ + { + text: 'Changelog', + link: 'https://github.com/vuejs/vitepress/blob/main/CHANGELOG.md' + }, + { + text: 'مشارکت', + link: 'https://github.com/vuejs/vitepress/blob/main/.github/contributing.md' + } + ] + } + ] +} + +function sidebarGuide(): DefaultTheme.SidebarItem[] { + return [ + { + text: 'معرفی', + collapsed: false, + items: [ + { text: 'ویت‌پرس چیست؟', link: 'what-is-vitepress' }, + { text: 'شروع کار', link: 'getting-started' }, + { text: 'مسیریابی', link: 'routing' }, + { text: 'استقرار', link: 'deploy' } + ] + }, + { + text: 'نوشتن', + collapsed: false, + items: [ + { text: 'افزونه‌های Markdown', link: 'markdown' }, + { text: 'مدیریت منابع', link: 'asset-handling' }, + { text: 'Frontmatter', link: 'frontmatter' }, + { text: 'استفاده از Vue در Markdown', link: 'using-vue' }, + { text: 'بین‌المللی سازی', link: 'i18n' } + ] + }, + { + text: 'شخصی‌سازی', + collapsed: false, + items: [ + { text: 'استفاده از تم شخصی', link: 'custom-theme' }, + { + text: 'گسترش تم پیش‌فرض', + link: 'extending-default-theme' + }, + { text: 'بارگیری داده در زمان Build', link: 'data-loading' }, + { text: 'سازگاری SSR', link: 'ssr-compat' }, + { text: 'اتصال به CMS', link: 'cms' } + ] + }, + { + text: 'آزمایشی', + collapsed: false, + items: [ + { text: 'حالت MPA', link: 'mpa-mode' }, + { text: 'جنریت کردن Sitemap', link: 'sitemap-generation' } + ] + }, + { text: 'پیکربندی و مرجع API', base: 'fa/reference/', link: 'site-config' } + ] +} + +function sidebarReference(): DefaultTheme.SidebarItem[] { + return [ + { + text: 'مرجع', + base: 'fa/reference/', + items: [ + { text: 'پیکربندی Site', link: 'site-config' }, + { text: 'پیکربندی Frontmatter', link: 'frontmatter-config' }, + { text: 'Runtime API', link: 'runtime-api' }, + { text: 'CLI', link: 'cli' }, + { + text: 'تم پیش‌فرض', + base: 'fa/reference/default-theme-', + items: [ + { text: 'بررسی اجمالی', link: 'config' }, + { text: 'ناوبری', link: 'nav' }, + { text: 'نوار کنار صفحه', link: 'sidebar' }, + { text: 'صفحه اصلی', link: 'home-page' }, + { text: 'پاورقی', link: 'footer' }, + { text: 'طرح', link: 'layout' }, + { text: 'نشان', link: 'badge' }, + { text: 'صفحه تیم', link: 'team-page' }, + { text: 'لینک‌های قبلی / بعدی', link: 'prev-next-links' }, + { text: 'ویرایش لینک', link: 'edit-link' }, + { text: 'Timestamp آخرین به‌روزرسانی', link: 'last-updated' }, + { text: 'جستجو', link: 'search' }, + { text: 'تبلیغات Carbon', link: 'carbon-ads' } + ] + } + ] + } + ] +} + +function searchOptions(): Partial { + return { + placeholder: 'جستجوی مستندات', + translations: { + button: { + buttonText: 'جستجو', + buttonAriaLabel: 'جستجو' + }, + modal: { + searchBox: { + resetButtonTitle: 'آغاز مجدد جستجو', + resetButtonAriaLabel: 'آغاز مجدد جستجو', + cancelButtonText: 'لغو', + cancelButtonAriaLabel: 'لغو' + }, + startScreen: { + recentSearchesTitle: 'جستجو‌های اخیر', + noRecentSearchesText: 'تاریخچه جستجویی یافت نشد.', + saveRecentSearchButtonTitle: 'ذخیره تاریخچه جستجو', + removeRecentSearchButtonTitle: 'حذف تاریخچه جستجو', + favoriteSearchesTitle: 'موارد دلخواه', + removeFavoriteSearchButtonTitle: 'حذف مورد دلخواه' + }, + errorScreen: { + titleText: 'نتیجه‌ای یافت نشد برای', + helpText: 'اتصال شبکه خود را بررسی کنید' + }, + footer: { + selectText: 'انتخاب', + navigateText: 'رفتن', + closeText: 'بستن', + searchByText: ' جستجو با ' + }, + noResultsScreen: { + noResultsText: 'نتیجه‌ای یافت نشد برای' + } + } + } + } +} diff --git a/docs/fa/guide/asset-handling.md b/docs/fa/guide/asset-handling.md new file mode 100644 index 00000000..efa4710f --- /dev/null +++ b/docs/fa/guide/asset-handling.md @@ -0,0 +1,63 @@ +# مدیریت منابع {#asset-handling} + +## ارجاع به منابع ایستا {#referencing-static-assets} + +تمام فایل‌های Markdown به کامپوننت‌های Vue تبدیل و توسط [Vite](https://vitejs.dev/guide/assets.html) پردازش می‌شوند. شما می‌توانید، **و باید**، هر نوع دارایی را با استفاده از URL‌های نسبی مرجع قرار دهید: + +```md +![تصویر](./image.png) +``` + +شما می‌توانید منابع ایستا را در فایل‌های Markdown خود، کامپوننت‌های `*.vue` در قالب، استایل‌ها و فایل‌های `.css` ساده، با استفاده از مسیرهای عمومی مطلق (براساس ریشه پروژه) یا مسیرهای نسبی (براساس سیستم فایل شما) ارجاع دهید. روش دوم مشابه رفتاری است که در صورت استفاده از Vite، Vue CLI یا `file-loader` webpack با آن آشنا هستید. + +انواع شایع تصویر، رسانه و فایل فونت به طور خودکار شناسایی و به عنوان منابع درج می‌شوند. + +::: tip فایل‌های لینک شده به عنوان دارایی محسوب نمی‌شوند +PDFها یا سند‌های دیگر که از طریق پیوندها در فایل‌های Markdown ارجاع داده شده‌اند به طور خودکار به عنوان دارایی در نظر گرفته نمی‌شوند. برای دسترسی به فایل‌های لینک شده، باید آن‌ها را به صورت دستی در دایرکتوری [`public`](#the-public-directory) پروژه قرار دهید. +::: + +تمام منابع ارجاع داده شده، شامل آن‌هایی که از مسیرهای مطلق استفاده می‌کنند، در مرحله تولید به دایرکتوری خروجی با نام فایلی بر اساس یک هش کپی خواهند شد. دارایی‌هایی که هرگز ارجاع نداده شوند، کپی نخواهند شد. منابع تصویر کوچک‌تر از 4 کیلوبایت به صورت base64 درون خطی می‌شوند - این می‌تواند از طریق گزینه پیکربندی [`vite`](../reference/site-config#vite) تنظیم شود. + +تمام ارجاع‌های مسیر **ایستا**، شامل مسیرهای مطلق، باید بر اساس ساختار دایرکتوری کاری شما تعیین شوند. + +## دایرکتوری عمومی {#the-public-directory} + +گاهی اوقات ممکن است نیاز داشته باشید منابع ایستا را فراهم کنید که به صورت مستقیم در هیچ‌یک از Markdown یا کامپوننت‌های قالب شما ارجاع نشده‌اند، یا ممکن است بخواهید برخی فایل‌ها را با نام اصلی خود سرویس دهید. به عنوان مثال، فایل‌هایی مانند `robots.txt`، آیکون‌های fav، و آیکون‌های PWA. + +شما می‌توانید این فایل‌ها را در دایرکتوری `public` تحت [دایرکتوری منبع](./routing#source-directory) قرار دهید. به عنوان مثال، اگر ریشه پروژه شما `./docs` است و از محل پیش‌فرض دایرکتوری منبع استفاده می‌کنید، آنگاه دایرکتوری عمومی شما `./docs/public` خواهد بود. + +منابع قرار داده شده در `public` به صورت اصلی در ریشه دایرکتوری خروجی کپی خواهند شد. + +توجه داشته باشید که باید به فایل‌های قرار داده شده در `public` با استفاده از مسیر مطلق ریشه ارجاع دهید - به عنوان مثال، `public/icon.png` همیشه باید به عنوان `/icon.png` در کد منبع ارجاع داده شود. + +## URL پایه {#base-url} + +اگر وب‌سایت شما به URL غیر ریشه استقرار می‌یابد، باید گزینه `base` را در `.vitepress/config.js` تنظیم کنید. به عنوان مثال، اگر قصد دارید وب‌سایت خود را به `https://foo.github.io/bar/` استقرار دهید، آنگاه `base` باید به `'/bar/'` تنظیم شود (همیشه باید با یک خط شروع و پایان یابد). + +تمام مسیرهای دارایی ایستا شما به صورت خودکار پردازش می‌شوند تا با ارزش‌های `base` مختلف تطبیق یابند. به عنوان مثال، اگر به یک ارجاع مطلق به یک دارایی زیر `public` در Markdown خود اشاره کرده‌اید: + +```md +![تصویر](/image-inside-public.png) +``` + +در این حالت، شما **نیازی ندارید** که آن را به روز کنید وقتی که مقدار پیکربندی `base` را تغییر می‌دهید. + +اما، اگر شما در حال نویسندگی یک کامپوننت قالب هستید که به صورت پویا به منابع لینک می‌دهد، به عنوان مثال یک تصویر که `src` آن براساس مقدار پیکربندی قالب است: + +```vue + +``` + +در این حالت، توصیه می‌شود که مسیر را با استفاده از کمکی [`withBase`](../reference/runtime-api#withbase) ارائه شده توسط ویت‌پرس بپوشانید: + +```vue + + + +``` diff --git a/docs/fa/guide/cms.md b/docs/fa/guide/cms.md new file mode 100644 index 00000000..44359780 --- /dev/null +++ b/docs/fa/guide/cms.md @@ -0,0 +1,56 @@ +--- +outline: deep +--- + +# اتصال به یک سیستم مدیریت محتوا (CMS) {#connecting-to-a-cms} + +## گام‌های کلی {#general-workflow} + +اتصال ویت‌پرس به یک سیستم مدیریت محتوا به طور عمده بر اساس [مسیریابی پویا](./routing#dynamic-routes) خواهد بود. حتماً قبل از شروع، با روش کار آن آشنا شوید. + +از آنجایی که هر سیستم مدیریت محتوا به طریقی متفاوت کار می‌کند، در اینجا تنها می‌توانیم یک جریان کاری عمومی را ارائه دهیم که شما باید آن را برای حالت خاص خودتان سفارشی کنید. + +1. اگر سیستم مدیریت محتوا نیاز به احراز هویت دارد، یک فایل `.env` برای ذخیره توکن‌های API خود ایجاد کنید و آن را بارگذاری کنید: + + ```js + // posts/[id].paths.js + import { loadEnv } from 'vitepress' + + const env = loadEnv('', process.cwd()) + ``` + +2. داده‌های مورد نیاز را از سیستم مدیریت محتوا بازیابی کرده و به شکل داده‌های مسیر مناسب فرمت کنید: + + ```js + export default { + async paths() { + // از کتابخانه مشتری مربوط به سیستم مدیریت محتوا استفاده کنید اگر نیاز دارید + const data = await (await fetch('https://my-cms-api', { + headers: { + // توکن در صورت لزوم + } + })).json() + + return data.map(entry => { + return { + params: { id: entry.id, /* عنوان، نویسندگان، تاریخ و غیره */ }, + content: entry.content + } + }) + } + } + ``` + +3. نمایش محتوا در صفحه: + + ```md + # {{ $params.title }} + + - نوشته شده توسط {{ $params.author }} در تاریخ {{ $params.date }} + + + ``` + +## راهنماهای ادغام {#integration-guides} + +اگر راهنمایی درباره ادغام ویت‌پرس با یک سیستم مدیریت محتوا خاص نوشته‌اید، لطفاً از لینک "ویرایش این صفحه" زیر استفاده کنید تا آن را ارسال کنید! diff --git a/docs/fa/guide/custom-theme.md b/docs/fa/guide/custom-theme.md new file mode 100644 index 00000000..e2f52797 --- /dev/null +++ b/docs/fa/guide/custom-theme.md @@ -0,0 +1,220 @@ +--- +outline: deep +--- + +# استفاده از یک تم سفارشی {#using-a-custom-theme} + +## Resolve کردن تم {#theme-resolving} + +می‌توانید با ایجاد یک فایل `.vitepress/theme/index.js` یا `.vitepress/theme/index.ts` (فایل ورودی تم) تم سفارشی را فعال کنید: + +``` +. +├─ docs # ریشه پروژه +│ ├─ .vitepress +│ │ ├─ theme +│ │ │ └─ index.js # ورودی تم +│ │ └─ config.js # فایل پیکربندی +│ └─ index.md +└─ package.json +``` + +وقتی ویت‌پرس حضور یک فایل ورودی تم را شناسایی کند، همواره از تم سفارشی به جای تم پیش‌فرض استفاده می‌کند. با این حال، شما می‌توانید [تم پیش‌فرض را گسترش دهید](./extending-default-theme) تا سفارشی‌سازی‌های پیشرفته‌تری را روی آن اعمال کنید. + +## رابط تم {#theme-interface} + +یک تم سفارشی ویت‌پرس به عنوان یک شی تعریف می‌شود که شامل رابط زیر است: + +```ts +interface Theme { + /** + * کامپوننت لایه‌ی ریشه برای هر صفحه + * @required + */ + Layout: Component + /** + * تقویت نمونه Vue اپلیکیشن + * @optional + */ + enhanceApp?: (ctx: EnhanceAppContext) => Awaitable + /** + * گسترش یک تم دیگر، با فراخوانی `enhanceApp` آن پیش از ما + * @optional + */ + extends?: Theme +} + +interface EnhanceAppContext { + app: App // نمونه Vue اپلیکیشن + router: Router // نمونه روتر ویت‌پرس + siteData: Ref // متادیتاهای سطح سایت +} +``` + +فایل ورودی تم باید تم را به عنوان export پیش‌فرض خود export کند: + +```js [.vitepress/theme/index.js] + +// شما می‌توانید فایل‌های Vue را مستقیماً در ورودی تم وارد کنید +// ویت‌پرس با @vitejs/plugin-vue پیش‌تنظیم شده است. +import Layout from './Layout.vue' + +export default { + Layout, + enhanceApp({ app, router, siteData }) { + // ... + } +} +``` + +export پیش‌فرض تنها قراردادی برای یک تم سفارشی است و تنها ویژگی `Layout` لازم است. بنابراین، به شیء تم ویت‌پرس می‌توان به عنوان یک کامپوننت Vue ساده ترتیب داد. + +درون کامپوننت لایه‌ی خود، دقیقاً مانند یک برنامه Vite + Vue 3 عادی عمل می‌کند. با این وجود، توجه داشته باشید که تم همچنین باید [سازگار با SSR](./ssr-compat) باشد. + +## ساخت یک لایه {#building-a-layout} + +بیشترین لایه‌ی پایه‌ای نیازمند دارای یک کامپوننت `` است: + +```vue [.vitepress/theme/Layout.vue] + +``` + +لایه‌ی بالا به سادگی تمام محتوای markdown هر صفحه را به عنوان HTML نمایش می‌دهد. اولین بهبودی که می‌توانیم اعمال کنیم، مدیریت خطاهای 404 است: + +```vue{1-4,9-12} + + + +``` + +کمک‌کننده [`useData()`](../reference/runtime-api#usedata) اطلاعات اجرایی مورد نیاز ما را برای رندر شرایطی صفحات مختلف فراهم می‌کند. یکی از دیگر اطلاعاتی که ما می‌توانیم به آن دسترسی داشته باشیم، اطلاعات اولیه صفحه فعلی است. ما می‌توانیم از این اطلاعات برای اجازه دادن به کاربر برای کنترل لایه در هر صفحه استفاده کنیم. به عنوان مثال، کاربر می‌تواند مشخص کند که صفحه باید از یک طرح صفحه خانه خاص استفاده کند با: + +```md +--- +layout: home +--- +``` + +و ما می‌توانیم تم خود را تنظیم کنیم تا با این موضوع برخورد کند: + +```vue{3,12-14} + + + +``` + +طبیعتا، شما می‌توانید لایه‌ی خود را به کامپوننت‌های بیشتری تقسیم کنید: + +```vue{3-5,12-15} + + + +``` + +برای همه چیزی که در کامپوننت‌های تم موجود است، به [مستندات API اجرایی](../reference/runtime-api) مراجعه کنید. به علاوه، شما می‌توانید از [بارگذاری داده در زمان ساخت](./data-loading) استفاده کنید تا لایه‌های مبتنی بر داده را تولید کنید - به عنوان مثال، یک صفحه که تمام پست‌های وبلاگ در پروژه فعلی را لیست می‌کند. + +## توزیع یک تم سفارشی {#distributing-a-custom-theme} + +آسان‌ترین روش برای توزیع یک تم سفارشی ارائه آن به عنوان [قالب مخزن در GitHub](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-template-repository) است. + +اگر می‌خواهید تم را به عنوان یک بسته npm توزیع کنید، مراحل زیر را دنبال کنید: + +1. شیء تم را به عنوان export پیش‌فرض در ورودی بسته‌تان export کنید. + +2. اگر امکان دارد، تعریف نوع پیکربندی تم خود را به عنوان `ThemeConfig` export کنید. + +3. اگر تم شما نیاز به تنظیم پیکربندی ویت‌پرس دارد، پیکربندی را تحت یک زیر‌مسیر بسته (مانند `my-theme/config`) export کنید تا کاربر بتواند آن را گسترش دهد. + +4. گزینه‌های پیکربندی تم را مستند کنید (هم از طریق فایل پیکربندی و هم از طریق frontmatter). + +5. دستورالعمل‌های روشنی برای مصرف تم خود ارائه دهید (مانند زیر). + +## مصرف یک تم سفارشی {#consuming-a-custom-theme} + +برای مصرف یک تم خارجی، آن را از ورودی تم سفارشی وارد و دوباره export کنید: + +```js [.vitepress/theme/index.js] +import Theme from 'awesome-vitepress-theme' + +export default Theme +``` + +اگر تم نیاز به گسترش دارد: + +```js [.vitepress/theme/index.js] +import Theme from 'awesome-vitepress-theme' + +export default { + extends: Theme, + enhanceApp(ctx) { + // ... + } +} +``` + +اگر تم نیاز به پیکربندی خاص ویت‌پرس دارد، شما همچنین باید آن را در پیکربندی خود گسترش دهید: + +```ts [.vitepress/config.ts] +import baseConfig from 'awesome-vitepress-theme/config' + +export default { + // گسترش پیکربندی پایه‌ی تم (اگر لازم باشد) + extends: baseConfig +} +``` + +سرانجام، اگر تم انواع خود را برای پیکربندی تم‌اش ارائه می‌دهد: + +```ts [.vitepress/config.ts] +import baseConfig from 'awesome-vitepress-theme/config' +import { defineConfigWithTheme } from 'vitepress' +import type { ThemeConfig } from 'awesome-vitepress-theme' + +export default defineConfigWithTheme({ + extends: baseConfig, + themeConfig: { + // نوع `ThemeConfig` است + } +}) +``` diff --git a/docs/fa/guide/data-loading.md b/docs/fa/guide/data-loading.md new file mode 100644 index 00000000..5d9d5631 --- /dev/null +++ b/docs/fa/guide/data-loading.md @@ -0,0 +1,246 @@ +# بارگذاری داده در زمان ساخت {#build-time-data-loading} + +ویت‌پرس یک ویژگی به نام **بارگذارهای داده** ارائه می‌دهد که به شما این امکان را می‌دهد که داده‌های دلخواه را بارگیری کنید و آن‌ها را از صفحات یا اجزا وارد کنید. بارگذاری داده فقط **در زمان ساخت** اجرا می‌شود: داده‌های حاصل به صورت JSON در بسته JavaScript نهایی سریالیزه می‌شوند. + +بارگذارهای داده می‌توانند برای بارگیری داده‌های از راه دور یا تولید فراداده‌ها بر اساس فایل‌های محلی استفاده شوند. به عنوان مثال، می‌توانید از بارگذارهای داده استفاده کنید تا تمام صفحات API محلی خود را تجزیه کنید و به طور خودکار یک فهرست از تمام ورودی‌های API تولید کنید. + +## استفاده ابتدایی {#basic-usage} + +یک فایل بارگذار داده باید با `.data.js` یا `.data.ts` پایان یابد. فایل باید یک صادرات پیش‌فرض از یک شی با متد `load()` داشته باشد: + +```js [example.data.js] +export default { + load() { + return { + hello: 'world' + } + } +} +``` + +ماژول بارگذار فقط در Node.js ارزیابی می‌شود، بنابراین شما می‌توانید API ‌های Node و وابستگی‌های npm را به عنوان نیازهای خود وارد کنید. + +سپس می‌توانید داده را از این فایل در صفحات `.md` و اجزا `.vue` با استفاده از صادرات نام‌گذاری شده `data` وارد کنید: + +```vue + + +
{{ data }}
+``` + +خروجی: + +```json +{ + "hello": "world" +} +``` + +شما متوجه خواهید شد که بارگذار داده خودش داده را صادر نمی‌کند. ویت‌پرس پشت صحنه متد `load()` را فراخوانی می‌کند و به طور ضمنی نتیجه را از طریق صادرات نام‌گذاری شده `data` ارائه می‌دهد. + +این کار حتی اگر بارگذار async باشد انجام می‌شود: + +```js +export default { + async load() { + // دریافت داده از راه دور + return (await fetch('...')).json() + } +} +``` + +## داده از فایل‌های محلی {#data-from-local-files} + +وقتی نیاز به تولید داده بر اساس فایل‌های محلی دارید، باید از گزینه `watch` در بارگذار داده استفاده کنید تا تغییرات اعمال شده به این فایل‌ها بتواند به روزرسانی‌های سریع منجر شود. + +گزینه `watch` همچنین در آنجا مفید است که می‌توانید از [الگوهای glob](https://github.com/mrmlnc/fast-glob#pattern-syntax) برای تطابق با چندین فایل استفاده کنید. الگوها می‌توانند نسبت به فایل بارگذار خود نسبی باشند و تابع `load()` فایل‌های تطابق یافته را به عنوان مسیرهای مطلق دریافت می‌کند. + +مثال زیر نشان می‌دهد که چگونه فایل‌های CSV را بارگذاری کرده و آن‌ها را با استفاده از [csv-parse](https://github.com/adaltas/node-csv/tree/master/packages/csv-parse/) به JSON تبدیل می‌کند. این فایل تنها در زمان ساخت اجرا می‌شود، بنابراین شما نیازی به ارسال پارسر CSV به مشتری ندارید! + +```js +import fs from 'node:fs' +import { parse } from 'csv-parse/sync' + +export default { + watch: ['./data/*.csv'], + load(watchedFiles) { + // watchedFiles یک آرایه از مسیرهای مطلق فایل‌های تطابق یافته خواهد بود. + // تولید یک آرایه از فراداده‌های پست وبلاگ که می‌تواند برای نمایش + // یک لیست در طرح استفاده شود + return watchedFiles.map((file) => { + return parse(fs.readFileSync(file, 'utf-8'), { + columns: true, + skip_empty_lines: true + }) + }) + } +} +``` + +## `createContentLoader` {#createcontentloader} + +وقتی که در حال ساختن یک سایت متمرکز بر محتوا هستیم، اغلب نیاز به ایجاد یک "بایگانی" یا "فهرست" صفحه داریم: یک صفحه که ما همه ورودی‌های موجود در مجموعه محتوای خود را لیست می‌کنیم، به عنوان مثال پست‌های وبلاگ یا صفحات API. ما می‌توانیم این کار را مستقیماً با API بارگذار داده انجام دهیم، اما از آنجا که این یک حالت استفاده رایج است، ویت‌پرس همچنین یک کمک‌کننده به نام `createContentLoader` را فراهم می‌کند تا این فرآیند را ساده‌تر کند: + +```js [posts.data.js] +import { createContentLoader } from 'vitepress' + +export default createContentLoader('posts/*.md', /* گزینه‌ها */) +``` + +کمک‌کننده یک الگوی glob را نسبت به [دایرکتوری منبع](./routing#source-directory) مشخص می‌کند و یک شی `{ watch، load }` را که می‌تواند به عنوان صادرات پیش‌فرض در یک فایل بارگذار داده استفاده شود، برمی‌گرداند. همچنین پیاده‌سازی حافظه پنهانی بر اساس برچسب‌های تغییر مدیریت + +می‌کند تا عملکرد توسعه را بهبود بخشد. + +لطفاً توجه داشته باشید که بارگذار فقط با فایل‌های Markdown کار می‌کند - فایل‌های غیر-Markdown تطابق یافته حذف می‌شوند. + +داده بارگذاری شده یک آرایه با نوع `ContentData[]` خواهد بود: + +```ts +interface ContentData { + // آدرس URL برای صفحه. به عنوان مثال /posts/hello.html (شامل پایه نمی‌شود) + // تکرار دستی یا استفاده از `transform` سفارشی برای نرمال کردن مسیرها + url: string + // اطلاعات frontmatter صفحه + frontmatter: Record + + // موارد زیر فقط وقتی که گزینه‌های مربوط فعال باشند + // ما در زیر آنها را بررسی می‌کنیم + src: string | undefined + html: string | undefined + excerpt: string | undefined +} +``` + +به طور پیش‌فرض، تنها `url` و `frontmatter` ارائه می‌شوند. این به خاطر این است که داده بارگذاری شده به عنوان JSON در بسته مشتری نهایی درج می‌شود، بنابراین ما باید در مورد اندازه آن محتاط باشیم. در زیر مثالی از استفاده از داده برای ساخت یک صفحه فهرست کمینه وبلاگ آورده شده است: + +```vue + + + +``` + +### گزینه‌ها {#options} + +احتمالاً داده پیش‌فرض به تمام نیازها پاسخ نمی‌دهد - شما می‌توانید با استفاده از گزینه‌ها به تبدیل داده‌ها مشترک شوید: + +```js [posts.data.js] +import { createContentLoader } from 'vitepress' + +export default createContentLoader('posts/*.md', { + includeSrc: true, // آیا منبع اصلی مارک‌داون را اضافه کنیم؟ + render: true, // آیا صفحه HTML را نیز شامل کنیم؟ + excerpt: true, // آیا خلاصه را نیز شامل کنیم؟ + transform(rawData) { + // نقشه‌برداری، مرتب‌سازی یا فیلتر کردن داده‌های اصلی به دلخواه. + // نتیجه نهایی آنچه است که به مشتری ارسال خواهد شد. + return rawData.sort((a, b) => { + return +new Date(b.frontmatter.date) - +new Date(a.frontmatter.date) + }).map((page) => { + page.src // منبع اصلی مارک‌داون + page.html // صفحه HTML کامل + page.excerpt // خلاصه HTML (محتوای بالای اولین `---`) + return {/* ... */} + }) + } +}) +``` + +بررسی کنید که چگونه در [وبلاگ Vue.js](https://github.com/vuejs/blog/blob/main/.vitepress/theme/posts.data.ts) استفاده شده است. + +API `createContentLoader` همچنین می‌تواند در داخل [هوک‌های ساخت](../reference/site-config#build-hooks) استفاده شود: + +```js [.vitepress/config.js] +export default { + async buildEnd() { + const posts = await createContentLoader('posts/*.md').load() + // تولید فایل‌های بر اساس فراداده‌های پست‌ها، مثلاً فید RSS + } +} +``` + +**انواع** + +```ts +interface ContentOptions { + /** + * آیا منبع اصلی را اضافه کنیم؟ + * @default false + */ + includeSrc?: boolean + + /** + * آیا منبع را به HTML تبدیل کرده و در داده شامل کنیم؟ + * @default false + */ + render?: boolean + + /** + * اگر `boolean` باشد، آیا باید خلاصه را تجزیه و شامل کنیم؟ (به صورت HTML) + * + * اگر `function` باشد، کنترل نحوه استخراج خلاصه از محتوا. + * + * اگر `string` باشد، تعیین کنید که چگونه جداکننده سفارشی باید برای استخراج خلاصه استفاده شود. + * جداکننده پیش‌فرض `---` است اگر `excerpt` `true` باشد. + * + * @see https://github.com/jonschlinkert/gray-matter#optionsexcerpt + * @see https://github.com/jonschlinkert/gray-matter#optionsexcerpt_separator + * + * @default false + */ + excerpt?: + | boolean + | ((file: { data: { [key: string]: any }; content: string; excerpt?: string }, options?: any) => void) + | string + + /** + * تبدیل داده. توجه داشته باشید که داده به عنوان JSON در بسته مشتری درج خواهد شد + * اگر از اجزا یا فایل‌های مارک‌داون وارد شود. + */ + transform?: (data: ContentData[]) => T | Promise +} +``` + +## بارگذارهای داده تایپ شده {#typed-data-loaders} + +زمان استفاده از TypeScript، می‌توانید بارگذار و صادرات `data` خود را به این شکل تایپ کنید: + +```ts +import { defineLoader } from 'vitepress' + +export interface Data { + // نوع داده +} + +declare const data: Data +export { data } + +export default defineLoader({ + // گزینه‌های بارگذاری با تایپ چک شده + watch: ['...'], + async load(): Promise { + // ... + } +}) +``` + +## پیکربندی {#configuration} + +برای دریافت اطلاعات پیکربندی در داخل یک بارگذار، می‌توانید از کدی مانند زیر استفاده کنید: + +```ts +import type { SiteConfig } from 'vitepress' + +const config: SiteConfig = (globalThis as any).VITEPRESS_CONFIG +``` diff --git a/docs/fa/guide/deploy.md b/docs/fa/guide/deploy.md new file mode 100644 index 00000000..1b89f334 --- /dev/null +++ b/docs/fa/guide/deploy.md @@ -0,0 +1,337 @@ +--- +outline: deep +--- + +# استقرار وب‌سایت ویت‌پرس شما {#deploy-your-vitepress-site} + +راهنماهای زیر بر اساس برخی فرضیات مشترک است: + +- وب‌سایت ویت‌پرس در دایرکتوری `docs` پروژه شما قرار دارد. +- شما از دایرکتوری خروجی پیش‌فرض ساخته‌شده (`.vitepress/dist`) استفاده می‌کنید. +- ویت‌پرس به‌عنوان یک وابستگی محلی در پروژه شما نصب شده است و شما اسکریپت‌های زیر را در `package.json` پیکربندی کرده‌اید: + + ```json [package.json] + { + "scripts": { + "docs:build": "vitepress build docs", + "docs:preview": "vitepress preview docs" + } + } + ``` + +## ساخت و تست محلی {#build-and-test-locally} + +1. برای ساخت اسناد، این دستور را اجرا کنید: + + ```sh + $ npm run docs:build + ``` + +2. پس از ساخت، آن را به‌صورت محلی پیش‌نمایش دهید با اجرای این دستور: + + ```sh + $ npm run docs:preview + ``` + + دستور `preview` یک سرور وب ایستا محلی راه‌اندازی می‌کند که دایرکتوری خروجی `.vitepress/dist` را در آدرس `http://localhost:4173` ارائه می‌دهد. شما می‌توانید از این امکان استفاده کنید تا اطمینان حاصل کنید که همه چیز قبل از رفع به محیط تولیدی به‌درستی نمایش داده می‌شود. + +3. می‌توانید پورت سرور را با انتقال `--port` به‌عنوان یک آرگمان پیکربندی کنید. + + ```json + { + "scripts": { + "docs:preview": "vitepress preview docs --port 8080" + } + } + ``` + + حالا اسکریپت `docs:preview` سرور را در `http://localhost:8080` راه‌اندازی خواهد کرد. + +## تنظیم مسیر پایه عمومی {#setting-a-public-base-path} + +به‌طور پیش‌فرض، ما فرض می‌کنیم که وب‌سایت در مسیر ریشه دامنه (`/`) انتشار می‌یابد. اگر وب‌سایت شما باید در یک زیرمسیر ارائه شود، مانند `https://mywebsite.com/blog/`، در این صورت باید گزینه [`base`](../reference/site-config#base) را به `'/blog/'` در پیکربندی ویت‌پرس تنظیم کنید. + +**مثال:** اگر از صفحات GitHub (یا GitLab) استفاده می‌کنید و به `user.github.io/repo/` انتشار می‌دهید، آنگاه `base` را به `/repo/` تنظیم کنید. + +## سربرگ‌های حافظه نهان HTTP {#http-cache-headers} + +اگر شما کنترلی بر روی سربرگ‌های HTTP در سرور تولیدی خود دارید، می‌توانید سربرگ‌های `cache-control` را پیکربندی کنید تا بهبود عملکرد در بازدیدهای تکراری داشته باشید. + +بسیاری از فایل‌های ایستا (مانند JavaScript، CSS و سایر فایل‌های وارد شده که در `public` نیستند) از نام‌های فایل با هش استفاده می‌کنند. اگر پیش‌نمایش تولیدی را با استفاده از تب شبکه ابزارهای توسعه مرورگر خود بررسی کنید، فایل‌هایی مانند `app.4f283b18.js` را خواهید دید. + +این هش `4f283b18` از محتوای این فایل تولید شده است. اگر محتوا تغییر کند، URL‌ها نیز تغییر می‌کنند. این به این معنی است که می‌توانید برای این فایل‌ها سربرگ‌های حافظه نهان قدرتمند را استفاده کنید. همه این فایل‌ها در زیردایرکتوری `assets/` در دایرکتوری خروجی قرار می‌گیرند، بنابراین می‌توانید برای آن‌ها سربرگ زیر را پیکربندی کنید: + +``` +Cache-Control: max-age=31536000,immutable +``` + +::: details مثال فایل `_headers` برای Netlify + +``` +/assets/* + cache-control: max-age=31536000 + cache-control: immutable +``` + +توجه: فایل `_headers` باید در [دایرکتوری عمومی](./asset-handling#the-public-directory) قرار گیرد - در این مورد، `docs/public/_headers` - تا کپی شود بطور صحیح به دایرکتوری خروجی. + +[مستندات سربرگ‌های سفارشی Netlify](https://docs.netlify.com/routing/headers/) + +::: + +::: details پیکربندی مثال Vercel در `vercel.json` + +```json +{ + "headers": [ + { + "source": "/assets/(.*)", + "headers": [ + { + "key": "Cache-Control", + "value": "max-age=31536000, immutable" + } + ] + } + ] +} +``` + +توجه: فایل `vercel.json` باید در ریشه مخزن شما قرار گیرد. + +[مستندات Vercel در مورد پیکربندی سربرگ‌ها](https://vercel.com/docs/concepts/projects/project-configuration#headers) + +::: + +## راهنمای‌های پلتفرم {#platform-guides} + +### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render {#netlify-vercel-cloudflare-pages-aws-amplify-render} + +یک پروژه جدید راه‌اندازی کرده و این تنظیمات را با استفاده از داشبورد خود تغییر دهید: + +- **دستور ساخت:** `npm run docs:build` +- **دایرکتوری خروجی:** `docs/.vitepress/dist` +- **نسخه Node:** `18` (یا بالاتر) + +::: warning هشدار +گزینه‌هایی مانند _Auto Minify_ را برای کد HTML فعال نکنید. این گزینه‌ها ممکن است توضیحاتی را که به Vue معنا دارد، از خروجی حذف کنند. ممکن است خطاهای ناسازگاری را در اجرا ببینید اگر حذف شوند. +::: + +### صفحات GitHub {#github-pages} + +1. یک فایل به نام `deploy.yml` در دایرکتوری `.github/workflows` پروژه خود ایجاد کنید با محتوایی مانند زیر: + + ```yaml [.github/workflows/deploy.yml] + # Sample workflow for building and deploying a ویت‌پرس site to GitHub Pages + # + name: Deploy ویت‌پرس site to Pages + + on: + # Runs on pushes targeting the `main` branch. Change this to `master` if you're + # using the `master` branch as the default branch. + push: + branches: [main] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + + # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages + permissions: + contents: read + pages: write + id-token: write + + # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. + # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. + concurrency: + group: pages + cancel-in-progress: false + + jobs: + # Build job + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Not needed if lastUpdated is not enabled + # - uses: pnpm/action-setup@v3 # Uncomment this if you're using pnpm + # - uses: oven-sh/setup-bun@v1 # Uncomment this if you're using Bun + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm # or pnpm / yarn + - name: Setup Pages + uses: actions/configure-pages@v4 + - name: Install dependencies + run: npm ci # or pnpm install / yarn install / bun install + - name: Build with ویت‌پرس + run: npm run docs:build # or pnpm docs:build / yarn docs:build / bun run docs:build + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: docs/.vitepress/dist + + # Deployment job + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + needs: build + runs-on: ubuntu-latest + name: Deploy + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 + ``` + +::: warning هشدار + مطمئن شوید که گزینه `base` در ویت‌پرس به‌درستی پیکربندی شده است. برای اطلاعات بیشتر به [تنظیم مسیر پایه عمومی](#setting-a-public-base-path) مراجعه کنید. + ::: + +2. در تنظیمات مخزن خود در زیرمنوی "Build and deployment > Source" در "Github Actions" را انتخاب کنید. + +3. تغییرات خود را به شاخه `main` ارسال کنید و منتظر GitHub Actions workflow بمانید. شما باید وب‌سایت خود را در `https://.github.io/[repository]/` یا `https:///` بسته به تنظیمات خود دیده شده است. وب‌سایت شما به‌طور خودکار در هر بار فشرده‌سازی به شاخه `main` ارسال می‌شود. + +### صفحات GitLab {#gitlab-pages} + +1. `outDir` را در پیکربندی ویت‌پرس به `../public` تنظیم کنید. گزینه `base` را به `'//'` تنظیم کنید اگر می‌خواهید در `https://.gitlab.io//` انتشار دهید. + +2. یک فایل به نام `.gitlab-ci.yml` در ریشه پروژه خود با محتوای زیر ایجاد کنید. این کار به ساخت و انتشار وب‌سایت شما هر زمانی که تغییری در محتوا ایجاد می‌کنید، می‌پردازد: + + ```yaml [.gitlab-ci.yml] + image: node:18 + pages: + cache: + paths: + - node_modules/ + script: + # - apk add git # Uncomment this if you're using small docker images like alpine and have lastUpdated enabled + - npm install + - npm run docs:build + artifacts: + paths: + - public + only: + - main + ``` + +### Azure Static Web Apps {#azure-static-web-apps} + +1. دستورالعمل [رسمی](https://docs.microsoft.com/en-us/azure/static-web-apps/build-configuration) را دنبال کنید. + +2. این مقادیر را در فایل پیکربندی خود تنظیم کنید (و مواردی که نیازی به آن‌ها ندارید، مانند `api_location` را حذف کنید): + + - **`app_location`**: `/` + - **`output_location`**: `docs/.vitepress/dist` + - **`app_build_command`**: `npm run docs:build` + +### Firebase {#firebase} + +1. فایل‌های `firebase.json` و `.firebaserc` را در ریشه پروژه خود ایجاد کنید: + + `firebase.json`: + + ```json [firebase.json] + { + "hosting": { + "public": "docs/.vitepress/dist", + "ignore": [] + } + } + ``` + + `.firebaserc`: + + ```json [.firebaserc] + { + "projects": { + "default": "" + } + } + ``` + +2. بعد از اجرای `npm run docs:build`، دستور زیر را برای انتشار اجرا کنید: + + ```sh + firebase deploy + ``` + +### Surge {#surge} + +1. بعد از اجرای `npm run docs:build`، دستور زیر را برای انتشار اجرا کنید: + + ```sh + npx surge docs/.vitepress/dist + ``` + +### Heroku {#heroku} + +1. دستورالعمل و راهنماها را در [`heroku-buildpack-static`](https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-static) دنبال کنید. + +2. یک فایل به نام `static.json` در ریشه پروژه خود با محتوای زیر ایجاد کنید: + + ```json [static.json] + { + "root": "docs/.vitepress/dist" + } + ``` + +### Edgio {#edgio} + +به [ایجاد و انتشار یک برنامه ویت‌پرس در Edgio](https://docs.edg.io/guides/vitepress) مراجعه کنید. + +### Kinsta Static Site Hosting {#kinsta-static-site-hosting} + +شما می‌توانید وب‌سایت ویت‌پرس خود را بر روی [Kinsta](https://kinsta.com/static-site-hosting/) با دنبال کردن این [دستورالعمل‌ها](https://kinsta.com/docs/vitepress-static-site-example/) انتشار دهید. + +### Stormkit + +شما می‌توانید پروژه ویت‌پرس خود را به [Stormkit](https://www.stormkit.io) با دنبال کردن این [دستورالعمل‌ها](https://stormkit.io/blog/how-to-deploy-vitepress) انتشار دهید. + +### Nginx + +اینجا یک مثال از پیکربندی بلوک سرور Nginx است. این تنظیم شامل فشرده‌سازی gzip برای فایل‌های متن معمولی، قوانین برای سرویس فایل‌های ایستا سایت ویت‌پرس شما با هدرهای مناسب برای حافظه‌نگهداری مناسب است و همچنین مدیریت `cleanUrls: true` می‌کند. + +```nginx +server { + gzip on; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + + listen 80; + server_name _; + index index.html; + + location / { + # content location + root /app; + + # exact matches -> reverse clean urls -> folders -> not found + try_files $uri $uri.html $uri/ =404; + + # non existent pages + error_page 404 /404.html; + + # a folder without index.html raises 403 in this setup + error_page 403 /404.html; + + # adjust caching headers + # files in the assets folder have hashes filenames + location ~* ^/assets/ { + expires 1y; + add_header Cache-Control "public, immutable"; + } + } +} +``` + +این پیکربندی فرض می‌کند که سایت ویت‌پرس ساخته شده شما در دایرکتوری `/app` در سرور شما قرار دارد. دستورالعمل `root` را از ابزارهای مربوطه استفاده کنید اگر فایل‌های سایت شما در جای دیگری قرار دارد. + +::: warning هشدار +مسیر تنظیمات try_files نباید به طور پیش‌فرض به index.html مانند برنامه‌های دیگر Vue مشخص شود. این کار باعث وضعیت نامعتبر صفحه می‌شود. +::: + +اطلاعات بیشتر را در [مستندات رسمی nginx](https://nginx.org/en/docs/)، در این مسائل [#2837](https://github.com/vuejs/vitepress/discussions/2837)، [#3235](https://github.com/vuejs/vitepress/issues/3235) و همچنین در این [پست وبلاگ](https://blog.mehdi.cc/articles/vitepress-cleanurls-on-nginx-environment#readings) از Mehdi Merah پیدا کنید. diff --git a/docs/fa/guide/extending-default-theme.md b/docs/fa/guide/extending-default-theme.md new file mode 100644 index 00000000..2aaefa7a --- /dev/null +++ b/docs/fa/guide/extending-default-theme.md @@ -0,0 +1,333 @@ +--- +outline: deep +--- + +# گسترش تم پیش‌فرض {#extending-the-default-theme} + +تم پیش‌فرض ویت‌پرس برای مستندات بهینه‌سازی شده است و قابلیت سفارشی‌سازی دارد. برای دریافت لیست جامع گزینه‌ها، به [نمای کلی از تنظیمات تم پیش‌فرض](../reference/default-theme-config) مراجعه کنید. + +با این حال، مواردی وجود دارد که فقط با تنظیمات کافی نخواهد بود. به عنوان مثال: + +1. نیاز به تنظیم استایل CSS دارید؛ +2. نیاز به اصلاح نمونه برنامه Vue، به عنوان مثال برای ثبت مولفه‌های عمومی؛ +3. نیاز به درج محتوای سفارشی در تم از طریق slot‌های طرح. + +این سفارش‌های پیشرفته نیازمند استفاده از یک تم سفارشی هستند که از تم پیش‌فرض "گسترش" می‌کند. + +::: tip نکته +قبل از ادامه، ابتدا [استفاده از یک تم سفارشی](./custom-theme) را بخوانید تا نحوه کار تم‌های سفارشی را درک کنید. +::: + +## سفارشی‌سازی CSS {#customizing-css} + +CSS تم پیش‌فرض با نادیده گرفتن متغیرهای CSS سطح ریشه قابل سفارشی‌سازی است: + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme' +import './custom.css' + +export default DefaultTheme +``` + +```css +/* .vitepress/theme/custom.css */ +:root { + --vp-c-brand-1: #646cff; + --vp-c-brand-2: #747bff; +} +``` + +لیست متغیرهای CSS [تم پیش‌فرض](https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css) که می‌توانند سفارشی‌سازی شوند را ببینید. + +## استفاده از فونت‌های مختلف {#using-different-fonts} + +ویت‌پرس از [Inter](https://rsms.me/inter/) به عنوان فونت پیش‌فرض استفاده می‌کند و فونت‌ها را در خروجی ساخته‌شده شامل می‌شود. این فونت همچنین در محصولات خودکار پیش‌بارگذاری می‌شود. با این حال، این ممکن است مطلوب نباشد اگر می‌خواهید از یک فونت اصلی مختلف استفاده کنید. + +برای جلوگیری از شامل شدن Inter در خروجی ساخته‌شده، تم را به جای `vitepress/theme-without-fonts` وارد کنید: + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme-without-fonts' +import './my-fonts.css' + +export default DefaultTheme +``` + +```css +/* .vitepress/theme/custom.css */ +:root { + --vp-font-family-base: /* فونت متن عادی */ + --vp-font-family-mono: /* فونت کد */ +} +``` + +::: warning هشدار +اگر از مولفه‌های اختیاری مانند مولفه‌های [صفحه تیم](../reference/default-theme-team-page) استفاده می‌کنید، اطمینان حاصل کنید که آن‌ها را هم از `vitepress/theme-without-fonts` وارد می‌کنید! +::: + +اگر فونت شما یک فایل محلی است که از طریق `@font-face` ارجاع شده است، به عنوان یک دارایی پردازش می‌شود و با نام فایل هشداردار در `.vitepress/dist/assets` شامل می‌شود. برای پیش‌بارگذاری این فایل، از هوک ساخت [transformHead](../reference/site-config#transformhead) استفاده کنید: + +```js [.vitepress/config.js] +export default { + transformHead({ assets }) { + // منظور شده برای همسان سازی font خود، regex مورد نیاز را تنظیم کنید + const myFontFile = assets.find(file => /font-name\.[\w-]+\.woff2/.test(file)) + if (myFontFile) { + return [ + [ + 'link', + { + rel: 'preload', + href: myFontFile, + as: 'font', + type: 'font/woff2', + crossorigin: '' + } + ] + ] + } + } +} +``` + +## ثبت مولفه‌های عمومی {#registering-global-components} + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme' + +/** @type {import('vitepress').Theme} */ +export default { + extends: DefaultTheme, + enhanceApp({ app }) { + // ثبت مولفه‌های عمومی سفارشی‌شده خود را + app.component('MyGlobalComponent' /* ... */) + } +} +``` + +اگر از TypeScript استفاده می‌کنید: +```ts [.vitepress/theme/index.ts] +import type { Theme } from 'vitepress' +import DefaultTheme from 'vitepress/theme' + +export default { + extends: DefaultTheme, + enhanceApp({ app }) { + // ثبت مولفه‌های عمومی سفارشی‌شده خود را + app.component('MyGlobalComponent' /* ... */) + } +} satisfies Theme +``` + +از آنجا که از Vite استفاده می‌کنیم، می‌توانید از ویژگی [import glob](https://vitejs.dev/guide/features.html#glob-import) در Vite برای خودکار ثبت یک پوشه از مولفه‌ها استفاده کنید. + +## slot ‌های طرح {#layout-slots} + +کامپوننت `` تم پیش‌فرض چندین slot دارد که می‌توانید محتوا را در موقعیت‌های مختلف صفحه در آن‌ها درج کنید. در زیر مثالی از درج یک کامپوننت در قبل از طرح داده شده است: + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme' +import MyLayout from './MyLayout.vue' + +export default { + extends: DefaultTheme, + // جایگزینی Layout با یک کامپوننت پوشه‌بندی که slot‌ها را درج می‌کند + Layout: MyLayout +} +``` + +```vue [.vitepress/theme/MyLayout.vue] + + + +``` + +یا می‌توانید از تابع رندر نیز استفاده کنید. + +```js [.vitepress/theme/index.js] +import { h } from 'vue' +import DefaultTheme from 'vitepress/theme' +import MyComponent from './MyComponent.vue' + +export default { + extends: DefaultTheme, + Layout() { + return h(DefaultTheme.Layout, null, { + 'aside-outline-before': () => h(MyComponent) + }) + } +} +``` + +لیست کاملی از slot‌های موجود در طرح پیش‌فرض: + +- وقتی `layout: 'doc'` (پیش‌فرض) از طریق frontmatter فعال است: + - `doc-top` + - `doc-bottom` + - `doc-footer-before` + - `doc-before` + - `doc-after` + - `sidebar-nav-before` + - `sidebar-nav-after` + - `aside-top` + - `aside-bottom` + - `aside-outline-before` + - `aside-outline-after` + - `aside-ads-before` + - `aside-ads-after` +- وقتی `layout: 'home'` از طریق frontmatter فعال است: + - `home-hero-before` + - `home-hero-info-before` + - `home-hero-info` + - `home-hero-info-after` + - `home-hero-actions-after` + - `home-hero-image` + - `home-hero-after` + - `home-features-before` + - `home-features-after` +- وقتی `layout: 'page'` از طریق frontmatter فعال است: + - `page-top` + - `page-bottom` +- در صفحه یافت نشد (404): + - `not-found` +- همیشه: + - `layout-top` + - `layout-bottom` + - `nav-bar-title-before` + - `nav-bar-title-after` + - `nav-bar-content-before` + - `nav-bar-content-after` + - `nav-screen-content-before` + - `nav-screen-content-after` + + +## استفاده از API انتقال نمایش {#using-view-transitions-api} + +### در تغییر ظاهر {#on-appearance-toggle} + +شما می‌توانید تم پیش‌فرض را گسترش دهید تا هنگام تغییر حالت رنگ، یک انتقال سفارشی را فراهم کند. به عنوان مثال: + +```vue [.vitepress/theme/Layout.vue] + + + + + +``` + +نتیجه (**هشدار!**: رنگ‌های فلاشینگ، حرکات ناگهانی، نورهای شدید): + +
+نمایش + +![نمایش انتقال ظاهر تغییر](/appearance-toggle-transition.webp) + +
+ +برای جزئیات بیشتر در مورد انتقال‌های نمایش به [اسناد کروم](https://developer.chrome.com/docs/web-platform/view-transitions/) مراجعه کنید. + +### در تغییر مسیر {#on-route-change} + +به زودی. + +## جایگزینی کامپوننت‌های داخلی {#overriding-internal-components} + +شما می‌توانید با استفاده از [alias های Vite](https://vitejs.dev/config/shared-options.html#resolve-alias)، کامپوننت‌های تم پیش‌فرض را با کامپوننت‌های سفارشی خود جایگزین کنید: + +```ts +import { fileURLToPath, URL } from 'node:url' +import { defineConfig } from 'vitepress' + +export default defineConfig({ + vite: { + resolve: { + alias: [ + { + find: /^.*\/VPNavBar\.vue$/, + replacement: fileURLToPath( + new URL('./components/CustomNavBar.vue', import.meta.url) + ) + } + ] + } + } +}) +``` + +برای دریافت نام دقیق کامپوننت به [کد منبع ما](https://github.com/vuejs/vitepress/tree/main/src/client/theme-default/components) مراجعه کنید. از آنجا که کامپوننت‌ها داخلی هستند، احتمال آنکه نام آن‌ها بین انتشارات کوچک تغییر کند، وجود دارد. diff --git a/docs/fa/guide/frontmatter.md b/docs/fa/guide/frontmatter.md new file mode 100644 index 00000000..4b4af163 --- /dev/null +++ b/docs/fa/guide/frontmatter.md @@ -0,0 +1,48 @@ +# Frontmatter + +## استفاده {#usage} + +ویت‌پرس پشتیبانی از frontmatter YAML در تمام فایل‌های Markdown را دارد و آن‌ها را با استفاده از [gray-matter](https://github.com/jonschlinkert/gray-matter) تجزیه می‌کند. Frontmatter باید در بالای فایل Markdown قرار داشته باشد (قبل از هر عنصر از جمله برچسب‌های ` + + +``` + +## پشتیبانی از RTL (آزمایشی) {#rtl-support-experimental} + +برای پشتیبانی از RTL، `dir: 'rtl'` را در پیکربندی مشخص کنید و از پلاگین‌های PostCSS RTLCSS مانند ، یا استفاده کنید. باید پلاگین PostCSS خود را به کارگیری `:where([dir="ltr"])` و `:where([dir="rtl"])` به عنوان پیشوندها جلوگیری از مشکلات اولویت CSS استفاده کنید. diff --git a/docs/fa/guide/markdown.md b/docs/fa/guide/markdown.md new file mode 100644 index 00000000..1d2ca9f9 --- /dev/null +++ b/docs/fa/guide/markdown.md @@ -0,0 +1,921 @@ +# افزونه‌های Markdown {#markdown-extensions} + +ویت‌پرس با افزونه‌های markdown داخلی ارائه شده است. + +## لینک‌های هدر {#header-anchors} + +هدرها به طور خودکار لینک‌های anchor دریافت می‌کنند. نمایش anchor ها با استفاده از گزینه `markdown.anchor` قابل پیکربندی است. + +### anchor های سفارشی {#custom-anchors} + +برای مشخص کردن تگ anchor سفارشی برای یک هدینگ به جای استفاده از تگ خودکار، یک پسوند به هدینگ اضافه کنید: + +``` +# Using custom anchors {#my-anchor} +``` + +این به شما امکان می‌دهد که به جای استفاده از به جای استفاده از `#using-custom-anchors`، به هدینگ به عنوان `#my-anchor` لینک دهید. + +## لینک‌ها {#links} + +هم لینک‌های داخلی و هم خارجی با دستورالعمل‌های خاصی ارائه می‌شوند. + +### لینک‌های داخلی {#internal-links} + +لینک‌های داخلی به لینک روتر برای ناوبری SPA تبدیل می‌شوند. همچنین، هر `index.md` موجود در هر زیرپوشه به طور خودکار به `index.html` تبدیل می‌شود، با URL متناظر `/`. + +به عنوان مثال، با توجه به ساختار پوشه زیر: + +``` +. +├─ index.md +├─ foo +│ ├─ index.md +│ ├─ one.md +│ └─ two.md +└─ bar + ├─ index.md + ├─ three.md + └─ four.md +``` + +و با فرض این که شما در `foo/one.md` هستید: + +```md +[Home](/) +[foo](/foo/) +[foo heading](./#heading) +[bar - three](../bar/three) +[bar - three](../bar/three.md) +[bar - four](../bar/four.html) +``` + +### پسوند صفحه {#page-suffix} + +صفحات و لینک‌های داخلی به طور پیش‌فرض با پسوند `.html` تولید می‌شوند. + +### لینک‌های خارجی {#external-links} + +لینک‌های خروجی به طور خودکار دارای `target="_blank" rel="noreferrer"` هستند: + +- [vuejs.org](https://vuejs.org) +- [ویت‌پرس در GitHub](https://github.com/vuejs/vitepress) + +## Frontmatter {#frontmatter} + +[YAML frontmatter](https://jekyllrb.com/docs/front-matter/) به طور پیش‌فرض پشتیبانی می‌شود: + +```yaml +--- +title: عنوان صفحه +lang: fa-IR +--- +``` + +این داده‌ها برای بقیه صفحه در دسترس خواهد بود، همراه با تمامی اجزاهای سفارشی و تم. + +برای اطلاعات بیشتر، به [Frontmatter](../reference/frontmatter-config) مراجعه کنید. + +## جداول مانند Github {#github-style-tables} + +**ورودی** + +```md +| Tables | Are | Cool | +| ------------- | :-----------: | ----: | +| col 3 is | right-aligned | $1600 | +| col 2 is | centered | $12 | +| zebra stripes | are neat | $1 | +``` + +**خروجی** + +| Tables | Are | Cool | +| ------------- | :-----------: | ----: | +| col 3 is | right-aligned | $1600 | +| col 2 is | centered | $12 | +| zebra stripes | are neat | $1 | + +## اموجی :tada: {#emoji} + +**ورودی** + +``` +:tada: :100: +``` + +**خروجی** + +:tada: :100: + +یک [لیست از همه اموجی ها](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.mjs) در دسترس است. + +## فهرست مطالب {#table-of-contents} + +**ورودی** + +``` +[[toc]] +``` + +**خروجی** + +[[toc]] + +نحوه پردازش فهرست مطالب با استفاده از گزینه `markdown.toc` قابل پیکربندی است. + +## کانتینرهای سفارشی {#custom-containers} + +کانتینرهای سفارشی می‌توانند توسط انواع، عناوین و محتویات خود تعریف شوند. + +### عنوان پیش‌فرض {#default-title} + +**ورودی** + +```md +::: info +این یک جعبه اطلاعات است. +::: + +::: tip +این یک نکته است. +::: + +::: warning +این یک هشدار است. +::: + +::: danger +این یک هشدار خطرناک است. +::: + +::: details +این یک بلوک جزئیات است. +::: +``` + +**خروجی** + +::: info اطلاعات +این یک جعبه اطلاعات است. +::: + +::: tip نکته +این یک نکته است. +::: + +::: warning هشدار +این یک هشدار است. +::: + +::: danger خطر +این یک هشدار خطرناک است. +::: + +::: details جزئیات +این یک بلوک جزئیات است. +::: + +### عنوان سفارشی {#custom-title} + +می‌توانید عنوان سفارشی را با اضافه کردن متن به انتهای نوع کانتینر تنظیم کنید. + +**ورودی** + +````md +::: danger ایست! +منطقه خطرناک، ادامه ندهید +::: + +::: details برای مشاهده کد کلیک کنید +```js +console.log('Hello, ویت‌پرس!') +``` +::: +```` + +**خروجی** + +::: danger ایست! +منطقه خطرناک، ادامه ندهید +::: + +::: details برای مشاهده کد کلیک کنید +```js +console.log('Hello, ویت‌پرس!') +``` +::: + +این همچنین امکان دارد که شما عنوان‌های سفارشی را به صورت global تنظیم کنید با اضافه کردن محتوای زیر به تنظیمات سایت. این امکان خاصا اگر به زبان انگلیسی نوشته نمی‌شود، بسیار مفید است: + +```ts +// config.ts +export default defineConfig({ + // ... + markdown: { + container: { + tipLabel: 'نکته', + warningLabel: 'اخطار', + dangerLabel: 'خطر', + infoLabel: 'اطلاعات', + detailsLabel: 'جزئیات' + } + } + // ... +}) +``` + +### `raw` {#raw} + +این یک کانتینر ویژه است که می‌تواند برای جلوگیری از تداخل استایل و روتر با ویت‌پرس استفاده شود. این به ویژه زمانی مفید است که شما کتابخانه‌های کامپوننت را مستند کنید. می‌توانید همچنین [whyframe](https://whyframe.dev/docs/integrations/vitepress) را برای ایزوله‌تر شدن بیشتر بررسی کنید. + +**نحوه استفاده** + +```md +::: raw +بسته‌بندی در یک `
` +::: +``` + +کلاس `vp-raw` می‌تواند به صورت مستقیم بر روی عناصر استفاده شود. ایزوله‌سازی استایل در حال حاضر انتخابی است: + +- `postcss` را با مدیر بسته‌های مورد علاقه‌تان نصب کنید: + + ```sh + $ npm add -D postcss + ``` + +- یک فایل با نام `docs/postcss.config.mjs` ایجاد کنید و کد زیر را به آن اضافه کنید: + + ```js + import { postcssIsolateStyles } from 'vitepress' + + export default { + plugins: [postcssIsolateStyles()] + } + ``` + + این از [`postcss-prefix-selector`](https://github.com/postcss/postcss-load-config) استفاده می‌کند. می‌توانید گزینه‌های آن را به این صورت پاس بدهید: + + ```js + postcssIsolateStyles({ + includeFiles: [/vp-doc\.css/] // به طور پیش‌فرض /base\.css/ + }) + ``` + +## هشدارهای GitHub {#github-flavored-alerts} + +ویت‌پرس همچنین [هشدارهای 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 +> [!NOTE] +> اطلاعاتی که کاربران باید به آن توجه کنند، حتی اگر سریع بخوانند. + +> [!TIP] +> اطلاعات اختیاری برای کمک به کاربر برای موفقیت بیشتر. + +> [!IMPORTANT] +> اطلاعات حیاتی برای موفقیت کاربران. + +> [!WARNING] +> محتوای بحرانی که نیاز به توجه فوری کاربر دارد به دلیل خطرات پتانسیلی. + +> [!CAUTION] +> پیامدهای منفی احتمالی یک عمل. +``` + +> [!NOTE] +> اطلاعاتی که کاربران باید به آن توجه کنند، حتی اگر سریع بخوانند. + +> [!TIP] +> اطلاعات اختیاری برای کمک به کاربر برای موفقیت بیشتر. + +> [!IMPORTANT] +> اطلاعات حیاتی برای موفقیت کاربران. + +> [!WARNING] +> محتوای بحرانی که نیاز به توجه فوری کاربر دارد به دلیل خطرات پتانسیلی. + +> [!CAUTION] +> پیامدهای منفی احتمالی یک عمل. + +## Syntax Highlighting در بلوک‌های کد {#syntax-highlighting-in-code-blocks} + +ویت‌پرس از [Shiki](https://github.com/shikijs/shiki) برای syntax highlighting زبان در بلوک‌های کد Markdown با استفاده از متن رنگی استفاده می‌کند. Shiki از تنوع وسیعی از زبان‌های برنامه‌نویسی پشتیبانی می‌کند. تنها کافی است که یک نام مستعار زبان معتبر به بکتیک‌ها ابتدایی کد اضافه کنید: + +**ورودی** + +```` +```js +export default { + name: 'MyComponent', + // ... +} +``` +```` + +```` +```html +
    +
  • + {{ todo.text }} +
  • +
+``` +```` + +**خروجی** + +```js +export default { + name: 'MyComponent' + // ... +} +``` + +```html +
    +
  • + {{ todo.text }} +
  • +
+``` + +یک [لیست از زبان‌های معتبر](https://shiki.style/languages) در مخزن Shiki موجود است. + +همچنین می‌توانید تم syntax highlighting را در تنظیمات برنامه سفارشی کنید. لطفاً به [گزینه‌های Markdown](../reference/site-config#markdown) برای جزئیات بیشتر مراجعه کنید. + +## برجسته‌سازی خطوط در بلوک‌های کد {#line-highlighting-in-code-blocks} + +**ورودی** + +```` +```js{4} +export default { + data () { + return { + msg: 'برجسته‌سازی شده!' + } + } +} +``` +```` + +**خروجی** + +```js{4} +export default { + data () { + return { + msg: 'برجسته‌سازی شده!' + } + } +} +``` + +علاوه بر یک خط، می‌توانید چندین خط تکی، محدوده‌ها یا هر دو را نیز مشخص کنید: + +- محدوده‌های خط: به عنوان مثال `{5-8}`, `{3-10}`, `{10-17}` +- چند خط تک: به عنوان مثال `{4,7,9}` +- محدوده‌های خط و خط‌های تک: به عنوان مثال `{4,7-13,16,23-27,40}` + +**ورودی** + +```` +```js{1,4-6} +const message = 'Hello, World!'; + +console.log(message); +``` +```` + +**خروجی** + +```js{1,4-6} +const message = 'Hello, World!'; + +console.log(message); +``` + +## فکوس در بلاک‌های کد {#focus-in-code-blocks} + +افزودن کامنت `// [!code focus]` به یک خط، روی آن فکوس می‌کند و بخش‌های دیگر کد را مات می‌کند. + +به‌علاوه، می‌توانید با استفاده از `// [!code focus:]` تعدادی خط را برای فکوس تعیین کنید. + +**ورودی** + +```` +```js +export default { + data () { + return { + msg: 'Focused!' // [!!code focus] + } + } +} +``` +```` + +**خروجی** + +```js +export default { + data() { + return { + msg: 'Focused!' // [!code focus] + } + } +} +``` + +## تفاوت‌های رنگی در بلاک‌های کد {#colored-diffs-in-code-blocks} + +افزودن کامنت `// [!code --]` یا `// [!code ++]` به یک خط، یک تفاوت را در آن خط ایجاد می‌کند، با حفظ رنگ‌های بلاک کد. + +**ورودی** + +```` +```js +export default { + data () { + return { + msg: 'Removed' // [!!code --] + msg: 'Added' // [!!code ++] + } + } +} +``` +```` + +**خروجی** + +```js +export default { + data () { + return { + msg: 'Removed' // [!code --] + msg: 'Added' // [!code ++] + } + } +} +``` + +## خطاها و هشدارها در بلاک‌های کد {#errors-and-warnings-in-code-blocks} + +افزودن کامنت `// [!code warning]` یا `// [!code error]` به یک خط، آن را مطابق با نوع، رنگ می‌کند. + +**ورودی** + +```` +```js +export default { + data () { + return { + msg: 'Error', // [!!code error] + msg: 'Warning' // [!!code warning] + } + } +} +``` +```` + +**خروجی** + +```js +export default { + data() { + return { + msg: 'Error', // [!code error] + msg: 'Warning' // [!code warning] + } + } +} +``` + +## شماره‌گذاری خطوط {#line-numbers} + +می‌توانید با استفاده از تنظیمات، شماره‌گذاری خطوط را برای هر بلاک کد فعال کنید: + +```js +export default { + markdown: { + lineNumbers: true + } +} +``` + +لطفاً [گزینه‌های markdown](../reference/site-config#markdown) را برای جزئیات بیشتر ببینید. + +می‌توانید با استفاده از `:line-numbers` / `:no-line-numbers` در بلاک‌های کد شماره‌گذاری خطوط را نادیده بگیرید یا تنظیمات اصلی را با `=` پس از `:line-numbers` سفارشی کنید. به عنوان مثال، `:line-numbers=2` به معنای شروع شماره‌گذاری از خط `2` است. + +**ورودی** + +````md +```ts {1} +// شماره‌گذاری خطوط به طور پیش‌فرض غیرفعال است +const line2 = 'این خط ۲ است' +const line3 = 'این خط ۳ است' +``` + +```ts:line-numbers {1} +// شماره‌گذاری خطوط فعال است +const line2 = 'این خط ۲ است' +const line3 = 'این خط ۳ است' +``` + +```ts:line-numbers=2 {1} +// شماره‌گذاری خطوط فعال است و از خط ۲ شروع می‌شود +const line3 = 'این خط ۳ است' +const line4 = 'این خط ۴ است' +``` +```` + +**خروجی** + +```ts {1} +// شماره‌گذاری خطوط به طور پیش‌فرض غیرفعال است +const line2 = 'این خط ۲ است' +const line3 = 'این خط ۳ است' +``` + +```ts:line-numbers {1} +// شماره‌گذاری خطوط فعال است +const line2 = 'این خط ۲ است' +const line3 = 'این خط ۳ است' +``` + +```ts:line-numbers=2 {1} +// شماره‌گذاری خطوط فعال است و از خط ۲ شروع می‌شود +const line3 = 'این خط ۳ است' +const line4 = 'این خط ۴ است' +``` + +## وارد کردن Snippet کد {#import-code-snippets} + +می‌توانید snippet های کد را از فایل‌های موجود با استفاده از دستور زیر وارد کنید: + +```md +<<< @/filepath +``` + +این دستور [highlight کردن خط](#line-highlighting-in-code-blocks) را نیز پشتیبانی می‌کند: + +```md +<<< @/filepath{highlightLines} +``` + +**ورودی** + +```md +<<< @/snippets/snippet.js{2} +``` + +**فایل کد** + +<<< @/snippets/snippet.js + +**خروجی** + +<<< @/snippets/snippet.js{2} + +::: tip نکته +مقدار `@` با ریشه منبع مطابقت دارد. به‌طور پیش‌فرض، این ریشه پروژه ویت‌پرس است، مگر اینکه `srcDir` پیکربندی شده باشد. به‌طور جایگزینی، می‌توانید از مسیرهای نسبی وارد کنید: + +```md +<<< ../snippets/snippet.js +``` + +::: + +همچنین می‌توانید [ناحیه VS Code](https://code.visualstudio.com/docs/editor/codebasics#_folding) را برای اضافه کردن قسمت مربوطه فایل کد استفاده کنید. می‌توانید نام ناحیه سفارشی را پس از `#` به دنبال مسیر فایل تعیین کنید: + +**ورودی** + +```md +<<< @/snippets/snippet-with-region.js#snippet{1} +``` + +**فایل کد** + +<<< @/snippets/snippet-with-region.js + +**خروجی** + +<<< @/snippets/snippet-with-region.js#snippet{1} + +همچنین می‌توانید زبان را داخل آکولادها (`{}`) مشخص کنید: + +```md +<<< @/snippets/snippet.cs{c#} + + + +<<< @/snippets/snippet.cs{1,2,4-6 c#} + + + +<<< @/snippets/snippet.cs{1,2,4-6 c#:line-numbers} +``` + +این قابلیت مفید است اگر زبان منبع نمی‌تواند از پسوند فایل استنتاج شود. + + +### گروه‌های کد {#code-groups} + +می‌توانید چندین بلوک کد را به این شکل گروه‌بندی کنید: + +**ورودی** + +````md +::: code-group + +```js [config.js] +/** + * @type {import('vitepress').UserConfig} + */ +const config = { + // ... +} + +export default config +``` + +```ts [config.ts] +import type { UserConfig } from 'vitepress' + +const config: UserConfig = { + // ... +} + +export default config +``` + +::: +```` + +**خروجی** + +::: code-group + +```js [config.js] +/** + * @type {import('vitepress').UserConfig} + */ +const config = { + // ... +} + +export default config +``` + +```ts [config.ts] +import type { UserConfig } from 'vitepress' + +const config: UserConfig = { + // ... +} + +export default config +``` + +::: + +همچنین می‌توانید [قطعات کد](#import-code-snippets) را در گروه‌های کد وارد کنید: + +**ورودی** + +```md +::: code-group + + + +<<< @/snippets/snippet.js + + + +<<< @/snippets/snippet-with-region.js#snippet{1,2 ts:line-numbers} [قطعه با منطقه] +::: +``` + +**خروجی** + +::: code-group + +<<< @/snippets/snippet.js + +<<< @/snippets/snippet-with-region.js#snippet{1,2 ts:line-numbers} [قطعه با منطقه] +::: + +## ادغام فایل‌های Markdown {#markdown-file-inclusion} + +می‌توانید یک فایل Markdown را در یک فایل Markdown دیگر، حتی در صورت وجود تو در تو، وارد کنید. + +::: tip نکته +می‌توانید مسیر Markdown را با `@` پیش‌فرض کنید. این به عنوان ریشه منبع عمل می‌کند. به طور پیش‌فرض، ریشه پروژه ویت‌پرس است، مگر اینکه `srcDir` پیکربندی شده باشد. +::: + +به عنوان مثال، می‌توانید یک فایل Markdown نسبی را با استفاده از این کد وارد کنید: + +**ورودی** + +```md +# مستندات + +## مبانی + + +``` + +**قسمت فایل** (`parts/basics.md`) + +```md +بعضی موارد مربوط به شروع کار. + +### پیکربندی + +می‌توان با استفاده از `.foorc.json` ایجاد شد. +``` + +**کد معادل** + +```md +# مستندات + +## مبانی + +بعضی موارد مربوط به شروع کار. + +### پیکربندی + +می‌توان با استفاده از `.foorc.json` ایجاد شد. +``` + +همچنین از انتخاب یک محدوده خطی پشتیبانی می‌کند: + +**ورودی** + +```md +# مستندات + +## مبانی + + +``` + +**قسمت فایل** (`parts/basics.md`) + +```md +بعضی موارد مربوط به شروع کار. + +### پیکربندی + +می‌توان با استفاده از `.foorc.json` ایجاد شد. +``` + +**کد معادل** + +```md +# مستندات + +## مبانی + +### پیکربندی + +می‌توان با استفاده از `.foorc.json` ایجاد شد. +``` + +قالب محدوده خطی می‌تواند شامل `{3,}`, `{,10}`, `{1,10}` باشد. + +همچنین می‌توانید از [ناحیه VS Code](https://code.visualstudio.com/docs/editor/codebasics#_folding) برای اضافه کردن بخش متناظر فایل کد استفاده کنید. می‌توانید پس از `#` نام ناحیه سفارشی را پس از مسیر فایل دنبال کنید: + +**ورودی** + +```md +# مستندات + +## مبانی + + + +``` + +**قسمت فایل** (`parts/basics.md`) + +```md + +## استفاده خط 1 + +## استفاده خط 2 + +## استفاده خط 3 + +``` + +**کد معادل** + +```md +# مستندات + +## مبانی + +## استفاده خط 1 + +## استفاده خط 3 +``` + +::: warning هشدار +توجه داشته باشید که این اقدام منجر به خطا نمی‌شود اگر فایل شما وجود نداشته باشد. بنابراین، در استفاده از این ویژگی، مطمئن شوید که محتوا به درستی نمایش داده می‌شود. +::: + +## معادلات ریاضی {#math-equations} + +در حال حاضر این گزینه اختیاری است. برای فعال‌سازی آن، باید `markdown-it-mathjax3` را نصب کرده و `markdown.math` را در فایل پیکربندی خود به `true` تنظیم کنید: + +```sh +npm add -D markdown-it-mathjax3 +``` + +```ts [.vitepress/config.ts] +export default { + markdown: { + math: true + } +} +``` + +**ورودی** + +```md +وقتی $a \ne 0$ است، دو حل برای $(ax^2 + bx + c = 0)$ وجود دارد و آن‌ها عبارتند از +$$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ + +**معادلات مکسول** + +| equation | description | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | +| $\nabla \cdot \vec{\mathbf{B}} = 0$ | تنوع $\vec{\mathbf{B}}$ صفر است | +| $\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | curl $\vec{\mathbf{E}}$ نسبت به نرخ تغییر $\vec{\mathbf{B}}$ نسبی است | +| $\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | _چیست؟_ | +``` + +**خروجی** + +وقتی $a \ne 0$ است، دو حل برای $(ax^2 + bx + c = 0)$ + +وجود دارد و آن‌ها عبارتند از +$$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ + +**معادلات مکسول** + +| equation | description | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | +| $\nabla \cdot \vec{\mathbf{B}} = 0$ | تنوع $\vec{\mathbf{B}}$ صفر است | +| $\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | curl $\vec{\mathbf{E}}$ نسبت به نرخ تغییر $\vec{\mathbf{B}}$ نسبی است | +| $\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | _چیست؟_ | + +## بارگذاری lazy تصویر {#image-lazy-loading} + +می‌توانید بارگذاری تنبلی را برای هر تصویر اضافه شده از طریق Markdown با تنظیم `lazyLoading` به `true` در فایل پیکربندی فعال کنید: + +```js +export default { + markdown: { + image: { + // بارگذاری تنبلی تصویر به طور پیش‌فرض غیرفعال است + lazyLoading: true + } + } +} +``` + +## پیکربندی پیشرفته {#advanced-configuration} + +ویت‌پرس از [markdown-it](https://github.com/markdown-it/markdown-it) به عنوان نمایشگر Markdown استفاده می‌کند. اکثر افزونه‌های فوق را با استفاده از افزونه‌های سفارشی پیاده‌سازی کرده‌ایم. می‌توانید نمونه‌ای بیشتر از نمونه `markdown-it` را با استفاده از گزینه `markdown` در `.vitepress/config.js` سفارشی‌سازی کنید: + +```js +import { defineConfig } from 'vitepress' +import markdownItAnchor from 'markdown-it-anchor' +import markdownItFoo from 'markdown-it-foo' + +export default defineConfig({ + markdown: { + // گزینه‌های markdown-it-anchor + // https://github.com/valeriangalliat/markdown-it-anchor#usage + anchor: { + permalink: markdownItAnchor.permalink.headerLink() + }, + + // گزینه‌های @mdit-vue/plugin-toc + // https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-toc#options + toc: { level: [1, 2] }, + + config: (md) => { + // استفاده از افزونه‌های markdown-it بیشتر! + md.use(markdownItFoo) + } + } +}) +``` + +برای دیدن لیست کامل خصوصیات قابل تنظیم، به [مرجع تنظیمات: پیکربندی برنامه](../reference/site-config#markdown) مراجعه کنید. diff --git a/docs/fa/guide/migration-from-vitepress-0.md b/docs/fa/guide/migration-from-vitepress-0.md new file mode 100644 index 00000000..211bb0f9 --- /dev/null +++ b/docs/fa/guide/migration-from-vitepress-0.md @@ -0,0 +1,23 @@ +# مهاجرت از ویت‌پرس 0.x + +اگر از نسخه 0.x ویت‌پرس می‌آیید، تغییرات قابل توجهی به دلیل ویژگی‌ها و بهبودهای جدید وجود دارد. لطفاً این راهنما را دنبال کنید تا ببینید چگونه برنامه خود را به ویت‌پرس جدیدتر منتقل کنید. + +## پیکربندی برنامه + +- ویژگی بین‌المللی‌سازی هنوز اجرا نشده است. + +## پیکربندی تم + +- گزینه `sidebar` ساختار خود را تغییر داده است. + - کلید `children` حالا به نام `items` نامیده می‌شود. + - در حال حاضر ممکن است مورد بالادستی حاوی `link` نباشد. ما قصد داریم این گزینه را بازگردانیم. +- `repo`، `repoLabel`، `docsDir`، `docsBranch`، `editLinks`، `editLinkText` به منظور API انعطاف‌پذیرتر حذف شده‌اند. + - برای اضافه کردن لینک GitHub با آیکون به نوار ناوبری، از ویژگی [پیوندهای اجتماعی](../reference/default-theme-nav#navigation-links) استفاده کنید. + - برای اضافه کردن ویژگی "ویرایش این صفحه"، از ویژگی [پیوند ویرایش](../reference/default-theme-edit-link) استفاده کنید. +- گزینه `lastUpdated` حالا به `config.lastUpdated` و `themeConfig.lastUpdatedText` تقسیم شده است. +- `carbonAds.carbon` به `carbonAds.code` تغییر کرده است. + +## پیکربندی Frontmatter + +- گزینه `home: true` به `layout: home` تغییر کرده است. همچنین، تنظیمات مربوط به صفحه اصلی بسیار تغییر کرده‌اند تا ویژگی‌های اضافی را ارائه دهند. برای جزئیات بیشتر، [راهنمای صفحه اصلی](../reference/default-theme-home-page) را ببینید. +- گزینه `footer` به [`themeConfig.footer`](../reference/default-theme-config#footer) منتقل شده است. diff --git a/docs/fa/guide/migration-from-vuepress.md b/docs/fa/guide/migration-from-vuepress.md new file mode 100644 index 00000000..536a37c5 --- /dev/null +++ b/docs/fa/guide/migration-from-vuepress.md @@ -0,0 +1,30 @@ +# مهاجرت از VuePress + +## پیکربندی + +### نوار کناری + +نوار کناری دیگر به طور خودکار از frontmatter پر نمی‌شود. شما می‌توانید [frontmatter را خودتان بخوانید](https://github.com/vuejs/vitepress/issues/572#issuecomment-1170116225) تا نوار کناری به طور پویا پر شود. ابزارهای [اضافی برای این منظور](https://github.com/vuejs/vitepress/issues/96) ممکن است در آینده ارائه شود. + +## Markdown + +### تصاویر + +برخلاف VuePress، ویت‌پرس وقتی شما از تصویر استاتیک استفاده می‌کنید، [`base`](./asset-handling#base-url) پیکربندی شما را به طور خودکار مدیریت می‌کند. + +بنابراین، اکنون می‌توانید تصاویر را بدون استفاده از تگ `img` نمایش دهید. + +```diff +- foo ++ ![foo](/foo.png) +``` + +::: warning +برای تصاویر پویا، همچنان نیاز به استفاده از `withBase` به طوری که در [راهنمای Base URL](./asset-handling#base-url) نشان داده شده است، دارید. +::: + +از عبارت `!` برای جستجو و جایگزینی با `![$2]($1)` استفاده کنید تا تمام تصاویر را با سینتکس `![](...)` جایگزین کنید. + +--- + +ادامه دارد... diff --git a/docs/fa/guide/mpa-mode.md b/docs/fa/guide/mpa-mode.md new file mode 100644 index 00000000..a18bb1c2 --- /dev/null +++ b/docs/fa/guide/mpa-mode.md @@ -0,0 +1,23 @@ +# حالت MPA {#mpa-mode} + +حالت MPA (برنامه چند صفحه) می‌تواند از طریق خط فرمان با `vitepress build --mpa` فعال شود، یا از طریق تنظیمات با گزینه `mpa: true`. + +در حالت MPA، همه صفحات به طور پیش‌فرض بدون هیچ جاوااسکریپتی رندر می‌شوند. به همین دلیل، سایت تولیدی احتمالاً امتیاز بهتری از ابزارهای آزمایشی در اولین بازدید دریافت خواهد کرد. + +با این حال، به دلیل عدم وجود مسیریابی SPA، لینک‌های متقاطع به بازنشانی کامل صفحه منتهی می‌شوند. ناوبری پس از بارگیری در حالت MPA حساسیت به همان اندازه با حالت SPA نخواهد داشت. + +همچنین توجه داشته باشید که عدم وجود JS به طور پیش‌فرض به این معنی است که شما اساساً Vue را به عنوان یک زبان قالب‌بندی سمت سرور استفاده می‌کنید. هیچ کنترل کننده رویدادی در مرورگر اضافه نمی‌شود، بنابراین هیچ تعاملی وجود نخواهد داشت. برای بارگیری JS سمت کلاینت، شما باید از تگ خاص ` + +# سلام +``` + +` +``` + +### نمایش محتوای خام {#rendering-raw-content} + +پارامترهای ارسال شده به صفحه در بارگذاری JavaScript کلاینت سریال می‌شوند، بنابراین باید از ارسال داده‌های سنگین در پارامترها خودداری کنید، برای مثال محتوای خام Markdown یا HTML از یک CMS از راه دور. + +به جای اینکه می‌توانید محتوای چنین محتوایی را در هر صفحه با استفاده از خاصیت `content` روی هر شیء مسیر ارسال کنید: + +```js +export default { + async paths() { + const posts = await (await fetch('https://my-cms.com/blog-posts')).json() + + return posts.map((post) => { + return { + params: { id: post.id }, + content: post.content // Markdown یا HTML خام + } + }) + } +} +``` + +سپس، از دستورات ویژه‌ی زیر برای نمایش محتوا به عنوان بخشی از فایل Markdown استفاده کنید: + +```md + +``` diff --git a/docs/fa/guide/sitemap-generation.md b/docs/fa/guide/sitemap-generation.md new file mode 100644 index 00000000..4fa808f1 --- /dev/null +++ b/docs/fa/guide/sitemap-generation.md @@ -0,0 +1,58 @@ +# جنریت کردن Sitemap {#sitemap-generation} + +ویت‌پرس با پشتیبانی بیرونی برای تولید فایل `sitemap.xml` برای سایت شما ارائه می‌شود. برای فعال‌سازی آن، موارد زیر را به فایل `.vitepress/config.js` خود اضافه کنید: + +```ts +export default { + sitemap: { + hostname: 'https://example.com' + } +} +``` + +برای داشتن تگ‌های `` در فایل `sitemap.xml` خود، می‌توانید گزینه [`lastUpdated`](../reference/default-theme-last-updated) را فعال کنید. + +## گزینه‌ها {#options} + +پشتیبانی از sitemap توسط ماژول [`sitemap`](https://www.npmjs.com/package/sitemap) ارائه شده است. می‌توانید هر گزینه‌ای که توسط این ماژول پشتیبانی می‌شود را به گزینه `sitemap` در فایل پیکربندی خود منتقل کنید. این گزینه‌ها به طور مستقیم به سازنده `SitemapStream` منتقل می‌شوند. برای جزئیات بیشتر به [مستندات sitemap](https://www.npmjs.com/package/sitemap#options-you-can-pass) مراجعه کنید. مثال: + +```ts +export default { + sitemap: { + hostname: 'https://example.com', + lastmodDateOnly: false + } +} +``` + +اگر از `base` در پیکربندی خود استفاده می‌کنید، باید آن را به گزینه `hostname` اضافه کنید: + +```ts +export default { + base: '/my-site/', + sitemap: { + hostname: 'https://example.com/my-site/' + } +} +``` + +## هوک `transformItems` {#transformitems-hook} + +می‌توانید از هوک `sitemap.transformItems` برای اصلاح موارد sitemap قبل از نوشتن آن‌ها به فایل `sitemap.xml` استفاده کنید. این هوک با یک آرایه از موارد sitemap فراخوانی می‌شود و انتظار دارد که یک آرایه از موارد sitemap بازگردانده شود. مثال: + +```ts +export default { + sitemap: { + hostname: 'https://example.com', + transformItems: (items) => { + // اضافه کردن موارد جدید یا اصلاح/فیلتر کردن موارد موجود + items.push({ + url: '/extra-page', + changefreq: 'monthly', + priority: 0.8 + }) + return items + } + } +} +``` diff --git a/docs/fa/guide/ssr-compat.md b/docs/fa/guide/ssr-compat.md new file mode 100644 index 00000000..1d4a924e --- /dev/null +++ b/docs/fa/guide/ssr-compat.md @@ -0,0 +1,134 @@ +--- +outline: deep +--- + +# تطابق SSR {#ssr-compatibility} + +ویت‌پرس، با استفاده از قابلیت‌های رندرینگ سمت سرور (SSR) ارائه شده توسط Vue، اپلیکیشن را در Node.js در هنگام ساخت تولیدی پیش از رندر می‌کند. این بدان معناست که کلیه کدهای سفارشی در اجزای تم به تطابق SSR وابسته هستند. + +[بخش SSR در مستندات رسمی Vue](https://vuejs.org/guide/scaling-up/ssr.html) بیشتر در مورد SSR، ارتباط بین SSR / SSG و نکات متداول در نوشتن کد‌های سازگار با SSR توضیح می‌دهد. قانون عمده این است که فقط در `beforeMount` یا `mounted` هوک‌های اجزای Vue از API‌های مرورگر / DOM استفاده کنید. + +## `` {#clientonly} + +اگر از اجزا یا دموهایی استفاده می‌کنید که سازگاری با SSR ندارند (برای مثال حاوی دستورالعمل‌های سفارشی هستند)، می‌توانید آن‌ها را درون کامپوننت داخلی `` قرار دهید: + +```md + + + +``` + +## کتابخانه‌هایی که در هنگام وارد کردن به API مرورگر دسترسی دارند {#libraries-that-access-browser-api-on-import} + +بعضی از کتابخانه‌ها یا اجزا در هنگام وارد کردن به API‌های مرورگر **دسترسی دارند**. برای استفاده از کدی که فرض می‌کند محیطی مرورگر در هنگام وارد کردن وجود دارد، باید آن‌ها را به صورت پویا وارد کنید. + +### وارد کردن در هوک Mounted {#importing-in-mounted-hook} + +```vue + +``` + +### وارد کردن شرطی {#conditional-import} + +می‌توانید همچنین وابستگی را با استفاده از `import.meta.env.SSR` (قسمتی از [متغیرهای env Vite](https://vitejs.dev/guide/env-and-mode.html#env-variables)) به شرط وارد کنید: + +```js +if (!import.meta.env.SSR) { + import('./lib-that-access-window-on-import').then((module) => { + // استفاده از کد + }) +} +``` + +از آنجا که `Theme.enhanceApp` می‌تواند async باشد، می‌توانید به صورت شرطی پلاگین‌های Vue را که دسترسی به API‌های مرورگر را هنگام وارد کردن دارند، وارد و ثبت کنید: + +```js [.vitepress/theme/index.js] +/** @type {import('vitepress').Theme} */ +export default { + // ... + async enhanceApp({ app }) { + if (!import.meta.env.SSR) { + const plugin = await import('plugin-that-access-window-on-import') + app.use(plugin.default) + } + } +} +``` + +اگر از TypeScript استفاده می‌کنید: +```ts [.vitepress/theme/index.ts] +import type { Theme } from 'vitepress' + +export default { + // ... + async enhanceApp({ app }) { + if (!import.meta.env.SSR) { + const plugin = await import('plugin-that-access-window-on-import') + app.use(plugin.default) + } + } +} satisfies Theme +``` + +### `defineClientComponent` {#defineclientcomponent} + +ویت‌پرس یک کمک‌کننده راحتی برای وارد کردن کامپوننت‌های Vue که هنگام وارد کردن به API‌های مرورگر دسترسی دارند فراهم می‌کند. + +```vue + + + +``` + +همچنین می‌توانید props/children/slots را به کامپوننت مقصد منتقل کنید: + +```vue + + + +``` + +کامپوننت مقصد فقط در هوک Mounted کامپوننت پوشش وارد می‌شود. diff --git a/docs/fa/guide/using-vue.md b/docs/fa/guide/using-vue.md new file mode 100644 index 00000000..b24abb52 --- /dev/null +++ b/docs/fa/guide/using-vue.md @@ -0,0 +1,257 @@ +# استفاده از Vue در Markdown {#using-vue-in-markdown} + +در ویت‌پرس، هر فایل Markdown به HTML تبدیل شده و سپس به عنوان یک [کامپوننت فایل تکی Vue](https://vuejs.org/guide/scaling-up/sfc.html) پردازش می‌شود. این بدان معنی است که شما می‌توانید از هر ویژگی Vue در داخل Markdown استفاده کنید، شامل قالب‌بندی پویا، استفاده از کامپوننت‌های Vue، یا منطق کامپوننت Vue دلخواه در داخل صفحه با افزودن تگ ` + +## محتوای Markdown + +تعداد: {{ count }} + + + + +``` + +::: warning اجتناب از ` +``` + +## استفاده از Teleport {#using-teleports} + +در حال حاضر ویت‌پرس پشتیبانی از SSG برای teleport به body را دارد. برای اهداف دیگر، می‌توانید آنها را درون کامپوننت `` یا نشانه تله‌پورت به مکان مناسب در HTML صفحه نهایی خود از طریق [هوک postRender](../reference/site-config#postrender) درج کنید. + + + +::: details جزئیات +<<< @/components/ModalDemo.vue +::: + +```md + + +
+ // ... +
+
+
+``` + + + + diff --git a/docs/fa/guide/what-is-vitepress.md b/docs/fa/guide/what-is-vitepress.md new file mode 100644 index 00000000..1522f603 --- /dev/null +++ b/docs/fa/guide/what-is-vitepress.md @@ -0,0 +1,57 @@ +# ویت‌پرس چیست؟ {#what-is-vitepress} + +ویت‌پرس یک [تولید کننده سایت ایستا](https://en.wikipedia.org/wiki/Static_site_generator) (SSG) است که برای ساخت وب‌سایت‌های سریع و محتوا محور طراحی شده است. به طور خلاصه، ویت‌پرس محتوای منبع شما که به زبان [Markdown](https://en.wikipedia.org/wiki/Markdown) نوشته شده است را گرفته، یک تم بر روی آن اعمال می‌کند و صفحات HTML ایستا تولید می‌کند که به راحتی در هر جایی قابل استقرار هستند. + +
+ +فقط می‌خواهید آن را امتحان کنید؟ به [شروع سریع](./getting-started) بروید. + +
+ +## موارد استفاده {#use-cases} + +- **مستندسازی** + + ویت‌پرس با یک تم پیش‌فرض طراحی شده برای مستندات فنی ارائه می‌شود. این صفحه‌ای که اکنون در حال خواندن آن هستید و همچنین مستندات [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/) نیز بر پایه ویت‌پرس ساخته شده است، اما از یک تم سفارشی که بین چندین ترجمه مشترک است استفاده می‌کند. + +- **وبلاگ‌ها، نمونه کارها و سایت‌های بازاریابی** + + ویت‌پرس از [تم‌های کاملاً سفارشی](./custom-theme) پشتیبانی می‌کند، با تجربه توسعه مشابه یک برنامه استاندارد Vite + Vue. با ساختن بر روی Vite، این امکان وجود دارد که مستقیماً از پلاگین‌های Vite از اکوسیستم غنی آن استفاده کنید. علاوه بر این، ویت‌پرس API‌های انعطاف‌پذیری برای [بارگذاری داده](./data-loading) (محلی یا از راه دور) و [تولید پویا مسیرها](./routing#dynamic-routes) ارائه می‌دهد. شما می‌توانید تقریباً هر چیزی را بسازید به شرطی که داده‌ها در زمان ساخت تعیین شوند. + + وبلاگ رسمی [Vue.js](https://blog.vuejs.org/) یک وبلاگ ساده است که صفحه فهرست خود را بر اساس محتوای محلی تولید می‌کند. + +## تجربه توسعه دهنده {#developer-experience} + +ویت‌پرس هدف ارائه یک تجربه عالی برای توسعه دهنده (DX) هنگام کار با محتوای Markdown را دارد. + +- **[قدرت گرفته از Vite:](https://vitejs.dev/)** شروع سرور فوری، با بازتاب ویرایش‌ها به صورت آنی (<100ms) بدون بارگذاری مجدد صفحه. + +- **[افزونه‌های داخلی Markdown:](./markdown)** استفاده از Frontmatter، جداول، syntax highlighting... هرچه که بخواهید. ویت‌پرس به ویژه ویژگی‌های پیشرفته زیادی برای کار با بلوک‌های کد فراهم می‌کند، که آن را برای مستندات فنی بسیار مناسب می‌کند. + +- **[Markdown بهبود یافته با Vue:](./using-vue)** هر صفحه Markdown نیز یک [کامپوننت تک فایل Vue](https://vuejs.org/guide/scaling-up/sfc.html) است، به لطف سازگاری ۱۰۰٪ سینتکسی قالب Vue با HTML. شما می‌توانید از ویژگی‌های قالب‌بندی Vue یا کامپوننت‌های وارد شده Vue برای ایجاد تعامل در محتوای ایستا خود استفاده کنید. + +## عملکرد {#performance} + +بر خلاف بسیاری از SSG‌های سنتی که هر ناوبری منجر به بارگذاری کامل صفحه می‌شود، یک وب‌سایت تولید شده توسط ویت‌پرس در بازدید اولیه HTML ایستا را سرو می‌کند، اما برای ناوبری‌های بعدی در سایت به یک [برنامه تک صفحه‌ای](https://en.wikipedia.org/wiki/Single-page_application) (SPA) تبدیل می‌شود. به نظر ما، این مدل برای عملکرد بهترین تعادل را فراهم می‌کند: + +- **بارگذاری اولیه سریع** + + بازدید اولیه از هر صفحه، HTML پیش‌پردازش شده ایستا را برای سرعت بارگذاری سریع و بهینه‌سازی SEO سرو می‌کند. سپس صفحه یک بسته JavaScript را بارگذاری می‌کند که صفحه را به یک SPA Vue تبدیل می‌کند ("hydration"). بر خلاف فرضیات رایج که hydration برای SPA کند است، این فرآیند در واقع بسیار سریع است به لطف عملکرد خام Vue 3 و بهینه‌سازی‌های کامپایلر. در [PageSpeed Insights](https://pagespeed.web.dev/report?url=https%3A%2F%2Fvitepress.dev%2F)، سایت‌های معمولی ویت‌پرس حتی در دستگاه‌های موبایل پایین‌رده با شبکه کند به امتیازهای عملکردی تقریباً کامل دست می‌یابند. + +- **ناوبری سریع پس از بارگذاری** + + مهم‌تر از آن، مدل SPA منجر به تجربه کاربری بهتر **پس از** بارگذاری اولیه می‌شود. ناوبری‌های بعدی در سایت دیگر باعث بارگذاری کامل صفحه نمی‌شوند. در عوض، محتوای صفحه ورودی بارگذاری و به صورت پویا به‌روزرسانی می‌شود. ویت‌پرس همچنین به صورت خودکار تکه‌های صفحه را برای لینک‌هایی که در viewport هستند پیش‌بارگذاری (pre-fetch) می‌کند. در بیشتر موارد، ناوبری پس از بارگذاری به صورت آنی احساس می‌شود. + +- **تعامل بدون جریمه** + + برای اینکه بتوانید بخش‌های پویا Vue جاسازی شده در داخل Markdown ایستا را hydrated کنید، هر صفحه Markdown به عنوان یک کامپوننت Vue پردازش و به JavaScript کامپایل می‌شود. این ممکن است غیر بهینه به نظر برسد، اما کامپایلر Vue به اندازه کافی هوشمند است که بخش‌های ایستا و پویا را جدا کند، هزینه hydration و اندازه محموله را به حداقل برساند. برای بارگذاری اولیه صفحه، بخش‌های ایستا به صورت خودکار از محموله JavaScript حذف می‌شوند و در حین hydration نادیده گرفته می‌شوند. + +## درباره VuePress چه؟ {#what-about-vuepress} + +ویت‌پرس جانشین معنوی VuePress است. VuePress اصلی بر پایه Vue 2 و webpack بود. با Vue 3 و Vite در هسته، ویت‌پرس تجربه توسعه بهتر، عملکرد تولید بهتر، تم پیش‌فرض کامل‌تر و API سفارشی‌سازی انعطاف‌پذیرتری ارائه می‌دهد. + +تفاوت API بین ویت‌پرس و VuePress عمدتاً در زمینه تم‌سازی و سفارشی‌سازی است. اگر از VuePress 1 با تم پیش‌فرض استفاده می‌کنید، باید مهاجرت به ویت‌پرس نسبتاً ساده باشد. + +همچنین تلاش‌هایی برای VuePress 2 انجام شده است، که از Vue 3 و Vite با سازگاری بیشتر با VuePress 1 پشتیبانی می‌کند. با این حال، نگهداری دو SSG به صورت موازی پایدار نیست، بنابراین تیم Vue تصمیم گرفته است که در دراز مدت بر روی ویت‌پرس به عنوان SSG اصلی توصیه شده تمرکز کند. diff --git a/docs/fa/index.md b/docs/fa/index.md new file mode 100644 index 00000000..8fa79bd3 --- /dev/null +++ b/docs/fa/index.md @@ -0,0 +1,35 @@ +--- +layout: home + +hero: + name: ویت‌پرس + text: سازنده سایت‌های ایستا به کمک Vite و Vue + tagline: تبدیل Markdown به مستندات زیبا در چند دقیقه + actions: + - theme: brand + text: ویت‌پرس چیست؟ + link: fa/guide/what-is-vitepress + - theme: alt + text: شروع سریع + link: fa/guide/getting-started + - theme: alt + text: گیت‌هاب + link: https://github.com/vuejs/vitepress + image: + src: /vitepress-logo-large.svg + alt: ویت‌پرس + +features: + - icon: 📝 + title: تمرکز روی محتوا + details: ایجاد سایت‌های مستند‌سازی زیبا بدون زحمت و فقط با Markdown + - icon: + title: لذت از تجربه توسعه با Vite + details: شروع فوری سرور، به‌روزرسانی‌های سریع و استفاده از افزونه‌های اکوسیستم Vite + - icon: + title: شخصی‌سازی با Vue + details: استفاده مستقیم از syntax و کامپوننت‌های Vue در Markdown، یا ایجاد تم‌های شخصی به کمک Vue + - icon: 🚀 + title: ارسال سایت های سریع + details: بارگذاری اولیه سریع با HTML ایستا، ناوبری سریع پس از بارگیری با مسیریابی سمت کلاینت +--- diff --git a/docs/fa/reference/cli.md b/docs/fa/reference/cli.md new file mode 100644 index 00000000..c8ad10ff --- /dev/null +++ b/docs/fa/reference/cli.md @@ -0,0 +1,74 @@ +# رابط خط فرمان {#command-line-interface} + +## `vitepress dev` {#vitepress-dev} + +شروع سرور توسعه ویت‌پرس با استفاده از دایرکتوری مشخص به عنوان ریشه. به طور پیش‌فرض از دایرکتوری فعلی استفاده می‌شود. دستور `dev` همچنین می‌تواند حذف شود زمانی که در دایرکتوری فعلی اجرا می‌شود. + +### استفاده {#usage} + +```sh +# شروع در دایرکتوری فعلی، بدون `dev` +vitepress + +# شروع در زیردایرکتوری +vitepress dev [root] +``` + +### گزینه‌ها {#options} + +| گزینه | توضیحات | +| --------------- | ----------------------------------------------------------------- | +| `--open [path]` | باز کردن مرورگر در زمان راه‌اندازی (`boolean \| string`) | +| `--port ` | تعیین پورت (`number`) | +| `--base ` | مسیر پایه عمومی (پیش‌فرض: `/`) (`string`) | +| `--cors` | فعال‌سازی CORS | +| `--strictPort` | خروج در صورت استفاده از پورت مشخص شده (`boolean`) | +| `--force` | اجبار به نادیده گرفتن حافظه پنهان و بازسازی (`boolean`) | + +## `vitepress build` {#vitepress-build} + +ساخت سایت ویت‌پرس برای تولید نهایی. + +### استفاده {#usage-1} + +```sh +vitepress build [root] +``` + +### گزینه‌ها {#options-1} + +| گزینه | توضیحات | +| ------------------------------ | ---------------------------------------------------------------------------------------------------------------- | +| `--mpa` (آزمایشی) | ساخت در حالت [MPA](../guide/mpa-mode) بدون هیدراسیون سمت مشتری (`boolean`) | +| `--base ` | مسیر پایه عمومی (پیش‌فرض: `/`) (`string`) | +| `--target ` | هدف ترنسپایل (پیش‌فرض: `"modules"`) (`string`) | +| `--outDir ` | دایرکتوری خروجی نسبت به **cwd** (پیش‌فرض: `/.vitepress/dist`) (`string`) | +| `--minify [minifier]` | فعال یا غیرفعال کردن فشرده‌سازی، یا تعیین فشرده‌سازی برای استفاده (پیش‌فرض: `"esbuild"`) (`boolean \| "terser" \| "esbuild"`) | +| `--assetsInlineLimit ` | آستانه تبدیل پایه ۶۴ استاتیک به بایت (پیش‌فرض: `4096`) (`number`) | + +## `vitepress preview` {#vitepress-preview} + +پیش‌نمایش محلی برای ساخت تولیدی را نمایش دهید. + +### استفاده {#usage-2} + +```sh +vitepress preview [root] +``` + +### گزینه‌ها {#options-2} + +| گزینه | توضیحات | +| --------------- | ---------------------------------------- | +| `--base ` | مسیر پایه عمومی (پیش‌فرض: `/`) (`string`) | +| `--port ` | تعیین پورت (`number`) | + +## `vitepress init` {#vitepress-init} + +شروع [جادوگر راه‌اندازی](../guide/getting-started#setup-wizard) در دایرکتوری فعلی. + +### استفاده {#usage-3} + +```sh +vitepress init +``` diff --git a/docs/fa/reference/default-theme-badge.md b/docs/fa/reference/default-theme-badge.md new file mode 100644 index 00000000..b399eb90 --- /dev/null +++ b/docs/fa/reference/default-theme-badge.md @@ -0,0 +1,72 @@ +# نشان {#badge} + +برچسب به شما امکان می‌دهد وضعیت‌های مختلفی را به سربرگ‌های خود اضافه کنید. به عنوان مثال، می‌تواند مفید باشد تا نوع بخش را مشخص کنید یا نسخه‌های پشتیبانی شده را نشان دهید. + +## استفاده {#usage} + +شما می‌توانید از کامپوننت `Badge` که به صورت جهانی در دسترس است، استفاده کنید. + +```html +### عنوان +### عنوان +### عنوان +### عنوان +``` + +کد بالا به صورت زیر نمایش داده می‌شود: + +### عنوان {#title} + +### عنوان {#title-1} + +### عنوان {#title-2} + +### عنوان {#title-3} + +## ارائه دادن محتوای دلخواه {#custom-children} + +`` می‌پذیرد `children` که در برچسب نمایش داده خواهد شد. + +```html +### عنوان عنصر سفارشی +``` + +### عنوان عنصر سفارشی + +## سفارشی‌سازی رنگ نوع {#customize-type-color} + +شما می‌توانید استایل برچسب‌ها را با دوباره‌نویسی متغیرهای css سفارشی کنید. مقادیر پیش‌فرض به شرح زیر هستند: + +```css +:root { + --vp-badge-info-border: transparent; + --vp-badge-info-text: var(--vp-c-text-2); + --vp-badge-info-bg: var(--vp-c-default-soft); + + --vp-badge-tip-border: transparent; + --vp-badge-tip-text: var(--vp-c-brand-1); + --vp-badge-tip-bg: var(--vp-c-brand-soft); + + --vp-badge-warning-border: transparent; + --vp-badge-warning-text: var(--vp-c-warning-1); + --vp-badge-warning-bg: var(--vp-c-warning-soft); + + --vp-badge-danger-border: transparent; + --vp-badge-danger-text: var(--vp-c-danger-1); + --vp-badge-danger-bg: var(--vp-c-danger-soft); +} +``` + +## `` {#badge-1} + +کامپوننت `` پراپ‌های زیر را می‌پذیرد: + +```ts +interface Props { + // وقتی `` ارسال می‌شود، این مقدار نادیده گرفته می‌شود. + text?: string + + // پیش‌فرض به `tip`. + type?: 'info' | 'tip' | 'warning' | 'danger' +} +``` diff --git a/docs/fa/reference/default-theme-carbon-ads.md b/docs/fa/reference/default-theme-carbon-ads.md new file mode 100644 index 00000000..da22258f --- /dev/null +++ b/docs/fa/reference/default-theme-carbon-ads.md @@ -0,0 +1,22 @@ +# تبلیغات Carbon {#carbon-ads} + +ویت‌پرس پشتیبانی داخلی برای [Carbon Ads](https://www.carbonads.net/) را دارد. با تعریف مشخصات تبلیغات Carbon در تنظیمات، ویت‌پرس تبلیغات را در صفحه نمایش می‌دهد. + +```js +export default { + themeConfig: { + carbonAds: { + code: 'your-carbon-code', + placement: 'your-carbon-placement' + } + } +} +``` + +این مقادیر برای فراخوانی اسکریپت CDN Carbon به شکل زیر استفاده می‌شوند. + +```js +`//cdn.carbonads.com/carbon.js?serve=${code}&placement=${placement}` +``` + +برای یادگیری بیشتر درباره پیکربندی تبلیغات Carbon، لطفاً به [وب‌سایت Carbon Ads](https://www.carbonads.net/) مراجعه کنید. diff --git a/docs/fa/reference/default-theme-config.md b/docs/fa/reference/default-theme-config.md new file mode 100644 index 00000000..1040f79b --- /dev/null +++ b/docs/fa/reference/default-theme-config.md @@ -0,0 +1,469 @@ +# پیکربندی پیش‌فرض تم {#default-theme-config} + +پیکربندی تم به شما امکان می‌دهد تا تم خود را سفارشی کنید. شما می‌توانید پیکربندی تم را از طریق گزینه `themeConfig` در فایل پیکربندی تعریف کنید: + +```ts +export default { + lang: 'en-US', + title: 'ویت‌پرس', + description: 'Vite & Vue powered static site generator.', + + // پیکربندی‌های مربوط به تم. + themeConfig: { + logo: '/logo.svg', + nav: [...], + sidebar: { ... } + } +} +``` + +**گزینه‌های مستند شده در این صفحه تنها برای تم پیش‌فرض اعمال می‌شوند.** تم‌های مختلف انتظار دارند که پیکربندی تم متفاوتی داشته باشند. در هنگام استفاده از یک تم سفارشی، شیء پیکربندی تم به تم منتقل می‌شود تا تم بتواند بر اساس آن رفتار شرطی را تعریف کند. + +## i18nRouting {#i18nrouting} + +- نوع: `boolean` + +تغییر زبان به `zh` باعث تغییر URL از `/foo` (یا `/en/foo/`) به `/zh/foo` می‌شود. شما می‌توانید این رفتار را با تنظیم `themeConfig.i18nRouting` به `false` غیرفعال کنید. + +## logo {#logo} + +- نوع: `ThemeableImage` + +فایل لوگو برای نمایش در نوار ناوبری، به سمت راست قبل از عنوان سایت. یک رشته مسیر یا یک شیء برای تنظیم لوگو متفاوت برای حالت نوری/تاریک قبول می‌کند. + +```ts +export default { + themeConfig: { + logo: '/logo.svg' + } +} +``` + +```ts +type ThemeableImage = + | string + | { src: string; alt?: string } + | { light: string; dark: string; alt?: string } +``` + +## siteTitle + +- نوع: `string | false` + +شما می‌توانید این مورد را سفارشی کنید تا عنوان سایت پیش‌فرض (`title` در پیکربندی برنامه) را در ناوبری جایگزین کنید. هنگامی که به `false` تنظیم می‌شود، عنوان در ناوبری غیرفعال می‌شود. این قابلیت مفید است زمانی که شما لوگو دارید که حاوی متن عنوان سایت است. + +```ts +export default { + themeConfig: { + siteTitle: 'Hello World' + } +} +``` + +## nav + +- نوع: `NavItem` + +پیکربندی برای موارد منوی ناوبری. جزئیات بیشتر در [تم پیش‌فرض: ناوبری](./default-theme-nav#navigation-links). + +```ts +export default { + themeConfig: { + nav: [ + { text: 'راهنما', link: '/guide' }, + { + text: 'منوی کشویی', + items: [ + { text: 'مورد الف', link: '/item-1' }, + { text: 'مورد ب', link: '/item-2' }, + { text: 'مورد ج', link: '/item-3' } + ] + } + ] + } +} +``` + +```ts +type NavItem = NavItemWithLink | NavItemWithChildren + +interface NavItemWithLink { + text: string + link: string + activeMatch?: string + target?: string + rel?: string + noIcon?: boolean +} + +interface NavItemChildren { + text?: string + items: NavItemWithLink[] +} + +interface NavItemWithChildren { + text?: string + items: (NavItemChildren | NavItemWithLink)[] + activeMatch?: string +} +``` + +## sidebar + +- نوع: `Sidebar` + +پیکربندی برای موارد منوی نوار کناری. جزئیات بیشتر در [تم پیش‌فرض: نوار کناری](./default-theme-sidebar). + +```ts +export default { + themeConfig: { + sidebar: [ + { + text: 'راهنما', + items: [ + { text: 'معرفی', link: '/introduction' }, + { text: 'شروع کار', link: '/getting-started' }, + ... + ] + } + ] + } +} +``` + +```ts +export type Sidebar = SidebarItem[] | SidebarMulti + +export interface SidebarMulti { + [path: string]: SidebarItem[] | { items: SidebarItem[]; base: string } +} + +export type SidebarItem = { + /** + * برچسب متنی مورد. + */ + text?: string + + /** + * لینک مورد. + */ + link?: string + + /** + * فرزندان مورد. + */ + items?: SidebarItem[] + + /** + * اگر مشخص نشده باشد، گروه قابل جمع‌شدن نیست. + * + * اگر `true` باشد، گروه قابل جمع‌شدن است و به طور پیش‌فرض جمع شده است + * + * اگر `false` باشد، گروه قابل جمع‌شدن است اما به طور پیش‌فرض باز شده است + */ + collapsed?: boolean + + /** + * مسیر پایه برای موارد فرزند. + */ + base?: string + + /** + * سفارشی‌سازی متنی که در پا صفحه قبلی/بعدی نمایش داده می‌شود. + */ + docFooterText?: string + + rel?: string + target?: string +} +``` + +## aside + +- نوع: `boolean | 'left'` +- پیش‌فرض: `true` +- می‌تواند به صورت خودکار برای هر صفحه از طریق [frontmatter](./frontmatter-config#aside) بازنویسی شود. + +تنظیم این مقدار به `false` از رندر کردن کانتینر اطراف خودداری می‌کند.\ +تنظیم این مقدار به `true` کانتینر اطراف را به راست رندر می‌کند.\ +تنظیم این مقدار به `left` کانتینر اطراف را به چپ رندر می‌کند. + +اگر می‌خواهید آن را برای تمام نمایه‌گرها غیرفعال کنید، به جای آن باید از `outline: false` استفاده کنید. + +## outline + +- نوع: `Outline | Outline['level'] | false` +- می‌تواند به صورت خودکار برای هر صفحه از طریق [frontmatter](./frontmatter-config#outline) بازنویسی شود. + +تنظیم این مقدار به `false` از + +رندر کردن کانتینر آوند خودداری می‌کند. به این رابط مراجعه کنید تا جزئیات بیشتری را بدانید: + +```ts +interface Outline { + /** + * سطوح سرفصل‌هایی که در آوند نمایش داده خواهند شد. + * یک عدد تک را به این معنا است که تنها سرفصل‌های آن سطح نمایش داده می‌شوند. + * اگر یک دوتایی گذر داده شود، عدد اول سطح حداقل و عدد دوم سطح حداکثر است. + * `'deep'` مانند `[2، 6]` است، که به معنای همه سرفصل‌ها از `

` تا `

` است. + * + * @default 2 + */ + level?: number | [number، number] | 'deep' + + /** + * عنوانی که باید در آوند نمایش داده شود. + * + * @default 'On this page' + */ + label?: string +} +``` + +## socialLinks + +- نوع: `SocialLink[]` + +می‌توانید این گزینه را تعریف کنید تا لینک‌های حساب اجتماعی خود را با آیکون‌ها در ناوبری نمایش دهید. + +```ts +export default { + themeConfig: { + socialLinks: [ + { icon: 'github', link: 'https://github.com/vuejs/vitepress' }, + { icon: 'twitter', link: '...' }, + // شما همچنین می‌توانید آیکون‌های سفارشی را با ارسال SVG به عنوان رشته اضافه کنید: + { + icon: { + svg: 'Dribbble' + }, + link: '...', + // شما همچنین می‌توانید برچسب سفارشی را برای دسترسی (اختیاری اما توصیه می‌شود) شامل کنید: + ariaLabel: 'لینک جذاب' + } + ] + } +} +``` + +```ts +interface SocialLink { + icon: SocialLinkIcon + link: string + ariaLabel?: string +} + +type SocialLinkIcon = + | 'discord' + | 'facebook' + | 'github' + | 'instagram' + | 'linkedin' + | 'mastodon' + | 'npm' + | 'slack' + | 'twitter' + | 'x' + | 'youtube' + | { svg: string } +``` + +## footer + +- نوع: `Footer` +- می‌تواند به صورت خودکار برای هر صفحه از طریق [frontmatter](./frontmatter-config#footer) بازنویسی شود. + +پیکربندی پا. شما می‌توانید پیام یا متن حق کپی را در پا اضافه کنید، با این حال، فقط زمانی نمایش داده می‌شود که صفحه شامل نوار کناری نباشد. این به دلایل طراحی است. + +```ts +export default { + themeConfig: { + footer: { + message: 'منتشر شده تحت مجوز MIT.', + copyright: 'حق نشر © 2019-present Evan You' + } + } +} +``` + +```ts +export interface Footer { + message?: string + copyright?: string +} +``` + +## editLink + +- نوع: `EditLink` +- می‌تواند به صورت خودکار برای هر صفحه از طریق [frontmatter](./frontmatter-config#editlink) بازنویسی شود. + +پیوند ویرایش به شما امکان می‌دهد که یک لینک به ویرایش صفحه را در خدمات مدیریت گیت مانند GitHub یا GitLab نمایش دهید. برای جزئیات بیشتر به [تم پیش‌فرض: لینک ویرایش](./default-theme-edit-link) مراجعه کنید. + +```ts +export default { + themeConfig: { + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + text: 'ویرایش این صفحه در GitHub' + } + } +} +``` + +```ts +export interface EditLink { + pattern: string + text?: string +} +``` + +## lastUpdated + +- نوع: `LastUpdatedOptions` + +امکانات سفارشی‌سازی برای متن به‌روز شده و فرمت تاریخ. + +```ts +export default { + themeConfig: { + lastUpdated: { + text: 'به‌روزرسانی شده در', + formatOptions: { + dateStyle: 'full', + timeStyle: 'medium' + } + } + } +} +``` + +```ts +export interface LastUpdatedOptions { + /** + * @default 'آخرین به‌روزرسانی' + */ + text?: string + + /** + * @default + * { dateStyle: 'short', timeStyle: 'short' } + */ + formatOptions?: Intl.DateTimeFormatOptions & { forceLocale?: boolean } +} +``` + +## algolia + +- نوع: `AlgoliaSearch` + +یک گزینه برای پشتیبانی از جستجو در سایت مستندات خود با استفاده از [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch). بیشتر در [تم پیش‌فرض: جستجو](./default-theme-search) بیاموزید. + +```ts +export interface AlgoliaSearchOptions extends DocSearchProps { + locales?: Record> +} +``` + +گزینه‌های کامل را [اینجا](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts) مشاهده کنید. + +## carbonAds {#carbon-ads} + +- نوع: `CarbonAdsOptions` + +یک گزینه برای نمایش [Carbon Ads](https://www.carbonads.net/). + +```ts +export default { + themeConfig: { + carbonAds: { + code: 'your-carbon-code', + placement: 'your-carbon-placement' + } + } +} +``` + +```ts +export interface CarbonAdsOptions { + code: string + placement: string +} +``` + +بیشتر در [تم پیش‌فرض: Carbon Ads](./default-theme-carbon-ads) بیاموزید. + +## docFooter + +- نوع: `DocFooter` + +می‌تواند برای سفارشی‌سازی متنی که در بالای لینک‌های قبلی و بعدی نمایش داده می‌شود استفاده شود. مفید است اگر مستندات خود را به زبانی غیر از انگلیسی نوشته باشید. همچنین می‌تواند برای غیرفعال کردن لینک‌های قبلی/بعدی به صورت جهانی استفاده شود. اگر می‌خواهید لینک‌های قبلی/بعدی را به صورت انتخابی فعال + +/غیرفعال کنید، می‌توانید از [frontmatter](./default-theme-prev-next-links) استفاده کنید. + +```ts +export default { + themeConfig: { + docFooter: { + prev: 'صفحه قبلی', + next: 'صفحه بعدی' + } + } +} +``` + +```ts +export interface DocFooter { + prev?: string | false + next?: string | false +} +``` + +## darkModeSwitchLabel + +- نوع: `string` +- پیش‌فرض: `ظاهر` + +می‌تواند برای سفارشی‌سازی برچسب سوئیچ حالت تاریک استفاده شود. این برچسب تنها در نمای تلفن همراه نمایش داده می‌شود. + +## lightModeSwitchTitle + +- نوع: `string` +- پیش‌فرض: `تغییر به تم روشن` + +می‌تواند برای سفارشی‌سازی عنوان سوئیچ حالت روشن که در بالا حاشیه دار می‌شود، استفاده شود. + +## darkModeSwitchTitle + +- نوع: `string` +- پیش‌فرض: `تغییر به تم تاریک` + +می‌تواند برای سفارشی‌سازی عنوان سوئیچ حالت تاریک که در بالا حاشیه دار می‌شود، استفاده شود. + +## sidebarMenuLabel + +- نوع: `string` +- پیش‌فرض: `منو` + +می‌تواند برای سفارشی‌سازی برچسب منوی نوار کناری استفاده شود. این برچسب تنها در نمای تلفن همراه نمایش داده می‌شود. + +## returnToTopLabel + +- نوع: `string` +- پیش‌فرض: `بازگشت به بالا` + +می‌تواند برای سفارشی‌سازی برچسب دکمه بازگشت به بالا استفاده شود. این برچسب تنها در نمای تلفن همراه نمایش داده می‌شود. + +## langMenuLabel + +- نوع: `string` +- پیش‌فرض: `تغییر زبان` + +می‌تواند برای سفارشی‌سازی برچسب aria- توگل زبان در ناوبری استفاده شود. این فقط در صورت استفاده از [i18n](../guide/i18n) استفاده می‌شود. + +## externalLinkIcon + +- نوع: `boolean` +- پیش‌فرض: `false` + +آیا باید نمایش آیکون لینک خارجی کنار لینک‌های خارجی در مارک‌داون باشد. diff --git a/docs/fa/reference/default-theme-edit-link.md b/docs/fa/reference/default-theme-edit-link.md new file mode 100644 index 00000000..7acab905 --- /dev/null +++ b/docs/fa/reference/default-theme-edit-link.md @@ -0,0 +1,60 @@ +# پیوند ویرایش {#edit-link} + +## پیکربندی سطح سایت {#site-level-config} + +پیوند ویرایش به شما این امکان را می‌دهد که یک پیوند به صفحه ویرایش را در خدمات مدیریت گیت مانند GitHub یا GitLab نمایش دهید. برای فعال‌سازی آن، گزینه `themeConfig.editLink` را به پیکربندی خود اضافه کنید. + +```js +export default { + themeConfig: { + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path' + } + } +} +``` + +گزینه `pattern` ساختار URL را برای پیوند تعیین می‌کند و `:path` با مسیر صفحه جایگزین خواهد شد. + +همچنین می‌توانید یک تابع خالص ارائه دهید که `PageData` را به عنوان آرگومان دریافت کرده و رشته URL را برمی‌گرداند. + +```js +export default { + themeConfig: { + editLink: { + pattern: ({ filePath }) => { + if (filePath.startsWith('packages/')) { + return `https://github.com/acme/monorepo/edit/main/${filePath}` + } else { + return `https://github.com/acme/monorepo/edit/main/docs/${filePath}` + } + } + } + } +} +``` + +این تابع نباید اثر جانبی داشته باشد و هیچ چیز خارج از دامنه خود را دسترسی ندهد، زیرا که در مرورگر سریالیزه و اجرا خواهد شد. + +به طور پیش‌فرض، این عبارت "ویرایش این صفحه" را در پایین صفحه مستندات اضافه می‌کند. می‌توانید این متن را با تعریف گزینه `text` سفارشی‌سازی کنید. + +```js +export default { + themeConfig: { + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + text: 'ویرایش این صفحه در GitHub' + } + } +} +``` + +## پیکربندی Frontmatter {#frontmatter-config} + +می‌توانید این امکان را برای هر صفحه با استفاده از گزینه `editLink` در frontmatter غیرفعال کنید: + +```yaml +--- +editLink: false +--- +``` diff --git a/docs/fa/reference/default-theme-footer.md b/docs/fa/reference/default-theme-footer.md new file mode 100644 index 00000000..67faa72c --- /dev/null +++ b/docs/fa/reference/default-theme-footer.md @@ -0,0 +1,53 @@ +# پاورقی {#footer} + +وقتی `themeConfig.footer` حاضر باشد، ویت‌پرس پاورقی جهانی را در پایین صفحه نمایش می‌دهد. + +```ts +export default { + themeConfig: { + footer: { + message: 'Released under the MIT License.', + copyright: 'Copyright © 2019-present Evan You' + } + } +} +``` + +```ts +export interface Footer { + // پیام نمایش داده شده درست قبل از حق نسخه. + message?: string + + // متن حق نسخه واقعی. + copyright?: string +} +``` + +پیکربندی بالا همچنین از رشته‌های HTML پشتیبانی می‌کند. بنابراین، به عنوان مثال، اگر می‌خواهید متن پاورقی دارای برخی از لینک‌ها باشد، می‌توانید پیکربندی را به شکل زیر تنظیم کنید: + +```ts +export default { + themeConfig: { + footer: { + message: 'Released under the MIT License.', + copyright: 'Copyright © 2019-present Evan You' + } + } +} +``` + +::: warning هشدار +تنها عناصر مستقیم می‌توانند در `message` و `copyright` استفاده شوند زیرا در داخل یک عنصر `

` رندر می‌شوند. اگر می‌خواهید عناصر بلوکی را اضافه کنید، در نظر داشته باشید که به جای این، از [اسلات `layout-bottom`](../guide/extending-default-theme#layout-slots) استفاده کنید. +::: + +توجه داشته باشید که پاورقی نمایش داده نمی‌شود زمانی که [نوار کناری](./default-theme-sidebar) قابل مشاهده باشد. + +## پیکربندی Frontmatter {#frontmatter-config} + +این می‌تواند برای هر صفحه با استفاده از گزینه `footer` در frontmatter غیرفعال شود: + +```yaml +--- +footer: false +--- +``` diff --git a/docs/fa/reference/default-theme-home-page.md b/docs/fa/reference/default-theme-home-page.md new file mode 100644 index 00000000..5503ac0a --- /dev/null +++ b/docs/fa/reference/default-theme-home-page.md @@ -0,0 +1,193 @@ +# صفحه اصلی {#home-page} + +قالب پیش‌فرض ویت‌پرس یک طرح صفحه اصلی فراهم می‌کند که می‌توانید آن را همچنین در [صفحه اصلی این سایت](../) مشاهده کنید. شما می‌توانید آن را در هر یک از صفحات خود با تعیین `layout: home` در [frontmatter](./frontmatter-config) استفاده کنید. + +```yaml +--- +layout: home +--- +``` + +اما این گزینه به تنهایی خیلی کاربردی نخواهد بود. شما می‌توانید با اضافه کردن بخش‌های "قالب‌های پیش‌فرض" مختلف، چندین بخش متفاوت را به صفحه اصلی اضافه کنید مانند `hero` و `features`. + +## بخش Hero {#hero-section} + +بخش Hero در بالای صفحه اصلی قرار دارد. در ادامه می‌توانید نحوه پیکربندی بخش Hero را ببینید. + +```yaml +--- +layout: home + +hero: + name: ویت‌پرس + text: Vite & Vue powered static site generator. + tagline: Lorem ipsum... + image: + src: /logo.png + alt: ویت‌پرس + actions: + - theme: brand + text: Get Started + link: /guide/what-is-vitepress + - theme: alt + text: View on GitHub + link: https://github.com/vuejs/vitepress +--- +``` + +```ts +interface Hero { + // رشته نمایش داده شده در بالای `text`. همراه با رنگ برند و انتظار می‌رود که کوتاه باشد، مانند نام محصول. + name?: string + + // متن اصلی بخش Hero. این به عنوان تگ `h1` تعریف می‌شود. + text: string + + // تگ‌لاین نمایش داده شده زیر `text`. + tagline?: string + + // تصویر که در کنار ناحیه متن و تگ‌لاین نمایش داده می‌شود. + image?: ThemeableImage + + // دکمه‌های اقدام برای نمایش در بخش Hero صفحه اصلی. + actions?: HeroAction[] +} + +type ThemeableImage = + | string + | { src: string; alt?: string } + | { light: string; dark: string; alt?: string } + +interface HeroAction { + // رنگ تم دکمه. به طور پیش‌فرض `brand` است. + theme?: 'brand' | 'alt' + + // برچسب دکمه. + text: string + + // مقصد لینک دکمه. + link: string + + // ویژگی هدف لینک. + target?: string + + // ویژگی rel لینک. + rel?: string +} +``` + +### سفارشی‌سازی رنگ نام {#customizing-the-name-color} + +ویت‌پرس از رنگ برند (`--vp-c-brand-1`) برای `name` استفاده می‌کند. با این حال، شما می‌توانید این رنگ را با جایگذاری متغیر `--vp-home-hero-name-color` سفارشی کنید. + +```css +:root { + --vp-home-hero-name-color: blue; +} +``` + +همچنین می‌توانید با ترکیب `--vp-home-hero-name-background`، رنگ گرادیانت `name` را تعیین کنید. + +```css +:root { + --vp-home-hero-name-color: transparent; + --vp-home-hero-name-background: -webkit-linear-gradient(120deg, #bd34fe, #41d1ff); +} +``` + +## {#features-section} بخش ویژگی‌ها + +در بخش ویژگی‌ها، می‌توانید هر تعدادی ویژگی که مایلید پس از بخش Hero نمایش دهید، لیست کنید. برای پیکربندی آن، گزینه `features` را به frontmatter ارسال کنید. + +می‌توانید برای هر ویژگی آیکونی ارائه دهید که می‌تواند یک ایموجی یا هر نوع تصویر دیگری باشد. زمانی که آیکون پیکربندی شده یک تصویر است (svg، png، jpeg...). باید آیکون را با عرض و ارتفاع مناسب ارائه دهید. شما همچنین می‌توانید توضیحات، اندازه داخلی آن و نسخه‌های آن برای تم تاریک و روشن را ارائه دهید هنگام لزوم. + +```yaml +--- +layout: home + +features: + - icon: 🛠️ + title: ساده و کم حجم، همیشه + details: Lorem ipsum... + - icon: + src: /cool-feature-icon.svg + title: ویژگی جالب دیگر + details: Lorem ipsum... + - icon: + dark: /dark-feature-icon.svg + light: /light-feature-icon.svg + title: ویژگی جالب دیگر + details: Lorem ipsum... +--- +``` + +```ts +interface Feature { + // نمایش آیکون در هر جعبه ویژگی. + icon?: FeatureIcon + + // عنوان ویژگی. + title: string + + // جزئیات ویژگی. + details: string + + // لینک زمانی که بر روی جزئیات کلیک می‌کنید. لینک می‌تواند داخلی یا خارجی باشد. + // + // به عنوان مثال: `guide/reference/default-theme-home-page` یا `https://example.com` + link?: string + + // متن لینکی که داخل جزئیات کامپوننت نمایش داده می‌شود. بهتر است با گزینه `link` استفاده شود. + // + // به عنوان مثال: `بیشتر بدانید`، `صفحه بازدید` و غیره. + linkText?: string + + // ویژگی rel لینک برای گزینه `link`. + // + // به عنوان مثال: `external` + rel?: string + + // ویژگی target لینک برای گزینه `link`. + target?: string +} + +type FeatureIcon = + | string + | { src: string; alt?: string; width?: string; height: string } + | { + light: string + dark: string + alt?: string + width?: string + height: string + } +``` + +## محتوای Markdown {#markdown-content} + +می‌توانید محتوای اضافی را به صفحه اصلی سایت خود اضافه کنید فقط با افزودن Markdown زیر تقسیم‌کننده `---` در پایین frontmatter. + +````md +--- +layout: home + +hero: + name + +: ویت‌پرس + text: Vite & Vue powered static site generator. +--- + +## شروع کردن + +می‌توانید بلافاصله با استفاده از `npx` از ویت‌پرس شروع کنید! + +```sh +npm init +npx vitepress init +``` +```` + +::: info اطلاعات +ویت‌پرس همیشه استایل اضافی محتوای صفحه `layout: home` را خودکار نمی‌کند. برای بازگشت به رفتار قدیمی، می‌توانید `markdownStyles: false` را به frontmatter اضافه کنید. +::: diff --git a/docs/fa/reference/default-theme-last-updated.md b/docs/fa/reference/default-theme-last-updated.md new file mode 100644 index 00000000..5bb286e1 --- /dev/null +++ b/docs/fa/reference/default-theme-last-updated.md @@ -0,0 +1,27 @@ +# آخرین بروزرسانی {#last-updated} + +زمان به روزرسانی آخرین محتوا در گوشه پایین سمت راست صفحه نمایش داده خواهد شد. برای فعال‌سازی آن، گزینه `lastUpdated` را به پیکربندی خود اضافه کنید. + +::: tip نکته +برای دیدن زمان به‌روزرسانی، باید فایل Markdown را commit کنید. +::: + +## پیکربندی سطح سایت {#site-level-config} + +```js +export default { + lastUpdated: true +} +``` + +## پیکربندی Frontmatter {#frontmatter-config} + +می‌توانید این امکان را برای هر صفحه با استفاده از گزینه `lastUpdated` در frontmatter غیرفعال کنید: + +```yaml +--- +lastUpdated: false +--- +``` + +همچنین به [پیکربندی پیش‌فرض: آخرین بروزرسانی](./default-theme-config#lastupdated) مراجعه کنید تا اطلاعات بیشتری دریافت کنید. هر مقدار حقیقی در سطح تم از ویژگی را فعال خواهد کرد مگر آنکه به صورت صریح در سطح سایت یا صفحه غیرفعال شود. diff --git a/docs/fa/reference/default-theme-layout.md b/docs/fa/reference/default-theme-layout.md new file mode 100644 index 00000000..def9bea5 --- /dev/null +++ b/docs/fa/reference/default-theme-layout.md @@ -0,0 +1,62 @@ +# طرح بندی {#layout} + +می‌توانید طرح صفحه را با تنظیم گزینه `layout` در [frontmatter](./frontmatter-config) صفحه انتخاب کنید. سه گزینه طرح وجود دارد، `doc`، `page` و `home`. اگر هیچ چیز مشخص نشده باشد، صفحه به عنوان صفحه `doc` در نظر گرفته می‌شود. + +```yaml +--- +layout: doc +--- +``` + +## طرح Doc {#doc-layout} + +گزینه `doc` طرح پیش‌فرض است و تمام محتوای Markdown را به "نمایشگاه" درست می‌کند. این با پوشاندن کل محتوا در داخل کلاس css `vp-doc` کار می‌کند و استایل‌های لازم را بر روی عناصر زیرش اعمال می‌کند. + +تقریباً همه عناصر عمومی مانند `p` یا `h2` استایل‌های خاصی دارند. بنابراین، به یاد داشته باشید که اگر HTML سفارشی‌ای درون محتوای Markdown اضافه کنید، این استایل‌ها روی آن‌ها هم اعمال خواهند شد. + +این طرح ویژگی‌های خاص مستندسازی زیر را فراهم می‌کند. این ویژگی‌ها فقط در این طرح فعال هستند. + +- پیوند ویرایش +- پیوند قبلی و بعدی +- ساختار +- [تبلیغات Carbon](./default-theme-carbon-ads) + +## طرح Page {#page-layout} + +گزینه `page` به عنوان "صفحه خالی" در نظر گرفته می‌شود. Markdown همچنان تجزیه و تحلیل می‌شود و تمامی [توسعه‌های Markdown](../guide/markdown) به عنوان طرح `doc` کار می‌کنند، اما هیچ استایل پیش‌فرضی به آن اعمال نمی‌شود. + +طرح صفحه به شما این امکان را می‌دهد که همه چیز را به دلخواه خود شخصی‌سازی کنید بدون این که طرح ویت‌پرس بر روی مارک‌آپ تاثیر بگذارد. این کار بسیار مفید است زمانی که می‌خواهید صفحه سفارشی خود را ایجاد کنید. + +توجه داشته باشید که حتی در این طرح، نوار کناری نیز نمایش داده می‌شود اگر صفحه دارای پیکربندی نوار کناری مطابق باشد. + +## طرح Home {#home-layout} + +گزینه `home` صفحه "خانه" قالب‌بندی می‌کند. در این طرح، می‌توانید گزینه‌های اضافی مانند `hero` و `features` را برای دلخواه‌سازی محتوا تنظیم کنید. لطفاً [صفحه پیش‌فرض: صفحه خانه](./default-theme-home-page) را برای اطلاعات بیشتر مشاهده کنید. + +## بدون طرح {#no-layout} + +اگر نمی‌خواهید هیچ طرحی داشته باشید، می‌توانید با گذراندن `layout: false` از frontmatter، از این گزینه استفاده کنید. این گزینه مفید است اگر صفحهٔ نخستی کاملاً قابل تنظیم (بدون هیچ نوار کناری، نوار ناوبری یا پاورقی به صورت پیش‌فرض) را می‌خواهید. + +## طرح سفارشی {#custom-layout} + +همچنین می‌توانید از یک طرح سفارشی استفاده کنید: + +```md +--- +layout: foo +--- +``` + +این دستور به دنبال یک کامپوننت به نام `foo` ثبت شده در محیط است. به عنوان مثال، می‌توانید کامپوننت خود را به صورت گلوبال در `.vitepress/theme/index.ts` ثبت کنید: + +```ts +import DefaultTheme from 'vitepress/theme' +import Foo from './Foo.vue' + +export default { + extends: DefaultTheme, + enhanceApp({ app }) { + app.component('foo', Foo) + } +} +``` diff --git a/docs/fa/reference/default-theme-nav.md b/docs/fa/reference/default-theme-nav.md new file mode 100644 index 00000000..eafc5b53 --- /dev/null +++ b/docs/fa/reference/default-theme-nav.md @@ -0,0 +1,215 @@ +# ناوبری {#nav} + +ناوبری نوار ناوبری است که در بالای صفحه نمایش داده می‌شود و شامل عنوان سایت، لینک‌های منوی جهانی، و غیره می‌باشد. + +## عنوان سایت و لوگو {#site-title-and-logo} + +به طور پیش‌فرض، ناو نام سایت را با ارجاع به مقدار [`config.title`](./site-config#title) نمایش می‌دهد. اگر می‌خواهید تغییر دهید که چه چیزی در ناو نمایش داده شود، می‌توانید متن سفارشی را در گزینه `themeConfig.siteTitle` تعریف کنید. + +```js +export default { + themeConfig: { + siteTitle: 'عنوان سفارشی من' + } +} +``` + +اگر برای سایت خود لوگو دارید، می‌توانید آن را با ارسال مسیر تصویر نمایش دهید. شما باید لوگو را در دایرکتوری `public` قرار داده و مسیر مطلق آن را تعریف کنید. + +```js +export default { + themeConfig: { + logo: '/my-logo.svg' + } +} +``` + +هنگام افزودن یک لوگو، آن به همراه عنوان سایت نمایش داده می‌شود. اگر لوگوی شما همه چیزی است که نیاز دارید و اگر می‌خواهید متن عنوان سایت را پنهان کنید، گزینه `siteTitle` را برابر با `false` قرار دهید. + +```js +export default { + themeConfig: { + logo: '/my-logo.svg', + siteTitle: false + } +} +``` + +همچنین می‌توانید به عنوان لوگو یک شیء را نیز ارسال کنید اگر می‌خواهید ویژگی `alt` را اضافه کنید یا آن را بر اساس حالت تاریک / روشن سفارشی‌سازی کنید. برای جزئیات بیشتر به [`themeConfig.logo`](./default-theme-config#logo) مراجعه کنید. + +## لینک‌های ناوبری {#navigation-links} + +شما می‌توانید گزینه `themeConfig.nav` را تعریف کنید تا لینک‌ها را به ناوبری خود اضافه کنید. + +```js +export default { + themeConfig: { + nav: [ + { text: 'راهنما', link: '/guide' }, + { text: 'پیکربندی', link: '/config' }, + { text: 'تغییرات', link: 'https://github.com/...' } + ] + } +} +``` + +`text` متن واقعی است که در ناوبری نمایش داده می‌شود و `link` لینکی است که هنگام کلیک بر روی متن به آن ناوبری می‌شود. برای لینک، مسیر را به صورت واقعی بدون پیشوند `.md` تنظیم کنید و همیشه با `/` شروع کنید. + +لینک‌های ناوبری همچنین می‌توانند منوهای کشویی باشند. برای این کار، کلید `items` را در گزینه لینک تنظیم کنید. + +```js +export default { + themeConfig: { + nav: [ + { text: 'راهنما', link: '/guide' }, + { + text: 'منوی کشویی', + items: [ + { text: 'مورد الف', link: '/item-1' }, + { text: 'مورد ب', link: '/item-2' }, + { text: 'مورد ج', link: '/item-3' } + ] + } + ] + } +} +``` + +لطفا توجه داشته باشید که عنوان منوی کشویی (`منوی کشویی` در مثال بالا) نمی‌تواند خاصیت `link` داشته باشد زیرا این دکمه برای باز کردن صفحه گفتگوی کشویی می‌شود. + +همچنین می‌توانید بخش‌هایی را نیز به موارد منوی کشویی با ارسال موارد بیشتر تو در تو اضافه کنید. + +```js +export default { + themeConfig: { + nav: [ + { text: 'راهنما', link: '/guide' }, + { + text: 'منوی کشویی', + items: [ + { + // عنوان بخش + text: 'عنوان بخش A', + items: [ + { text: 'آیتم A بخش A', link: '...' }, + { text: 'آیتم B بخش B', link: '...' } + ] + } + ] + }, + { + text: 'منوی کشویی', + items: [ + { + // شما همچنین می‌توانید عنوان را حذف کنید. + items: [ + { text: 'آیتم A بخش A', link: '...' }, + { text: 'آیتم B بخش B', link: '...' } + ] + } + ] + } + ] + } +} +``` + +### سفارشی‌سازی وضعیت "فعال" لینک {#customize-link-s-active-state} + +موارد منوی ناوبری زمانی که صفحه فعلی زیر مسیر مطابقت دارد، مشخص می‌شوند. اگر می‌خواهید مسیر مطابقت را سفارشی کنید، ویژگی `activeMatch` و regex را به عنوان مقدار رشته تعریف کنید. + +```js +export default { + themeConfig: { + nav: [ + // این لینک وضعیت فعال را در زمانی که کاربر در مسیر `/config/` است، دریافت می‌کند. + { + text: 'راهنما', + link: '/guide', + activeMatch: '/config/' + } + ] + } +} +``` + +::: warning هشدار +`activeMatch` انتظار می‌رود که به عنوان یک رشته regex باشد، اما شما باید آن را به عنوان یک رشته تعریف کنید. ما نمی‌توانیم از شیء RegExp واقعی اینجا استفاده کنیم زیرا در زمان ساخت غیر قابل سریالیز کردن است. +::: + +### سفارشی‌سازی ویژگی‌های "target" و "rel" لینک {#customize-link-s-target-and-rel-attributes} + +به طور پیش‌فرض، ویت‌پرس به طور خودکار ویژگی‌های + +`target` و `rel` را بر اساس اینکه لینک یک لینک خارجی است یا خیر، تعیین می‌کند. اما اگر می‌خواهید، شما همچنین می‌توانید آن‌ها را سفارشی کنید. + +```js +export default { + themeConfig: { + nav: [ + { + text: 'کالای معاملاتی', + link: 'https://www.thegithubshop.com/', + target: '_self', + rel: 'sponsored' + } + ] + } +} +``` + +## لینک‌های اجتماعی {#social-links} + +به [`socialLinks`](./default-theme-config#sociallinks) مراجعه کنید. + +## اجزای سفارشی + +می‌توانید اجزای سفارشی را در نوار ناوبری با استفاده از گزینه `component` اضافه کنید. کلید `component` باید نام مؤلفه Vue باشد و باید به صورت جهانی با استفاده از [Theme.enhanceApp](../guide/custom-theme#theme-interface) ثبت شود. + +```js [.vitepress/config.js] +export default { + themeConfig: { + nav: [ + { + text: 'منوی من', + items: [ + { + component: 'MyCustomComponent', + // پارامترهای اختیاری برای ارسال به مؤلفه + props: { + title: 'مؤلفه سفارشی من' + } + } + ] + }, + { + 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) + } +} +``` + +اجزای شما در نوار ناوبری نمایش داده خواهد شد. ویت‌پرس ویژگی‌های اضافی زیر را به مؤلفه ارائه می‌دهد: + +- `screenMenu`: یک بولین اختیاری که نشان می‌دهد آیا مؤلفه در منوی ناوبری تلفن همراه است یا خیر + +می‌توانید یک نمونه را در آزمایش‌های e2e [اینجا](https://github.com/vuejs/vitepress/tree/main/__tests__/e2e/.vitepress) بررسی کنید. diff --git a/docs/fa/reference/default-theme-prev-next-links.md b/docs/fa/reference/default-theme-prev-next-links.md new file mode 100644 index 00000000..e17358cc --- /dev/null +++ b/docs/fa/reference/default-theme-prev-next-links.md @@ -0,0 +1,43 @@ +# پیوندهای قبلی و بعدی {#prev-next-links} + +شما می‌توانید متن و پیوند برای صفحات قبلی و بعدی را سفارشی‌سازی کنید (نمایش داده شده در پایین صفحه مستندات). این مفید است اگر می‌خواهید متن دیگری را در این قسمت نمایش دهید که با آنچه در نوار کناری دارید، متفاوت باشد. همچنین، ممکن است مفید باشد که فوتر را غیرفعال کنید یا به یک صفحه لینک کنید که در نوار کناری شما وجود ندارد. + +## prev + +- نوع: `string | false | { text?: string; link?: string }` + +- جزئیات: + + مشخص می‌کند متن/لینکی که برای لینک به صفحه قبلی نمایش داده خواهد شد. اگر این را در frontmatter تنظیم نکنید، متن/لینک از تنظیمات نوار کناری استخراج خواهد شد. + +- مثال‌ها: + + - برای فقط سفارشی‌سازی متن: + + ```yaml + --- + prev: 'شروع کنید | مارک‌داون' + --- + ``` + + - برای سفارشی‌سازی هم متن و هم لینک: + + ```yaml + --- + prev: + text: 'مارک‌داون' + link: '/guide/markdown' + --- + ``` + + - برای مخفی کردن صفحه قبلی: + + ```yaml + --- + prev: false + --- + ``` + +## next + +مشابه `prev` اما برای صفحه بعدی. diff --git a/docs/fa/reference/default-theme-search.md b/docs/fa/reference/default-theme-search.md new file mode 100644 index 00000000..2694a291 --- /dev/null +++ b/docs/fa/reference/default-theme-search.md @@ -0,0 +1,379 @@ +--- +outline: deep +--- + +# جستجو {#search} + +## جستجوی محلی {#local-search} + +ویت‌پرس از جستجوی متن کامل نامتقارن با استفاده از یک فهرست در مرورگر با تشکر از [minisearch](https://github.com/lucaong/minisearch/) پشتیبانی می‌کند. برای فعال‌سازی این ویژگی، کافی است گزینه `themeConfig.search.provider` را به `'local'` در فایل `.vitepress/config.ts` خود تنظیم کنید: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local' + } + } +}) +``` + +نمونه نتیجه: + +![تصویر نمایشی از مودال جستجو](/search.png) + +همچنین، می‌توانید از [Algolia DocSearch](#algolia-search) یا برخی افزونه‌های جامعه‌ای مانند یا استفاده کنید. + +### بین‌المللی‌سازی {#local-search-i18n} + +می‌توانید با استفاده از تنظیماتی مانند این برای جستجوی چندزبانه استفاده کنید: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + locales: { + zh: { // اگر می‌خواهید زبان پیش‌فرض را ترجمه کنید، این را به `root` تغییر دهید + translations: { + button: { + buttonText: 'جستجو', + buttonAriaLabel: 'جستجو' + }, + modal: { + displayDetails: 'نمایش جزئیات', + resetButtonTitle: 'بازنشانی جستجو', + backButtonTitle: 'بستن جستجو', + noResultsText: 'نتیجه‌ای یافت نشد', + footer: { + selectText: 'انتخاب', + selectKeyAriaLabel: 'ورود', + navigateText: 'پیمایش', + navigateUpKeyAriaLabel: 'کلید بالا', + navigateDownKeyAriaLabel: 'کلید پایین', + closeText: 'بستن', + closeKeyAriaLabel: 'esc' + } + } + } + } + } + } + } + } +}) +``` + +### گزینه‌های miniSearch {#minisearch-options} + +می‌توانید MiniSearch را به این صورت پیکربندی کنید: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + miniSearch: { + /** + * @type {Pick} + */ + options: { + /* ... */ + }, + /** + * @type {import('minisearch').SearchOptions} + * @default + * { fuzzy: 0.2, prefix: true, boost: { title: 4, text: 2, titles: 1 } } + */ + searchOptions: { + /* ... */ + } + } + } + } + } +}) +``` + +برای کسب اطلاعات بیشتر به [اسناد MiniSearch](https://lucaong.github.io/minisearch/classes/MiniSearch.MiniSearch.html) مراجعه کنید. + +### سفارشی‌سازی رندر محتوا {#custom-content-renderer} + +می‌توانید تابع استفاده شده برای رندر محتوای Markdown قبل از فهرست‌بندی آن را سفارشی‌سازی کنید: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + /** + * @param {string} src + * @param {import('vitepress').MarkdownEnv} env + * @param {import('markdown-it-async')} md + */ + async _render(src, env, md) { + // بازگشت رشته HTML + } + } + } + } +}) +``` + +این تابع از داده‌های سایت سمت کلاینت پاک خواهد شد، بنابراین شما می‌توانید از API‌های Node.js در آن استفاده کنید. + +#### مثال: استثنای صفحات از جستجو {#example-excluding-pages-from-search} + +می‌توانید با اضافه کردن `search: false` به frontmatter صفحه، صفحات را از جستجو استثنا دهید. به طور جایگزین: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + async _render(src, env, md) { + const html = await md.renderAsync(src, env) + if (env.frontmatter?.search === false) return '' + if (env.relativePath.startsWith('some/path')) return '' + return html + } + } + } + } +}) +``` + +::: warning توجه +در صورت ارائه تابع `_render` سفارشی، باید خودتان بررسی کنید که آیا frontmatter `search: false` را مدیریت می‌کند یا خیر. همچنین، شی env قبل از فراخوانی `md.renderAsync` کاملاً پر نمی‌شود، بنابراین هر بررسی‌ای روی ویژگی‌های اختیاری env مانند `frontmatter` باید بعد از آن انجام شود. +::: + +#### مثال: تبدیل محتوا - افزودن لینک‌های صفحه {#example-transforming-content-adding-anchors} + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + async _render(src, env, md) { + const html = await md.renderAsync(src, env) + if (env.frontmatter?.title) + return await md.renderAsync(`# ${env.frontmatter.title}`) + html + return html + } + } + } + } +}) +``` + +## جستجوی Algolia {#algolia-search} + +ویت‌پرس از جستجو در سایت مستندات شما با استفاده از [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch) پشتیبانی می‌کند. به راهنمای شروع کار آن‌ها مراجعه کنید. در فایل `.vitepress/config.ts` شما نیاز دارید که حداقل موارد زیر را فراهم کنید تا کار کند: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'algolia', + options: { + appId: '...', + apiKey: '...', + indexName: '...' + } + } + } +}) +``` + +### بین‌المللی‌سازی {#algolia-search-i18n} + +می‌توانید با استفاده از تنظیماتی مانند این برای جستجوی چندزبانه استفاده کنید: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: + + { + search: { + provider: 'algolia', + options: { + appId: '...', + apiKey: '...', + indexName: '...', + locales: { + zh: { + placeholder: 'جستجو در مستندات', + translations: { + button: { + buttonText: 'جستجو در مستندات', + buttonAriaLabel: 'جستجو در مستندات' + }, + modal: { + searchBox: { + resetButtonTitle: 'پاک کردن شرایط جستجو', + resetButtonAriaLabel: 'پاک کردن شرایط جستجو', + cancelButtonText: 'لغو', + cancelButtonAriaLabel: 'لغو' + }, + startScreen: { + recentSearchesTitle: 'تاریخچه جستجو', + noRecentSearchesText: 'هیچ تاریخچه جستجویی وجود ندارد', + saveRecentSearchButtonTitle: 'ذخیره در تاریخچه جستجو', + removeRecentSearchButtonTitle: 'حذف از تاریخچه جستجو' + }, + errorScreen: { + titleText: 'نمایش نتایج امکان‌پذیر نیست', + helpText: 'شما ممکن است نیاز به بررسی اتصال اینترنت خود داشته باشید' + }, + footer: { + selectText: 'انتخاب', + navigateText: 'جابجایی', + closeText: 'بستن', + searchByText: 'جستجو توسط' + }, + noResultsScreen: { + noResultsText: 'نتیجه‌ای پیدا نشد', + suggestedQueryText: 'می‌توانید امتحان کنید', + reportMissingResultsText: 'فکر می‌کنید باید نتایجی وجود داشته باشد؟', + reportMissingResultsLinkText: 'برای بازخورد کلیک کنید' + } + } + } + } + } + } + } + } +}) +``` + +این [گزینه‌ها](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts) می‌توانند بازنویسی شوند. برای یادگیری بیشتر درباره آن‌ها به اسناد رسمی Algolia مراجعه کنید. + +### پیکربندی Crawler {#crawler-config} + +در اینجا یک پیکربندی نمونه بر اساس آنچه که این سایت استفاده می‌کند آمده است: + +```ts +new Crawler({ + appId: '...', + apiKey: '...', + rateLimit: 8, + startUrls: ['https://vitepress.dev/'], + renderJavaScript: false, + sitemaps: [], + exclusionPatterns: [], + ignoreCanonicalTo: false, + discoveryPatterns: ['https://vitepress.dev/**'], + schedule: 'at 05:10 on Saturday', + actions: [ + { + indexName: 'vitepress', + pathsToMatch: ['https://vitepress.dev/**'], + recordExtractor: ({ $, helpers }) => { + return helpers.docsearch({ + recordProps: { + lvl1: '.content h1', + content: '.content p, .content li', + lvl0: { + selectors: '', + defaultValue: 'Documentation' + }, + lvl2: '.content h2', + lvl3: '.content h3', + lvl4: '.content h4', + lvl5: '.content h5' + }, + indexHeadings: true + }) + } + } + ], + initialIndexSettings: { + vitepress: { + attributesForFaceting: ['type', 'lang'], + attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'], + attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'], + attributesToSnippet: ['content:10'], + camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'], + searchableAttributes: [ + 'unordered(hierarchy_radio_camel.lvl0)', + 'unordered(hierarchy_radio.lvl0)', + 'unordered(hierarchy_radio_camel.lvl1)', + 'unordered(hierarchy_radio.lvl1)', + 'unordered(hierarchy_radio_camel.lvl2)', + 'unordered(hierarchy_radio.lvl2)', + 'unordered(hierarchy_radio_camel.lvl3)', + 'unordered(hierarchy_radio.lvl3)', + 'unordered(hierarchy_radio_camel.lvl4)', + 'unordered(hierarchy_radio.lvl4)', + 'unordered(hierarchy_radio_camel.lvl5)', + 'unordered(hierarchy_radio.lvl5)', + 'unordered(hierarchy_radio_camel.lvl6)', + 'unordered(hierarchy_radio.lvl6)', + 'unordered(hierarchy_camel.lvl0)', + 'unordered(hierarchy.lvl0)', + 'unordered(hierarchy_camel.lvl1)', + 'unordered(hierarchy.lvl1)', + 'unordered(hierarchy_camel.lvl2)', + 'unordered(hierarchy.lvl2)', + 'unordered(hierarchy_camel.lvl3)', + 'unordered(hierarchy.lvl3)', + 'unordered(hierarchy_camel.lvl4)', + 'unordered(hierarchy.lvl4)', + 'unordered(hierarchy_camel.lvl5)', + 'unordered(hierarchy.lvl5)', + 'unordered(hierarchy_camel.lvl6)', + 'unordered(hierarchy.lvl6)', + 'content' + ], + distinct: true, + attributeForDistinct: 'url', + customRanking: [ + 'desc(weight.pageRank)', + 'desc(weight.level)', + 'asc(weight.position)' + ], + ranking: [ + 'words', + 'filters', + 'typo', + 'attribute', + 'proximity', + 'exact', + 'custom' + ], + highlightPreTag: '', + highlightPostTag: '', + minWordSizefor1Typo: 3, + minWordSizefor2Typos: 7, + allowTyposOnNumericTokens: false, + minProximity: 1, + ignorePlurals: true, + advancedSyntax: true, + attributeCriteriaComputedByMinProximity: true, + removeWordsIfNoResults: 'allOptional' + } + } +}) +``` diff --git a/docs/fa/reference/default-theme-sidebar.md b/docs/fa/reference/default-theme-sidebar.md new file mode 100644 index 00000000..96433c2d --- /dev/null +++ b/docs/fa/reference/default-theme-sidebar.md @@ -0,0 +1,180 @@ +# نوار کناری {#sidebar} + +نوار کناری بلوک اصلی ناوبری برای مستندات شما است. شما می‌توانید منوی نوار کناری را در [`themeConfig.sidebar`](./default-theme-config#sidebar) پیکربندی کنید. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'راهنما', + items: [ + { text: 'مقدمه', link: '/introduction' }, + { text: 'شروع کردن', link: '/getting-started' }, + ... + ] + } + ] + } +} +``` + +## مبانی {#the-basics} + +ساده‌ترین فرم منوی نوار کناری ارسال یک آرایه تکی از لینک‌هاست. آیتم سطح اول "بخش" نوار کناری را تعریف می‌کند. باید شامل `text` باشد که عنوان بخش است و `items` که لینک‌های واقعی ناوبری هستند. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'عنوان بخش A', + items: [ + { text: 'آیتم A', link: '/item-a' }, + { text: 'آیتم B', link: '/item-b' }, + ... + ] + }, + { + text: 'عنوان بخش B', + items: [ + { text: 'آیتم C', link: '/item-c' }, + { text: 'آیتم D', link: '/item-d' }, + ... + ] + } + ] + } +} +``` + +هر `link` باید مسیر به فایل واقعی را با `/` آغاز کند. اگر شما `/` را به انتهای لینک اضافه کنید، صفحه `index.md` دایرکتوری متناظر را نمایش می‌دهد. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'راهنما', + items: [ + // این صفحه `/guide/index.md` را نمایش می‌دهد. + { text: 'مقدمه', link: '/guide/' } + ] + } + ] + } +} +``` + +شما می‌توانید آیتم‌های نوار کناری را تا عمق ۶ سطح تعویض کنید که از سطح ریشه شمارش می‌شود. توجه داشته باشید که عمق بیشتر از ۶ سطح از آیتم‌های تو در تو نادیده گرفته می‌شود و در نوار کناری نمایش داده نمی‌شود. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'سطح ۱', + items: [ + { + text: 'سطح ۲', + items: [ + { + text: 'سطح ۳', + items: [ + ... + ] + } + ] + } + ] + } + ] + } +} +``` + +## نوارهای کناری چندگانه {#multiple-sidebars} + +می‌توانید بسته به مسیر صفحه، نوار کناری مختلفی را نمایش دهید. به عنوان مثال، همانطور که در این سایت نشان داده شده است، ممکن است بخواهید برای مستندات خود بخش‌های جداگانه مانند صفحه "راهنما" و صفحه "پیکربندی" را ایجاد کنید. + +برای این کار، ابتدا صفحات خود را در دایرکتوری‌های مختلف برای هر بخش مورد نظر خود سازماندهی کنید: + +``` +. +├─ guide/ +│ ├─ index.md +│ ├─ one.md +│ └─ two.md +└─ config/ + ├─ index.md + ├─ three.md + └─ four.md +``` + +سپس، پیکربندی خود را برای تعریف نوار کناری برای هر بخش تعیین کنید. در این موارد، شما باید به جای یک آرایه، یک شیء را ارسال کنید. + +```js +export default { + themeConfig: { + sidebar: { + // این نوار کناری نمایش داده می‌شود زمانی که کاربر در دایرکتوری `guide` است. + '/guide/': [ + { + text: 'راهنما', + items: [ + { text: 'فهرست', link: '/guide/' }, + { text: 'یک', link: '/guide/one' }, + { text: 'دو', link: '/guide/two' } + ] + } + ], + + // این نوار کناری نمایش داده می‌شود زمانی که کاربر در دایرکتوری `config` است. + '/config/': [ + { + text: 'پیکربندی', + items: [ + { text: 'فهرست', link: '/config/' }, + { text: 'سه', link: '/config/three' }, + { text: 'چهار', link: '/config/four' } + ] + } + ] + } + } +} +``` + +## گروه‌های نوار کناری قابل جمع و جور {#collapsible-sidebar-groups} + +با اضافه کردن گزینه `collapsed` به گروه نوار کناری، دکمه جداگانه‌ای برای پنهان کردن/نمایش هر بخش نمایش داده می‌شود. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'عنوان بخش A', + collapsed: false, + items: [...] + } + ] + } +} +``` + +تمام بخش‌ها به طور پیش‌فرض "باز" هستند. اگر می‌خواهید آن‌ها را در بارگذاری اولیه صفحه "بسته" کنید، گزینه `collapsed` را به `true` تنظیم کنید. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'عنوان بخش A', + collapsed: true, + items: [...] + } + ] + } +} +``` diff --git a/docs/fa/reference/default-theme-team-page.md b/docs/fa/reference/default-theme-team-page.md new file mode 100644 index 00000000..57fc2814 --- /dev/null +++ b/docs/fa/reference/default-theme-team-page.md @@ -0,0 +1,253 @@ + + +# صفحه تیم {#team-page} + +اگر می‌خواهید تیم خود را معرفی کنید، می‌توانید از کامپوننت‌های تیم برای ساخت صفحه تیم استفاده کنید. دو راه برای استفاده از این کامپوننت‌ها وجود دارد. یکی اینکه آنها را در صفحه مستندات قرار دهید و دیگری اینکه یک صفحه کامل تیم ایجاد کنید. + +## نمایش اعضای تیم در یک صفحه {#show-team-members-in-a-page} + +می‌توانید از کامپوننت `` که از `vitepress/theme` قابل دسترسی است، برای نمایش لیست اعضای تیم در هر صفحه‌ای استفاده کنید. + +```html + + +# تیم ما + +با سلام به تیم فوق‌العاده‌ی ما خوش آمدید. + + +``` + +بالا به صورت عنصری با شکل کارتی اعضای تیم را نمایش می‌دهد. باید به شکل زیر نمایش داده شود. + + + +کامپوننت `` دارای دو اندازه مختلف، `small` و `medium` است. معمولاً اندازه `small` برای استفاده در صفحات مستندات مناسب‌تر است. همچنین می‌توانید ویژگی‌های بیشتری برای هر عضو اضافه کنید مانند "توضیحات" یا "دکمه حامی". جهت کسب اطلاعات بیشتر به [``](#vpteammembers) مراجعه کنید. + +قرار دادن اعضای تیم در صفحه مستندات برای تیم‌های کوچک مناسب است که ایجاد یک صفحه کامل تیم ممکن است بیش از حد باشد یا معرفی اعضا به عنوان مرجع در زمینه مستندات. + +اگر تعداد اعضا بسیار زیاد است یا به سادگی می‌خواهید بیشتر فضا برای نمایش اعضای تیم داشته باشید، در نظر بگیرید [ایجاد یک صفحه کامل تیم](#create-a-full-team-page). + +## ایجاد یک صفحه کامل تیم {#create-a-full-team-page} + +بجای اضافه کردن اعضای تیم به صفحه مستندات، می‌توانید یک صفحه کامل تیم را ایجاد کنید، مشابه اینکه چگونه می‌توانید یک [صفحه خانگی سفارشی](./default-theme-home-page) ایجاد کنید. + +برای ایجاد یک صفحه تیم، ابتدا یک فایل md جدید بسازید. نام فایل مهم نیست، اما در اینجا آن را `team.md` می‌نامیم. در این فایل، گزینه `layout: page` را در فرانت‌ماتر تنظیم کنید، سپس می‌توانید ساختار صفحه خود را با استفاده از کامپوننت‌های `TeamPage` ایجاد کنید. + +```html +--- +layout: page +--- + + + + + + + + + +``` + +در ایجاد یک صفحه کامل تیم، به یاد داشته باشید که همهٔ کامپوننت‌ها را با کامپوننت `` بپوشانید. این کامپوننت تضمین می‌کند که همهٔ کامپوننت‌های مرتبط با تیم در ساختار طراحی مناسبی مانند فضاهای خالی قرار می‌گیرند. + +کامپوننت `` بخش عنوان صفحه را اضافه می‌کند. عنوان به عنوان `

` نمایش داده می‌شود. از اسلات‌های `#title` و `#lead` برای مستندسازی در مورد تیم خود استفاده کنید. + +`` به عنوان زمانی که در یک صفحه مستند استفاده می‌شود، کار می‌کند. این لیست اعضا را نمایش می‌دهد. + +### اضافه کردن بخش‌ها برای تقسیم اعضای تیم {#add-sections-to-divide-team-members} + +می‌توانید بخش‌ها را به صفحه تیم اضافه کنید. به عنوان مثال، ممکن است اعضای مختلف تیمی مانند اعضای تیم اصلی و شرکای اجتماعی داشته باشید. شما می‌توانید این اعضا را به بخش‌ها تقسیم کنید تا نقش هر گروه بهتر توضیح داده شود. + +برای این کار، کامپوننت `` را به فایل `team.md` اضافه کنید که قبلاً ایجاد کردیم. + +```html +--- +layout: page +--- + + + + + + + + + + + + + + +``` + +کامپوننت `` می‌تواند همچون کامپوننت `VPTeamPageTitle` دارای اسلات‌های `#title` و `#lead` باشد و همچنین اسلات `#members` را برای نمایش اعضای تیم پذیرفته است. + +به یاد داشته باشید که کامپوننت `` را درون اسلات `#members` قرار دهید. + +## `` {#vpteammembers} + +کامپوننت `` لیست داده‌شده از اعضا را نمایش می‌دهد. + +```html + +``` + +```ts +interface Props { + // اندازه هر عضو. پیش‌فرض به `medium`. + size?: 'small' | 'medium' + + // لیست اعضا برای نمایش. + members: TeamMember[] +} + +interface TeamMember { + // تصویر آواتار برای عضو. + avatar: string + + // نام عضو. + name: string + + // عنوانی که زیر نام عضو نمایش داده خواهد شد. + // برای مثال، توسعه‌دهنده، مهندس نرم‌افزار و غیره. + title?: string + + // سازمانی که عضو به آن تعلق دارد. + org?: string + + // پیوند URL برای سازمان. + orgLink?: string + + // توضیحات برای عضو. + desc?: string + + // پیوندهای اجتماعی. برای مثال، GitHub، Twitter و غیره. می‌توانید شیء پیوندهای اجتماعی را در اینجا ارسال کنید. + // مشاهده: https://vitepress.dev/reference/default-theme-config.html#sociallinks + links?: SocialLink[] + + // URL برای صفحه حامی برای عضو. + sponsor?: string + + // متن برای لینک حامی. پیش‌فرض به 'حمایت‌کننده'. + actionText?: string +} +``` + +## `` {#vpteampage} + +کامپوننت ریشه هنگام ایجاد یک صفحه کامل تیم. فقط یک اسلات را قبول می‌کند. این همه کامپوننت‌های مربوط به تیم را استایل می‌کند. + +## `` {#vpteampagetitle} + +بخش "عنوان" صفحه را اضافه می‌کند. بهترین استفاده را در ابتدایی‌ترین جای زیر `` داشته باشد. این اسلات‌های `#title` و `#lead` را قبول می‌کند. + +```html + + + + + + +``` + +## `` {#vpteampagesection} + +یک "بخش" را درون صفحه تیم ایجاد می‌کند. اسلات‌های `#title`، `#lead` و `#members` را قبول می‌کند. می‌توانید هر تعداد بخش را درون `` اضافه کنید. + +```html + + ... + + + + + + +``` diff --git a/docs/fa/reference/frontmatter-config.md b/docs/fa/reference/frontmatter-config.md new file mode 100644 index 00000000..01b0b169 --- /dev/null +++ b/docs/fa/reference/frontmatter-config.md @@ -0,0 +1,223 @@ +--- +outline: deep +--- + +# تنظیمات Frontmatter {#frontmatter-config} + +Frontmatter امکان پیکربندی بر اساس صفحه را فراهم می‌کند. در هر فایل markdown، شما می‌توانید از تنظیمات frontmatter برای بازنویسی تنظیمات سطح سایت یا تم استفاده کنید. همچنین، تنظیماتی وجود دارند که فقط می‌توانید آن‌ها را در frontmatter تعریف کنید. + +نمونه استفاده: + +```md +--- +title: مستندات با ویت‌پرس +editLink: true +--- +``` + +شما می‌توانید به داده‌های frontmatter از طریق `$frontmatter` در بیانیه‌های Vue دسترسی داشته باشید: + +```md +{{ $frontmatter.title }} +``` + +## title + +- نوع: `string` + +عنوان صفحه. همانطور که در [config.title](./site-config#title) است، این تنظیمات سطح سایت را بازنویسی می‌کند. + +```yaml +--- +title: ویت‌پرس +--- +``` + +## titleTemplate + +- نوع: `string | boolean` + +پسوند برای عنوان. همانطور که در [config.titleTemplate](./site-config#titletemplate) است، این تنظیمات سطح سایت را بازنویسی می‌کند. + +```yaml +--- +title: ویت‌پرس +titleTemplate: Vite & Vue powered static site generator +--- +``` + +## description + +- نوع: `string` + +توضیحات صفحه. همانطور که در [config.description](./site-config#description) است، این تنظیمات سطح سایت را بازنویسی می‌کند. + +```yaml +--- +description: ویت‌پرس +--- +``` + +## head + +- نوع: `HeadConfig[]` + +تگ‌های head اضافی برای درج در صفحه فعلی. پس از تگ‌های head تزریق شده توسط تنظیمات سطح سایت، این تنظیمات درج می‌شوند. + +```yaml +--- +head: + - - meta + - name: description + content: hello + - - meta + - name: keywords + content: super duper SEO +--- +``` + +```ts +type HeadConfig = + | [string, Record] + | [string, Record, string] +``` + +## فقط برای تم پیش‌فرض {#default-theme-only} + +گزینه‌های frontmatter زیر فقط زمانی قابل استفاده هستند که از تم پیش‌فرض استفاده می‌کنید. + +### layout + +- نوع: `doc | home | page` +- پیش‌فرض: `doc` + +تعیین چیدمان صفحه. + +- `doc` - این چیدمان استایل‌های مستندات پیش‌فرض را به محتوای markdown اعمال می‌کند. +- `home` - چیدمان ویژه برای "صفحه اصلی". شما می‌توانید گزینه‌های اضافی مانند `hero` و `features` را اضافه کنید تا به سرعت یک صفحه نخست زیبا ایجاد کنید. +- `page` - مشابه `doc` عمل می‌کند اما هیچ استایلی به محتوا اعمال نمی‌شود. مفید است زمانی که می‌خواهید یک صفحه کاملاً سفارشی ایجاد کنید. + +```yaml +--- +layout: doc +--- +``` + +### hero {#hero} + +تعیین محتویات بخش hero صفحه اصلی هنگامی که `layout` به `home` تنظیم شده است. جزئیات بیشتر در [تم پیش‌فرض: صفحه اصلی](./default-theme-home-page). + +### features {#features} + +تعیین مواردی که در بخش ویژگی‌ها باید نمایش داده شوند هنگامی که `layout` به `home` تنظیم شده است. جزئیات بیشتر در [تم پیش‌فرض: صفحه اصلی](./default-theme-home-page). + +### navbar + +- نوع: `boolean` +- پیش‌فرض: `true` + +آیا باید [نوار ناوبری](./default-theme-nav) نمایش داده شود یا خیر؟ + +```yaml +--- +navbar: false +--- +``` + +### sidebar + +- نوع: `boolean` +- پیش‌فرض: `true` + +آیا باید [نوار کناری](./default-theme-sidebar) نمایش داده شود یا خیر؟ + +```yaml +--- +sidebar: false +--- +``` + +### aside + +- نوع: `boolean | 'left'` +- پیش‌فرض: `true` + +تعیین مکان کامپوننت aside در چیدمان `doc`. + +- اگر این مقدار را به `false` تنظیم کنید، اجرای کانتینر aside جلوگیری می‌کند. +- اگر این مقدار را به `true` تنظیم کنید، aside به راست اجرا می‌شود. +- اگر این مقدار را به `'left'` تنظیم کنید، aside به چپ اجرا می‌شود. + +```yaml +--- +aside: false +--- +``` + +### outline + +- نوع: `number | [number, number] | 'deep' | false` +- پیش‌فرض: `2` + +سطوح سرفصل‌های مورد نمایش برای صفحه. همانطور که در [config.themeConfig.outline.level](./default-theme-config#outline) است، این مقدار سطح مجموعه سایت را بازنویسی می‌کند. + +### lastUpdated + +- نوع: `boolean | Date` +- پیش‌فرض: `true` + +آیا متن [آخرین به‌روزرسانی](./default-theme-last-updated) را در پاورقی صفحه فعلی نمایش دهد یا خیر؟ اگر تاریخ و زمان مشخص شده باشد، به جای زمان اصلاح شده git نمایش داده می‌شود. + +```yaml +--- +lastUpdated: false +--- +``` + +### editLink + +- نوع: `boolean` +- پیش‌فرض: `true` + +آیا [پیوند ویرایش](./default-theme-edit-link) را در پاورقی صفحه فعلی نمایش دهد یا خیر؟ + +```yaml +--- +editLink: false +--- +``` + +### footer + +- نوع: `boolean` +- پیش‌فرض: `true` + +آیا [پاورقی](./default-theme-footer) را + +نمایش دهد یا خیر؟ + +```yaml +--- +footer: false +--- +``` + +### pageClass + +- نوع: `string` + +افزودن نام کلاس اضافی به یک صفحه خاص. + +```yaml +--- +pageClass: custom-page-class +--- +``` + +سپس می‌توانید استایل‌های این صفحه خاص را در فایل `.vitepress/theme/custom.css` سفارشی کنید: + +```css +.custom-page-class { + /* استایل‌های مخصوص صفحه */ +} +``` diff --git a/docs/fa/reference/runtime-api.md b/docs/fa/reference/runtime-api.md new file mode 100644 index 00000000..67e076cd --- /dev/null +++ b/docs/fa/reference/runtime-api.md @@ -0,0 +1,168 @@ +# API زمان اجرا {#runtime-api} + +ویت‌پرس چندین API داخلی را ارائه می‌دهد تا به شما امکان دسترسی به داده‌های برنامه را بدهد. همچنین، ویت‌پرس با چندین کامپوننت داخلی همراه است که می‌توانید به صورت جهانی از آن‌ها استفاده کنید. + +متدهای کمکی به صورت جهانی از `vitepress` قابل وارد کردن هستند و معمولاً در کامپوننت‌های Vue سفارشی تم استفاده می‌شوند. با این حال، آن‌ها همچنین در صفحات `.md` قابل استفاده هستند زیرا فایل‌های markdown به [کامپوننت‌های فایل تکی](https://vuejs.org/guide/scaling-up/sfc.html) Vue ترجمه می‌شوند. + +متدهایی که با `use*` آغاز می‌شوند نشان می‌دهند که این یک تابع [API ترکیبی Vue 3](https://vuejs.org/guide/introduction.html#composition-api) ("Composable") است که فقط می‌تواند در `setup()` یا ` + + +``` + +## `useRoute` {#useroute} + +شیء مسیر فعلی را با این نوع برمی‌گرداند: + +```ts +interface Route { + path: string + data: PageData + component: Component | null +} +``` + +## `useRouter` {#userouter} + +نمونه راوتر ویت‌پرس را برمی‌گرداند تا بتوانید به صورت برنامه‌ریزی‌شده به صفحه دیگری ناوبری کنید. + +```ts +interface Router { + /** + * Route فعلی + */ + route: Route + /** + * به URL جدید ناوبری کنید. + */ + go: (to?: string) => Promise + /** + * قبل از تغییر مسیر فراخوانی می‌شود. برای لغو ناوبری `false` را برگردانید. + */ + onBeforeRouteChange?: (to: string) => Awaitable + /** + * قبل از بارگذاری مؤلفه صفحه فراخوانی می‌شود (پس از به‌روزرسانی وضعیت تاریخچه). برای لغو ناوبری `false` را برگردانید. + */ + onBeforePageLoad?: (to: string) => Awaitable + /** + * پس از تغییر مسیر فراخوانی می‌شود. + */ + onAfterRouteChange?: (to: string) => Awaitable +} +``` + +## `withBase` {#withbase} + +- **نوع**: `(path: string) => string` + +پایه [پیکربندی‌شده](./site-config#base) را به یک مسیر URL داده شده اضافه می‌کند. همچنین به [آدرس پایه](../guide/asset-handling#base-url) مراجعه کنید. + +## `` {#content} + +کامپوننت `` محتوای markdown را نمایش می‌دهد. مفید است [هنگام ایجاد تم شخصی شما](../guide/custom-theme). + +```vue + +``` + +## `` {#clientonly} + +کامپوننت `` فقط اسلات خود را در سمت مشتری رندر می‌کند. + +چون برنامه‌های ویت‌پرس هنگام ایجاد از سمت سرور در Node.js رندر می‌شوند، هر استفاده از Vue باید به الزامات کد یکپارچه دنیا پاسخ دهد. به طور خلاصه، اطمینان حاصل کنید که فقط در قالب hooks `beforeMount` یا `mounted` به API‌های Browser / DOM دسترسی دارید. + +اگر از کامپوننت‌هایی استفاده یا نمایش دهنده‌هایی که با SSR سازگار نیستند (مانند دستورالعمل‌های سفارشی) استفاده می‌کنید، می‌توانید آن‌ها را داخل کامپوننت `ClientOnly` قرار دهید. + +```vue-html + + + +``` + +- مرتبط: [سازگاری با SSR](../guide/ssr-compat) + +## `$frontmatter` {#frontmatter} + +در بیانیه‌های Vue، به صورت مستقیم به [داده‌های frontmatter](../guide/frontmatter) صفحه فعلی دسترسی پیدا کنید. + +```md +--- +title: سلام +--- + +# {{ $frontmatter.title }} +``` + +## `$params` {#params} + +در بیانیه‌های Vue، به صورت مستقیم به [پارامترهای مسیر دینامیک](../guide/routing#dynamic-routes) صفحه فعلی دسترسی پیدا کنید. + +```md +- نام بسته: {{ $params.pkg }} +- نسخه: {{ $params.version }} +``` diff --git a/docs/fa/reference/site-config.md b/docs/fa/reference/site-config.md new file mode 100644 index 00000000..72343ffa --- /dev/null +++ b/docs/fa/reference/site-config.md @@ -0,0 +1,726 @@ +--- +outline: deep +--- + +# تنظیمات سایت {#site-config} + +تنظیمات سایت جایی است که می‌توانید تنظیمات جهانی سایت را تعریف کنید. گزینه‌های تنظیمات برنامه شامل تنظیماتی است که برای هر سایت ویت‌پرس اعمال می‌شود، صرف نظر از اینکه از چه تمی استفاده می‌کند. برای مثال، دایرکتوری پایه یا عنوان سایت. + +## مروری کلی {#overview} + +### رفع تنظیمات {#config-resolution} + +فایل تنظیمات همیشه از `/.vitepress/config.[ext]` رفع می‌شود، جایی که `` ریشه پروژه ویت‌پرس شما است و `[ext]` یکی از پسوندهای فایل پشتیبانی شده است. تایپ‌اسکریپت به طور پیش‌فرض پشتیبانی می‌شود. پسوندهای پشتیبانی شده شامل `.js`, `.ts`, `.mjs` و `.mts` هستند. + +توصیه می‌شود از سینتکس ماژول‌های ES در فایل‌های تنظیمات استفاده کنید. فایل تنظیمات باید به طور پیش‌فرض یک شیء صادر کند: + +```ts +export default { + // گزینه‌های تنظیمات سطح برنامه + lang: 'en-US', + title: 'ویت‌پرس', + description: 'مولد سایت استاتیک توسط Vite & Vue.', + ... +} +``` + +:::details تنظیمات پویا (غیرهمزمان) + +اگر نیاز دارید به طور پویا تنظیمات را تولید کنید، می‌توانید یک تابع صادر کنید. به عنوان مثال: + +```ts +import { defineConfig } from 'vitepress' + +export default async () => { + const posts = await (await fetch('https://my-cms.com/blog-posts')).json() + + return defineConfig({ + // گزینه‌های تنظیمات سطح برنامه + lang: 'en-US', + title: 'ویت‌پرس', + description: 'مولد سایت استاتیک توسط Vite & Vue.', + + // گزینه‌های تنظیمات سطح تم + themeConfig: { + sidebar: [ + ...posts.map((post) => ({ + text: post.name, + link: `/posts/${post.name}` + })) + ] + } + }) +} +``` + +همچنین می‌توانید از `await` سطح بالا استفاده کنید. به عنوان مثال: + +```ts +import { defineConfig } from 'vitepress' + +const posts = await (await fetch('https://my-cms.com/blog-posts')).json() + +export default defineConfig({ + // گزینه‌های تنظیمات سطح برنامه + lang: 'en-US', + title: 'ویت‌پرس', + description: 'مولد سایت استاتیک توسط Vite & Vue.', + + // گزینه‌های تنظیمات سطح تم + themeConfig: { + sidebar: [ + ...posts.map((post) => ({ + text: post.name, + link: `/posts/${post.name}` + })) + ] + } +}) +``` + +::: + +### هوشمندی تنظیمات {#config-intellisense} + +استفاده از تابع `defineConfig` هوشمندی تایپ‌اسکریپت را برای گزینه‌های تنظیمات فراهم می‌کند. فرض کنید IDE شما از آن پشتیبانی می‌کند، این باید هم در جاوااسکریپت و هم تایپ‌اسکریپت کار کند. + +```js +import { defineConfig } from 'vitepress' + +export default defineConfig({ + // ... +}) +``` + +### تنظیمات تایپ‌شده تم {#typed-theme-config} + +به طور پیش‌فرض، تابع `defineConfig` انتظار دارد نوع تنظیمات تم از تم پیش‌فرض باشد: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + // نوع `DefaultTheme.Config` + } +}) +``` + +اگر از تم سفارشی استفاده می‌کنید و می‌خواهید بررسی نوع برای تنظیمات تم داشته باشید، باید به جای آن از `defineConfigWithTheme` استفاده کنید و نوع تنظیمات تم سفارشی خود را از طریق یک آرگومان جنریک منتقل کنید: + +```ts +import { defineConfigWithTheme } from 'vitepress' +import type { ThemeConfig } from 'your-theme' + +export default defineConfigWithTheme({ + themeConfig: { + // نوع `ThemeConfig` + } +}) +``` + +### تنظیمات Vite, Vue و Markdown {#vite-vue-markdown-config} + +- **Vite** + + شما می‌توانید نمونه پایه Vite را با استفاده از گزینه [vite](#vite) در تنظیمات ویت‌پرس خود پیکربندی کنید. نیازی به ایجاد فایل تنظیمات Vite جداگانه نیست. + +- **Vue** + + ویت‌پرس از قبل پلاگین رسمی Vue برای Vite ([@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue)) را شامل می‌شود. شما می‌توانید گزینه‌های آن را با استفاده از گزینه [vue](#vue) در تنظیمات ویت‌پرس خود پیکربندی کنید. + +- **Markdown** + + شما می‌توانید نمونه پایه [Markdown-It](https://github.com/markdown-it/markdown-it) را با استفاده از گزینه [markdown](#markdown) در تنظیمات ویت‌پرس خود پیکربندی کنید. + +## متاداده‌های سایت {#site-metadata} + +### عنوان {#title} + +- نوع: `string` +- پیش‌فرض: `ویت‌پرس` +- می‌تواند به ازای هر صفحه از طریق [frontmatter](./frontmatter-config#title) جایگزین شود. + +عنوان سایت. هنگامی که از تم پیش‌فرض استفاده می‌کنید، این در نوار ناوبری نمایش داده می‌شود. + +همچنین به عنوان پسوند پیش‌فرض برای تمام عناوین صفحات فردی استفاده می‌شود، مگر اینکه [`titleTemplate`](#titletemplate) تعریف شده باشد. عنوان نهایی صفحه‌ای به محتوای متنی اولین هدر `

` آن صفحه ترکیب می‌شود با `title` جهانی به عنوان پسوند. به عنوان مثال با تنظیمات زیر و محتوای صفحه: + +```ts +export default { + title: 'سایت فوق‌العاده من' +} +``` + +```md +# سلام +``` + +عنوان صفحه خواهد بود `سلام | سایت فوق‌العاده من`. + +### قالب عنوان {##titletemplate} + +- نوع: `string | boolean` +- می‌تواند به ازای هر صفحه از طریق [frontmatter](./frontmatter-config#titletemplate) جایگزین شود. + +اجازه می‌دهد پسوند عنوان هر صفحه یا کل عنوان را سفارشی کنید. به عنوان مثال: + +```ts +export default { + title: 'سایت فوق‌العاده من', + titleTemplate: 'پسوند سفارشی' +} +``` + +```md +# سلام +``` + +عنوان صفحه خواهد بود `سلام | پسوند سفارشی`. + +برای سفارشی کردن کامل نحوه نمایش عنوان، می‌توانید از نماد `:title` در `titleTemplate` استفاده کنید: + +```ts +export default { + titleTemplate: ':title - پسوند سفارشی' +} +``` + +اینجا `:title` با متن استنباط شده از اولین هدر `

` صفحه جایگزین می‌شود. عنوان صفحه مثال قبلی خواهد بود `سلام - پسوند سفارشی`. + +این گزینه می‌تواند به `false` تنظیم شود تا پسوندهای عنوان غیرفعال شوند. + +### توضیحات {#description} + +- نوع: `string` +- پیش‌فرض: `یک سایت ویت‌پرس` +- می‌تواند به ازای هر صفحه از طریق [frontmatter](./frontmatter-config#description) جایگزین شود. + +توضیحات برای سایت. این به عنوان یک تگ `` در HTML صفحه رندر خواهد شد. + +```ts +export default { + description: 'یک سایت ویت‌پرس' +} +``` + +### head + +- نوع: `HeadConfig[]` +- پیش‌فرض: `[]` +- می‌تواند به ازای هر صفحه از طریق [frontmatter](./frontmatter-config#head) افزوده شود. + +عناصر اضافی برای رندر در تگ `` در HTML صفحه. تگ‌های افزوده شده توسط کاربر قبل از بسته شدن تگ `head`، پس از تگ‌های ویت‌پرس رندر می‌شوند. + +```ts +type HeadConfig = + | [string, Record] + | [string, Record, string] +``` + +#### مثال: اضافه کردن یک favicon {#example-adding-a-favicon} + +```ts +export default { + head: [['link', { rel: 'icon', href: '/favicon.ico' }]] +} // favicon.ico را در دایرکتوری عمومی قرار دهید، اگر base تنظیم شده است، از /base/favicon.ico استفاده کنید. + +/* رندر خواهد شد: + +*/ +``` + +#### مثال: اضافه کردن فونت‌های گوگل {#example-adding-google-fonts} + +```ts +export default { + head: [ + [ + 'link', + { rel: 'preconnect', href: 'https://fonts.googleapis.com' } + ], + [ + 'link', + { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: '' } + ], + [ + 'link', + { href: 'https://fonts.googleapis.com/css2?family=Roboto&display=swap', rel: 'stylesheet' } + ] + ] +} + +/* رندر خواهد شد: + + + +*/ +``` + +#### مثال: ثبت یک سرویس ورکر {#example-registering-a-service-worker} + +```ts +export default { + head: [ + [ + 'script', + { id: 'register-sw' }, + `;(() => { + if ('serviceWorker' in navigator) { + navigator.serviceWorker.register('/sw.js') + } + })()` + ] + ] +} + +/* رندر خواهد شد + +: + +*/ +``` + +#### مثال: استفاده از گوگل آنالیتیکس {#example-using-google-analytics} + +```ts +export default { + head: [ + [ + 'script', + { async: '', src: 'https://www.googletagmanager.com/gtag/js?id=TAG_ID' } + ], + [ + 'script', + {}, + `window.dataLayer = window.dataLayer || []; + function gtag(){dataLayer.push(arguments);} + gtag('js', new Date()); + gtag('config', 'TAG_ID');` + ] + ] +} + +/* رندر خواهد شد: + + +*/ +``` + +### زبان {#lang} + +- نوع: `string` +- پیش‌فرض: `en-US` + +ویژگی زبان برای سایت. این به عنوان یک تگ `` در HTML صفحه رندر خواهد شد. + +```ts +export default { + lang: 'en-US' +} +``` + +### پایه {#base} + +- نوع: `string` +- پیش‌فرض: `/` + +آدرس پایه‌ای که سایت در آن مستقر خواهد شد. اگر قصد دارید سایت خود را در یک مسیر فرعی مستقر کنید، باید این تنظیم را انجام دهید، به عنوان مثال، صفحات GitHub. اگر قصد دارید سایت خود را در `https://foo.github.io/bar/` مستقر کنید، باید پایه را به `'/bar/'` تنظیم کنید. این باید همیشه با یک اسلش شروع و پایان یابد. + +پایه به طور خودکار به تمام آدرس‌های URL که با / شروع می‌شوند در سایر گزینه‌ها اضافه می‌شود، بنابراین فقط باید آن را یک بار مشخص کنید. + +```ts +export default { + base: '/base/' +} +``` + +## مسیریابی {#routing} + +### cleanUrls + +- نوع: `boolean` +- پیش‌فرض: `false` + +وقتی تنظیم شود به `true`، ویت‌پرس `.html` انتهایی را از URL ها حذف می‌کند. همچنین ببینید [تولید URL تمیز](../guide/routing#generating-clean-url). + +::: هشدار نیاز به پشتیبانی سرور +فعال کردن این ممکن است نیاز به پیکربندی اضافی در پلتفرم میزبان شما داشته باشد. برای اینکه کار کند، سرور شما باید بتواند `/foo.html` را زمانی که `/foo` بازدید می‌شود **بدون ریدایرکت** سرو کند. +::: + +### rewrites + +- نوع: `Record` + +تعریف نقشه‌برداری‌های سفارشی دایرکتوری <-> URL. جزئیات بیشتر را در [مسیریابی: بازنویسی مسیرها](../guide/routing#route-rewrites) ببینید. + +```ts +export default { + rewrites: { + 'source/:page': 'destination/:page' + } +} +``` + +## ساخت {#build} + +### srcDir + +- نوع: `string` +- پیش‌فرض: `.` + +دایرکتوری که صفحات مارک‌داون شما در آن ذخیره شده‌اند، نسبت به ریشه پروژه. همچنین ببینید [دایرکتوری ریشه و منبع](../guide/routing#root-and-source-directory). + +```ts +export default { + srcDir: './src' +} +``` + +### srcExclude + +- نوع: `string` +- پیش‌فرض: `undefined` + +یک [الگوی glob](https://github.com/mrmlnc/fast-glob#pattern-syntax) برای تطبیق فایل‌های مارک‌داون که باید به عنوان محتوای منبع حذف شوند. + +```ts +export default { + srcExclude: ['**/README.md', '**/TODO.md'] +} +``` + +### outDir + +- نوع: `string` +- پیش‌فرض: `./.vitepress/dist` + +مکان خروجی ساخت برای سایت، نسبت به [ریشه پروژه](../guide/routing#root-and-source-directory). + +```ts +export default { + outDir: '../public' +} +``` + +### assetsDir + +- نوع: `string` +- پیش‌فرض: `assets` + +دایرکتوری برای قرار دادن دارایی‌های تولید شده را مشخص کنید. مسیر باید داخل [`outDir`](#outdir) باشد و نسبت به آن حل شود. + +```ts +export default { + assetsDir: 'static' +} +``` + +### cacheDir + +- نوع: `string` +- پیش‌فرض: `./.vitepress/cache` + +دایرکتوری برای فایل‌های کش، نسبت به [ریشه پروژه](../guide/routing#root-and-source-directory). همچنین ببینید: [cacheDir](https://vitejs.dev/config/shared-options.html#cachedir). + +```ts +export default { + cacheDir: './.vitepress/.vite' +} +``` + +### ignoreDeadLinks + +- نوع: `boolean | 'localhostLinks' | (string | RegExp | ((link: string) => boolean))[]` +- پیش‌فرض: `false` + +زمانی که به `true` تنظیم شود، ویت‌پرس به دلیل لینک‌های مرده ساخت‌ها را شکست نخواهد داد. + +وقتی به `'localhostLinks'` تنظیم شود، ساخت بر روی لینک‌های مرده شکست خواهد خورد، اما لینک‌های `localhost` بررسی نخواهند شد. + +```ts +export default { + ignoreDeadLinks: true +} +``` + +همچنین می‌تواند یک آرایه از رشته‌های URL دقیق، الگوهای رگکس، یا توابع فیلتر سفارشی باشد. + +```ts +export default { + ignoreDeadLinks: [ + // نادیده گرفتن URL دقیق "/playground" + '/playground', + // نادیده گرفتن همه لینک‌های localhost + /^https?:\/\/localhost/, + // نادیده گرفتن همه لینک‌های شامل "/repl/"" + /\/repl\//, + // تابع سفارشی، نادیده گرفتن همه لینک‌های شامل "ignore" + (url) => { + return url.toLowerCase().includes('ignore') + } + ] +} +``` + +### metaChunk {#metachunk} + +- نوع: `boolean` +- پیش‌فرض: `false` + +زمانی که به `true` تنظیم شود، فراداده‌های صفحات را به یک قسمت جداگانه جاوااسکریپت استخراج می‌کند به جای درون‌گذاری آن در HTML اولیه. این کار باعث کاهش بار HTML هر صفحه می‌شود و فراداده‌های صفحات قابل کش شدن می‌شود، که منجر به کاهش پهنای باند سرور می‌شود وقتی که صفحات زیادی در سایت دارید. + +### mpa {#mpa} + +- نوع: `boolean` +- پیش‌فرض: `false` + +زمانی که به `true` تنظیم شود، اپلیکیشن تولید شده در [حالت MPA](../guide/mpa-mode) ساخته خواهد شد. حالت MPA به طور پیش‌فرض 0 کیلوبایت جاوااسکریپت ارسال می‌کند، به هزینه غیرفعال کردن ناوبری سمت کاربر و نیاز به opt-in صریح برای تعامل. + +## تم‌سازی {#theming} + +### appearance + +- نوع: `boolean | 'dark' | 'force-dark' | 'force-auto' | import('@vueuse/core').UseDarkOptions` +- پیش‌فرض: `true` + +آیا حالت تاریک فعال شود یا نه (با اضافه کردن کلاس `.dark` به عنصر ``). + +- اگر گزینه به `true` تنظیم شود، تم پیش‌فرض با توجه به طرح رنگ مورد نظر کاربر تعیین می‌شود. +- اگر گزینه به `dark` تنظیم شود، تم به صورت پیش‌فرض تاریک خواهد بود، مگر اینکه کاربر آن را به صورت دستی تغییر دهد. +- اگر گزینه به `false` تنظیم شود، کاربران قادر به تغییر تم نخواهند بود. +- اگر گزینه به `force-dark` تنظیم شود، تم همیشه تاریک خواهد بود و کاربران نمی‌توانند آن را تغییر دهند. +- اگر گزینه به `force-auto` تنظیم شود، تم همیشه با توجه به طرح رنگ مورد نظر کاربر تعیین می‌شود و کاربران نمی‌توانند آن را تغییر دهند. + +این گزینه یک اسکریپت داخلی تزریق می‌کند که تنظیمات کاربران را از حافظه محلی با استفاده از کلید `vitepress-theme-appearance` بازیابی می‌کند. این اطمینان حاصل می‌شود که کلاس `.dark` قبل از رندر شدن صفحه اعمال می‌شود تا از پرش جلوگیری شود. + +`appearance.initialValue` فقط می‌تواند `dark` یا `undefined` باشد. Refs یا getters پشتیبانی نمی‌شوند. + +### lastUpdated + +- نوع: `boolean` +- پیش‌فرض: `false` + +آیا زمان آخرین به‌روزرسانی برای هر صفحه با استفاده از Git دریافت شود. این زمان در داده‌های هر صفحه گنجانده خواهد شد و از طریق [`useData`](./runtime-api#usedata) قابل دسترسی خواهد بود. + +وقتی از تم پیش‌فرض استفاده می‌کنید، فعال کردن این گزینه زمان آخرین به‌روزرسانی هر صفحه را نمایش می‌دهد. می‌توانید متن را از طریق گزینه [`themeConfig.lastUpdatedText`](./default-theme-config#lastupdatedtext) سفارشی کنید. + +## سفارشی‌سازی {#customization} + +### markdown + +- نوع: `MarkdownOption` + +گزینه‌های پارسر مارک‌داون را تنظیم کنید. ویت‌پرس از [Markdown-it](https://github.com/markdown-it/markdown-it) به عنوان پارسر استفاده می‌کند و [Shiki](https://github.com/shikijs/shiki) را برای برجسته‌سازی نحو زبان استفاده می‌کند. در داخل این گزینه، می‌توانید گزینه‌های مختلف مرتبط با مارک‌داون را بر اساس نیازهای خود ارسال کنید. + +```js +export default { + markdown: {...} +} +``` + +برای مشاهده اعلامیه نوع و jsdocs برای همه گزینه‌های موجود، [type declaration and jsdocs](https://github.com/vuejs/vitepress/blob/main/src/node/markdown/markdown.ts) را بررسی کنید. + +### vite + +- نوع: `import('vite').UserConfig` + +پیکربندی خام [Vite Config](https://vitejs.dev/config/) را به سرور توسعه داخلی / بسته‌بند Vite ارسال کنید. + +```js +export default { + vite: { + // گزینه‌های پیکربندی Vite + } +} +``` + +### vue + +- نوع: `import('@vitejs/plugin-vue').Options` + +گزینه‌های خام [`@vitejs/plugin-vue` options](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue#options) را به نمونه افزونه داخلی ارسال کنید. + +```js +export default { + vue: { + // گزینه‌های @vitejs/plugin-vue + } +} +``` + +## قلاب‌های ساخت {#build-hooks} + +قلاب‌های ساخت ویت‌پرس به شما امکان اضافه کردن عملکرد و رفتارهای جدید به وب‌سایت خود را می‌دهند: + +- نقشه سایت +- شاخص‌بندی جستجو +- PWA +- Teleports + +### buildEnd + +- نوع: `(siteConfig: SiteConfig) => Awaitable` + +`buildEnd` یک قلاب CLI ساخت است، که بعد از اتمام ساخت (SSG) اجرا می‌شود اما قبل از خروج از فرآیند CLI ویت‌پرس. + +```ts +export default { + async buildEnd(siteConfig) { + // ... + } +} +``` + +### postRender + +- نوع: `(context: SSGContext) => Awaitable` + +`postRender` یک قلاب ساخت است که زمانی که رندر SSG انجام شد، فراخوانی می‌شود. این امکان را به شما می‌دهد که محتوای teleports را در حین SSG مدیریت کنید. + +```ts +export default { + async postRender(context) { + // ... + } +} +``` + +```ts +interface SSGContext { + content: string + teleports?: Record + [key: string]: any +} +``` + +### transformHead + +- نوع: `(context: TransformContext) => Awaitable` + +`transformHead` یک قلاب ساخت است که برای تغییر head قبل از تولید هر صفحه استفاده می‌شود. این امکان را به شما می‌دهد که ورودی‌های head اضافه کنید که نمی‌توانند به صورت استاتیک به تنظیمات ویت‌پرس اضافه شوند. شما فقط باید ورودی‌های اضافی را برگردانید، آنها به صورت خودکار با موارد موجود ترکیب می‌شوند. + +::: warning هشدار +هیچ‌چیزی را در داخل `context` تغییر ندهید. +::: + +```ts +export default { + async transform + +Head(context) { + // ... + } +} +``` + +```ts +interface TransformContext { + page: string // به عنوان مثال index.md (نسبت به srcDir) + assets: string[] // همه دارایی‌های غیر js/css به عنوان URL عمومی کاملاً حل شده + siteConfig: SiteConfig + siteData: SiteData + pageData: PageData + title: string + description: string + head: HeadConfig[] + content: string +} +``` + +توجه داشته باشید که این قلاب فقط زمانی که سایت به صورت استاتیک تولید می‌شود فراخوانی می‌شود. در زمان توسعه فراخوانی نمی‌شود. اگر نیاز به اضافه کردن ورودی‌های head دینامیک در زمان توسعه دارید، می‌توانید به جای آن از قلاب [`transformPageData`](#transformpagedata) استفاده کنید: + +```ts +export default { + transformPageData(pageData) { + pageData.frontmatter.head ??= [] + pageData.frontmatter.head.push([ + 'meta', + { + name: 'og:title', + content: + pageData.frontmatter.layout === 'home' + ? `ویت‌پرس` + : `${pageData.title} | ویت‌پرس` + } + ]) + } +} +``` + +#### مثال: اضافه کردن یک canonical URL `` {#example-adding-a-canonical-url-link} + +```ts +export default { + transformPageData(pageData) { + const canonicalUrl = `https://example.com/${pageData.relativePath}` + .replace(/index\.md$/, '') + .replace(/\.md$/, '.html') + + pageData.frontmatter.head ??= [] + pageData.frontmatter.head.push([ + 'link', + { rel: 'canonical', href: canonicalUrl } + ]) + } +} +``` + +### transformHtml + +- نوع: `(code: string, id: string, context: TransformContext) => Awaitable` + +`transformHtml` یک قلاب ساخت است که برای تغییر محتوای هر صفحه قبل از ذخیره به دیسک استفاده می‌شود. + +::: warning هشدار +هیچ‌چیزی را در داخل `context` تغییر ندهید. همچنین، تغییر محتوای html ممکن است باعث مشکلات هیدراتاسیون در زمان اجرا شود. +::: + +```ts +export default { + async transformHtml(code, id, context) { + // ... + } +} +``` + +### transformPageData + +- نوع: `(pageData: PageData, context: TransformPageContext) => Awaitable | { [key: string]: any } | void>` + +`transformPageData` یک قلاب است که برای تغییر `pageData` هر صفحه استفاده می‌شود. شما می‌توانید `pageData` را به صورت مستقیم تغییر دهید یا مقادیر تغییر یافته را برگردانید که به داده‌های صفحه ادغام خواهند شد. + +::: warning هشدار +هیچ‌چیزی را در داخل `context` تغییر ندهید و دقت کنید که این ممکن است بر عملکرد سرور توسعه تاثیر بگذارد، به ویژه اگر در این قلاب درخواست‌های شبکه یا محاسبات سنگین (مانند تولید تصاویر) داشته باشید. می‌توانید برای منطق شرطی بررسی کنید `process.env.NODE_ENV === 'production'`. +::: + +```ts +export default { + async transformPageData(pageData, { siteConfig }) { + pageData.contributors = await getPageContributors(pageData.relativePath) + } + + // یا داده‌ها را برای ادغام برگردانید + async transformPageData(pageData, { siteConfig }) { + return { + contributors: await getPageContributors(pageData.relativePath) + } + } +} +``` + +```ts +interface TransformPageContext { + siteConfig: SiteConfig +} +``` diff --git a/docs/guide/deploy.md b/docs/guide/deploy.md deleted file mode 100644 index 3bf9c3ea..00000000 --- a/docs/guide/deploy.md +++ /dev/null @@ -1,280 +0,0 @@ ---- -outline: deep ---- - -# Deploy Your VitePress Site - -The following guides are based on some shared assumptions: - -- The VitePress site is inside the `docs` directory of your project. -- You are using the default build output directory (`.vitepress/dist`). -- VitePress is installed as a local dependency in your project, and you have set up the following scripts in your `package.json`: - - ```json - { - "scripts": { - "docs:build": "vitepress build docs", - "docs:preview": "vitepress preview docs" - } - } - ``` - -## Build and Test Locally - -1. Run this command to build the docs: - - ```sh - $ npm run docs:build - ``` - -2. Once built, preview it locally by running: - - ```sh - $ npm run docs:preview - ``` - - The `preview` command will boot up a local static web server that will serve the output directory `.vitepress/dist` at `http://localhost:4173`. You can use this to make sure everything looks good before pushing to production. - -3. You can configure the port of the server by passing `--port` as an argument. - - ```json - { - "scripts": { - "docs:preview": "vitepress preview docs --port 8080" - } - } - ``` - -Now the `docs:preview` method will launch the server at `http://localhost:8080`. - -## Setting a Public Base Path - -By default, we assume the site is going to be deployed at the root path of a domain (`/`). If your site is going to be served at a sub-path, e.g. `https://mywebsite.com/blog/`, then you need to set the [`base`](../reference/site-config#base) option to `'/blog/'` in the VitePress config. - -**Example:** If you're using Github (or GitLab) Pages and deploying to `user.github.io/repo/`, then set your `base` to `/repo/`. - -## HTTP Cache Headers - -If you have control over the HTTP headers on your production server, you can configure `cache-control` headers to achieve better performance on repeated visits. - -The production build uses hashed file names for static assets (JavaScript, CSS and other imported assets not in `public`). If you inspect the production preview using your browser devtools' network tab, you will see files like `app.4f283b18.js`. - -This `4f283b18` hash is generated from the content of this file. The same hashed URL is guaranteed to serve the same file content - if the contents change, the URLs change too. This means you can safely use the strongest cache headers for these files. All such files will be placed under `assets/` in the output directory, so you can configure the following header for them: - -``` -Cache-Control: max-age=31536000,immutable -``` - -:::details Example Netlify `_headers` file - -``` -/assets/* - cache-control: max-age=31536000 - cache-control: immutable -``` - -Note: the `_headers` file should be placed in the [public directory](/guide/asset-handling#the-public-directory) - in our case, `docs/public/_headers` - so that it is copied verbatim to the output directory. - -[Netlify custom headers documentation](https://docs.netlify.com/routing/headers/) - -::: - -:::details Example Vercel config in `vercel.json` - -```json -{ - "headers": [ - { - "source": "/assets/(.*)", - "headers": [ - { - "key": "Cache-Control", - "value": "max-age=31536000, immutable" - } - ] - } - ] -} -``` - -Note: the `vercel.json` file should be placed at the root of your **repository**. - -[Vercel documentation on headers config](https://vercel.com/docs/concepts/projects/project-configuration#headers) - -::: - -## Platform Guides - -### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render - -Set up a new project and change these settings using your dashboard: - -- **Build Command:** `npm run docs:build` -- **Output Directory:** `docs/.vitepress/dist` -- **Node Version:** `16` (or above, by default it usually will be 14 or 16, but on Cloudflare Pages the default is still 12, so you may need to [change that](https://developers.cloudflare.com/pages/platform/build-configuration/)) - -::: warning -Don't enable options like _Auto Minify_ for HTML code. It will remove comments from output which have meaning to Vue. You may see hydration mismatch errors if they get removed. -::: - -### GitHub Pages - -1. In your theme config file, `docs/.vitepress/config.js`, set the `base` property to the name of your GitHub repository. If you plan to deploy your site to `https://foo.github.io/bar/`, then you should set base to `'/bar/'`. It should always start and end with a slash. - -2. Create a file named `deploy.yml` inside `.github/workflows` directory of your project with the following content: - - ```yaml - name: Deploy - on: - workflow_dispatch: {} - push: - branches: - - main - jobs: - deploy: - runs-on: ubuntu-latest - permissions: - pages: write - id-token: write - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - uses: actions/setup-node@v3 - with: - node-version: 16 - cache: npm - - run: npm ci - - name: Build - run: npm run docs:build - - uses: actions/configure-pages@v2 - - uses: actions/upload-pages-artifact@v1 - with: - path: docs/.vitepress/dist - - name: Deploy - id: deployment - uses: actions/deploy-pages@v1 - ``` - - ::: tip - Please replace the corresponding branch name. For example, if the branch you want to build is `master`, then you should replace `main` with `master` in the above file. - ::: - -3. In your repository's Settings under Pages menu item, select `GitHub Actions` in Build and deployment's Source. - -4. Now commit your code and push it to the `main` branch. - -5. Wait for actions to complete. - -6. In your repository's Settings under Pages menu item, click `Visit site`, then you can see your site. Your docs will automatically deploy each time you push. - -### GitLab Pages - -1. Set `outDir` in `docs/.vitepress/config.js` to `../public`. - -2. Still in your config file, `docs/.vitepress/config.js`, set the `base` property to the name of your GitLab repository. If you plan to deploy your site to `https://foo.gitlab.io/bar/`, then you should set base to `'/bar/'`. It should always start and end with a slash. - -3. Create a file called `.gitlab-ci.yml` in the root of your project with the content below. This will build and deploy your site whenever you make changes to your content: - - ```yaml - image: node:16 - pages: - cache: - paths: - - node_modules/ - script: - - npm install - - npm run docs:build - artifacts: - paths: - - public - only: - - main - ``` - -4. Alternatively, if you want to use an _alpine_ version of node, you have to install `git` manually. In that case, the code above modifies to this: - ```yaml - image: node:16-alpine - pages: - cache: - paths: - - node_modules/ - before_script: - - apk add git - script: - - npm install - - npm run docs:build - artifacts: - paths: - - public - only: - - main - ``` - -### Azure Static Web Apps - -1. Follow the [official documentation](https://docs.microsoft.com/en-us/azure/static-web-apps/build-configuration). - -2. Set these values in your configuration file (and remove the ones you don't require, like `api_location`): - - - **`app_location`**: `/` - - **`output_location`**: `docs/.vitepress/dist` - - **`app_build_command`**: `npm run docs:build` - -### Firebase - -1. Create `firebase.json` and `.firebaserc` at the root of your project: - - `firebase.json`: - - ```json - { - "hosting": { - "public": "docs/.vitepress/dist", - "ignore": [] - } - } - ``` - - `.firebaserc`: - - ```json - { - "projects": { - "default": "" - } - } - ``` - -2. After running `npm run docs:build`, run this command to deploy: - - ```sh - firebase deploy - ``` - -### Surge - -1. After running `npm run docs:build`, run this command to deploy: - - ```sh - npx surge docs/.vitepress/dist - ``` - -### Heroku - -1. Follow documentation and guide given in [`heroku-buildpack-static`](https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-static). - -2. Create a file called `static.json` in the root of your project with the below content: - - ```json - { - "root": "docs/.vitepress/dist" - } - ``` - -### Edgio - -Refer [Creating and Deploying a VitePress App To Edgio](https://docs.edg.io/guides/vitepress). diff --git a/docs/guide/vitepress-init.png b/docs/guide/vitepress-init.png deleted file mode 100644 index d1805cf7..00000000 Binary files a/docs/guide/vitepress-init.png and /dev/null differ diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index e3226eab..00000000 --- a/docs/index.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -layout: home - -title: VitePress -titleTemplate: Vite & Vue Powered Static Site Generator - -hero: - name: VitePress - text: Vite & Vue Powered Static Site Generator - tagline: Simple, powerful, and fast. Meet the modern SSG framework you've always wanted. - actions: - - theme: brand - text: Get Started - link: /guide/what-is-vitepress - - theme: alt - text: View on GitHub - link: https://github.com/vuejs/vitepress - -features: - - icon: 📝 - title: Focus on Your Content - details: Effortlessly create beautiful documentation sites with just markdown. - - icon: - title: Enjoy the Vite DX - details: Instant server start, lightning fast hot updates, and leverage Vite ecosystem plugins. - - icon: - title: Customize with Vue - details: Use Vue syntax and components directly in markdown, or build custom themes with Vue. - - icon: 🚀 - title: Ship Fast Sites - details: Fast initial load with static HTML, fast post-load navigation with client-side routing. ---- diff --git a/docs/ko/config.ts b/docs/ko/config.ts new file mode 100644 index 00000000..78b5c3f3 --- /dev/null +++ b/docs/ko/config.ts @@ -0,0 +1,263 @@ +import { createRequire } from 'module' +import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' + +const require = createRequire(import.meta.url) +const pkg = require('vitepress/package.json') + +export default defineAdditionalConfig({ + lang: 'ko-KR', + description: 'Vite 및 Vue 기반 정적 사이트 생성기.', + + themeConfig: { + nav: nav(), + + search: { options: searchOptions() }, + + sidebar: { + '/ko/guide/': { base: '/ko/guide/', items: sidebarGuide() }, + '/ko/reference/': { base: '/ko/reference/', items: sidebarReference() } + }, + + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + text: '이 페이지 편집 제안하기' + }, + + footer: { + message: 'Released under the MIT License.', + copyright: 'Copyright © 2019-present Evan You' + }, + + docFooter: { + prev: '이전', + next: '다음' + }, + + outline: { + label: '이 페이지 목차' + }, + + lastUpdated: { + text: '업데이트 날짜' + }, + + notFound: { + title: '페이지를 찾을 수 없습니다', + quote: + '방향을 바꾸지 않고 계속 찾다 보면 결국 당신이 가고 있는 곳에 도달할 수도 있습니다.', + linkLabel: '홈으로 가기', + linkText: '집으로 데려가줘' + }, + + langMenuLabel: '언어 변경', + returnToTopLabel: '맨 위로 돌아가기', + sidebarMenuLabel: '사이드바 메뉴', + darkModeSwitchLabel: '다크 모드', + lightModeSwitchTitle: '라이트 모드로 변경', + darkModeSwitchTitle: '다크 모드로 변경', + skipToContentLabel: '본문으로 건너뛰기' + } +}) + +function nav(): DefaultTheme.NavItem[] { + return [ + { + text: '가이드', + link: '/ko/guide/what-is-vitepress', + activeMatch: '/ko/guide/' + }, + { + text: '레퍼런스', + link: '/ko/reference/site-config', + activeMatch: '/ko/reference/' + }, + { + text: pkg.version, + items: [ + { + text: '변경 로그', + link: 'https://github.com/vuejs/vitepress/blob/main/CHANGELOG.md' + }, + { + text: '기여', + link: 'https://github.com/vuejs/vitepress/blob/main/.github/contributing.md' + } + ] + } + ] +} + +function sidebarGuide(): DefaultTheme.SidebarItem[] { + return [ + { + text: '소개', + collapsed: false, + items: [ + { + text: 'VitePress란 무엇인가?', + link: 'what-is-vitepress' + }, + { + text: '시작하기', + link: 'getting-started' + }, + { + text: '라우팅', + link: 'routing' + }, + { + text: '배포하기', + link: 'deploy' + } + ] + }, + { + text: '글쓰기', + collapsed: false, + items: [ + { + text: '마크다운 확장 기능', + link: 'markdown' + }, + { + text: '에셋 핸들링', + link: 'asset-handling' + }, + { + text: '전문(Front-matter)', + link: 'frontmatter' + }, + { + text: '마크다운에서 Vue 사용하기', + link: 'using-vue' + }, + { + text: 'i18n', + link: 'i18n' + } + ] + }, + { + text: '커스텀', + collapsed: false, + items: [ + { + text: '커스텀 테마 사용하기', + link: 'custom-theme' + }, + { + text: '기본 테마 확장하기', + link: 'extending-default-theme' + }, + { + text: '빌드할 때 데이터 로딩하기', + link: 'data-loading' + }, + { + text: 'SSR 호환성', + link: 'ssr-compat' + }, + { + text: 'CMS 연결하기', + link: 'cms' + } + ] + }, + { + text: '실험적인', + collapsed: false, + items: [ + { + text: 'MPA 모드', + link: 'mpa-mode' + }, + { + text: '사이트맵 생성', + link: 'sitemap-generation' + } + ] + }, + { + text: '구성 & API 레퍼런스', + base: '/ko/reference/', + link: 'site-config' + } + ] +} + +function sidebarReference(): DefaultTheme.SidebarItem[] { + return [ + { + text: '레퍼런스', + items: [ + { text: '사이트 구성', link: 'site-config' }, + { text: '전문(front-matter) 구성', link: 'frontmatter-config' }, + { text: '런타임 API', link: 'runtime-api' }, + { text: 'CLI', link: 'cli' }, + { + text: '기본 테마', + base: '/ko/reference/default-theme-', + items: [ + { text: '개요', link: 'config' }, + { text: '네비게이션 바', link: 'nav' }, + { text: '사이드바', link: 'sidebar' }, + { text: '홈 페이지', link: 'home-page' }, + { text: '푸터', link: 'footer' }, + { text: '레이아웃', link: 'layout' }, + { text: '배지(badge)', link: 'badge' }, + { text: '팀 페이지', link: 'team-page' }, + { text: '이전/다음 링크', link: 'prev-next-links' }, + { text: '편집 링크', link: 'edit-link' }, + { text: '마지막 업데이트 날짜', link: 'last-updated' }, + { text: '검색', link: 'search' }, + { text: '카본 광고', link: 'carbon-ads' } + ] + } + ] + } + ] +} + +function searchOptions(): Partial { + return { + placeholder: '문서 검색', + translations: { + button: { + buttonText: '검색', + buttonAriaLabel: '검색' + }, + modal: { + searchBox: { + resetButtonTitle: '검색 지우기', + resetButtonAriaLabel: '검색 지우기', + cancelButtonText: '취소', + cancelButtonAriaLabel: '취소' + }, + startScreen: { + recentSearchesTitle: '검색 기록', + noRecentSearchesText: '최근 검색 없음', + saveRecentSearchButtonTitle: '검색 기록에 저장', + removeRecentSearchButtonTitle: '검색 기록에서 삭제', + favoriteSearchesTitle: '즐겨찾기', + removeFavoriteSearchButtonTitle: '즐겨찾기에서 삭제' + }, + errorScreen: { + titleText: '결과를 가져올 수 없습니다', + helpText: '네트워크 연결을 확인하세요' + }, + footer: { + selectText: '선택', + navigateText: '탐색', + closeText: '닫기', + searchByText: '검색 기준' + }, + noResultsScreen: { + noResultsText: '결과를 찾을 수 없습니다', + suggestedQueryText: '새로운 검색을 시도할 수 있습니다', + reportMissingResultsText: '해당 검색어에 대한 결과가 있어야 합니까?', + reportMissingResultsLinkText: '피드백 보내기 클릭' + } + } + } + } +} diff --git a/docs/ko/guide/asset-handling.md b/docs/ko/guide/asset-handling.md new file mode 100644 index 00000000..5f6a35d1 --- /dev/null +++ b/docs/ko/guide/asset-handling.md @@ -0,0 +1,63 @@ +# 에셋 핸들링 {#asset-handling} + +## 정적 에셋 참조하기 {#referencing-static-assets} + +모든 마크다운 파일은 Vue 컴포넌트로 컴파일되어 [Vite](https://vitejs.dev/guide/assets.html)에 의해 처리됩니다. 모든 에셋은 상대 URL을 사용하여 참조할 수 있으며, **참조해야 합니다**: + +```md +![이미지](./image.png) +``` + +마크다운 파일에서 정적 에셋을 참조할 수 있으며, 테마 내의 `*.vue` 컴포넌트, 스타일 및 일반 `.css` 파일을 절대 경로(프로젝트 루트를 기준으로) 또는 상대 경로(파일 시스템을 기준으로)를 사용하여 참조할 수 있습니다. 후자는 Vite, Vue CLI 또는 webpack의 `file-loader` 동작과 유사합니다. + +일반적인 이미지, 미디어 및 글꼴 파일 형식은 자동으로 에셋으로 감지되어 포함됩니다. + +::: tip 링크를 통해 참조된 파일은 에셋으로 처리되지 않습니다 +마크다운 파일 내에서 링크로 참조된 PDF 또는 기타 문서는 자동으로 에셋으로 처리되지 않습니다. 링크된 파일을 접근 가능하게 하려면 프로젝트의 [`public`](#the-public-directory) 디렉토리에 수동으로 배치해야 합니다. +::: + +절대 경로를 사용하는 에셋을 포함하여 모든 참조된 에셋은 프로덕션 빌드에서 해시된 파일 이름으로 출력 디렉토리에 복사됩니다. 참조되지 않은 에셋은 복사되지 않습니다. 4kb보다 작은 이미지 에셋은 base64로 인라인됩니다. 이는 [`vite`](../reference/site-config#vite) 구성 옵션을 통해 구성할 수 있습니다. + +모든 **정적** 경로 참조는 절대 경로를 포함하여 작업 디렉토리 구조를 기반으로 해야 합니다. + +## Public 디렉터리 {#the-public-directory} + +때때로 마크다운이나 테마 컴포넌트에서 직접 참조되지 않는 정적 에셋을 제공해야 하거나 특정 파일을 원래 파일 이름으로 제공하고 싶을 때가 있습니다. 이러한 파일의 예로는 `robots.txt`, 파비콘, PWA 아이콘 등이 있습니다. + +이 파일들은 [소스 디렉토리](./routing#source-directory) 아래의 `public` 디렉토리에 놓을 수 있습니다. 예를 들어 프로젝트 루트가 `./docs`이고 기본 소스 디렉토리 위치를 사용 중인 경우, `public` 디렉토리는 `./docs/public`이 됩니다. + +`public`에 배치된 에셋은 출력 디렉토리의 루트로 그대로 복사됩니다. + +`public`에 배치된 파일은 루트 절대 경로를 사용하여 참조해야 한다는 점에 유의하세요. 예를 들어, `public/icon.png`는 소스 코드에서 항상 `/icon.png`로 참조되어야 합니다. + +## Base URL {#base-url} + +사이트가 루트 URL이 아닌 곳에 배포된 경우, `.vitepress/config.js`에서 `base` 옵션을 설정해야 합니다. 예를 들어, 사이트를 `https://foo.github.io/bar/`에 배포하려는 경우 `base`는 `'/bar/'`로 설정해야 합니다(항상 슬래시로 시작하고 끝나야 합니다). + +모든 정적 에셋 경로는 다른 `base` 구성 값에 맞게 자동으로 처리됩니다. 예를 들어, 마크다운에서 `public` 하위의 에셋에 대한 절대 참조가 있는 경우: + +```md +![이미지](/image-inside-public.png) +``` + +이 경우 `base` 구성 값을 변경할 때 **업데이트할 필요가 없습니다**. + +그러나 테마 구성 값을 기반으로 `src`가 설정된 이미지와 같이 동적으로 에셋에 링크하는 테마 컴포넌트를 작성하는 경우: + +```vue + +``` + +이 경우 VitePress에서 제공하는 [`withBase` 헬퍼](../reference/runtime-api#withbase)로 경로를 감싸는 것이 좋습니다: + +```vue + + + +``` diff --git a/docs/ko/guide/cms.md b/docs/ko/guide/cms.md new file mode 100644 index 00000000..712c2402 --- /dev/null +++ b/docs/ko/guide/cms.md @@ -0,0 +1,56 @@ +--- +outline: deep +--- + +# CMS에 연결하기 {#connecting-to-a-cms} + +## 일반적인 워크플로우 {#general-workflow} + +VitePress를 CMS에 연결하는 것은 주로 [동적 라우트](./routing#dynamic-routes)를 중심으로 이루어질 것입니다. 진행하기 전에 작동 방식을 이해해야 합니다. + +각 CMS가 다르게 작동하므로, 여기서는 특정 상황에 맞게 조정해야 하는 일반적인 워크플로우만 제공할 수 있습니다. + +1. CMS가 인증을 요구하는 경우, `.env` 파일을 생성하여 API 토큰을 저장하고 다음과 같이 로드하세요: + + ```js + // posts/[id].paths.js + import { loadEnv } from 'vitepress' + + const env = loadEnv('', process.cwd()) + ``` + +2. CMS에서 필요한 데이터를 가져와 적절한 경로 데이터로 형식을 지정하세요: + + ```js + export default { + async paths() { + // 필요한 경우 해당 CMS 클라이언트 라이브러리 사용 + const data = await (await fetch('https://my-cms-api', { + headers: { + // 필요한 경우 토큰을 사용 + } + })).json() + + return data.map(entry => { + return { + params: { id: entry.id, /* 제목, 저자, 날짜 등 */ }, + content: entry.content + } + }) + } + } + ``` + +3. 페이지의 컨텐츠를 렌더링하세요: + + ```md + # {{ $params.title }} + + - 작성자: {{ $params.author }}, 작성일: {{ $params.date }} + + + ``` + +## 통합 가이드 {#integration-guides} + +VitePress를 특정 CMS와 통합하는 방법에 대한 가이드를 작성한 경우 아래의 "이 페이지 편집 제안하기" 링크를 클릭하여 여기에 제출하세요! diff --git a/docs/ko/guide/custom-theme.md b/docs/ko/guide/custom-theme.md new file mode 100644 index 00000000..9c799f18 --- /dev/null +++ b/docs/ko/guide/custom-theme.md @@ -0,0 +1,216 @@ +# 커스텀 테마 사용하기 {#using-a-custom-theme} + +## 테마 사용법 {#theme-resolving} + +`.vitepress/theme/index.js` 또는 `.vitepress/theme/index.ts` 파일("테마 엔트리 파일")을 생성하여 커스텀 테마를 활성화할 수 있습니다: + +``` +. +├─ docs # 프로젝트 루트 +│ ├─ .vitepress +│ │ ├─ theme +│ │ │ └─ index.js # 테마 엔트리 +│ │ └─ config.js # 구성 파일 +│ └─ index.md +└─ package.json +``` + +VitePress는 테마 엔트리 파일이 존재를 감지하면 기본 테마 대신 커스텀 테마를 사용합니다. 아니면 [기본 테마 확장하기](./extending-default-theme)를 통해 이를 기반으로 고급 커스터마이징을 수행할 수 있습니다. + +## 테마 인터페이스 {#theme-interface} + +VitePress 커스텀 테마는 아래와 같은 인터페이스 객체로 정의됩니다: + +```ts +interface Theme { + /** + * 모든 페이지의 루트 레이아웃 컴포넌트 + * @required + */ + Layout: Component + /** + * Vue 애플리케이션 인스턴스 추가조작 (의역: "enhance → 추가조작") + * @optional + */ + enhanceApp?: (ctx: EnhanceAppContext) => Awaitable + /** + * 현재 `enhanceApp`를 호출하기 전, 다른 테마를 먼저 확장 + * @optional + */ + extends?: Theme +} + +interface EnhanceAppContext { + app: App // Vue 애플리케이션 인스턴스 + router: Router // VitePress 라우터 인스턴스 + siteData: Ref // 사이트 수준 메타데이터 +} +``` + +테마 엔트리 파일은 테마(Theme 객체)를 "export default" 해야 합니다: + +```js [.vitepress/theme/index.js] + +// 테마 엔트리에서 Vue 파일을 직접 "import" 할 수 있습니다. +// VitePress는 @vitejs/plugin-vue가 사전 구성되어 있습니다. +import Layout from './Layout.vue' + +export default { + Layout, + enhanceApp({ app, router, siteData }) { + // ... + } +} +``` + +"export default"는 커스텀 테마를 설정하는 유일한 방법이며, `Layout` 프로퍼티만 필수입니다. 따라서 기술적으로 VitePress 테마는 단일 Vue 컴포넌트처럼 간단할 수 있습니다. + +레이아웃 컴포넌트 내부에서는 일반적인 Vite + Vue 3 애플리케이션처럼 동작합니다. 또한 테마가 [SSR 호환](./ssr-compat)이 되어야 합니다. + +## 레이아웃 만들기 {#building-a-layout} + +가장 기본적인 레이아웃 컴포넌트는 [``](../reference/runtime-api#content) 컴포넌트가 포함되어야 합니다: + +```vue [.vitepress/theme/Layout.vue] + +``` + +위의 레이아웃은 각 페이지의 마크다운을 HTML로 렌더링합니다. 첫 번째로 개선 사항은 404 에러를 처리하는 것입니다: + +```vue{1-4,9-12} + + + +``` + +[`useData()`](../reference/runtime-api#usedata) 헬퍼는 다양한 레이아웃을 조건부로 렌더링하는 데 필요한 모든 런타임 데이터를 제공합니다. 접근할 수 있는 다른 데이터 중 하나는 현재 페이지의 전문(front-matter)입니다. 이를 활용하여 각 페이지에 맞게 레이아웃을 제어할 수 있습니다. 예를 들어 특정 페이지에서 홈 페이지 레이아웃을 사용하도록 지정할 수 있습니다: + +```md +--- +layout: home +--- +``` + +그리고 이를 처리하도록 테마를 조정할 수 있습니다: + +```vue{3,12-14} + + + +``` + +물론 레이아웃을 더 많은 컴포넌트로 나눌 수 있습니다: + +```vue{3-5,12-15} + + + +``` + +테마 컴포넌트에서 사용할 수 있는 모든 항목에 대해서는 [런타임 API 레퍼런스](../reference/runtime-api)를 참고하세요. 또한 [빌드할 때 데이터 로딩하기](./data-loading)를 활용하여 데이터 기반의 레이아웃을 생성할 수 있습니다. 예를 들어 현재 프로젝트의 모든 블로그 게시물을 나열하는 페이지를 만들 수 있습니다. + +## 사용자 정의 테마 배포하기 {#distributing-a-custom-theme} + +커스텀 테마를 배포하는 가장 쉬운 방법은 [GitHub 템플릿 리포지토리](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-template-repository)로 제공하는 것입니다. + +테마를 npm 패키지로 배포하려면 다음 단계를 따라야 합니다: + +1. 패키지 엔트리에서 테마 객체를 "export default" 합니다. + +2. 해당되는 경우, 테마 구성 타입 정의를 `ThemeConfig`로 "export" 합니다. + +3. 테마에서 VitePress 구성을 조정해야 하는 경우, 사용자가 확장할 수 있도록 패키지 하위 경로(예: `my-theme/config`)에 해당 구성을 "export" 합니다. + +4. 테마 구성 옵션을 문서화합니다 (구성 파일과 전문 둘 다). + +5. 테마를 사용하는 방법에 대한 명확한 지침을 제공합니다 (아래 참조). + +## 커스텀 테마 사용하기 {#consuming-a-custom-theme} + +외부 테마를 사용하려면, 커스텀 테마 엔트리에서 테마를 "import" 후 다시 "export"합니다: + +```js [.vitepress/theme/index.js] +import Theme from 'awesome-vitepress-theme' + +export default Theme +``` + +테마를 확장해야 하는 경우: + +```js [.vitepress/theme/index.js] +import Theme from 'awesome-vitepress-theme' + +export default { + extends: Theme, + enhanceApp(ctx) { + // ... + } +} +``` + +테마가 특별한 VitePress 구성을 요구하는 경우, 해당 구성을 (외부 커스텀 테마를 사용하는 자신의) 구성 파일에서도 확장해야 합니다: + +```ts [.vitepress/config.ts] +import baseConfig from 'awesome-vitepress-theme/config' + +export default { + // 필요한 경우 테마 기본 구성 확장 + extends: baseConfig +} +``` + +마지막으로 테마가 테마 구성에 대한 타입을 제공하는 경우: + +```ts [.vitepress/config.ts] +import baseConfig from 'awesome-vitepress-theme/config' +import { defineConfigWithTheme } from 'vitepress' +import type { ThemeConfig } from 'awesome-vitepress-theme' + +export default defineConfigWithTheme({ + extends: baseConfig, + themeConfig: { + // 타입은 `ThemeConfig`입니다. + } +}) +``` diff --git a/docs/ko/guide/data-loading.md b/docs/ko/guide/data-loading.md new file mode 100644 index 00000000..9ac88f7a --- /dev/null +++ b/docs/ko/guide/data-loading.md @@ -0,0 +1,245 @@ +# 빌드할 때 데이터 로딩하기 {#build-time-data-loading} + +VitePress는 페이지나 컴포넌트에서 임의의 데이터를 로드하고 이를 가져올 수 있는 **데이터 로더** 기능을 제공합니다. 데이터 로딩은 **빌드할 때에만** 실행되며, 결과적으로 생성된 데이터는 최종 JavaScript 번들에 JSON으로 직렬화됩니다. + +데이터 로더는 원격 데이터를 가져오거나 로컬 파일을 기반으로 메타데이터를 생성하는 데 사용할 수 있습니다. 예를 들어, 데이터 로더를 사용하여 모든 로컬 API 페이지를 파싱하고 모든 API 항목의 색인을 자동으로 생성할 수 있습니다. + +## 기본 사용법 {#basic-usage} + +데이터 로더 파일은 반드시 `.data.js` 또는 `.data.ts`로 끝나야 합니다. 이 파일은 `load()` 메서드를 가진 객체를 "export default" 해야 합니다: + +```js [example.data.js] +export default { + load() { + return { + hello: 'world' + } + } +} +``` + +로더 모듈은 Node.js에서만 평가되므로, 필요한 경우 Node API와 npm 종속성을 "import" 할 수 있습니다. + +그런 다음 `.md` 페이지와 `.vue` 컴포넌트에서 `data`라는 이름으로 "export" 한 데이터를 이 파일에서 "import" 할 수 있습니다: + +```vue + + +
{{ data }}
+``` + +출력: + +```json +{ + "hello": "world" +} +``` + +데이터 로더 자체가 `data`를 "export" 하지 않는다는 점에 주목하십시오. VitePress가 백그라운드에서 `load()` 메서드를 호출하고 결과를 암묵적으로 `data`라는 이름으로 "export" 하기 때문입니다. + +이 방법은 로더가 비동기적이어도 작동합니다: + +```js +export default { + async load() { + // 원격 데이터 가져오기 + return (await fetch('...')).json() + } +} +``` + +## 로컬 파일에서 데이터 가져오기 {#data-from-local-files} + +로컬 파일을 기반으로 데이터를 생성해야 할 때는 데이터 로더에서 `watch` 옵션을 사용해야 합니다. 이 옵션을 사용하면 이러한 파일에 변경이 있을 때 핫 업데이트를 트리거할 수 있습니다. + +`watch` 옵션은 또한 여러 파일을 매칭하는 [glob 패턴](https://github.com/mrmlnc/fast-glob#pattern-syntax)을 사용할 수 있어서 편리합니다. 패턴은 로더 파일 자체에 상대적일 수 있으며, `load()` 함수는 매칭된 파일을 절대 경로로 받게 됩니다. + +다음 예제는 CSV 파일을 로드하고 이를 [csv-parse](https://github.com/adaltas/node-csv/tree/master/packages/csv-parse/)를 사용하여 JSON으로 변환하는 방법을 보여줍니다. 이 파일은 빌드할 때에만 실행되므로 CSV 파서를 클라이언트로 전송하지 않습니다! + +```js +import fs from 'node:fs' +import { parse } from 'csv-parse/sync' + +export default { + watch: ['./data/*.csv'], + load(watchedFiles) { + // watchedFiles는 매칭된 파일의 절대 경로 배열 입니다. + // 테마 레이아웃에서 목록을 렌더링하는 데 사용할 수 있는 + // 블로그 포스트 메타데이터 배열을 생성합니다. + return watchedFiles.map((file) => { + return parse(fs.readFileSync(file, 'utf-8'), { + columns: true, + skip_empty_lines: true + }) + }) + } +} +``` + +## `createContentLoader` + +콘텐츠가 많은 사이트를 구축할 때, 종종 "아카이브" 또는 "인덱스" 페이지를 만들어야 합니다. 이 페이지는 콘텐츠 모음에 있는 모든 항목(예: 블로그 게시물, API 페이지)을 나열하는 페이지입니다. 데이터 로더 API를 직접 사용하여 이를 구현할 수 있지만, VitePress는 이러한 일반적인 사용 사례를 간소화하기 위해 `createContentLoader` 헬퍼를 제공합니다: + +```js [posts.data.js] +import { createContentLoader } from 'vitepress' + +export default createContentLoader('posts/*.md', /* options */) +``` + +이 헬퍼는 [소스 디렉터리](./routing#source-directory)를 기준으로 glob 패턴을 허용하고 데이터 로드 파일에서 "default export"로 사용할 수 있는 `{ watch, load }` 데이터 로더 객체를 반환합니다. 또한 파일 수정 타임스탬프를 기반으로 캐싱을 구현하여 개발 성능을 향상시킵니다. + +참고로 로더는 마크다운 파일에서만 작동하며, 매칭되는 마크다운이 아닌 파일은 건너뜁니다. + +로드된 데이터는 `ContentData[]` 타입의 배열입니다: + +```ts +interface ContentData { + // 페이지에 매핑된 URL입니다. 예: /posts/hello.html (base는 포함하지 않음) + // 수동으로 반복하거나 커스텀 `transform`을 사용하여 경로를 정규화. + url: string + // 페이지의 전문(front-matter) 데이터 + frontmatter: Record + + // 다음은 관련 옵션이 활성화된 경우에만 나타납니다. + // 아래에서 이에 대해 논의할 것입니다. + src: string | undefined + html: string | undefined + excerpt: string | undefined +} +``` + +기본적으로 `url`과 `frontmatter`만 제공됩니다. 이는 로드된 데이터가 클라이언트 번들에 JSON으로 인라인되기 때문에 크기에 주의해야 합니다. 다음은 데이터를 사용하여 최소한의 블로그 인덱스 페이지를 구축하는 예입니다: + +```vue + + + +``` + +### 옵션 {#options} + +기본 데이터가 모든 요구 사항에 충족하지 않을 수 있습니다. 옵션을 사용하여 데이터를 변환할 수 있습니다: + +```js [posts.data.js] +import { createContentLoader } from 'vitepress' + +export default createContentLoader('posts/*.md', { + includeSrc: true, // 원시 마크다운 소스를 포함할까요? + render: true, // 렌더링된 전체 페이지 HTML을 포함할까요? + excerpt: true, // 발췌문을 포함할까요? + transform(rawData) { + // 필요에 따라 원시 데이터를 매핑, 정렬 또는 필터링. + // 최종 결과를 클라이언트에 전달. + return rawData.sort((a, b) => { + return +new Date(b.frontmatter.date) - +new Date(a.frontmatter.date) + }).map((page) => { + page.src // 원시 마크다운 소스 + page.html // 렌더링된 전체 페이지 HTML + page.excerpt // 렌더링된 발췌문 HTML (첫 번째 `---` 위에 있는 내용) + return {/* ... */} + }) + } +}) +``` + +[Vue.js 블로그](https://github.com/vuejs/blog/blob/main/.vitepress/theme/posts.data.ts)에서 어떻게 사용되었는지 확인해보세요. + +`createContentLoader` API는 [빌드 훅](../reference/site-config#build-hooks) 내에서도 사용할 수 있습니다: + +```js [.vitepress/config.js] +export default { + async buildEnd() { + const posts = await createContentLoader('posts/*.md').load() + // 포스트 메타데이터를 기반으로 파일 생성하기, 예: RSS 피드 + // 게시물 메타데이터를 기반으로 파일 생성, 예: RSS 피드 + } +} +``` + +**타입** + +```ts +interface ContentOptions { + /** + * src를 포함할까요? + * @default false + */ + includeSrc?: boolean + + /** + * src를 HTML로 렌더링하고 데이터에 포함할까요? + * @default false + */ + render?: boolean + + /** + * `boolean` 타입인 경우, 발췌문을 파싱하고 포함할지 여부를 나타냅니다. (HTML로 렌더링됨) + * + * `function` 타입인 경우, 콘텐츠에서 발췌문을 추출하는 방법을 제어합니다. + * + * `string` 타입인 경우, 발췌문을 추출하는 데 사용할 커스텀 구분자를 정의합니다. + * `excerpt`가 `true`인 경우 기본 구분자는 `---`입니다. + * + * @see https://github.com/jonschlinkert/gray-matter#optionsexcerpt + * @see https://github.com/jonschlinkert/gray-matter#optionsexcerpt_separator + * + * @default false + */ + excerpt?: + | boolean + | ((file: { data: { [key: string]: any }; content: string; excerpt?: string }, options?: any) => void) + | string + + /** + * 데이터를 변환합니다. 데이터는 컴포넌트나 마크다운 파일에서 가져올 경우, + * 클라이언트 번들에 JSON으로 포함됩니다. + */ + transform?: (data: ContentData[]) => T | Promise +} +``` + +## 데이터 로더의 "export" 타입 {#typed-data-loaders} + +TypeScript를 사용할 때, 로더와 `data` "export"를 다음과 같이 타입 지정할 수 있습니다: + +```ts +import { defineLoader } from 'vitepress' + +export interface Data { + // 데이터 타입 +} + +declare const data: Data +export { data } + +export default defineLoader({ + // type checked loader options + watch: ['...'], + async load(): Promise { + // ... + } +}) +``` + +## 구성 {#configuration} + +로더 내부에서 구성 정보를 가져오려면 다음과 같이 코드를 사용해야 합니다: + +```ts +import type { SiteConfig } from 'vitepress' + +const config: SiteConfig = (globalThis as any).VITEPRESS_CONFIG +``` diff --git a/docs/ko/guide/deploy.md b/docs/ko/guide/deploy.md new file mode 100644 index 00000000..7a57a8ad --- /dev/null +++ b/docs/ko/guide/deploy.md @@ -0,0 +1,338 @@ +--- +outline: deep +--- + +# VitePress 사이트 배포하기 {#deploy-your-vitepress-site} + +다음 가이드는 몇 가지 공통된 가정을 기반으로 합니다: + +- VitePress 사이트는 프로젝트의 `docs` 디렉토리 안에 있다. +- 기본 빌드 출력 디렉토리(`.vitepress/dist`)를 사용하고 있다. +- VitePress는 프로젝트의 로컬 종속성으로 설치되어 있으며, `package.json`에 다음 스크립트가 설정되어 있다: + + ```json [package.json] + { + "scripts": { + "docs:build": "vitepress build docs", + "docs:preview": "vitepress preview docs" + } + } + ``` + +## 로컬에서 빌드하고 테스트하기 {#build-and-test-locally} + +1. 이 명령어를 실행하여 문서를 빌드합니다: + + ```sh + $ npm run docs:build + ``` + +2. 빌드가 완료되면, 다음 명령어를 실행하여 로컬에서 미리보기를 합니다: + + ```sh + $ npm run docs:preview + ``` + + `preview` 명령은 출력 디렉토리 `.vitepress/dist`를 `http://localhost:4173`에서 제공할 것입니다. 이를 사용하여 프로덕션에 푸시하기 전에 모든 것이 잘 보이는지 확인할 수 있습니다. + +3. `--port` 인자를 전달하여 서버의 포트를 구성할 수 있습니다. + + ```json + { + "scripts": { + "docs:preview": "vitepress preview docs --port 8080" + } + } + ``` + + 이제 `docs:preview` 메서드가 `http://localhost:8080`에서 서버를 시작합니다. + +## public 기본 경로 설정하기 {#setting-a-public-base-path} + +기본적으로 사이트가 도메인의 루트 경로(`/`)에 배포된다고 가정합니다. 예를 들어 사이트가 `https://mywebsite.com/blog/` 와 같은 서브 경로에서 제공될 경우, VitePress 구성에서 [`base`](../reference/site-config#base) 옵션을 `'/blog/'`로 설정해야 합니다. + +**예**: Github(또는 GitLab) Pages를 사용하여 `user.github.io/repo/`에 배포하는 경우, `base`를 `/repo/`로 설정하세요. + +## HTTP 캐시 헤더 {#http-cache-headers} + +프로덕션 서버에서 HTTP 헤더를 제어할 수 있다면, 반복 방문 시 더 나은 성능을 위해 `cache-control` 헤더를 구성할 수 있습니다. + +프로덕션 빌드는 정적 자산(JavaScript, CSS, `public`가 아닌 곳에서 가져온 에셋)에 대해 해시된 파일 이름을 사용합니다. 브라우저 개발 도구의 네트워크 탭을 사용하여 프로덕션 미리보기를 검사하면 `app.4f283b18.js`와 같은 파일을 볼 수 있습니다. + +이 `4f283b18` 해시는 파일의 내용에서 생성됩니다. 동일한 해시된 URL은 동일한 파일 내용을 제공할 것이 보장되며, 내용이 변경되면 URL도 변경됩니다. 이는 이러한 파일에 대해 가장 강력한 캐시 헤더를 안전하게 사용할 수 있음을 의미합니다. 모든 이러한 파일은 출력 디렉토리의 `assets/` 아래에 배치되므로, 다음 헤더를 구성할 수 있습니다: + +``` +Cache-Control: max-age=31536000,immutable +``` + +::: details Netlify `_headers` 파일 예시 + +``` +/assets/* + cache-control: max-age=31536000 + cache-control: immutable +``` + +참고: `_headers` 파일은 [public 디렉토리](./asset-handling#the-public-directory)에 배치해야 합니다. 이 경우 `docs/public/_headers`에 위치하여 출력 디렉토리에 그대로 복사됩니다. + +[Netlify 커스텀 헤더 문서](https://docs.netlify.com/routing/headers/) + +::: + +::: details Vercel 내의 `vercel.json` 구성 예시 + +```json +{ + "headers": [ + { + "source": "/assets/(.*)", + "headers": [ + { + "key": "Cache-Control", + "value": "max-age=31536000, immutable" + } + ] + } + ] +} +``` + +참고: `vercel.json` 파일은 **리포지토리**의 루트에 배치해야 합니다. + +[Vercel 헤더 구성에 대한 문서](https://vercel.com/docs/concepts/projects/project-configuration#headers) + +::: + +## 플랫폼 가이드 {#platform-guides} + +### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render + +새 프로젝트를 설정하고 대시보드를 사용하여 다음 설정을 변경하세요: + +- **빌드 명령어:** `npm run docs:build` +- **출력 디렉토리:** `docs/.vitepress/dist` +- **노드 버전:** `18` (또는 그 이상) + +::: warning +HTML 코드에 대해 _Auto Minify_ 옵션을 활성화하지 마세요. 이는 Vue에 의미가 있는 주석을 출력에서 제거할 것입니다. 제거되면 하이드레이션 불일치 오류가 발생할 수 있습니다. +::: + +### GitHub Pages + +1. 프로젝트의 `.github/workflows` 디렉토리 안에 `deploy.yml`이라는 파일을 만들고 다음과 같은 내용을 추가하세요: + + ```yaml [.github/workflows/deploy.yml] + # VitePress 사이트를 GitHub Pages에 빌드하고 배포하는 샘플 워크플로우 + # + name: VitePress 사이트를 Pages에 배포 + + on: + # `main` 브랜치를 대상으로 하는 푸시에서 실행됩니다. 기본 브랜치로 `master`를 사용하는 경우 여기를 `master`로 변경하세요. + push: + branches: [main] + + # Actions 탭에서 이 워크플로우를 수동으로 실행할 수 있게 합니다. + workflow_dispatch: + + # GitHub Pages에 배포할 수 있도록 GITHUB_TOKEN의 권한을 설정합니다. + permissions: + contents: read + pages: write + id-token: write + + # 진행 중인 실행과 마지막으로 대기 중인 실행 사이에 대기 중인 실행을 건너뛰어 하나의 동시 배포만 허용합니다. + # 그러나 이러한 프로덕션 배포가 완료되도록 진행 중인 실행은 취소하지 않습니다. + concurrency: + group: pages + cancel-in-progress: false + + jobs: + # 빌드 작업 + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 # lastUpdated가 활성화되지 않은 경우 필요하지 않음 + # - uses: pnpm/action-setup@v3 # pnpm을 사용하는 경우 주석 해제 + # with: + # version: 9 + # - uses: oven-sh/setup-bun@v1 # Bun을 사용하는 경우 주석 해제 + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm # 또는 pnpm / yarn + - name: Setup Pages + uses: actions/configure-pages@v4 + - name: Install dependencies + run: npm ci # 또는 pnpm install / yarn install / bun install + - name: Build with VitePress + run: npm run docs:build # 또는 pnpm docs:build / yarn docs:build / bun run docs:build + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: docs/.vitepress/dist + + # 배포 작업 + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + needs: build + runs-on: ubuntu-latest + name: Deploy + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 + ``` + + ::: warning + VitePress의 `base` 옵션이 제대로 구성되어 있는지 확인하세요. 자세한 내용은 [public 기본 경로 설정하기](#setting-a-public-base-path)를 참고하세요. + ::: + +2. 리포지토리 설정의 "Pages" 메뉴 항목에서 "Build and deployment > Source"에서 "GitHub Actions"를 선택하세요. + +3. 변경 사항을 `main` 브랜치에 푸시하고 GitHub Actions 워크플로우가 완료될 때까지 기다립니다. 설정에 따라 사이트가 `https://.github.io/[repository]/` 또는 `https:///`에 배포된 것을 볼 수 있습니다. 사이트는 `main` 브랜치에 푸시할 때마다 자동으로 배포됩니다. + +### GitLab Pages + +1. VitePress 구성에서 `outDir`을 `../public`으로 설정하세요. `https://.gitlab.io//`에 배포하려면 `base` 옵션을 `'//'`로 구성하세요. 커스텀 도메인, 유저 또는 그룹 페이지에 배포하거나 GitLab에서 "Use unique domain" 설정이 활성화된 경우에는 `base`가 필요하지 않습니다. + +2. 변경 사항을 적용할 때마다 사이트를 빌드하고 배포하도록 하기 위해 프로젝트의 루트에 다음 내용을 가진 `.gitlab-ci.yml` 파일을 생성하세요: + + ```yaml [.gitlab-ci.yml] + image: node:18 + pages: + cache: + paths: + - node_modules/ + script: + # - apk add git # alpine 과 같은 작은 도커 이미지를 사용하고 있고 lastUpdated 가 활성화된 경우 주석 처리를 제거하세요. + - npm install + - npm run docs:build + artifacts: + paths: + - public + only: + - main + ``` + +### Azure 정적 Web 앱 {#azure-static-web-apps} + +1. [공식 문서](https://docs.microsoft.com/en-us/azure/static-web-apps/build-configuration)를 따르세요. + +2. 구성 파일에 다음 값을 설정하세요(필요하지 않은 값들, 예를 들어 `api_location` 같은 것은 제거하세요): + + - **`app_location`**: `/` + - **`output_location`**: `docs/.vitepress/dist` + - **`app_build_command`**: `npm run docs:build` + +### Firebase {#firebase} + +1. 프로젝트 루트에 `firebase.json`과 `.firebaserc`를 생성하세요: + + `firebase.json`: + + ```json [firebase.json] + { + "hosting": { + "public": "docs/.vitepress/dist", + "ignore": [] + } + } + ``` + + `.firebaserc`: + + ```json [.firebaserc] + { + "projects": { + "default": "" + } + } + ``` + +2. `npm run docs:build`를 실행한 후, 배포하려면 이 명령어를 실행하세요: + + ```sh + firebase deploy + ``` + +### Surge + +1. `npm run docs:build`를 실행한 후, 배포하기 위해 이 명령어를 실행하세요: + + ```sh + npx surge docs/.vitepress/dist + ``` + +### Heroku + +1. [`heroku-buildpack-static`](https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-static)에 제공된 문서와 가이드를 따르세요. + +2. 프로젝트 루트에 아래 내용을 포함한 `static.json` 파일을 생성하세요: + + ```json [static.json] + { + "root": "docs/.vitepress/dist" + } + ``` + +### Edgio + +[Edgio에 VitePress 앱 생성 및 배포하기](https://docs.edg.io/guides/vitepress)를 참고하세요. + +### Kinsta 정적 사이트 호스팅 {#kinsta-static-site-hosting} + +[VitePress](https://kinsta.com/static-site-hosting/) 웹사이트를 [Kinsta](https://kinsta.com/static-site-hosting/)에 배포하려면 이 [지침](https://kinsta.com/docs/vitepress-static-site-example/)을 따르세요. + +### Stormkit + +[VitePress](https://stormkit.io) 프로젝트를 [Stormkit](https://www.stormkit.io)에 배포하려면 이 [지침](https://stormkit.io/blog/how-to-deploy-vitepress)을 따르세요. + +### Nginx + +다음은 Nginx 서버 블록 구성의 예입니다. 이 설정은 일반적인 텍스트 기반 에셋에 대한 gzip 압축, VitePress 사이트의 정적 파일을 적절한 캐싱 헤더와 함께 제공하는 규칙 및 `cleanUrls: true`를 처리하는 규칙을 포함합니다. + +```nginx +server { + gzip on; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + + listen 80; + server_name _; + index index.html; + + location / { + # 콘텐츠 위치 + root /app; + + # 정확히 일치하는 파일 -> 정제된 URL로 역방향 매핑 -> 폴더 -> 파일 없음 + try_files $uri $uri.html $uri/ =404; + + # 존재하지 않는 페이지 + error_page 404 /404.html; + + # index.html이 없는 폴더는 이 설정에서 403 오류를 발생시킴 + error_page 403 /404.html; + + # 캐싱 헤더 조정 + # assets 폴더의 파일들은 해시된 파일명 사용 + location ~* ^/assets/ { + expires 1y; + add_header Cache-Control "public, immutable"; + } + } +} +``` + +이 구성은 빌드된 VitePress 사이트가 서버의 `/app` 디렉토리에 위치한다고 가정합니다. 사이트 파일이 다른 곳에 위치한 경우 `root` 지시문을 적절하게 조정하세요. + +::: warning 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)에서 확인할 수 있습니다. diff --git a/docs/ko/guide/extending-default-theme.md b/docs/ko/guide/extending-default-theme.md new file mode 100644 index 00000000..0207e049 --- /dev/null +++ b/docs/ko/guide/extending-default-theme.md @@ -0,0 +1,331 @@ +--- +outline: deep +--- + +# 기본 테마 확장하기 {#extending-the-default-theme} + +VitePress의 기본 테마는 문서화에 최적화되어 있으며, 커스텀할 수 있습니다. 포괄적인 옵션 목록은 [기본 테마 구성](../reference/default-theme-config)을 참고하세요. + +그러나 구성만으로는 충분하지 않을 수 있습니다. 예를 들어: + +1. CSS 스타일링을 조정해야 하는 경우. +2. 전역 컴포넌트를 등록하기 위해 Vue 애플리케이션 인스턴스를 수정해야 하는 경우. +3. 레이아웃 슬롯을 통해 테마에 커스텀 컨텐츠를 삽입해야 하는 경우. + +이러한 고급 커스터마이징은 기본 테마를 "확장"하는 커스텀 테마 사용이 필요 합니다. + +::: tip +진행하기 전에, 커스텀 테마가 어떻게 작동하는지 이해하려면 먼저 [커스텀 테마 사용하기](./custom-theme)를 읽어보세요. +::: + +## CSS 커스터마이징하기 {#customizing-css} + +기본 테마의 CSS는 루트 레벨의 CSS 변수를 재정의하여 커스터마이징 할 수 있습니다: + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme' +import './custom.css' + +export default DefaultTheme +``` + +```css +/* .vitepress/theme/custom.css */ +:root { + --vp-c-brand-1: #646cff; + --vp-c-brand-2: #747bff; +} +``` + +재정의할 수 있는 기본 테마 CSS 변수는 [여기](https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css)를 참고하세요. + +## 다른 폰트 사용하기 {#using-different-fonts} + +VitePress는 기본 폰트로 [Inter](https://rsms.me/inter/)를 사용하며, 빌드 결과물에 폰트를 포함시킵니다. 폰트는 프로덕션 환경에서 자동으로 미리 로드되지만, 다른 메인 폰트를 사용하고자 할 경우 이는 바람직하지 않을 수 있습니다. + +빌드 결과물에 Inter를 포함시키지 않으려면, `vitepress/theme-without-fonts`에서 테마를 "import" 합니다: + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme-without-fonts' +import './my-fonts.css' + +export default DefaultTheme +``` + +```css +/* .vitepress/theme/my-fonts.css */ +:root { + --vp-font-family-base: /* 일반 텍스트 폰트 */ + --vp-font-family-mono: /* 코드 폰트 */ +} +``` + +::: warning +선택적 컴포넌트인 [팀 페이지](../reference/default-theme-team-page) 등을 사용하는 경우, 반드시 이들도 `vitepress/theme-without-fonts`에서 "import" 해야 합니다! +::: + +폰트가 `@font-face`를 통해 참조된 로컬 파일인 경우, 에셋으로 처리되어 해시된 파일 이름으로 `.vitepress/dist/assets`에 포함됩니다. 이 파일을 미리 로드하려면 [transformHead](../reference/site-config#transformhead) 빌드 훅을 사용해야 합니다: + +```js [.vitepress/config.js] +export default { + transformHead({ assets }) { + // 폰트를 매칭하기 위해 정규식을 적절히 조정하세요 + const myFontFile = assets.find(file => /font-name\.[\w-]+\.woff2/.test(file)) + if (myFontFile) { + return [ + [ + 'link', + { + rel: 'preload', + href: myFontFile, + as: 'font', + type: 'font/woff2', + crossorigin: '' + } + ] + ] + } + } +} +``` + +## 전역 컴포넌트 등록하기 {#registering-global-components} + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme' + +/** @type {import('vitepress').Theme} */ +export default { + extends: DefaultTheme, + enhanceApp({ app }) { + // 커스텀 전역 컴포넌트 등록 + app.component('MyGlobalComponent' /* ... */) + } +} +``` + +TypeScript를 사용하는 경우: +```ts [.vitepress/theme/index.ts] +import type { Theme } from 'vitepress' +import DefaultTheme from 'vitepress/theme' + +export default { + extends: DefaultTheme, + enhanceApp({ app }) { + // 커스텀 전역 컴포넌트 등록 + app.component('MyGlobalComponent' /* ... */) + } +} satisfies Theme +``` + +Vite를 사용하므로, Vite의 [glob import 기능](https://vitejs.dev/guide/features.html#glob-import)을 활용하여 컴포넌트 디렉터리를 자동으로 등록할 수 있습니다. + +## 레이아웃 슬롯 {#layout-slots} + +기본 테마의 `` 컴포넌트는 페이지의 특정 위치에 컨텐츠를 삽입할 수 있는 몇 가지 슬롯을 가지고 있습니다. 다음은 아웃라인 앞에 컴포넌트를 삽입하는 예제입니다: + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme' +import MyLayout from './MyLayout.vue' + +export default { + extends: DefaultTheme, + // 슬롯을 삽입하는 래퍼 컴포넌트로 + // Layout을 재정의합니다 + Layout: MyLayout +} +``` + +```vue [.vitepress/theme/MyLayout.vue] + + + +``` + +또는 렌더 함수를 사용할 수도 있습니다. + +```js [.vitepress/theme/index.js] +import { h } from 'vue' +import DefaultTheme from 'vitepress/theme' +import MyComponent from './MyComponent.vue' + +export default { + extends: DefaultTheme, + Layout() { + return h(DefaultTheme.Layout, null, { + 'aside-outline-before': () => h(MyComponent) + }) + } +} +``` + +기본 테마 레이아웃에서 사용할 수 있는 슬롯의 전체 목록: + +- 전문(front-matter)으로 `layout: 'doc'` (기본값)이 활성화된 경우: + - `doc-top` + - `doc-bottom` + - `doc-footer-before` + - `doc-before` + - `doc-after` + - `sidebar-nav-before` + - `sidebar-nav-after` + - `aside-top` + - `aside-bottom` + - `aside-outline-before` + - `aside-outline-after` + - `aside-ads-before` + - `aside-ads-after` +- 전문으로 `layout: 'home'`이 활성화된 경우: + - `home-hero-before` + - `home-hero-info-before` + - `home-hero-info` + - `home-hero-info-after` + - `home-hero-actions-after` + - `home-hero-image` + - `home-hero-after` + - `home-features-before` + - `home-features-after` +- 전문으로 `layout: 'page'`이 활성화된 경우: + - `page-top` + - `page-bottom` +- 페이지를 찾을 수 없음(404)일 때: + - `not-found` +- 항상: + - `layout-top` + - `layout-bottom` + - `nav-bar-title-before` + - `nav-bar-title-after` + - `nav-bar-content-before` + - `nav-bar-content-after` + - `nav-screen-content-before` + - `nav-screen-content-after` + +## 뷰 트랜지션 API 사용하기 {#using-view-transitions-api} + +### 외형 토글 {#on-appearance-toggle} + +기본 테마를 확장하여 컬러 모드가 전환될 때 커스텀 트랜지션 효과를 제공할 수 있습니다. 예제: + +```vue [.vitepress/theme/Layout.vue] + + + + + +``` + +결과 (**광과민성 주의!**: 색상 깜빡임, 갑작스러운 움직임, 밝은 빛): + +
+데모 + +![외형 토글 트랜지션 데모](/appearance-toggle-transition.webp) + +
+ +뷰 트랜지션에 대한 자세한 정보는 [크롬 문서](https://developer.chrome.com/docs/web-platform/view-transitions/)를 참고하세요. + +### 라우트 변경 시 {#on-route-change} + +곧 제공될 예정입니다. + +## 내부 컴포넌트 재정의하기 {#overriding-internal-components} + +Vite의 [별칭](https://vitejs.dev/config/shared-options.html#resolve-alias)을 사용하여 기본 테마 컴포넌트를 커스텀 컴포넌트로 대체할 수 있습니다: + +```ts +import { fileURLToPath, URL } from 'node:url' +import { defineConfig } from 'vitepress' + +export default defineConfig({ + vite: { + resolve: { + alias: [ + { + find: /^.*\/VPNavBar\.vue$/, + replacement: fileURLToPath( + new URL('./components/CustomNavBar.vue', import.meta.url) + ) + } + ] + } + } +}) +``` + +컴포넌트의 정확한 이름을 알고 싶다면 [Vitepress 소스 코드](https://github.com/vuejs/vitepress/tree/main/src/client/theme-default/components)를 참고하세요. 컴포넌트는 내부적으로 사용되기 때문에, 마이너 릴리즈 사이에 이름이 변경될 가능성이 있습니다. diff --git a/docs/ko/guide/frontmatter.md b/docs/ko/guide/frontmatter.md new file mode 100644 index 00000000..09b1a2cd --- /dev/null +++ b/docs/ko/guide/frontmatter.md @@ -0,0 +1,48 @@ +# 전문 {#frontmatter} + +## 사용법 {#usage} + +VitePress는 모든 마크다운 파일에서 YAML 전문(frontmatter)을 지원하며, [gray-matter](https://github.com/jonschlinkert/gray-matter)로 이를 파싱합니다. 전문은 마크다운 파일의 맨 위에 있어야 하며(모든 엘리먼트 포함 ` + + +``` + +## RTL 지원 (실험적) {#rtl-support-experimental} + +RTL 지원을 위해, 구성 파일에 `dir: 'rtl'`을 지정하고 , 또는 와 같은 RTLCSS PostCSS 플러그인을 사용하세요. PostCSS 플러그인을 구성하여 CSS 명시성 문제를 방지하기 위해 `:where([dir="ltr"])` 및 `:where([dir="rtl"])`을 접두사로 사용해야 합니다. diff --git a/docs/ko/guide/markdown.md b/docs/ko/guide/markdown.md new file mode 100644 index 00000000..5f03bbf6 --- /dev/null +++ b/docs/ko/guide/markdown.md @@ -0,0 +1,966 @@ +# 마크다운 확장 기능 {#markdown-extensions} + +VitePress는 내장된 마크다운 확장 기능을 제공합니다. + +## 헤더 앵커 {#header-anchors} + +헤더에는 자동으로 앵커 링크가 적용됩니다. 앵커 렌더링은 `markdown.anchor` 옵션을 사용하여 구성할 수 있습니다. + +### 커스텀 앵커 {#custom-anchors} + +자동 생성된 앵커 대신 커스텀 앵커 태그를 지정하려면 헤딩에 접미사를 추가하세요: + +``` +# Using custom anchors {#my-anchor} +``` + +이를 통해 기본값인 `#using-custom-anchors` 대신 `#my-anchor`로 헤딩에 링크할 수 있습니다. + +## 링크 {#links} + +내부 링크와 외부 링크 모두 특별하게 취급됩니다. + +### 내부 링크 {#internal-links} + +내부 링크는 SPA 탐색을 위한 라우터 링크로 변환됩니다. 또한 각 하위 디렉터리에 포함된 모든 `index.md`는 자동으로 `index.html`로 변환되며, 해당 URL은 `/`로 설정됩니다. + +예를 들어, 다음과 같은 디렉터리 구조가 주어진 경우: + +``` +. +├─ index.md +├─ foo +│ ├─ index.md +│ ├─ one.md +│ └─ two.md +└─ bar + ├─ index.md + ├─ three.md + └─ four.md +``` + +그리고 현재 `foo/one.md`에 있다고 가정하면: + +```md +[Home](/) +[foo](/foo/) +[foo heading](./#heading) +[bar - three](../bar/three) +[bar - three](../bar/three.md) +[bar - four](../bar/four.html) +``` + +### 페이지 접미사 {#page-suffix} + +페이지와 내부 링크는 기본적으로 `.html` 접미사와 함께 생성됩니다. + +### 외부 링크 {#external-links} + +외부 링크는 자동으로 `target="_blank" rel="noreferrer"`를 갖습니다. + +- [vuejs.org](https://vuejs.org) +- [VitePress on GitHub](https://github.com/vuejs/vitepress) + +## 전문 {#frontmatter} + +[YAML 전문](https://jekyllrb.com/docs/front-matter/)이 기본적으로 지원됩니다: + +```yaml +--- +title: Blogging Like a Hacker +lang: en-US +--- +``` + +이 데이터는 페이지의 나머지 부분과 모든 커스텀 및 테마 컴포넌트에서 사용할 수 있습니다. + +자세한 내용은 [전문](../reference/frontmatter-config)을 참고하세요. + +## GitHub 스타일 테이블 {#github-style-tables} + +**입력** + +```md +| Tables | Are | Cool | +| ------------- | :-----------: | ----: | +| col 3 is | right-aligned | $1600 | +| col 2 is | centered | $12 | +| zebra stripes | are neat | $1 | +``` + +**출력** + +| Tables | Are | Cool | +| ------------- | :-----------: | ----: | +| col 3 is | right-aligned | $1600 | +| col 2 is | centered | $12 | +| zebra stripes | are neat | $1 | + +## 이모지 :tada: {#emoji} + +**입력** + +``` +:tada: :100: +``` + +**출력** + +:tada: :100: + +[모든 이모지의 목록](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.mjs)이 제공됩니다. + +## 목차 {#table-of-contents} + +**입력** + +``` +[[toc]] +``` + +**출력** + +[[toc]] + +목차의 렌더링은 `markdown.toc` 옵션을 사용하여 구성할 수 있습니다. + +## 커스텀 컨테이너 {#custom-containers} + +커스텀 컨테이너는 타입, 제목, 콘텐츠를 정의할 수 있습니다. + +### 기본 제목 {#default-title} + +**입력** + +```md +::: info +정보 상자입니다. +::: + +::: tip +팁입니다. +::: + +::: warning +경고입니다. +::: + +::: danger +위험한 경고입니다. +::: + +::: details +세부 정보 블록입니다. +::: +``` + +**출력** + +::: info +정보 상자입니다. +::: + +::: tip +팁입니다. +::: + +::: warning +경고입니다. +::: + +::: danger +위험한 경고입니다. +::: + +::: details +세부 정보 블록입니다. +::: + +### 사용자 정의 제목 {#custom-title} + +컨테이너의 "타입" 바로 뒤에 텍스트를 추가하여 커스텀 제목을 설정할 수 있습니다. + +**입력** + +````md +::: danger 정지 +위험 지대, 진행하지 마세요 +::: + +::: details 코드를 보려면 클릭하세요 +```js +console.log('Hello, VitePress!') +``` +::: +```` + +**출력** + +::: danger 정지 +위험 지대, 진행하지 마세요 +::: + +::: details 코드를 보려면 클릭하세요 +```js +console.log('Hello, VitePress!') +``` +::: + +또는 사이트 구성에 다음을 추가하여 커스텀 제목을 전역적으로 설정할 수 있습니다. 이는 제목을 영어로 작성하지 않을 경우 유용합니다: + +```ts +// config.ts +export default defineConfig({ + // ... + markdown: { + container: { + tipLabel: '팁', + warningLabel: '경고', + dangerLabel: '위험', + infoLabel: '정보', + detailsLabel: '세부 정보' + } + } + // ... +}) +``` + +### `raw` + +이것은 VitePress와 스타일 및 라우터 충돌을 방지하기 위해 사용할 수 있는 특별한 컨테이너입니다. 컴포넌트 라이브러리를 문서화할 때 특히 유용합니다. 더 나은 분리를 위해 [whyframe](https://whyframe.dev/docs/integrations/vitepress)을 참고해 볼 수 있습니다. + +**문법** + +```md +::: raw +`
`로 감쌉니다 +::: +``` + +`vp-raw` 클래스는 엘리먼트에 직접 사용할 수도 있습니다. 스타일 분리는 현재 선택 사항입니다: + +- 선호하는 패키지 매니저를 사용하여 `postcss`를 설치하세요: + + ```sh + $ npm add -D postcss + ``` + +- `docs/postcss.config.mjs`라는 파일을 만들고 다음 내용을 추가하세요: + + ```js + import { postcssIsolateStyles } from 'vitepress' + + export default { + plugins: [postcssIsolateStyles()] + } + ``` + + 이것은 기본적으로 [`postcss-prefix-selector`](https://github.com/RadValentin/postcss-prefix-selector)를 사용합니다. 다음과 같이 옵션을 전달할 수 있습니다: + + ```js + postcssIsolateStyles({ + includeFiles: [/vp-doc\.css/] // 기본값은 /base\.css/ + }) + ``` + +## 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)와 같은 방식으로 렌더링됩니다. + +```md +> [!NOTE] +> 문서를 빠르게 탐색할 때에도 사용자가 놓치지 말아야 할 중요한 정보. + +> [!TIP] +> 사용자가 보다 원활하게 목표를 달성하는 데 도움이 되는 정보 + +> [!IMPORTANT] +> 사용자가 목표를 달성하는 데 중요한 정보. + +> [!WARNING] +> 위험 가능성 때문에 사용자의 즉각적인 주의가 필요한 중요한 정보. + +> [!CAUTION] +> 실행할 경우 잠재적으로 부정적인 결과를 생성한다는 것을 알리는 정보. +``` + +> [!NOTE] +> 문서를 빠르게 탐색할 때에도 사용자가 놓치지 말아야 할 중요한 정보. + +> [!TIP] +> 사용자가 보다 원활하게 목표를 달성하는 데 도움이 되는 정보 + +> [!IMPORTANT] +> 사용자가 목표를 달성하는 데 중요한 정보. + +> [!WARNING] +> 위험 가능성 때문에 사용자의 즉각적인 주의가 필요한 중요한 정보. + +> [!CAUTION] +> 실행할 경우 잠재적으로 부정적인 결과를 생성한다는 것을 알리는 정보. + +## 코드 블록 내 구문 강조 {#syntax-highlighting-in-code-blocks} + +VitePress는 마크다운 코드 블록 내 언어 문법을 색상이 있는 텍스트로 강조하기 위해 [Shiki](https://github.com/shikijs/shiki)를 사용합니다. Shiki는 다양한 프로그래밍 언어를 지원합니다. 코드 블록의 시작 백틱에 유효한 언어 별칭을 추가하기만 하면 됩니다: + +**입력** + +````markdown +```js +export default { + name: 'MyComponent', + // ... +} +``` +```` + +````markdown +```html +
    +
  • + {{ todo.text }} +
  • +
+``` +```` + +**출력** + +```js +export default { + name: 'MyComponent', + // ... +} +``` + +```html +
    +
  • + {{ todo.text }} +
  • +
+``` + +Shiki의 리포지터리에서 사용 가능한 [유효한 언어 목록](https://shiki.style/languages)이 제공됩니다. + +또한 애플리케이션 구성에서 구문 강조 테마를 커스텀 할 수 있습니다. 자세한 내용은 [`markdown` 옵션](../reference/site-config#markdown)을 참고하세요. + +## 코드 블록에서 라인 강조 {#line-highlighting-in-code-blocks} + +**입력** + +````markdown +```js{4} +export default { + data () { + return { + msg: '강조됨!' + } + } +} +``` +```` + +**출력** + +```js{4} +export default { + data() { + return { + msg: '강조됨!' + } + } +} +``` + +단일 라인 뿐만 아니라 여러 개의 단일 라인, 범위 또는 둘 다 지정할 수도 있습니다: + +- 라인 범위: `{5-8}`, `{3-10}`, `{10-17}` +- 여러 단일 라인: `{4,7,9}` +- 라인 범위와 단일 라인: `{4,7-13,16,23-27,40}` + +**입력** + +````markdown +```js{1,4,6-8} +export default { // 강조됨 + data () { + return { + msg: `강조됨! + 이 줄은 강조되지 않습니다, + 하지만 이 줄과 다음 2줄은 강조됩니다.`, + motd: 'VitePress는 멋져요', + lorem: 'ipsum' + } + } +} +``` +```` + +**출력** + +```js{1,4,6-8} +export default { // 강조됨 + data () { + return { + msg: `강조됨! + 이 줄은 강조되지 않습니다, + 하지만 이 줄과 다음 2줄은 강조됩니다.`, + motd: 'VitePress는 멋져요', + lorem: 'ipsum', + } + } +} +``` + +또는 `// [!code highlight]` 주석을 사용하여 직접 라인에 강조를 추가할 수 있습니다. + +**입력** + +````markdown +```js +export default { + data () { + return { + msg: '강조됨!' // [!!code highlight] + } + } +} +``` +```` + +**출력** + +```js +export default { + data () { + return { + msg: '강조됨!' // [!code highlight] + } + } +} +``` + +## 코드 블록에서 포커싱 {#focus-in-code-blocks} + +`// [!code focus]` 주석을 라인에 추가하면 해당 라인이 포커싱되고 코드의 다른 부분은 흐릿하게 처리됩니다. + +추가로 `// [!code focus:]`를 사용하여 포커싱할 라인 수를 정의할 수 있습니다. + +**입력** + +````markdown +```js +export default { + data () { + return { + msg: '포커싱됨!' // [!!code focus] + } + } +} +``` +```` + +**출력** + +```js +export default { + data () { + return { + msg: '포커싱됨!' // [!code focus] + } + } +} +``` + +## 코드 블록 내 차이점 색 강조 {#colored-diffs-in-code-blocks} + +`// [!code --]` 또는 `// [!code ++]` 주석을 라인에 추가하면 해당 라인의 차이점을 나타내며, 코드 블록의 색상을 유지합니다. + +**입력** + +````markdown +```js +export default { + data () { + return { + msg: '삭제됨' // [!!code --] + msg: '추가됨' // [!!code ++] + } + } +} +``` +```` + +**출력** + +```js +export default { + data () { + return { + msg: '삭제됨' // [!code --] + msg: '추가됨' // [!code ++] + } + } +} +``` + +## 코드 블록 내 오류 및 경고 {#errors-and-warnings-in-code-blocks} + +`// [!code warning]` 또는 `// [!code error]` 주석을 라인에 추가하면 해당 라인이 색칠됩니다. + +**입력** + +````markdown +```js +export default { + data () { + return { + msg: '오류', // [!!code error] + msg: '경고' // [!!code warning] + } + } +} +``` +```` + +**출력** + +```js +export default { + data () { + return { + msg: '오류', // [!code error] + msg: '경고' // [!code warning] + } + } +} +``` + +## 라인 번호 {#line-numbers} + +구성을 통해 각 코드 블록에 라인 번호를 활성화할 수 있습니다: + +```js +export default { + markdown: { + lineNumbers: true + } +} +``` + +자세한 내용은 [`markdown` 옵션](../reference/site-config#markdown)을 참고하세요. + +구성에서 지정한 값을 무시하려면 펜싱 코드 블록에 `:line-numbers` / `:no-line-numbers` 마크를 추가하면 됩니다. + +또한 `=`를 `:line-numbers` 뒤에 추가하여 시작 라인 번호를 커스텀 할 수도 있습니다. 예를 들어 `:line-numbers=2`는 코드 블록의 라인 번호가 `2`부터 시작함을 의미합니다. + +**입력** + +````md +```ts {1} +// 줄 번호는 기본적으로 비활성화되어 있음 +const line2 = 'This is line 2' +const line3 = 'This is line 3' +``` + +```ts:line-numbers {1} +// 줄 번호가 활성화됨 +const line2 = 'This is line 2' +const line3 = 'This is line 3' +``` + +```ts:line-numbers=2 {1} +// 줄 번호가 활성화되고 2부터 시작함 +const line3 = 'This is line 3' +const line4 = 'This is line 4' +``` +```` + +**출력** + +```ts {1} +// 줄 번호는 기본적으로 비활성화되어 있음 +const line2 = 'This is line 2' +const line3 = 'This is line 3' +``` + +```ts:line-numbers {1} +// 줄 번호가 활성화됨 +const line2 = 'This is line 2' +const line3 = 'This is line 3' +``` + +```ts:line-numbers=2 {1} +// 줄 번호가 활성화되고 2부터 시작함 +const line3 = 'This is line 3' +const line4 = 'This is line 4' +``` + +## 코드 스니펫 가져오기 {#import-code-snippets} + +다음 문법을 통해 기존 파일에서 코드 스니펫을 가져올 수 있습니다: + +```md +<<< @/파일경로 +``` + +다음과 같이 [라인 강조](#line-highlighting-in-code-blocks)도 지원합니다: + +```md +<<< @/파일경로{강조 할 라인} +``` + +**입력** + +```md +<<< @/snippets/snippet.js{2} +``` + +**코드 파일** + +<<< @/snippets/snippet.js + +**출력** + +<<< @/snippets/snippet.js{2} + +::: tip +`@`의 값은 소스 루트에 해당합니다. 기본값은 VitePress 프로젝트 루트이지만, `srcDir`이 구성되어 있을 경우에는 다릅니다. 상대 경로에서도 가져올 수도 있습니다: + +```md +<<< ../snippets/snippet.js +``` + +::: + +특정 부분의 코드 파일만 포함하려면 [VS Code 리전](https://code.visualstudio.com/docs/editor/codebasics#_folding)을 사용할 수 있습니다. 파일 경로 뒤에 `#`을 사용한 다음 커스텀 리전 이름을 제공할 수 있습니다: + +**입력** + +```md +<<< @/snippets/snippet-with-region.js#snippet{1} +``` + +**코드 파일** + +<<< @/snippets/snippet-with-region.js + +**출력** + +<<< @/snippets/snippet-with-region.js#snippet{1} + +괄호(`{}`) 안에 언어를 지정할 수도 있습니다: + +```md +<<< @/snippets/snippet.cs{c#} + + + +<<< @/snippets/snippet.cs{1,2,4-6 c#} + + + +<<< @/snippets/snippet.cs{1,2,4-6 c#:line-numbers} +``` + +이는 파일 확장명에서 소스 언어를 유추할 수 없을 때 유용합니다. + +## 코드 그룹 {#code-groups} + +다음과 같이 여러 코드 블록을 그룹화할 수 있습니다: + +**입력** + +````md +::: code-group + +```js [config.js] +/** + * @type {import('vitepress').UserConfig} + */ +const config = { + // ... +} + +export default config +``` + +```ts [config.ts] +import type { UserConfig } from 'vitepress' + +const config: UserConfig = { + // ... +} + +export default config +``` + +::: +```` + +**출력** + +::: code-group + +```js [config.js] +/** + * @type {import('vitepress').UserConfig} + */ +const config = { + // ... +} + +export default config +``` + +```ts [config.ts] +import type { UserConfig } from 'vitepress' + +const config: UserConfig = { + // ... +} + +export default config +``` + +::: + +코드 그룹에서 [스니펫 가져오기](#import-code-snippets)도 할 수 있습니다: + +**입력** + +```md +::: code-group + + + +<<< @/snippets/snippet.js + + + +<<< @/snippets/snippet-with-region.js#snippet{1,2 ts:line-numbers} [지역 스니펫] + +::: +``` + +**출력** + +::: code-group + +<<< @/snippets/snippet.js + +<<< @/snippets/snippet-with-region.js#snippet{1,2 ts:line-numbers} [지역 스니펫] + +::: + +## 마크다운 파일 포함 {#markdown-file-inclusion} + +마크다운 파일을 다른 마크다운 파일에 포함시킬 수 있으며, 중첩도 가능합니다. + +::: tip +마크다운 경로 앞에 `@`를 붙일 수도 있으며, 이는 소스 루트로 작동합니다. 기본적으로 이는 VitePress 프로젝트 루트이며, `srcDir`이 구성되지 않은 경우입니다. +::: + +다음과 같이 상대적인 마크다운 파일을 포함시킬 수 있습니다: + +**입력** + +```md +# Docs + +## Basics + + +``` + +**해당 파일** (`parts/basics.md`) + +```md +Some getting started stuff. + +### Configuration + +Can be created using `.foorc.json`. +``` + +**동일한 코드** + +```md +# Docs + +## Basics + +Some getting started stuff. + +### Configuration + +Can be created using `.foorc.json`. +``` + +라인 범위 선택도 지원합니다: + +**입력** + +```md +# Docs + +## Basics + + +``` + +**해당 파일** (`parts/basics.md`) + +```md +Some getting started stuff. + +### Configuration + +Can be created using `.foorc.json`. +``` + +**동일한 코드** + +```md +# Docs + +## Basics + +### Configuration + +Can be created using `.foorc.json`. +``` + +선택된 라인 범위의 형식은 `{3,}`, `{,10}`, `{1,10}`이 될 수 있습니다. + +[VS Code 리전](https://code.visualstudio.com/docs/editor/codebasics#_folding)을 사용하여 코드 파일의 해당 부분만 포함할 수도 있습니다. 파일 경로 뒤에 `#`를 붙이고 커스텀 영역 이름을 제공할 수 있습니다: + +**입력** + +```md +# Docs + +## Basics + + + +``` + +**해당 파일** (`parts/basics.md`) + +```md + +## Usage Line 1 + +## Usage Line 2 + +## Usage Line 3 + +``` + +**동일한 코드** + +```md +# Docs + +## Basics + +## Usage Line 1 + +## Usage Line 3 +``` + +::: warning +파일이 존재하지 않더라도 오류가 발생하지 않는다는 점에 유의하십시오. 따라서 이 기능을 사용할 때 내용이 예상대로 렌더링되고 있는지 확인해야 합니다. +::: + +## 수식 {#math-equations} + +선택 사항입니다. 활성화하려면 `markdown-it-mathjax3`를 설치하고 설정 파일에서 `markdown.math`를 `true`로 설정해야 합니다: + +```sh +npm add -D markdown-it-mathjax3 +``` + +```ts [.vitepress/config.ts] +export default { + markdown: { + math: true + } +} +``` + +**입력** + +```md +$a \ne 0$ 일 때, $(ax^2 + bx + c = 0)$의 두 해는 다음과 같습니다: +$$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ + +**맥스웰 방정식:** + +| 방정식 | 설명 | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | +| $\nabla \cdot \vec{\mathbf{B}} = 0$ | $\vec{\mathbf{B}}$의 발산은 0입니다 | +| $\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | $\vec{\mathbf{E}}$의 회전은 $\vec{\mathbf{B}}$의 시간에 따른 변화율에 비례합니다 | +| $\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | _wha?_ | +``` + +**출력** + +$a \ne 0$ 일 때, $(ax^2 + bx + c = 0)$의 두 해는 다음과 같습니다: +$$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ + +**맥스웰 방정식:** + +| 방정식 | 설명 | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | +| $\nabla \cdot \vec{\mathbf{B}} = 0$ | $\vec{\mathbf{B}}$의 발산은 0입니다 | +| $\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | $\vec{\mathbf{E}}$의 회전은 $\vec{\mathbf{B}}$의 시간에 따른 변화율에 비례합니다 | +| $\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | _wha?_ | + +## 이미지 지연 로딩 {#image-lazy-loading} + +마크다운을 통해 추가된 각 이미지에 대해 지연 로딩을 활성화하려면 구성 파일에서 `lazyLoading`을 `true`로 설정하세요: + +```js +export default { + markdown: { + image: { + // 이미지 지연 로딩은 기본적으로 비활성화 되어 있습니다 + lazyLoading: true + } + } +} +``` + +## 고급 설정 {#advanced-configuration} + +VitePress는 마크다운 렌더러로 [markdown-it](https://github.com/markdown-it/markdown-it)을 사용합니다. 위의 많은 확장 기능은 커스텀 플러그인을 통해 구현됩니다. `.vitepress/config.js`의 `markdown` 옵션을 사용하여 `markdown-it` 인스턴스를 추가로 커스터마이즈할 수 있습니다: + +```js +import { defineConfig } from 'vitepress' +import markdownItAnchor from 'markdown-it-anchor' +import markdownItFoo from 'markdown-it-foo' + +export default defineConfig({ + markdown: { + // markdown-it-anchor의 옵션 + // https://github.com/valeriangalliat/markdown-it-anchor#usage + anchor: { + permalink: markdownItAnchor.permalink.headerLink() + }, + + // @mdit-vue/plugin-toc의 옵션 + // https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-toc#options + toc: { level: [1, 2] }, + + config: (md) => { + // 더 많은 markdown-it 플러그인을 사용! + md.use(markdownItFoo) + } + } +}) +``` + +구성 가능한 프로퍼티의 전체 목록은 [레퍼런스: 앱 구성](../reference/site-config#markdown)에서 확인하세요. diff --git a/docs/ko/guide/migration-from-vitepress-0.md b/docs/ko/guide/migration-from-vitepress-0.md new file mode 100644 index 00000000..f3ba5293 --- /dev/null +++ b/docs/ko/guide/migration-from-vitepress-0.md @@ -0,0 +1,23 @@ +# Migration from VitePress 0.x {#migration-from-vitepress-0-x} + +If you're coming from VitePress 0.x version, there're several breaking changes due to new features and enhancement. Please follow this guide to see how to migrate your app over to the latest VitePress. + +## App Config {#app-config} + +- The internationalization feature is not yet implemented. + +## Theme Config {#theme-config} + +- `sidebar` option has changed its structure. + - `children` key is now named `items`. + - Top level item may not contain `link` at the moment. We're planning to bring it back. +- `repo`, `repoLabel`, `docsDir`, `docsBranch`, `editLinks`, `editLinkText` are removed in favor of more flexible api. + - For adding GitHub link with icon to the nav, use [Social Links](../reference/default-theme-nav#navigation-links) feature. + - For adding "Edit this page" feature, use [Edit Link](../reference/default-theme-edit-link) feature. +- `lastUpdated` option is now split into `config.lastUpdated` and `themeConfig.lastUpdatedText`. +- `carbonAds.carbon` is changed to `carbonAds.code`. + +## Frontmatter Config {#frontmatter-config} + +- `home: true` option has changed to `layout: home`. Also, many Homepage related settings have been modified to provide additional features. See [Home Page guide](../reference/default-theme-home-page) for details. +- `footer` option is moved to [`themeConfig.footer`](../reference/default-theme-config#footer). diff --git a/docs/ko/guide/migration-from-vuepress.md b/docs/ko/guide/migration-from-vuepress.md new file mode 100644 index 00000000..c554e260 --- /dev/null +++ b/docs/ko/guide/migration-from-vuepress.md @@ -0,0 +1,30 @@ +# Migration from VuePress {#migration-from-vuepress} + +## Config {#config} + +### Sidebar {#sidebar} + +The sidebar is no longer automatically populated from frontmatter. You can [read the frontmatter yourself](https://github.com/vuejs/vitepress/issues/572#issuecomment-1170116225) to dynamically populate the sidebar. [Additional utilities for this](https://github.com/vuejs/vitepress/issues/96) may be provided in the future. + +## Markdown {#markdown} + +### Images {#images} + +Unlike VuePress, VitePress handles [`base`](./asset-handling#base-url) of your config automatically when you use static image. + +Hence, now you can render images without `img` tag. + +```diff +- foo ++ ![foo](/foo.png) +``` + +::: warning +For dynamic images you still need `withBase` as shown in [Base URL guide](./asset-handling#base-url). +::: + +Use `` regex to find and replace it with `![$2]($1)` to replace all the images with `![](...)` syntax. + +--- + +more to follow... diff --git a/docs/ko/guide/mpa-mode.md b/docs/ko/guide/mpa-mode.md new file mode 100644 index 00000000..b3308738 --- /dev/null +++ b/docs/ko/guide/mpa-mode.md @@ -0,0 +1,23 @@ +# MPA 모드 {#mpa-mode} + +MPA (다중 페이지 애플리케이션) 모드는 명령줄에서 `vitepress build --mpa`를 통해 활성화할 수 있으며, 구성 파일에서 `mpa: true` 옵션을 통해서도 활성화할 수 있습니다. + +MPA 모드에서는 모든 페이지가 기본적으로 JavaScript 없이 렌더링됩니다. 그 결과, 프로덕션 사이트는 감사 도구로부터 초기 방문 성능 점수가 더 좋을 가능성이 있습니다. + +그러나 SPA 탐색이 없기 때문에 페이지 간 링크는 전체 페이지를 새로 고침합니다. MPA 모드에서의 포스트-로드 탐색은 SPA 모드만큼 즉각적으로 느껴지지 않을 것입니다. + +또한 기본적으로 JS가 없다는 것은 Vue를 순전히 서버 사이드 템플릿 언어로 사용하고 있다는 것을 의미합니다. 브라우저에서는 이벤트 핸들러가 첨부되지 않으므로 상호작용이 없습니다. 클라이언트 사이드 JavaScript를 로드하려면 특별한 ` + +# Hello +``` + +` +``` + +### 원시 콘텐츠 렌더링 {#rendering-raw-content} + +페이지에 전달되는 파라미터는 클라이언트 JavaScript 페이로드에서 직렬화되므로, 원격 CMS에서 가져온 원시 Markdown이나 HTML 콘텐츠와 같은 무거운 데이터를 파라미터로 전달하지 마십시오. + +대신, 각 경로 객체의 `content` 프로퍼티를 사용하여 이러한 콘텐츠를 각 페이지에 전달할 수 있습니다: + +```js +export default { + async paths() { + const posts = await (await fetch('https://my-cms.com/blog-posts')).json() + + return posts.map((post) => { + return { + params: { id: post.id }, + content: post.content // 원시 마크다운 또는 HTML + } + }) + } +} +``` + +그런 다음 특수 문법을 사용하여 마크다운 파일 자체의 일부로 콘텐츠를 렌더링할 수 있습니다: + +```md + +``` diff --git a/docs/ko/guide/sitemap-generation.md b/docs/ko/guide/sitemap-generation.md new file mode 100644 index 00000000..54db8e8a --- /dev/null +++ b/docs/ko/guide/sitemap-generation.md @@ -0,0 +1,58 @@ +# 사이트맵 생성 {#sitemap-generation} + +VitePress는 사이트의 `sitemap.xml` 파일 생성을 지원합니다. 이를 활성화하려면 `.vitepress/config.js`에 다음을 추가하십시오: + +```ts +export default { + sitemap: { + hostname: 'https://example.com' + } +} +``` + +`` 태그를 `sitemap.xml`에 포함하려면 [`lastUpdated`](../reference/default-theme-last-updated) 옵션을 활성화할 수 있습니다. + +## 옵션 {#options} + +사이트맵 지원은 [`sitemap`](https://www.npmjs.com/package/sitemap) 모듈에 의해 제공됩니다. 구성 파일의 `sitemap` 옵션에 지원되는 모든 옵션을 전달할 수 있습니다. 이러한 옵션은 `SitemapStream` 생성자에 직접 전달됩니다. 자세한 내용은 [`sitemap` 문서](https://www.npmjs.com/package/sitemap#options-you-can-pass)를 참고하세요. 예: + +```ts +export default { + sitemap: { + hostname: 'https://example.com', + lastmodDateOnly: false + } +} +``` + +구성 파일에서 `base`를 사용하는 경우, `hostname` 옵션에 이것을 추가해야 합니다: + +```ts +export default { + base: '/my-site/', + sitemap: { + hostname: 'https://example.com/my-site/' + } +} +``` + +## `transformItems` Hook {#transformitems-hook} + +`sitemap.transformItems` 훅을 사용하여 `sitemap.xml` 파일에 작성되기 전에 사이트맵 아이템을 수정할 수 있습니다. 이 훅은 사이트맵 아이템 배열을 인자로 받고 사이트맵 아이템 배열을 반환해야 합니다. 예제: + +```ts +export default { + sitemap: { + hostname: 'https://example.com', + transformItems: (items) => { + // 새로운 아이템 추가 또는 기존 아이템 수정/필터링 + items.push({ + url: '/extra-page', + changefreq: 'monthly', + priority: 0.8 + }) + return items + } + } +} +``` diff --git a/docs/ko/guide/ssr-compat.md b/docs/ko/guide/ssr-compat.md new file mode 100644 index 00000000..acf595e1 --- /dev/null +++ b/docs/ko/guide/ssr-compat.md @@ -0,0 +1,134 @@ +--- +outline: deep +--- + +# SSR 호환성 {#ssr-compatibility} + +VitePress는 Vue의 서버 사이드 렌더링(SSR) 기능을 사용하여 프로덕션 빌드 중에 Node.js에서 애플리케이션을 사전 렌더링합니다. 이는 테마 컴포넌트의 모든 커스텀 코드가 SSR 호환성을 준수해야 함을 의미합니다. + +공식 Vue 문서의 [SSR 섹션](https://vuejs.org/guide/scaling-up/ssr.html)은 SSR이 무엇인지, SSR / SSG 간의 관계, 그리고 SSR 친화적인 코드를 작성할 때의 일반적인 주의 사항에 대해 더 많은 정보를 제공합니다. 핵심 원칙은 Vue 컴포넌트의 `beforeMount` 또는 `mounted` 훅에서만 브라우저 / DOM API에 접근하는 것입니다. + +## `` + +SSR 친화적이지 않은 컴포넌트(예: 커스텀 디렉티브를 포함한 컴포넌트)를 사용하거나 시연하는 경우, 내장된 `` 컴포넌트로 해당 컴포넌트를 래핑할 수 있습니다: + +```md + + + +``` + +## "import" 시 브라우저 API에 접근하는 라이브러리 {#libraries-that-access-browser-api-on-import} + +일부 컴포넌트나 라이브러리는 **"import" 시** 브라우저 API에 접근합니다. "import" 시 브라우저 환경을 가정하는 코드를 사용하려면, 동적 "import"를 사용해야 합니다. + +### Mounted 훅에서 가져오기 {#importing-in-mounted-hook} + +```vue + +``` + +### 조건부 가져오기 {#conditional-import} + +`import.meta.env.SSR` 플래그([Vite 환경 변수](https://vitejs.dev/guide/env-and-mode.html#env-variables)의 일부)를 사용하여 종속성을 조건부로 "import" 할 수도 있습니다: + +```js +if (!import.meta.env.SSR) { + import('./lib-that-access-window-on-import').then((module) => { + // 코드 사용하기 + }) +} +``` + +[`Theme.enhanceApp`](./custom-theme#theme-interface)은 비동기로 사용할 수 있기 때문에, "import" 시 브라우저 API에 접근하는 Vue 플러그인을 조건부로 "import"하고 등록할 수 있습니다: + +```js [.vitepress/theme/index.js] +/** @type {import('vitepress').Theme} */ +export default { + // ... + async enhanceApp({ app }) { + if (!import.meta.env.SSR) { + const plugin = await import('plugin-that-access-window-on-import') + app.use(plugin.default) + } + } +} +``` + +TypeScript를 사용하는 경우: +```ts [.vitepress/theme/index.ts] +import type { Theme } from 'vitepress' + +export default { + // ... + async enhanceApp({ app }) { + if (!import.meta.env.SSR) { + const plugin = await import('plugin-that-access-window-on-import') + app.use(plugin.default) + } + } +} satisfies Theme +``` + +### `defineClientComponent` + +VitePress는 "import" 시 브라우저 API에 접근하는 Vue 컴포넌트를 "import" 할 수 있는 편리한 헬퍼를 제공합니다. + +```vue + + + +``` + +대상 컴포넌트에 props/children/slots를 전달할 수도 있습니다: + +```vue + + + +``` + +대상 컴포넌트는 래퍼 컴포넌트의 mounted 훅에서만 "import" 됩니다. diff --git a/docs/ko/guide/using-vue.md b/docs/ko/guide/using-vue.md new file mode 100644 index 00000000..0146352a --- /dev/null +++ b/docs/ko/guide/using-vue.md @@ -0,0 +1,256 @@ +# 마크다운에서 Vue 사용하기 {#using-vue-in-markdown} + +VitePress에서는 각 마크다운 파일이 HTML로 컴파일된 후 [Vue 단일 파일 컴포넌트](https://vuejs.org/guide/scaling-up/sfc.html)로 처리됩니다. 이는 마크다운 내에서 Vue 컴포넌트를 사용하거나 동적 템플릿을 사용하거나 ` + +## 마크다운 컨텐츠 + +현재 카운트: {{ count }} + + + + +``` + +::: warning 마크다운에서 ` +``` + +## 텔레포트 사용하기 {#using-teleports} + +VitePress는 현재 body로 텔레포트를 사용하는 SSG만 지원합니다. 다른 대상에 대해 텔레포트를 사용하려면 내장된 `` 컴포넌트로 감싸거나 [`postRender` 훅](../reference/site-config#postrender)을 통해 최종 페이지 HTML의 올바른 위치에 텔레포트 마크업을 삽입할 수 있습니다. + + + +::: details +<<< @/components/ModalDemo.vue +::: + +```md + + +
+ // ... +
+
+
+``` + + + + diff --git a/docs/ko/guide/what-is-vitepress.md b/docs/ko/guide/what-is-vitepress.md new file mode 100644 index 00000000..9ad43c45 --- /dev/null +++ b/docs/ko/guide/what-is-vitepress.md @@ -0,0 +1,57 @@ +# VitePress란 무엇인가? {#what-is-vitepress} + +VitePress는 빠르고 컨텐츠 중심의 웹사이트를 구축하기 위해 설계된 [정적 사이트 생성기](https://en.wikipedia.org/wiki/Static_site_generator) (SSG)입니다. 다시말해 VitePress는 [마크다운](https://en.wikipedia.org/wiki/Markdown)으로 작성된 소스 컨텐츠를 가져와서 테마를 적용하고, 어디에나 쉽게 배포할 수 있는 정적 HTML 페이지를 생성합니다. + +
+ +그냥 한번 사용해보고 싶으신가요? [빠른 시작](./getting-started)으로 건너뛰세요. + +
+ +## 사용 사례 {#use-cases} + +- **문서화** + + 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 기반으로 되어 있으며, 여러 번역본에 걸쳐 공유되는 커스텀 테마를 사용합니다. + +- **블로그, 포트폴리오 및 마케팅 사이트** + + VitePress는 표준 Vite + Vue 애플리케이션의 개발자 경험을 가진 [커스텀 테마](./custom-theme)를 지원합니다. Vite 기반이기 때문에 Vite 생태계의 풍부한 플러그인을 직접 활용할 수 있습니다. 또한, VitePress는 [데이터 로딩](./data-loading) (로컬 또는 원격) 및 [동적 라우트 생성](./routing#dynamic-routes)을 위한 유연한 API를 제공합니다. 빌드 시점에 데이터를 결정할 수 있다면 거의 모든 것을 구축할 수 있습니다. + + 공식 [Vue.js 블로그](https://blog.vuejs.org/)는 로컬 콘텐츠 기반의 인덱스 페이지를 생성하는 간단한 블로그입니다. + +## 개발자 경험 {#developer-experience} + +VitePress는 마크다운 컨텐츠를 다룰 때 훌륭한 개발자 경험(DX)을 제공하고자 합니다. + +- **[Vite로 작동](https://vitejs.dev/)**: 즉각적인 서버 시작 가능, 페이지 새로고침 없이 즉시(<100ms) 수정 사항 반영. + +- **[내장된 마크다운 확장 기능](./markdown)**: 서문, 표, 구문 강조 등 무엇이든 가능. 특히 VitePress는 코드 블록 작업을 위한 고급 기능을 많이 제공하여 기술적 문서에 이상적. + +- **[Vue로 향상된 마크다운](./using-vue)**: 각 마크다운 페이지는 HTML과 100% 문법 호환성을 가진 Vue [단일 파일 컴포넌트](https://vuejs.org/guide/scaling-up/sfc.html)입니다. Vue 템플릿 기능이나 컴포넌트를 사용하여 정적 콘텐츠에 상호작용 기능을 포함할 수 있습니다. + +## 성능 {#performance} + +전통적인 SSG들과 달리, VitePress로 생성된 웹사이트는 초기 방문 시 정적 HTML을 제공하지만, 이후 사이트 내 탐색에 대해서는 [단일 페이지 애플리케이션](https://en.wikipedia.org/wiki/Single-page_application) (SPA)이 됩니다. 이 모델은 성능에 대한 최적의 균형을 제공합니다: + +- **빠른 초기 로딩** + + 초기 페이지 방문은 사전 렌더링된 HTML을 제공하여 빠른 로딩 속도와 최적의 SEO를 제공합니다. 그 후 페이지를 Vue SPA로 전환하는 JavaScript 번들이 로드됩니다(이것을 "하이드레이션"이라고 함). 일반적으로 SPA 하이드레이션이 느리다고 생각할 수 있지만, Vue 3의 성능과 컴파일러 최적화 덕분에 이 과정은 매우 빠릅니다. [PageSpeed Insights](https://pagespeed.web.dev/report?url=https%3A%2F%2Fvitepress.dev%2F)에서 일반적인 VitePress 사이트는 네트워크 속도가 느린 저가형 모바일 기기에서도 거의 완벽한 성능 점수를 얻습니다. + +- **빠른 포스트 로드 탐색** + + 더 중요한 것은 SPA 모델이 처음 로드된 후 더 나은 UX를 제공한다는 것입니다. 이후 사이트 내에서 탐색을 해도 전체 페이지가 다시 로드되는 현상이 더 이상 발생하지 않습니다. 대신 페이지의 콘텐츠를 불러와 동적으로 업데이트 합니다. 또한 VitePress는 뷰포트 내에 있는 링크의 페이지 청크를 자동으로 미리 가져옵니다. 이렇게 하면 대부분의 경우 유저는 이미 로드된 페이지에서 탐색할 때 새 페이지가 즉시 로드됩니다. + +- **페널티 없는 상호작용** + + 정적 마크다운 내에 내장된 동적 Vue 부분을 하이드레이션 할 수 있도록 각 마크다운 페이지는 Vue 컴포넌트로 처리되고 JavaScript로 컴파일됩니다. 이는 비효율적으로 보일 수 있지만, Vue 컴파일러는 정적 부분과 동적 부분을 분리하여 하이드레이션 비용과 페이로드 크기를 최소화합니다. 초기 페이지 로드 시, 정적 부분은 자동으로 JavaScript 페이로드에서 제거되고 하이드레이션 중 건너뜁니다. + +## VuePress는 어떤가요? {#what-about-vuepress} + +VitePress는 VuePress의 후속 버전 입니다. 원래 VuePress는 Vue 2와 webpack을 기반으로 했습니다. Vue 3와 Vite를 기반으로 한 VitePress는 훨씬 더 나은 DX, 더 나은 프로덕션 성능, 더 다듬어진 기본 테마, 더 유연한 커스터마이징 API를 제공합니다. + +VitePress와 VuePress의 API 차이는 주로 테마와 커스터마이징에 있습니다. 기본 테마를 사용하는 VuePress 1을 사용 중이라면 VitePress로의 마이그레이션은 비교적 간단할 것입니다. + +VuePress 2도 Vue 3와 Vite를 지원하며 VuePress 1과의 호환성을 높이기 위해 많은 노력이 투자되었습니다. 그러나 두 SSG를 병렬로 유지하는 것은 지속 가능하지 않으므로 Vue 팀은 장기적인 관점에서 주요 권장 SSG인 VitePress에 집중하기로 결정했습니다. diff --git a/docs/ko/index.md b/docs/ko/index.md new file mode 100644 index 00000000..ae7df4c8 --- /dev/null +++ b/docs/ko/index.md @@ -0,0 +1,35 @@ +--- +layout: home + +hero: + name: VitePress + text: Vite & Vue 기반 정적 사이트 생성기 + tagline: 단 몇 분 만에 마크다운을 우아한 문서로 변환 + actions: + - theme: brand + text: VitePress란 무엇인가? + link: /ko/guide/what-is-vitepress + - theme: alt + text: 빠른 시작 + link: /ko/guide/getting-started + - theme: alt + text: GitHub + link: https://github.com/vuejs/vitepress + image: + src: /vitepress-logo-large.svg + alt: VitePress + +features: + - icon: 📝 + title: 콘텐츠에 집중 + details: 마크다운으로만 아름다운 문서 사이트를 쉽게 만들기. + - icon: + title: Vite DX(개발자 경험) 즐겨보기 + details: 즉각적인 서버 시작, 매우 빠른 업데이트, Vite 생태계 플러그인을 활용. + - icon: + title: Vue로 커스터마이징 + details: Vue 문법과 컴포넌트를 마크다운에서 직접 사용하거나 Vue로 커스텀 테마를 구축. + - icon: 🚀 + title: 웹사이트를 빠르게 제공 + details: 정적 HTML로 빠른 초기 로딩, 클라이언트 측 라우팅을 통한 빠른 탐색. +--- diff --git a/docs/ko/reference/cli.md b/docs/ko/reference/cli.md new file mode 100644 index 00000000..4a76bd01 --- /dev/null +++ b/docs/ko/reference/cli.md @@ -0,0 +1,74 @@ +# 명령 줄 인터페이스 {#command-line-interface} + +## `vitepress dev` + +지정된 디렉터리를 루트로 하여 VitePress 개발 서버를 시작합니다. 기본값은 현재 디렉터리입니다. 현재 디렉터리에서 실행할 때 `dev` 명령은 생략할 수 있습니다. + +### 사용법 {#usage} + +```sh +# 현재 디렉토리에서 시작, `dev` 생략 +vitepress + +# 하위 디렉터리에서 시작 +vitepress dev [root] +``` + +### 옵션 {#options} + +| 옵션 | 설명 | +| ---------------- | ----------------------------------------------------------------- | +| `--open [path]` | 시작 시 브라우저 열기 (`boolean \| string`) | +| `--port ` | 포트 지정 (`number`) | +| `--base ` | Public 기본 경로 (기본값: `/`) (`string`) | +| `--cors` | CORS 활성화 | +| `--strictPort` | 지정된 포트가 이미 사용 중인 경우 종료 (`boolean`) | +| `--force` | 옵티마이저가 캐시를 무시하고 다시 번들링하도록 강제 (`boolean`) | + +## `vitepress build` + +VitePress 사이트를 프로덕션 빌드합니다. + +### 사용법 {#usage-1} + +```sh +vitepress build [root] +``` + +### 옵션 {#options-1} + +| 옵션 | 설명 | +| ----------------------------- |---------------------------------------------------------------------------------------------| +| `--mpa` (실험적) | 클라이언트 측 하이드레이션 없이 [MPA 모드](../guide/mpa-mode)로 빌드 (`boolean`) | +| `--base ` | Public 기본 경로 (기본값: `/`) (`string`) | +| `--target ` | 트랜스파일 대상 (기본값: `"modules"`) (`string`) | +| `--outDir ` | **cwd** 기준 출력 디렉터리 (기본값: `/.vitepress/dist`) (`string`) | +| `--minify [minifier]` | minify 활성화/비활성화 또는 사용할 minify 도구 지정 (기본값: `"esbuild"`) (`boolean \| "terser" \| "esbuild"`) | +| `--assetsInlineLimit `| 바이트 단위의 정적 에셋 base64 인라인 임계값 (기본값: `4096`) (`number`) | + +## `vitepress preview` + +프로덕션 빌드를 로컬에서 미리 보기 합니다. + +### 사용법 {#usage-2} + +```sh +vitepress preview [root] +``` + +### 옵션 {#options-2} + +| 옵션 | 설명 | +| ---------------- | ----------------------------------------- | +| `--base ` | Public 기본 경로 (기본값: `/`) (`string`) | +| `--port ` | 포트 지정 (`number`) | + +## `vitepress init` + +현재 디렉터리에서 [설정 마법사](../guide/getting-started#setup-wizard)를 시작합니다. + +### 사용법 {#usage-3} + +```sh +vitepress init +``` diff --git a/docs/ko/reference/default-theme-badge.md b/docs/ko/reference/default-theme-badge.md new file mode 100644 index 00000000..20bdcef9 --- /dev/null +++ b/docs/ko/reference/default-theme-badge.md @@ -0,0 +1,69 @@ +# 배지 {#badge} + +배지는 헤더에 상태를 추가할 수 있게 해줍니다. 예를 들어, 섹션의 타입을 지정하거나 지원되는 버전을 표시하는 데 유용할 수 있습니다. + +## 사용법 {#usage} + +`Badge` 컴포넌트는 전역으로 사용 가능합니다. + +```html +### 제목 +### 제목 +### 제목 +### 제목 +``` + +위 코드는 다음과 같이 렌더링됩니다: + +### 제목 +### 제목 +### 제목 +### 제목 + +## 커스텀 하위 노드 {#custom-children} + +``는 `children`을 받아서 배지 내부에 표시합니다. + +```html +### 제목 커스텀 노드 +``` + +### 제목 커스텀 노드 + +## 타입 색상 커스터마이징 {#customize-type-color} + +배지의 스타일은 CSS 변수를 재정의하여 커스터마이징 할 수 있습니다. 다음은 기본값입니다: + +```css +:root { + --vp-badge-info-border: transparent; + --vp-badge-info-text: var(--vp-c-text-2); + --vp-badge-info-bg: var(--vp-c-default-soft); + + --vp-badge-tip-border: transparent; + --vp-badge-tip-text: var(--vp-c-brand-1); + --vp-badge-tip-bg: var(--vp-c-brand-soft); + + --vp-badge-warning-border: transparent; + --vp-badge-warning-text: var(--vp-c-warning-1); + --vp-badge-warning-bg: var(--vp-c-warning-soft); + + --vp-badge-danger-border: transparent; + --vp-badge-danger-text: var(--vp-c-danger-1); + --vp-badge-danger-bg: var(--vp-c-danger-soft); +} +``` + +## `` + +`` 컴포넌트는 다음과 같은 프로퍼티를 사용합니다: + +```ts +interface Props { + // ``이 전달되면, 이 값은 무시됨. + text?: string + + // 기본값: `tip`. + type?: 'info' | 'tip' | 'warning' | 'danger' +} +``` diff --git a/docs/ko/reference/default-theme-carbon-ads.md b/docs/ko/reference/default-theme-carbon-ads.md new file mode 100644 index 00000000..6a677289 --- /dev/null +++ b/docs/ko/reference/default-theme-carbon-ads.md @@ -0,0 +1,22 @@ +# 카본 광고 {#carbon-ads} + +VitePress는 [카본 광고](https://www.carbonads.net/)에 대한 기본적인 지원을 제공합니다. 구성에서 카본 광고 자격 증명을 정의하면 VitePress는 페이지에 광고를 표시합니다. + +```js +export default { + themeConfig: { + carbonAds: { + code: 'your-carbon-code', + placement: 'your-carbon-placement' + } + } +} +``` + +이 값들은 아래와 같이 카본 CDN 스크립트를 호출하는 데 사용됩니다. + +```js +`//cdn.carbonads.com/carbon.js?serve=${code}&placement=${placement}` +``` + +카본 광고 구성에 대해 더 알고 싶다면 [카본 광고 웹사이트](https://www.carbonads.net/)를 방문하세요. diff --git a/docs/ko/reference/default-theme-config.md b/docs/ko/reference/default-theme-config.md new file mode 100644 index 00000000..b0df3361 --- /dev/null +++ b/docs/ko/reference/default-theme-config.md @@ -0,0 +1,451 @@ +# 기본 테마 구성 {#default-theme-config} + +테마 구성은 테마를 커스텀 할 수 있게 해줍니다. 구성 파일에서 `themeConfig` 옵션을 통해 테마 구성을 정의할 수 있습니다: + +```ts +export default { + lang: 'ko-KR', + title: 'VitePress', + description: 'Vite 및 Vue로 기반 정적 사이트 생성기.', + + // 테마 관련 구성. + themeConfig: { + logo: '/logo.svg', + nav: [...], + sidebar: { ... } + } +} +``` + +**이 페이지에 문서화된 옵션은 기본 테마에만 적용됩니다.** 다른 테마는 다른 테마 구성이 필요합니다. 커스텀 테마를 사용하는 경우, 테마 구성 객체는 테마에 전달되어 테마가 이를 기반으로 다르게 동작할 수 있습니다. + +## i18nRouting + +- 타입: `boolean` + +로케일을 `ko`로 변경하면 URL이 `/foo` (또는 `/en/foo/`)에서 `/ko/foo`로 변경됩니다. 이 동작을 비활성화하려면 `themeConfig.i18nRouting`을 `false`로 설정하세요. + +## logo + +- 타입: `ThemeableImage` + +네비게이션 바에 사이트 제목 바로 앞에 표시할 로고 파일입니다. 경로 문자열 또는 라이트/다크 모드에 대해 다른 로고를 설정할 수 있는 객체를 사용합니다. + +```ts +export default { + themeConfig: { + logo: '/logo.svg' + } +} +``` + +```ts +type ThemeableImage = + | string + | { src: string; alt?: string } + | { light: string; dark: string; alt?: string } +``` + +## siteTitle + +- 타입: `string | false` + +이 항목을 커스텀하여 네비게이션 바의 기본 사이트 제목(애플리케이션 구성의 `title`)을 대체할 수 있습니다. `false`로 설정하면 네비게이션 바에서 제목이 비활성화됩니다. 이미 사이트 제목 텍스트가 포함된 `logo`가 있을 때 유용합니다. + +```ts +export default { + themeConfig: { + siteTitle: 'Hello World' + } +} +``` + +## nav + +- 타입: `NavItem` + +네비게이션 바 메뉴 아이템의 구성입니다. 자세한 내용은 [기본 테마: 네비게이션 바](./default-theme-nav#navigation-links)를 참고하세요. + +```ts +export default { + themeConfig: { + nav: [ + { text: '가이드', link: '/guide' }, + { + text: '드롭다운 메뉴', + items: [ + { text: '항목 A', link: '/item-1' }, + { text: '항목 B', link: '/item-2' }, + { text: '항목 C', link: '/item-3' } + ] + } + ] + } +} +``` + +```ts +type NavItem = NavItemWithLink | NavItemWithChildren + +interface NavItemWithLink { + text: string + link: string + activeMatch?: string + target?: string + rel?: string + noIcon?: boolean +} + +interface NavItemChildren { + text?: string + items: NavItemWithLink[] +} + +interface NavItemWithChildren { + text?: string + items: (NavItemChildren | NavItemWithLink)[] + activeMatch?: string +} +``` + +## sidebar + +- 타입: `Sidebar` + +사이드바 메뉴 항목에 대한 구성입니다. 자세한 내용은 [기본 테마: 사이드바](./default-theme-sidebar)에서 확인하세요. + +```ts +export default { + themeConfig: { + sidebar: [ + { + text: '가이드', + items: [ + { text: '소개', link: '/introduction' }, + { text: '시작하기', link: '/getting-started' }, + ... + ] + } + ] + } +} +``` + +```ts +export type Sidebar = SidebarItem[] | SidebarMulti + +export interface SidebarMulti { + [path: string]: SidebarItem[] | { items: SidebarItem[]; base: string } +} + +export type SidebarItem = { + /** + * 아이템의 텍스트 레이블 + */ + text?: string + + /** + * 아이템의 링크 + */ + link?: string + + /** + * 아이템의 하위 항목 + */ + items?: SidebarItem[] + + /** + * 명시하지 않은 경우, 그룹을 접을 수 없습니다. + * + * `true`: 그룹은 접을 수 있고 기본적으로 접혀 있습니다. + * + * `false`: 그룹은 접을 수 있고 기본적으로 펼쳐져 있습니다. + */ + collapsed?: boolean + + /** + * 하위 아이템에 대한 기본 경로입니다. + */ + base?: string + + /** + * 이전/다음 페이지의 푸터에 나타나는 텍스트를 커스텀 합니다. + */ + docFooterText?: string + + rel?: string + target?: string +} +``` + +## aside + +- 타입: `boolean | 'left'` +- 기본값: `true` +- [전문](./frontmatter-config#aside)을 통해 페이지별로 재정의할 수 있습니다. + +`false`: 어사이드 컨테이너가 렌더링되지 않습니다.\ +`true`: 어사이드가 오른쪽에 렌더링됩니다.\ +`left`: 어사이드가 왼쪽에 렌더링됩니다. + +모든 뷰포트에서 비활성화하려면 `outline: false`를 사용해야 합니다. + +## outline + +- 타입: `Outline | Outline['level'] | false` +- [전문](./frontmatter-config#outline)을 사용해 각 페이지별로 계층 구조를 재정의할 수 있습니다. + +이 값을 `false`로 설정하면 아웃라인(개요) 컨테이너가 렌더링되지 않습니다. 자세한 내용은 아래 인터페이스를 참고하세요: + +```ts +interface Outline { + /** + * 아웃라인에 표시할 제목 레벨. + * 단일 숫자는 해당 레벨의 제목만 표시됨을 의미합니다. + * 튜플이 전달되면, 첫 번째 숫자는 최소 수준을, 두 번째 숫자는 최대 수준을 나타냅니다. + * `'deep'`은 `[2, 6]`과 동일하며, 이는 `

`에서 `

`까지의 모든 제목이 표시됨을 의미합니다. + * + * @default 2 + */ + level?: number | [number, number] | 'deep' + + /** + * 아웃라인에 표시될 제목. + * + * @default 'On this page' + */ + label?: string +} +``` + +## socialLinks + +- 타입: `SocialLink[]` + +이 옵션을 정의하여 네비게이션 바에 소셜 링크를 아이콘과 함께 표시할 수 있습니다. + +```ts +export default { + themeConfig: { + socialLinks: [ + { icon: 'github', link: 'https://github.com/vuejs/vitepress' }, + { icon: 'twitter', link: '...' }, + // SVG를 문자열로 전달하여 커스텀 아이콘을 추가할 수도 있습니다: + { + icon: { + svg: '' + }, + link: '...', + // 접근성을 위해 커스텀 레이블을 포함할 수도 있습니다 (선택 사항이지만 권장됨): + ariaLabel: '스타 링크' + } + ] + } +} +``` + +```ts +interface SocialLink { + icon: string | { svg: string } + link: string + ariaLabel?: string +} +``` + +## footer + +- 타입: `Footer` +- [전문](./frontmatter-config#footer)을 사용해 페이지별로 재정의할 수 있습니다. + +푸터 구성입니다. 메시지 또는 저작권 텍스트를 푸터에 추가할 수 있지만, 이는 페이지에 사이드바가 포함되지 않은 경우에만 표시됩니다. 이는 디자인상의 이유 때문입니다. + +```ts +export default { + themeConfig: { + footer: { + message: 'MIT 라이선스에 따라 릴리즈되었습니다.', + copyright: '저작권 © 2019-현재 홍길동' + } + } +} +``` + +```ts +export interface Footer { + message?: string + copyright?: string +} +``` + +## editLink + +- 타입: `EditLink` +- [전문](./frontmatter-config#footer)을 사용해 페이지별로 재정의할 수 있습니다. + +편집 링크 기능을 사용하면 GitHub 또는 GitLab과 같은 Git 관리 서비스에서 페이지를 편집할 수 있는 링크를 표시할 수 있습니다. 자세한 내용은 [기본 테마: 편집 링크](./default-theme-edit-link)를 참고하세요. + +```ts +export default { + themeConfig: { + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + text: 'GitHub에서 이 페이지 편집하기' + } + } +} +``` + +```ts +export interface EditLink { + pattern: string + text?: string +} +``` + +## lastUpdated + +- 타입: `LastUpdatedOptions` + +마지막 업데이트된 날짜의 텍스트와 날짜 형식을 커스텀 할 수 있습니다. + +```ts +export default { + themeConfig: { + lastUpdated: { + text: '마지막 업데이트 날짜', + formatOptions: { + dateStyle: 'full', + timeStyle: 'medium' + } + } + } +} +``` + +```ts +export interface LastUpdatedOptions { + /** + * @default 'Last updated' + */ + text?: string + + /** + * @default + * {dateStyle: 'short', timeStyle: 'short'} + */ + formatOptions?: Intl.DateTimeFormatOptions & { forceLocale?: boolean } +} +``` + +## algolia + +- 타입: `AlgoliaSearch` + +[Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch)를 사용하여 문서 사이트를 검색할 수 있는 옵션입니다. 자세한 내용은 [기본 테마: 검색](./default-theme-search)을 참고하세요. + +```ts +export interface AlgoliaSearchOptions extends DocSearchProps { + locales?: Record> +} +``` + +전체 옵션은 [여기](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts)에서 확인하세요. + +## carbonAds {#carbon-ads} + +- 타입: `CarbonAdsOptions` + +[Carbon Ads](https://www.carbonads.net/)를 표시할 수 있는 옵션입니다. + +```ts +export default { + themeConfig: { + carbonAds: { + code: 'your-carbon-code', + placement: 'your-carbon-placement' + } + } +} +``` + +```ts +export interface CarbonAdsOptions { + code: string + placement: string +} +``` + +자세한 내용은 [기본 테마: 카본 광고](./default-theme-carbon-ads)를 참고하세요. + +## docFooter + +- 타입: `DocFooter` + +이 옵션은 이전 및 다음 링크에 표시되는 텍스트를 커스텀하는 데 사용합니다. 영어로 문서를 작성하지 않는 경우 유용합니다. 또한 이전/다음 링크를 전역적으로 비활성화할 수도 있습니다. 선택적으로 이전/다음 링크를 활성화/비활성화하려면 [전문](./default-theme-prev-next-links)을 사용합니다. + +```ts +export default { + themeConfig: { + docFooter: { + prev: '이전 페이지', + next: '다음 페이지' + } + } +} +``` + +```ts +export interface DocFooter { + prev?: string | false + next?: string | false +} +``` + +## darkModeSwitchLabel + +- 타입: `string` +- 기본값: `Appearance` + +이 옵션은 다크 모드 스위치 레이블을 커스텀할 때 사용합니다. 이 레이블은 모바일 뷰에서만 표시됩니다. + +## lightModeSwitchTitle + +- 타입: `string` +- 기본값: `Switch to light theme` + +이 옵션은 라이트 모드 스위치 타이틀을 커스텀할 때 사용합니다. 이것은 호버(hover)할 때 나타납니다. + +## darkModeSwitchTitle + +- 타입: `string` +- 기본값: `Switch to dark theme` + +호버 시 나타나는 다크 모드 스위치 타이틀을 커스텀할 때 사용합니다. + +## sidebarMenuLabel + +- 타입: `string` +- 기본값: `Menu` + +사이드바 메뉴 레이블을 커스텀 할 때 사용합니다. 이 레이블은 모바일 뷰에서만 표시됩니다. + +## returnToTopLabel + +- 타입: `string` +- 기본값: `Return to top` + +맨 위로 이동 버튼의 레이블을 커스텀 할 때 사용합니다. 이 레이블은 모바일 뷰에서만 표시됩니다. + +## langMenuLabel + +- 타입: `string` +- 기본값: `Change language` + +네비게이션 바에서 언어 토글 버튼의 aria-label을 커스텀 할 때 사용합니다. 이는 [i18n](../guide/i18n)을 사용하는 경우에만 사용됩니다. + +## externalLinkIcon + +- 타입: `boolean` +- 기본값: `false` + +마크다운의 외부 링크 옆에 외부 링크 아이콘을 표시할지 여부를 설정합니다. diff --git a/docs/ko/reference/default-theme-edit-link.md b/docs/ko/reference/default-theme-edit-link.md new file mode 100644 index 00000000..4494b937 --- /dev/null +++ b/docs/ko/reference/default-theme-edit-link.md @@ -0,0 +1,60 @@ +# 편집 링크 {#edit-link} + +## 사이트 단계에서 설정하기 {#site-level-config} + +편집 링크는 GitHub, GitLab과 같은 Git 관리 서비스에서 페이지를 편집할 수 있는 링크를 표시할 수 있게 해줍니다. 이를 활성화하려면 `themeConfig.editLink` 옵션을 구성에 추가하세요. + +```js +export default { + themeConfig: { + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path' + } + } +} +``` + +`pattern` 옵션은 링크의 URL 구조를 정의하며, `:path`는 페이지 경로로 대체됩니다. + +또한, [`PageData`](./runtime-api#usedata)를 인자로 받아 URL 문자열을 반환하는 순수 함수를 사용할 수도 있습니다. + +```js +export default { + themeConfig: { + editLink: { + pattern: ({ filePath }) => { + if (filePath.startsWith('packages/')) { + return `https://github.com/acme/monorepo/edit/main/${filePath}` + } else { + return `https://github.com/acme/monorepo/edit/main/docs/${filePath}` + } + } + } + } +} +``` + +이 함수는 브라우저에서 직렬화되어 실행되므로, 부작용을 가지지 않고 해당 스코프 외부의 어떤 것도 참조하지 않도록 해야 합니다. + +기본적으로 이 설정은 문서 페이지 하단에 "Edit this page"이라는 텍스트 링크를 추가합니다. 이 텍스트는 `text` 옵션을 정의하여 커스터마이징 할 수 있습니다. + +```js +export default { + themeConfig: { + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + text: '이 페이지 편집 제안하기' + } + } +} +``` + +## 전문에서 설정하기 {#frontmatter-config} + +페이지별로 이 기능을 비활성화하려면, 전문에서 `editLink` 옵션을 사용하세요: + +```yaml +--- +editLink: false +--- +``` diff --git a/docs/ko/reference/default-theme-footer.md b/docs/ko/reference/default-theme-footer.md new file mode 100644 index 00000000..de808252 --- /dev/null +++ b/docs/ko/reference/default-theme-footer.md @@ -0,0 +1,53 @@ +# 푸터 {#footer} + +`themeConfig.footer`가 존재하면 VitePress는 페이지 하단에 전역 푸터를 표시합니다. + +```ts +export default { + themeConfig: { + footer: { + message: 'MIT 라이선스에 따라 릴리즈되었습니다.', + copyright: '저작권 © 2019-현재 홍길동' + } + } +} +``` + +```ts +export interface Footer { + // 저작권 전에 표시되는 메시지. + message?: string + + // 실제 저작권 텍스트. + copyright?: string +} +``` + +위의 구성은 HTML 문자열도 지원합니다. 예를 들어, 푸터 텍스트에 링크를 포함하고 싶다면, 다음과 같이 구성을 수정하면 됩니다: + +```ts +export default { + themeConfig: { + footer: { + message: 'MIT 라이선스에 따라 릴리즈되었습니다.', + copyright: '저작권 © 2019-현재 홍길동' + } + } +} +``` + +::: warning +`message`와 `copyright`는 `

` 엘리먼트 내부에 렌더링되므로 인라인 엘리먼트만 사용할 수 있습니다. 블록 엘리먼트를 추가하려면 [`layout-bottom`](../guide/extending-default-theme#layout-slots) 슬롯을 사용하는 것이 좋습니다. +::: + +[사이드바](./default-theme-sidebar)가 표시되는 경우 푸터는 표시되지 않습니다. + +## 전문에서 설정하기 {#frontmatter-config} + +이 기능은 전문의 `footer` 옵션을 사용하여 페이지별로 비활성화 할 수 있습니다. + +```yaml +--- +footer: false +--- +``` diff --git a/docs/ko/reference/default-theme-home-page.md b/docs/ko/reference/default-theme-home-page.md new file mode 100644 index 00000000..51550279 --- /dev/null +++ b/docs/ko/reference/default-theme-home-page.md @@ -0,0 +1,195 @@ +# 홈 페이지 {#home-page} + +VitePress 기본 테마는 홈 페이지 레이아웃을 제공합니다. 이것은 이 사이트의 [홈 페이지](../)에도 사용되었습니다. `layout: home`을 [전문](./frontmatter-config)에 지정하여 어느 페이지에서도 이를 사용할 수 있습니다. + +```yaml +--- +layout: home +--- +``` + +하지만 이 옵션만으로는 많은 것을 할 수 없습니다. 다행히도 `hero` 및 `features`와 같은 추가 옵션을 설정하여 홈 페이지에 다양한 사전 템플릿 "섹션"들을 추가할 수 있습니다. + +## Hero 섹션 {#hero-section} + +Hero 섹션은 홈 페이지의 상단에 위치합니다. Hero 섹션을 구성하는 방법은 다음과 같습니다. + +```yaml +--- +layout: home + +hero: + name: VitePress + text: Vite & Vue 기반 정적 사이트 생성기 + tagline: 단 몇 분 만에 마크다운을 우아한 문서로 변환 + image: + src: /logo.png + alt: VitePress + actions: + - theme: brand + text: VitePress란 무엇인가? + link: /guide/what-is-vitepress + - theme: alt + text: GitHub + link: https://github.com/vuejs/vitepress +--- +``` + +```ts +interface Hero { + // `text` 위에 브랜드 색상으로 표시되는 문자열. + // 제품명 등 간략한 내용을 추천. + name?: string + + // hero 섹션의 본문. + // `h1` 태그로 정의됨. + text: string + + // `text` 아래에 표시되는 슬로건 문자열. + tagline?: string + + // `text` 및 `tagline` 옆에 표시되는 이미지. + image?: ThemeableImage + + // hero 섹션에 표시할 버튼 리스트. + actions?: HeroAction[] +} + +type ThemeableImage = + | string + | { src: string; alt?: string } + | { light: string; dark: string; alt?: string } + +interface HeroAction { + // 버튼의 색상 테마. 기본값: `brand` + theme?: 'brand' | 'alt' + + // 버튼의 레이블. + text: string + + // 버튼의 목적지 링크. + link: string + + // 링크의 target 어트리뷰트. + target?: string + + // 링크의 rel 어트리뷰트. + rel?: string +} +``` + +### `name` 색상 커스터마이징 {#customizing-the-name-color} + +VitePress는 `name`에 브랜드 색상(`--vp-c-brand-1`)을 사용합니다. 하지만 `--vp-home-hero-name-color` 변수를 재정의하여 이 색상을 커스텀 할 수 있습니다. + +```css +:root { + --vp-home-hero-name-color: blue; +} +``` + +또한 `--vp-home-hero-name-background` 변수를 정의해 추가적으로 `name`을 그라데이션 색상으로 커스터마이징도 가능합니다. + +```css +:root { + --vp-home-hero-name-color: transparent; + --vp-home-hero-name-background: -webkit-linear-gradient(120deg, #bd34fe, #41d1ff); +} +``` + +## Features 섹션 {#features-section} + +Features 섹션에서는 Hero 섹션 바로 아래에 표시할 각 feature를 원하는 만큼 나열할 수 있습니다. 이를 구성하려면 `features` 옵션을 전문에 전달하면 됩니다. + +각 feature에 아이콘을 제공할 수 있으며, 이는 이모지 또는 이미지의 형태일 수 있습니다. 아이콘으로 이미지(svg, png, jpeg 등)를 사용하려면 적절한 너비와 높이를 제공해야 하며, 필요에 따라 설명, 이미지의 고유 크기, 다크 테마와 라이트 테마에 대한 변형 아이콘도 제공할 수 있습니다. + +```yaml +--- +layout: home + +features: + - icon: 🛠️ + title: Simple and minimal, always + details: Lorem ipsum... + - icon: + src: /cool-feature-icon.svg + title: Another cool feature + details: Lorem ipsum... + - icon: + dark: /dark-feature-icon.svg + light: /light-feature-icon.svg + title: Another cool feature + details: Lorem ipsum... +--- +``` + +```ts +interface Feature { + // 각 feature 박스에 표시할 아이콘. + icon?: FeatureIcon + + // feature의 제목. + title: string + + // feature의 세부 정보. + details: string + + // feature 컴포넌트 클릭 시 링크. + // 링크는 내부 또는 외부 모두 가능. + // + // 예: `guide/reference/default-theme-home-page` 또는 `https://example.com` + link?: string + + // feature 컴포넌트 내 표시될 링크 텍스트. + // `link` 옵션과 함께 사용하는 것을 추천. + // + // 예: `더 알아보기`, `페이지 방문` 등 + linkText?: string + + // `link` 옵션을 위한 링크 rel 어트리뷰트. + // + // 예: `external` + rel?: string + + // `link` 옵션을 위한 링크 target 어트리뷰트. + target?: string +} + +type FeatureIcon = + | string + | { src: string; alt?: string; width?: string; height: string } + | { + light: string + dark: string + alt?: string + width?: string + height: string + } +``` + +## 마크다운 컨텐츠 {#markdown-content} + +홈 페이지 레이아웃에 추가 컨텐츠를 작성하려면 전문 구분선 `---` 아래에 마크다운을 추가하면 됩니다. + +````md +--- +layout: home + +hero: + name: VitePress + text: Vite & Vue 기반 정적 사이트 생성기 +--- + +## 시작하기 + +`npx`를 사용하여 VitePress를 바로 시작할 수 있습니다! + +```sh +npm init +npx vitepress init +``` +```` + +::: info +`layout: home` 페이지의 추가 컨텐츠에 자동으로 기본 마크다운 스타일이 적용됩니다(영문 원서에서는 반대로 설명함). 스타일을 적용하지 않으려면 전문에 `markdownStyles: false`를 추가하면 됩니다. +::: diff --git a/docs/ko/reference/default-theme-last-updated.md b/docs/ko/reference/default-theme-last-updated.md new file mode 100644 index 00000000..2d4760e0 --- /dev/null +++ b/docs/ko/reference/default-theme-last-updated.md @@ -0,0 +1,27 @@ +# 마지막 업데이트 날짜 {#last-updated} + +마지막 업데이트 날짜는 페이지 오른쪽 하단에 표시됩니다. 이를 활성화하려면 구성 파일에 `lastUpdated` 옵션을 추가하세요. + +::: tip +마크다운 파일을 커밋해야 업데이트된 시간을 확인할 수 있습니다. +::: + +## 사이트 단계에서 설정하기 {#site-level-config} + +```js +export default { + lastUpdated: true +} +``` + +## 전문에서 설정하기 {#frontmatter-config} + +페이지별로 이 기능을 비활성화하려면, 전문에서 `lastUpdated` 옵션을 사용하세요: + +```yaml +--- +lastUpdated: false +--- +``` + +자세한 내용은 [기본 테마: lastUpdated](./default-theme-config#lastupdated)를 참고하세요. 테마 레벨에서 참(truthy) 값을 설정하면, 사이트나 페이지 레벨에서 명시적으로 비활성화하지 않는 한 이 기능이 활성화됩니다. diff --git a/docs/ko/reference/default-theme-layout.md b/docs/ko/reference/default-theme-layout.md new file mode 100644 index 00000000..cf97f416 --- /dev/null +++ b/docs/ko/reference/default-theme-layout.md @@ -0,0 +1,62 @@ +# 레이아웃 {#layout} + +페이지의 [전문](./frontmatter-config)에 `layout` 옵션을 설정하여 페이지 레이아웃을 선택할 수 있습니다. `doc`, `page`, `home` 세 가지 레이아웃 옵션이 있습니다. 아무것도 지정하지 않으면 `doc` 페이지로 처리됩니다. + +```yaml +--- +layout: doc +--- +``` + +## `doc` 레이아웃 {#doc-layout} + +`doc` 옵션은 기본 레이아웃으로, 전체 마크다운 콘텐츠를 "문서" 스타일로 변환합니다. 이 레이아웃은 전체 콘텐츠를 `vp-doc` CSS 클래스로 감싸고, 하위 엘리먼트에 스타일을 적용하는 방식으로 작동합니다. + +`p`나 `h2` 같은 거의 모든 일반적인 엘리먼트들이 특별한 스타일을 갖게 됩니다. 따라서 마크다운 콘텐츠에 커스텀 HTML을 추가할 경우, 해당 HTML도 이러한 스타일의 영향을 받게 된다는 점을 유념해야 합니다. + +이 레이아웃에서는 아래에 나열된 문서 전용 기능들도 제공됩니다. 이 기능들은 오직 이 레이아웃에서만 활성화됩니다. + +- 편집 링크 +- 이전/다음 링크 +- 개요(outline) +- [카본 광고](./default-theme-carbon-ads) + +## `page` 레이아웃 {#page-layout} + +`page` 옵션은 "빈 페이지"로 처리됩니다. 마크다운은 여전히 파싱되며, 모든 [마크다운 확장 기능](../guide/markdown)이 `doc` 레이아웃과 동일하게 작동하지만, 기본 스타일링은 적용되지 않습니다. + +이 페이지 레이아웃은 VitePress 테마가 마크업에 영향을 미치지 않도록 하여, 모든 스타일을 직접 지정할 수 있게 해줍니다. 이는 커스텀 페이지를 만들고자 할 때 유용합니다. + +이 레이아웃에서도 페이지에 매칭되는 사이드바 구성이 있는 경우 사이드바는 여전히 표시됩니다. + +## `home` 레이아웃 {#home-layout} + +`home` 옵션은 템플릿화된 "홈 페이지"를 생성합니다. 이 레이아웃에서는 `hero`와 `features` 같은 추가 옵션을 설정하여 콘텐츠를 더 커스터마이징 할 수 있습니다. 자세한 내용은 [기본 테마: 홈 페이지](./default-theme-home-page)를 참고하세요. + +## 레이아웃 없음 {#no-layout} + +어떤 레이아웃도 원하지 않는 경우, 전문에 `layout: false`를 전달할 수 있습니다. 이 옵션은 (기본적으로 사이드바, 네비게이션 바, 또는 푸터가 없는) 완전히 커스터마이징 가능한 랜딩 페이지를 만들고자 할 때 유용합니다. + +## 커스텀 레이아웃 {#custom-layout} + +커스텀 레이아웃을 사용할 수도 있습니다: + +```md +--- +layout: foo +--- +``` + +이것은 컨텍스트에 등록된 `foo`라는 이름의 컴포넌트를 찾습니다. 예를 들어 `.vitepress/theme/index.ts`에서 컴포넌트를 전역으로 등록할 수 있습니다: + +```ts +import DefaultTheme from 'vitepress/theme' +import Foo from './Foo.vue' + +export default { + extends: DefaultTheme, + enhanceApp({ app }) { + app.component('foo', Foo) + } +} +``` diff --git a/docs/ko/reference/default-theme-nav.md b/docs/ko/reference/default-theme-nav.md new file mode 100644 index 00000000..cdfdc7ef --- /dev/null +++ b/docs/ko/reference/default-theme-nav.md @@ -0,0 +1,214 @@ +# 네비게이션 바 {#nav} + +네비게이션 바는 페이지 상단에 표시되며, 사이트 제목, 전역 메뉴 링크 등이 포함됩니다. + +## 사이트 제목 및 로고 {#site-title-and-logo} + +기본적으로 네비게이션 바는 [`config.title`](./site-config#title) 값을 참조하여 사이트 제목을 표시합니다. 여기에 표시되는 내용을 변경하려면 `themeConfig.siteTitle` 옵션에 커스텀 텍스트를 정의합니다. + +```js +export default { + themeConfig: { + siteTitle: 'My Custom Title' + } +} +``` + +사이트에 로고가 있는 경우, 이미지의 경로를 전달하여 로고를 표시할 수 있습니다. 로고는 `public` 폴더에 배치하고, 이것의 절대 경로를 정의해야 합니다. + +```js +export default { + themeConfig: { + logo: '/my-logo.svg' + } +} +``` + +로고를 추가하면 사이트 제목과 함께 표시됩니다. 로고만 필요하고 사이트 제목 텍스트를 숨기고 싶다면, `siteTitle` 옵션을 `false`로 설정하면 됩니다. + +```js +export default { + themeConfig: { + logo: '/my-logo.svg', + siteTitle: false + } +} +``` + +로고에 `alt` 어트리뷰트를 추가하거나 다크/라이트 모드에 따라 커스터마이징 하려면, 로고를 객체 형태로 전달해야 합니다. 자세한 내용은 [`themeConfig.logo`](./default-theme-config#logo)를 참고하세요. + +## 네비게이션 바 링크 {#navigation-links} + +`themeConfig.nav` 옵션을 정의하여 네비게이션 바에 링크를 추가할 수 있습니다. + +```js +export default { + themeConfig: { + nav: [ + { text: '가이드', link: '/guide' }, + { text: '구성', link: '/config' }, + { text: '변경사항', link: 'https://github.com/...' } + ] + } +} +``` + +`text`는 네비게이션 바에 표시되는 실제 텍스트이며, `link`는 텍스트를 클릭했을 때 이동할 링크입니다. 링크의 경로는 `.md` 접미사 없이 실제 파일 경로로 설정하며, 항상 `/`로 시작해야 합니다. + +네비게이션 바 링크는 드롭다운 메뉴가 될 수 있습니다. 이를 위해 `link` 옵션에 `items` 키를 설정합니다. + +```js +export default { + themeConfig: { + nav: [ + { text: '가이드', link: '/guide' }, + { + text: '드롭다운 메뉴', + items: [ + { text: '항목 A', link: '/item-1' }, + { text: '항목 B', link: '/item-2' }, + { text: '항목 C', link: '/item-3' } + ] + } + ] + } +} +``` + +드롭다운 메뉴의 제목(위 예제에서 `드롭다운 메뉴`)은 드롭다운 대화 상자를 여는 버튼이 되므로 `link` 프로퍼티를 가질 수 없습니다. + +드롭다운 메뉴 아이템에 더 많은 중첩된 아이템을 전달하여 "섹션"을 추가할 수도 있습니다. + +```js +export default { + themeConfig: { + nav: [ + { text: '가이드', link: '/guide' }, + { + text: '드롭다운 메뉴', + items: [ + { + // 섹션의 제목. + text: '섹션 A 제목', + items: [ + { text: '섹션 A 항목 A', link: '...' }, + { text: '섹션 B 항목 B', link: '...' } + ] + } + ] + }, + { + text: '드롭다운 메뉴', + items: [ + { + // 제목을 생략할 수도 있습니다. + items: [ + { text: '섹션 A 항목 A', link: '...' }, + { text: '섹션 B 항목 B', link: '...' } + ] + } + ] + } + ] + } +} +``` + +### 링크의 "active" 상태 커스터마이징 {#customize-link-s-active-state} + +네비게이션 바 메뉴 아이템은 현재 페이지가 매칭되는 경로에 있을 때 강조 표시됩니다. 매칭할 경로를 커스터마이징 하려면 `activeMatch` 프로퍼티에 정규식을 문자열 값으로 정의합니다. + +```js +export default { + themeConfig: { + nav: [ + // `/config/` 경로에 있을 때 + // 이 링크는 활성화된 상태가 됩니다. + { + text: '가이드', + link: '/guide', + activeMatch: '/config/' + } + ] + } +} +``` + +::: warning +`activeMatch`는 정규식이어야 하지만, 문자열로 정의해야 합니다. 실제 RegExp 객체를 사용할 수 없는 이유는 빌드하는 동안 직렬화할 수 없기 때문입니다. +::: + +### 링크의 "target" 및 "rel" 어트리뷰트 커스터마이징 {#customize-link-s-target-and-rel-attributes} + +기본적으로 VitePress는 링크가 외부 링크인지 여부에 따라 `target`과 `rel` 어트리뷰트를 자동으로 결정합니다. 하지만 원한다면 이를 커스터마이징 할 수도 있습니다. + +```js +export default { + themeConfig: { + nav: [ + { + text: 'GitHub 쇼핑몰', + link: 'https://www.thegithubshop.com/', + target: '_self', + rel: 'sponsored' // https://developers.google.com/search/docs/crawling-indexing/qualify-outbound-links + } + ] + } +} +``` + +## 소셜 링크 {#social-links} + +[`socialLinks`](./default-theme-config#sociallinks)를 참고하세요. + +## 커스텀 컴포넌트 {#custom-components} + +네비게이션 바에 커스텀 컴포넌트를 포함하려면 `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: { + 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는 컴포넌트에 다음과 같은 추가 프로퍼티를 제공합니다: + +- `screenMenu`: 컴포넌트가 모바일 네비게이션 바 메뉴 내부에 있는지를 나타내는 선택적 boolean 값 + +e2e 테스트 예제를 [여기](https://github.com/vuejs/vitepress/tree/main/__tests__/e2e/.vitepress)에서 확인할 수 있습니다. diff --git a/docs/ko/reference/default-theme-prev-next-links.md b/docs/ko/reference/default-theme-prev-next-links.md new file mode 100644 index 00000000..276ae882 --- /dev/null +++ b/docs/ko/reference/default-theme-prev-next-links.md @@ -0,0 +1,43 @@ +# 이전/다음 링크 {#prev-next-links} + +문서 하단에 표시되는 이전 페이지와 다음 페이지의 텍스트와 링크를 커스터마이징 할 수 있습니다. 사이드바에 있는 텍스트와 다른 텍스트를 원할 경우 유용합니다. 또한 푸터를 비활성화하거나 사이드바에 포함되지 않은 페이지로 링크할 때도 유용할 수 있습니다. + +## prev + +- 타입: `string | false | { text?: string; link?: string }` + +- 세부 사항: + + 이전 페이지로 가는 링크에 표시할 텍스트/링크를 지정합니다. 전문에서 이 항목을 설정하지 않으면, 사이드바 구성에서 텍스트/링크가 유추됩니다. + +- 예제: + + - 텍스트만 커스터마이징하려면: + + ```yaml + --- + prev: '시작하기 | 마크다운' + --- + ``` + + - 텍스트와 링크를 모두 커스터마이즈하려면: + + ```yaml + --- + prev: + text: '마크다운 확장 기능' + link: '/guide/markdown' + --- + ``` + + - 이전 페이지를 숨기려면: + + ```yaml + --- + prev: false + --- + ``` + +## next + +`prev`와 동일하지만, 다음 페이지에 대한 설정입니다. diff --git a/docs/ko/reference/default-theme-search.md b/docs/ko/reference/default-theme-search.md new file mode 100644 index 00000000..69b633aa --- /dev/null +++ b/docs/ko/reference/default-theme-search.md @@ -0,0 +1,379 @@ +--- +outline: deep +--- + +# 검색 {#search} + +## 로컬 검색 {#local-search} + +VitePress는 [minisearch](https://github.com/lucaong/minisearch/)로 브라우저 내 인덱스를 사용하는 퍼지(full-text) 검색을 지원합니다. 이 기능을 활성화하려면 `.vitepress/config.ts` 파일에서 `themeConfig.search.provider` 옵션을 `'local'`로 설정하면 됩니다: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local' + } + } +}) +``` + +예제 결과: + +![검색 모달의 스크린샷](/search.png) + +대안으로 [Algolia DocSearch](#algolia-search), , 와 같은 커뮤니티 플러그인을 사용할 수도 있습니다. + +### i18n {#local-search-i18n} + +다국어 검색을 사용하려면 다음과 같은 구성을 사용해야 합니다: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + locales: { + ko: { // 기본 로케일을 번역하려면 이것을 `root`로 만드십시오. + translations: { + button: { + buttonText: '검색', + buttonAriaLabel: '검색' + }, + modal: { + displayDetails: '상세 목록 표시', + resetButtonTitle: '검색 지우기', + backButtonTitle: '검색 닫기', + noResultsText: '결과를 찾을 수 없습니다', + footer: { + selectText: '선택', + selectKeyAriaLabel: '선택하기', + navigateText: '탐색', + navigateUpKeyAriaLabel: '위로', + navigateDownKeyAriaLabel: '아래로', + closeText: '닫기', + closeKeyAriaLabel: 'esc' + } + } + } + } + } + } + } + } +}) +``` + +### MiniSearch 옵션 {#mini-search-options} + +MiniSearch를 다음과 같이 구성할 수 있습니다: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + miniSearch: { + /** + * @type {Pick} + */ + options: { + /* ... */ + }, + /** + * @type {import('minisearch').SearchOptions} + * @default + * { fuzzy: 0.2, prefix: true, boost: { title: 4, text: 2, titles: 1 } } + */ + searchOptions: { + /* ... */ + } + } + } + } + } +}) +``` + +더 자세한 내용은 [MiniSearch 문서](https://lucaong.github.io/minisearch/classes/MiniSearch.MiniSearch.html)를 참고하세요. + +### 커스텀 컨텐츠 렌더러 {#custom-content-renderer} + +마크다운 컨텐츠를 인덱싱하기 전에 렌더링하는 데 사용되는 함수를 커스터마이징할 수 있습니다: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + /** + * @param {string} src + * @param {import('vitepress').MarkdownEnv} env + * @param {import('markdown-it-async')} md + */ + async _render(src, env, md) { + // return html string + } + } + } + } +}) +``` + +이 함수는 클라이언트 사이드 사이트 데이터에서 제거되므로, Node.js API를 사용할 수 있습니다. + +#### 예제: 검색에서 페이지 제외 {#example-excluding-pages-from-search} + +페이지의 전문에 `search: false`를 추가하여 검색에서 해당 페이지를 제외할 수 있습니다. 또는: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + async _render(src, env, md) { + const html = await md.renderAsync(src, env) + if (env.frontmatter?.search === false) return '' + if (env.relativePath.startsWith('some/path')) return '' + return html + } + } + } + } +}) +``` + +::: warning 참고 +커스텀 `_render` 함수가 제공된 경우, `search: false` 전문을 직접 처리해야 합니다. 또한, `md.renderAsync`가 호출되기 전에 `env` 객체가 완전히 채워지지 않으므로, `frontmatter`와 같은 선택적 `env` 프로퍼티에 대한 검사는 그 이후에 수행해야 합니다. +::: + +#### 예제: 콘텐츠 변환 - 앵커 추가 {#example-transforming-content-adding-anchors} + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + async _render(src, env, md) { + const html = await md.renderAsync(src, env) + if (env.frontmatter?.title) + return await md.renderAsync(`# ${env.frontmatter.title}`) + html + return html + } + } + } + } +}) +``` + +## Algolia 검색 {#algolia-search} + +VitePress는 [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch)를 사용한 문서 사이트 검색 기능을 지원합니다. 시작 가이드를 참고하세요. `.vitepress/config.ts`에서 이 기능을 사용하려면 최소한 다음 구성을 제공해야 합니다: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'algolia', + options: { + appId: '...', + apiKey: '...', + indexName: '...' + } + } + } +}) +``` + +### i18n {#algolia-search-i18n} + +다국어 검색을 사용하려면 다음과 같이 구성해야 합니다: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'algolia', + options: { + appId: '...', + apiKey: '...', + indexName: '...', + locales: { + ko: { + placeholder: '문서 검색', + translations: { + button: { + buttonText: '검색', + buttonAriaLabel: '검색' + }, + modal: { + searchBox: { + resetButtonTitle: '검색 지우기', + resetButtonAriaLabel: '검색 지우기', + cancelButtonText: '취소', + cancelButtonAriaLabel: '취소' + }, + startScreen: { + recentSearchesTitle: '검색 기록', + noRecentSearchesText: '최근 검색 없음', + saveRecentSearchButtonTitle: '검색 기록에 저장', + removeRecentSearchButtonTitle: '검색 기록에서 삭제', + favoriteSearchesTitle: '즐겨찾기', + removeFavoriteSearchButtonTitle: '즐겨찾기에서 삭제' + }, + errorScreen: { + titleText: '결과를 가져올 수 없습니다', + helpText: '네트워크 연결을 확인하세요' + }, + footer: { + selectText: '선택', + navigateText: '탐색', + closeText: '닫기', + searchByText: '검색 기준' + }, + noResultsScreen: { + noResultsText: '결과를 찾을 수 없습니다', + suggestedQueryText: '새로운 검색을 시도할 수 있습니다', + reportMissingResultsText: '해당 검색어에 대한 결과가 있어야 합니까?', + reportMissingResultsLinkText: '피드백 보내기 클릭' + } + } + } + } + } + } + } + } +}) +``` + +[이 옵션들](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts)은 재작성 할 수 있습니다. 이에 대해 자세히 알고 싶다면 Algolia 공식 문서를 참고하세요. + +### 크롤러 구성 {#crawler-config} + +이 사이트에서 사용하는 예제 구성을 소개합니다: + +```ts +new Crawler({ + appId: '...', + apiKey: '...', + rateLimit: 8, + startUrls: ['https://vitepress.dev/'], + renderJavaScript: false, + sitemaps: [], + exclusionPatterns: [], + ignoreCanonicalTo: false, + discoveryPatterns: ['https://vitepress.dev/**'], + schedule: 'at 05:10 on Saturday', + actions: [ + { + indexName: 'vitepress', + pathsToMatch: ['https://vitepress.dev/**'], + recordExtractor: ({ $, helpers }) => { + return helpers.docsearch({ + recordProps: { + lvl1: '.content h1', + content: '.content p, .content li', + lvl0: { + selectors: 'section.has-active div h2', + defaultValue: 'Documentation' + }, + lvl2: '.content h2', + lvl3: '.content h3', + lvl4: '.content h4', + lvl5: '.content h5' + }, + indexHeadings: true + }) + } + } + ], + initialIndexSettings: { + vitepress: { + attributesForFaceting: ['type', 'lang'], + attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'], + attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'], + attributesToSnippet: ['content:10'], + camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'], + searchableAttributes: [ + 'unordered(hierarchy_radio_camel.lvl0)', + 'unordered(hierarchy_radio.lvl0)', + 'unordered(hierarchy_radio_camel.lvl1)', + 'unordered(hierarchy_radio.lvl1)', + 'unordered(hierarchy_radio_camel.lvl2)', + 'unordered(hierarchy_radio.lvl2)', + 'unordered(hierarchy_radio_camel.lvl3)', + 'unordered(hierarchy_radio.lvl3)', + 'unordered(hierarchy_radio_camel.lvl4)', + 'unordered(hierarchy_radio.lvl4)', + 'unordered(hierarchy_radio_camel.lvl5)', + 'unordered(hierarchy_radio.lvl5)', + 'unordered(hierarchy_radio_camel.lvl6)', + 'unordered(hierarchy_radio.lvl6)', + 'unordered(hierarchy_camel.lvl0)', + 'unordered(hierarchy.lvl0)', + 'unordered(hierarchy_camel.lvl1)', + 'unordered(hierarchy.lvl1)', + 'unordered(hierarchy_camel.lvl2)', + 'unordered(hierarchy.lvl2)', + 'unordered(hierarchy_camel.lvl3)', + 'unordered(hierarchy.lvl3)', + 'unordered(hierarchy_camel.lvl4)', + 'unordered(hierarchy.lvl4)', + 'unordered(hierarchy_camel.lvl5)', + 'unordered(hierarchy.lvl5)', + 'unordered(hierarchy_camel.lvl6)', + 'unordered(hierarchy.lvl6)', + 'content' + ], + distinct: true, + attributeForDistinct: 'url', + customRanking: [ + 'desc(weight.pageRank)', + 'desc(weight.level)', + 'asc(weight.position)' + ], + ranking: [ + 'words', + 'filters', + 'typo', + 'attribute', + 'proximity', + 'exact', + 'custom' + ], + highlightPreTag: '', + highlightPostTag: '', + minWordSizefor1Typo: 3, + minWordSizefor2Typos: 7, + allowTyposOnNumericTokens: false, + minProximity: 1, + ignorePlurals: true, + advancedSyntax: true, + attributeCriteriaComputedByMinProximity: true, + removeWordsIfNoResults: 'allOptional' + } + } +}) +``` diff --git a/docs/ko/reference/default-theme-sidebar.md b/docs/ko/reference/default-theme-sidebar.md new file mode 100644 index 00000000..8e4709cd --- /dev/null +++ b/docs/ko/reference/default-theme-sidebar.md @@ -0,0 +1,182 @@ +# 사이드바 {#sidebar} + +사이드바는 문서의 기본 탐색 블록입니다. [`themeConfig.sidebar`](./default-theme-config#sidebar)에서 사이드바 메뉴를 구성할 수 있습니다. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: '가이드', + items: [ + { text: '소개', link: '/introduction' }, + { text: '시작하기', link: '/getting-started' }, + ... + ] + } + ] + } +} +``` + +## 기본 사용법 {#the-basics} + +사이드바 메뉴의 가장 간단한 형태는 링크 배열을 전달하는 것입니다. 첫 번째 계층 아이템은 사이드바의 "섹션"을 정의합니다. 이 섹션에는 제목인 `text`와 실제 탐색 링크인 `items`가 포함되어야 합니다. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: '섹션 제목 A', + items: [ + { text: '아이템 A', link: '/item-a' }, + { text: '아이템 B', link: '/item-b' }, + ... + ] + }, + { + text: '섹션 제목 B', + items: [ + { text: '아이템 C', link: '/item-c' }, + { text: '아이템 D', link: '/item-d' }, + ... + ] + } + ] + } +} +``` + +각 `link`는 `/`로 시작하는 실제 파일 경로를 지정해야 합니다. 링크 끝에 슬래시를 추가하면 해당 디렉터리의 `index.md`를 보여줍니다. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: '가이드', + items: [ + // 이것은 `/guide/index.md` 페이지를 보여줍니다. + { text: '소개', link: '/guide/' } + ] + } + ] + } +} +``` + +사이드바 아이템을 루트 단계에서 최대 6단계까지 중첩할 수 있습니다. 6단계를 초과하는 중첩 아이템은 무시되며 사이드바에 표시되지 않습니다. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: '1단계', + items: [ + { + text: '2단계', + items: [ + { + text: '3단계', + items: [ + ... + ] + } + ] + } + ] + } + ] + } +} +``` + +## 여러 사이드바 {#multiple-sidebars} + +페이지 경로에 따라 다른 사이드바를 표시할 수 있습니다. 예를 들어 이 사이트처럼 문서의 각 섹션을 "가이드"와 "레퍼런스" 페이지에 따라 별도로 만들고 싶을 수 있습니다. + +이를 위해 먼저 각 섹션 디렉터리로 페이지를 구성합니다: + +``` +. +├─ guide/ +│ ├─ index.md +│ ├─ one.md +│ └─ two.md +└─ config/ + ├─ index.md + ├─ three.md + └─ four.md +``` + +그런 다음 각 섹션에 대한 사이드바를 정의하도록 구성 파일을 업데이트합니다. 이런 경우에는 배열 대신 객체를 전달해야 합니다. + +```js +export default { + themeConfig: { + sidebar: { + // 이 사이드바는 유저가 + // `guide` 디렉토리에 있을 때 표시됩니다. + '/guide/': [ + { + text: '가이드', + items: [ + { text: '개요', link: '/guide/' }, + { text: '하나', link: '/guide/one' }, + { text: '둘', link: '/guide/two' } + ] + } + ], + + // 이 사이드바는 유저가 + // `config` 디렉토리에 있을 때 표시됩니다. + '/config/': [ + { + text: '설정', + items: [ + { text: '개요', link: '/config/' }, + { text: '셋', link: '/config/three' }, + { text: '넷', link: '/config/four' } + ] + } + ] + } + } +} +``` + +## 접을 수 있는 사이드바 그룹 {#collapsible-sidebar-groups} + +사이드바 그룹에 `collapsed` 옵션을 추가하면 각 섹션을 접거나 펼칠 수 있는 토글 버튼이 표시됩니다. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: '섹션 제목 A', + collapsed: false, + items: [...] + } + ] + } +} +``` + +모든 섹션은 기본적으로 "열림" 상태입니다. 초기 페이지 로드 시 "닫힘" 상태로 두려면 `collapsed` 옵션을 `true`로 설정합니다. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: '섹션 제목 A', + collapsed: true, + items: [...] + } + ] + } +} +``` diff --git a/docs/ko/reference/default-theme-team-page.md b/docs/ko/reference/default-theme-team-page.md new file mode 100644 index 00000000..b4fddb0f --- /dev/null +++ b/docs/ko/reference/default-theme-team-page.md @@ -0,0 +1,256 @@ + + +# 팀 페이지 {#team-page} + +팀을 소개하고자 할 때, 팀 컴포넌트를 사용하여 팀 페이지를 구성할 수 있습니다. 이 컴포넌트를 사용하는 방법은 두 가지가 있습니다. 하나는 문서 페이지에 포함시키는 방법이고, 다른 하나는 전체 팀 페이지를 만드는 방법입니다. + +## 페이지에서 팀 구성원 보여주기 {#show-team-members-in-a-page} + +`vitepress/theme`에서 제공되는 `` 컴포넌트를 사용하여, 어떤 페이지에서도 팀 구성원 목록을 표시할 수 있습니다. + +```html + + +# Our Team + +Say hello to our awesome team. + + +``` + +위 코드는 카드 형태의 엘리먼트로 팀 구성원을 표시합니다. 아래와 비슷한 형태로 표시됩니다. + + + +`` 컴포넌트는 `small`과 `medium` 두 가지 크기로 제공됩니다. 개인의 선호도에 따라 선택할 수 있지만, 일반적으로 `small` 사이즈가 문서 페이지에 더 적합합니다. 또한, 각 구성원에 "설명"이나 "후원" 버튼과 같은 프로퍼티를 추가할 수도 있습니다. 자세한 내용은 [``](#vpteammembers)에서 확인할 수 있습니다. + +문서 페이지에 팀 구성원을 포함시키는 것은 전용 팀 페이지를 만드는 것이 과할 수 있는 소규모 팀이나, 문서의 맥락에 따라 일부 구성원을 소개할 때 좋습니다. + +만약 많은 수의 구성원이 있거나, 팀 구성원을 보여줄 더 많은 공간이 필요하다면, [전체 팀 페이지 만들기](#create-a-full-team-page)를 고려해 보세요. + +## 전체 팀 페이지 만들기 {#create-a-full-team-page} + +팀 구성원을 문서 페이지에 추가하는 대신, 전체 팀 페이지를 만들어 [홈 페이지](./default-theme-home-page)를 커스텀하는 것처럼 팀 페이지를 만들 수도 있습니다. + +팀 페이지를 만들려면, 먼저 새로운 마크다운 파일을 생성하세요. 파일 이름은 중요하지 않지만, 여기서는 `team.md`라고 부르겠습니다. 이 파일에서 전문 옵션에 `layout: page`를 설정한 후, `TeamPage` 컴포넌트를 사용하여 페이지 구조를 구성합니다. + +```html +--- +layout: page +--- + + + + + + + + + +``` + +전체 팀 페이지를 만들 때는 모든 컴포넌트를 `` 컴포넌트로 감싸야 합니다. 이 컴포넌트는 중첩된 팀 관련 컴포넌트들이 적절한 레이아웃 구조와 간격을 갖도록 합니다. + +`` 컴포넌트는 페이지 제목 섹션을 추가합니다. 제목은 `

` 헤딩으로 표시됩니다. `#title`과 `#lead` 슬롯을 사용하여 팀에 대한 설명을 작성할 수 있습니다. + +`` 컴포넌트는 문서 페이지에서 사용할 때와 동일하게 작동하며, 팀 구성원 목록을 표시합니다. + +### 팀 구성원을 구분하기 위한 섹션 추가 {#add-sections-to-divide-team-members} + +팀 페이지에 "섹션"을 추가할 수도 있습니다. 예를 들어, 핵심 팀 구성원과 커뮤니티 파트너와 같은 다양한 유형의 팀 구성원이 있을 수 있습니다. 이 구성원들을 섹션으로 나누어 각 그룹의 역할을 더 잘 설명할 수 있습니다. + +이를 위해 이전에 만든 `team.md` 파일에 `` 컴포넌트를 추가하세요. + +```html +--- +layout: page +--- + + + + + + + + + + + + + + +``` + +`` 컴포넌트는 `VPTeamPageTitle` 컴포넌트처럼 `#title`과 `#lead` 슬롯을 가질 수 있으며, 팀 구성원을 표시하기 위한 `#members` 슬롯도 있습니다. + +`#members` 슬롯 내부에는 `` 컴포넌트를 추가해야 합니다. + +## `` + +`` 컴포넌트는 주어진 팀 구성원 목록을 표시합니다. + +```html + +``` + +```ts +interface Props { + // 각 구성원 사이즈. 기본값: `medium` + size?: 'small' | 'medium' + + // 표시할 구성원 목록. + members: TeamMember[] +} + +interface TeamMember { + // 구성원 아바타 이미지. + avatar: string + + // 구성원 이름. + name: string + + // 구성원 이름 아래에 표시될 직함. + // 예: 개발자, 소프트웨어 엔지니어 등 + title?: string + + // 구성원이 속한 조직. + org?: string + + // 조직의 URL. + orgLink?: string + + // 구성원에 대한 설명. + desc?: string + + // 소셜 링크. 예: GitHub, Twitter 등. + // 소셜 링크 객체를 전달해야 함. + // 참고: https://vitepress.dev/ko/reference/default-theme-config.html#sociallinks + links?: SocialLink[] + + // 구성원의 후원 페이지 URL. + sponsor?: string + + // 후원 링크 텍스트. 기본값: 'Sponsor' + actionText?: string +} +``` + +## `` + +전체 팀 페이지를 만들 때 사용하는 루트 컴포넌트입니다. 단일 슬롯만 허용하며, 전달된 모든 팀 관련 컴포넌트에 스타일을 적용합니다. + +## `` + +페이지의 "제목" 섹션을 추가합니다. `` 아래 맨 처음에 사용하는 것이 가장 좋습니다. `#title`과 `#lead` 슬롯이 있습니다. + +```html + + + + + + +``` + +## `` + +팀 페이지 내에서 "섹션"을 생성합니다. `#title`, `#lead`, `#members` 슬롯이 있습니다. `` 안에 원하는 만큼 섹션을 추가할 수 있습니다. + +```html + + ... + + + + + + +``` diff --git a/docs/ko/reference/frontmatter-config.md b/docs/ko/reference/frontmatter-config.md new file mode 100644 index 00000000..b10768a4 --- /dev/null +++ b/docs/ko/reference/frontmatter-config.md @@ -0,0 +1,221 @@ +--- +outline: deep +--- + +# 전문 구성 {#frontmatter-config} + +전문은 페이지 기반 구성을 가능하게 합니다. 각 마크다운 파일에서 전문 구성을 사용하여 사이트 수준 또는 테마 수준의 구성 옵션을 재정의할 수 있습니다. 또한, 전문에서만 정의할 수 있는 구성 옵션도 있습니다. + +사용 예: + +```md +--- +title: Docs with VitePress +editLink: true +--- +``` + +Vue 표현식에서 `$frontmatter` 전역 변수를 통해 전문 데이터에 접근할 수 있습니다: + +```md +{{ $frontmatter.title }} +``` + +## title + +- 타입: `string` + +페이지의 제목입니다. [config.title](./site-config#title)과 동일하며, 사이트 레벨의 구성을 재정의합니다. + +```yaml +--- +title: VitePress +--- +``` + +## titleTemplate + +- 타입: `string | boolean` + +제목의 접미사입니다. [config.titleTemplate](./site-config#titletemplate)와 동일하며, 사이트 레벨의 구성을 재정의합니다. + +```yaml +--- +title: VitePress +titleTemplate: Vite & Vue powered static site generator +--- +``` + +## description + +- 타입: `string` + +페이지의 설명입니다. [config.description](./site-config#description)과 동일하며, 사이트 레벨의 구성을 재정의합니다. + +```yaml +--- +description: VitePress +--- +``` + +## head + +- 타입: `HeadConfig[]` + +현재 페이지에 삽입할 추가 head 태그를 지정합니다. 사이트 수준 구성에 의해 삽입된 head 태그 뒤에 추가됩니다. + +```yaml +--- +head: + - - meta + - name: description + content: hello + - - meta + - name: keywords + content: super duper SEO +--- +``` + +```ts +type HeadConfig = + | [string, Record] + | [string, Record, string] +``` + +## 기본 테마 전용 {#default-theme-only} + +다음 전문 옵션은 기본 테마를 사용할 때만 적용됩니다. + +### layout + +- 타입: `doc | home | page` +- 기본값: `doc` + +페이지의 레이아웃을 결정합니다. + +- `doc` - 마크다운 컨텐츠에 기본 문서 스타일을 적용합니다. +- `home` - "홈 페이지"를 위한 특별 레이아웃입니다. 아름다운 랜딩 페이지를 빠르게 만들기 위해 `hero` 및 `features`와 같은 옵션을 추가할 수 있습니다. +- `page` - `doc`과 유사하게 작동하지만 콘텐츠에 스타일을 적용하지 않습니다. 완전히 커스텀 페이지를 만들 때 유용합니다. + +```yaml +--- +layout: doc +--- +``` + +### hero + +`layout`이 `home`으로 설정된 경우, 홈 히어로 섹션의 내용을 정의합니다. 자세한 내용은 [기본 테마: 홈 페이지](./default-theme-home-page)에서 확인할 수 있습니다. + +### features + +`layout`이 `home`으로 설정된 경우, 기능 섹션에 표시할 항목을 정의합니다. 자세한 내용은 [기본 테마: 홈 페이지](./default-theme-home-page)에서 확인할 수 있습니다. + +### navbar + +- 타입: `boolean` +- 기본값: `true` + +[네비게이션 바](./default-theme-nav)를 표시할지 여부를 설정합니다. + +```yaml +--- +navbar: false +--- +``` + +### sidebar + +- 타입: `boolean` +- 기본값: `true` + +[사이드바](./default-theme-sidebar)를 표시할지 여부를 설정합니다. + +```yaml +--- +sidebar: false +--- +``` + +### aside + +- 타입: `boolean | 'left'` +- 기본값: `true` + +`doc` 레이아웃에서 어사이드(aside) 컴포넌트의 위치를 정의합니다. + +이 값을 `false`로 설정하면 어사이드 컨테이너가 렌더링되지 않습니다.\ +이 값을 `true`로 설정하면 어사이드를 오른쪽에 렌더링합니다.\ +이 값을 `'left'`로 설정하면 어사이드를 왼쪽에 렌더링합니다. + +```yaml +--- +aside: false +--- +``` + +### outline + +- 타입: `number | [number, number] | 'deep' | false` +- 기본값: `2` + +페이지에 표시할 아웃라인(개요) 헤더의 레벨을 설정합니다. [config.themeConfig.outline.level](./default-theme-config#outline)과 동일하며, 사이트 수준 구성에서 설정된 값을 재정의합니다. + +### lastUpdated + +- 타입: `boolean | Date` +- 기본값: `true` + +현재 페이지의 푸터에 [마지막 업데이트 날짜](./default-theme-last-updated) 텍스트를 표시할지 여부를 설정합니다. 날짜/시간이 지정되면 마지막 git 수정 타임스탬프 대신 해당 날짜/시간이 표시됩니다. + +```yaml +--- +lastUpdated: false +--- +``` + +### editLink + +- 타입: `boolean` +- 기본값: `true` + +현재 페이지의 푸터에 [편집 링크](./default-theme-edit-link)를 표시할지 여부를 설정합니다. + +```yaml +--- +editLink: false +--- +``` + +### footer + +- 타입: `boolean` +- 기본값: `true` + +[푸터](./default-theme-footer)를 표시할지 여부를 설정합니다. + +```yaml +--- +footer: false +--- +``` + +### pageClass + +- 타입: `string` + +페이지에 추가할 클래스 입니다. + +```yaml +--- +pageClass: custom-page-class +--- +``` + +그런 다음 `.vitepress/theme/custom.css` 파일에서 이 페이지의 스타일을 커스텀 할 수 있습니다: + +```css +.custom-page-class { + /* 페이지별 스타일 */ +} +``` diff --git a/docs/ko/reference/runtime-api.md b/docs/ko/reference/runtime-api.md new file mode 100644 index 00000000..e9a8e530 --- /dev/null +++ b/docs/ko/reference/runtime-api.md @@ -0,0 +1,169 @@ +# 런타임 API {#runtime-api} + +VitePress는 애플리케이션 데이터를 액세스할 수 있는 여러 내장 API를 제공합니다. 그리고 전역적으로 사용할 수 있는 몇 가지 내장 컴포넌트도 제공합니다. + +헬퍼 메서드는 `vitepress`에서 전역적으로 사용할 수 있으며, 주로 커스텀 테마의 Vue 컴포넌트에서 사용됩니다. 또한 마크다운 파일이 Vue [단일 파일 컴포넌트](https://vuejs.org/guide/scaling-up/sfc.html)로 컴파일되기 때문에 `.md` 페이지 내에서도 사용할 수 있습니다. + +`use*`로 시작하는 메서드는 [Vue 3 Composition API](https://vuejs.org/guide/introduction.html#composition-api) 함수("컴포저블")를 나타내며, 이는 `setup()` 또는 ` + + +``` + +## `useRoute` + +다음과 같은 타입으로 현재 라우트 객체를 반환합니다: + +```ts +interface Route { + path: string + data: PageData + component: Component | null +} +``` + +## `useRouter` + +프로그래밍 방식으로 다른 페이지로 이동할 수 있도록 VitePress 라우터 인스턴스를 반환합니다. + +```ts +interface Router { + /** + * 현재 route. + */ + route: Route + /** + * 새 URL로 이동. + */ + go: (to?: string) => Promise + /** + * 라우트가 변경되기 전에 호출. 탐색을 취소하려면 `false`를 반환. + */ + onBeforeRouteChange?: (to: string) => Awaitable + /** + * 페이지 컴포넌트가 로드되기 전(히스토리 상태가 업데이트된 후)에 호출. + * 탐색을 취소하려면 `false`를 반환. + */ + onBeforePageLoad?: (to: string) => Awaitable + /** + * 라우트가 변경된 후 호출. + */ + onAfterRouteChange?: (to: string) => Awaitable +} +``` + +## `withBase` + +- **타입**: `(path: string) => string` + +구성된 [`base`](./site-config#base)를 지정된 URL 경로에 추가합니다. [Base URL](../guide/asset-handling#base-url)을 참고하세요. + +## `` + +`` 컴포넌트는 렌더링된 마크다운 내용을 표시합니다. [커스텀 테마를 만들 때](../guide/custom-theme) 유용합니다. + +```vue + +``` + +## `` + +`` 컴포넌트는 클라이언트 측에서만 슬롯을 렌더링합니다. + +VitePress 애플리케이션은 정적 빌드를 생성할 때 Node.js에서 서버 렌더링되므로 모든 Vue 사용은 범용 코드 요구 사항을 준수해야 합니다. 간단히 말해서, 브라우저 / DOM API는 반드시 beforeMount 또는 mounted 훅에서만 접근해야 합니다. + +SSR 친화적이지 않은(예: 커스텀 디렉티브를 포함하는) 컴포넌트를 사용하는 경우, 이를 `ClientOnly` 컴포넌트 내부에 래핑할 수 있습니다. + +```vue-html + + + +``` + +- 참고: [SSR 호환성](../guide/ssr-compat) + +## `$frontmatter` + +Vue 표현식에서 현재 페이지의 [전문](../guide/frontmatter) 데이터에 직접 접근합니다. + +```md +--- +title: Hello +--- + +# {{ $frontmatter.title }} +``` + +## `$params` + +Vue 표현식에서 현재 페이지의 [동적 라우트 파라미터](../guide/routing#dynamic-routes)에 직접 접근합니다. + +```md +- package name: {{ $params.pkg }} +- version: {{ $params.version }} +``` diff --git a/docs/ko/reference/site-config.md b/docs/ko/reference/site-config.md new file mode 100644 index 00000000..25dbcc01 --- /dev/null +++ b/docs/ko/reference/site-config.md @@ -0,0 +1,722 @@ +--- +outline: deep +--- + +# 사이트 구성 {#site-config} + +사이트 구성(config)은 사이트의 전역 설정을 정의할 수 있는 곳입니다. 애플리케이션 구성 옵션은 사용 중인 테마와 상관없이 모든 VitePress 사이트에 적용되는 설정을 정의합니다. 예를 들어 기본 디렉터리나 사이트의 제목 등이 있습니다. + +## 개요 {#overview} + +### 구성 분석 {#config-resolution} + +구성 파일은 항상 `/.vitepress/config.[ext]`에서 처리됩니다. 여기서 ``는 VitePress [프로젝트 루트](../guide/routing#root-and-source-directory)를 의미하며, `[ext]`는 지원되는 파일 확장자 중 하나입니다. TypeScript는 기본적으로 지원됩니다. 지원되는 확장자에는 `.js`, `.ts`, `.mjs`, `.mts`가 포함됩니다. + +구성 파일에서는 ES 모듈 구문을 사용하는 것이 권장됩니다. 구성 파일은 객체를 "default export"해야 합니다: + +```ts +export default { + // 애플리케이션 레벨의 구성 옵션 + lang: 'en-US', + title: 'VitePress', + description: 'Vite & Vue powered static site generator.', + ... +} +``` + +::: details 동적(비동기) 구성 + +구성을 동적으로 생성해야 하는 경우, 함수를 "default export" 할 수 있습니다. 예: + +```ts +import { defineConfig } from 'vitepress' + +export default async () => { + const posts = await (await fetch('https://my-cms.com/blog-posts')).json() + + return defineConfig({ + // 애플리케이션 레벨의 구성 옵션 + lang: 'en-US', + title: 'VitePress', + description: 'Vite & Vue powered static site generator.', + + // 테마 레벨의 구성 옵션 + themeConfig: { + sidebar: [ + ...posts.map((post) => ({ + text: post.name, + link: `/posts/${post.name}` + })) + ] + } + }) +} +``` + +최상위 수준의 `await`도 사용할 수 있습니다. 예: + +```ts +import { defineConfig } from 'vitepress' + +const posts = await (await fetch('https://my-cms.com/blog-posts')).json() + +export default defineConfig({ + // 앱 레벨 설정 옵션 + lang: 'en-US', + title: 'VitePress', + description: 'Vite & Vue를 활용한 정적 사이트 생성기.', + + // 테마 레벨 설정 옵션 + themeConfig: { + sidebar: [ + ...posts.map((post) => ({ + text: post.name, + link: `/posts/${post.name}` + })) + ] + } +}) +``` + +::: + +### 구성 인텔리센스 {#config-intellisense} + +`defineConfig` 헬퍼를 사용하면 구성 옵션에 대해 TypeScript 기반의 인텔리센스(자동완성)를 제공받을 수 있습니다. IDE가 이를 지원하는 경우, JavaScript와 TypeScript 모두에서 작동합니다. + +```js +import { defineConfig } from 'vitepress' + +export default defineConfig({ + // ... +}) +``` + +### 타입이 지정된 테마 구성 {#typed-theme-config} + +기본적으로 `defineConfig` 헬퍼는 기본 테마에서 테마 구성 타입을 예측합니다: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + // 타입은 `DefaultTheme.Config` + } +}) +``` + +커스텀 테마를 사용하고 테마 구성에 대한 타입 검사를 원한다면, `defineConfigWithTheme`를 사용하고 제네릭 인수를 통해 커스텀 테마의 구성 타입을 전달해야 합니다: + +```ts +import { defineConfigWithTheme } from 'vitepress' +import type { ThemeConfig } from 'your-theme' + +export default defineConfigWithTheme({ + themeConfig: { + // 타입은 `ThemeConfig` + } +}) +``` + +### Vite, Vue, Markdown 설정 {#vite-vue-markdown-config} + +- **Vite** + + VitePress 구성에서 [vite](#vite) 옵션을 사용하여 기본 Vite 인스턴스를 구성할 수 있습니다. 별도의 Vite 구성 파일을 만들 필요는 없습니다. + +- **Vue** + + VitePress는 이미 Vite의 공식 Vue 플러그인([@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue))을 포함하고 있습니다. VitePress 구성에서 [vue](#vue) 옵션을 사용하여 해당 옵션을 구성할 수 있습니다. + +- **Markdown** + + [Markdown-It](https://github.com/markdown-it/markdown-it) 인스턴스를 VitePress 구성에서 [markdown](#markdown) 옵션을 사용하여 구성할 수 있습니다. + +## 사이트 메타데이터 {#site-metadata} + +### title + +- 타입: `string` +- 기본값: `VitePress` +- [전문](./frontmatter-config#title)을 통해 페이지별로 재정의 가능 + +사이트의 제목입니다. 기본 테마를 사용할 경우, 이는 내비게이션 바에 표시됩니다. + +[`titleTemplate`](#titletemplate)이 정의되지 않은 경우, 모든 개별 페이지 제목의 기본 접미사로 사용됩니다. 개별 페이지의 최종 제목은 첫 번째 `

` 헤더의 텍스트 콘텐츠와 전역 `title`을 접미사로 결합한 것입니다. 예를 들어 다음 구성과 페이지 콘텐츠가 있을 경우: + +```ts +export default { + title: 'My Awesome Site' +} +``` + +```md +# Hello +``` + +페이지의 제목은 `Hello | My Awesome Site`가 됩니다. + +### titleTemplate + +- 타입: `string | boolean` +- [전문](./frontmatter-config#titletemplate)을 통해 페이지별로 재정의 가능 + +각 페이지의 제목 접미사 또는 전체 제목을 커스터마이징할 수 있습니다. 예를 들어: + +```ts +export default { + title: 'My Awesome Site', + titleTemplate: 'Custom Suffix' +} +``` + +```md +# Hello +``` + +페이지의 제목은 `Hello | Custom Suffix`가 됩니다. + +제목이 렌더링되는 방식을 완전히 커스터마이징하려면 `titleTemplate`에서 `:title` 심볼을 사용할 수 있습니다: + +```ts +export default { + titleTemplate: ':title - Custom Suffix' +} +``` + +여기서 `:title`은 페이지의 첫 번째 `

` 헤더에서 추론된 텍스트로 대체됩니다. 이전 예제 페이지의 제목은 `Hello - Custom Suffix`가 됩니다. + +이 옵션을 `false`로 설정하여 제목 접미사를 비활성화할 수 있습니다. + +### description + +- 타입: `string` +- 기본값: `A VitePress site` +- [전문](./frontmatter-config#description)을 통해 페이지별로 재정의 가능 + +사이트의 설명입니다. 이는 페이지 HTML의 `` 태그로 렌더링됩니다. + +```ts +export default { + description: 'A VitePress site' +} +``` + +### head + +- 타입: `HeadConfig[]` +- 기본값: `[]` +- [전문](./frontmatter-config#head)을 통해 페이지별로 추가 가능 + +페이지 HTML의 `` 태그에 렌더링할 추가 엘리먼트입니다. 추가한 태그는 VitePress 태그 뒤 ~ 닫는 `head` 태그 앞에 렌더링됩니다. + +```ts +type HeadConfig = + | [string, Record] + | [string, Record, string] +``` + +#### 예제: 파비콘 추가 {#example-adding-a-favicon} + +```ts +export default { + head: [['link', { rel: 'icon', href: '/favicon.ico' }]] +} // favicon.ico를 public 디렉토리에 배치하거나 base가 설정된 경우, + // /base/favicon.ico를 사용하세요. +/* 다음과 같이 랜더링: + +*/ +``` + +#### 예제: Google 폰트 추가 {#example-adding-google-fonts} + +```ts +export default { + head: [ + [ + 'link', + { rel: 'preconnect', href: 'https://fonts.googleapis.com' } + ], + [ + 'link', + { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: '' } + ], + [ + 'link', + { href: 'https://fonts.googleapis.com/css2?family=Roboto&display=swap', rel: 'stylesheet' } + ] + ] +} + +/* 다음과 같이 랜더링: + + + +*/ +``` + +#### 예제: 서비스 워커 등록 {#example-registering-a-service-worker} + +```ts +export default { + head: [ + [ + 'script', + { id: 'register-sw' }, + `;(() => { + if ('serviceWorker' in navigator) { + navigator.serviceWorker.register('/sw.js') + } + })()` + ] + ] +} + +/* 다음과 같이 랜더링: + +*/ +``` + +#### 예제: Google Analytics 사용 {#example-using-google-analytics} + +```ts +export default { + head: [ + [ + 'script', + { async: '', src: 'https://www.googletagmanager.com/gtag/js?id=TAG_ID' } + ], + [ + 'script', + {}, + `window.dataLayer = window.dataLayer || []; + function gtag(){dataLayer.push(arguments);} + gtag('js', new Date()); + gtag('config', 'TAG_ID');` + ] + ] +} + +/* 다음과 같이 랜더링: + + +*/ +``` + +### lang + +- 타입: `string` +- 기본값: `en-US` + +사이트의 언어 어트리뷰트입니다. 이는 페이지 HTML의 `` 태그로 렌더링됩니다. + +```ts +export default { + lang: 'en-US' +} +``` + +### base + +- 타입: `string` +- 기본값: `/` + +사이트가 배포될 기본 URL입니다. 예를 들어 GitHub Pages와 같이 서브 경로에 사이트를 배포하려는 경우 이것을 설정해야 합니다. `https://foo.github.io/bar/` 에 사이트를 배포하려면 `'/bar/'`로 설정해야 합니다. 항상 슬래시로 시작하고 끝나야 합니다. + +이것은 다른 옵션에서 `/`로 시작하는 모든 URL에 자동으로 추가되므로, 한 번만 지정하면 됩니다. + +```ts +export default { + base: '/base/' +} +``` + +## 라우팅 {#routing} + +### cleanUrls + +- 타입: `boolean` +- 기본값: `false` + +`true`로 설정하면 VitePress는 URL에서 `.html`을 제거합니다. [간결한 URL 생성](../guide/routing#generating-clean-url)을 참고하세요. + +::: warning 서버 지원 필요 +이를 활성화하려면 호스팅 플랫폼에서 추가 구성이 필요할 수 있습니다. 서버가 `/foo`를 방문할 때 **리디렉션 없이** `/foo.html`을 제공할 수 있어야 합니다. +::: + +### rewrites + +- 타입: `Record` + +커스텀 디렉터리와 URL 매핑을 정의합니다. 자세한 내용은 [라우팅: 라우트 재작성](../guide/routing#route-rewrites)을 참고하세요. + +```ts +export default { + rewrites: { + 'source/:page': 'destination/:page' + } +} +``` + +## 빌드 {#build} + +### srcDir + +- 타입: `string` +- 기본값: `.` + +마크다운 페이지가 저장되는 디렉터리입니다. 프로젝트 루트에 상대적입니다. 또한 [루트와 소스 디렉터리](../guide/routing#root-and-source-directory)를 참고하세요. + +```ts +export default { + srcDir: './src' +} +``` + +### srcExclude + +- 타입: `string` +- 기본값: `undefined` + +소스 컨텐츠에서 제외해야 하는 마크다운 파일을 매칭하기 위한 [glob 패턴](https://github.com/mrmlnc/fast-glob#pattern-syntax)입니다. + +```ts +export default { + srcExclude: ['**/README.md', '**/TODO.md'] +} +``` + +### outDir + +- 타입: `string` +- 기본값: `./.vitepress/dist` + +사이트의 빌드 결과물 위치입니다. [프로젝트 루트](../guide/routing#root-and-source-directory)에 상대적입니다. + +```ts +export default { + outDir: '../public' +} +``` + +### assetsDir + +- 타입: `string` +- 기본값: `assets` + +생성된 에셋을 포함할 디렉터리를 지정합니다. 경로는 [`outDir`](#outdir) 내에 있어야 하며, 그것을 기준으로 처리됩니다. + +```ts +export default { + assetsDir: 'static' +} +``` + +### cacheDir + +- 타입: `string` +- 기본값: `./.vitepress/cache` + +캐시 파일을 위한 디렉터리입니다. [프로젝트 루트](../guide/routing#root-and-source-directory)에 상대적입니다. [cacheDir](https://vitejs.dev/config/shared-options.html#cachedir)을 참고하세요. + +```ts +export default { + cacheDir: './.vitepress/.vite' +} +``` + +### ignoreDeadLinks + +- 타입: `boolean | 'localhostLinks' | (string | RegExp | ((link: string) => boolean))[]` +- 기본값: `false` + +`true`로 설정하면, 빌드 시 죽은 링크로 인해 실패하지 않습니다. + +`'localhostLinks'`로 설정하면, 죽은 링크가 있으면 빌드에 실패하지만 `localhost` 링크는 확인하지 않습니다. + +```ts +export default { + ignoreDeadLinks: true +} +``` + +정확히 일치하는 URL 문자열, 정규 표현식 패턴, 커스텀 필터 함수로 구성된 배열도 가능합니다. + +```ts +export default { + ignoreDeadLinks: [ + // "/playground"과 정확히 일치하는 url 무시 + '/playground', + // 모든 localhost 링크 무시 + /^https?:\/\/localhost/, + // 모든 "/repl/" 포함 링크 무시 + /\/repl\//, + // 커스텀 함수, "ignore"를 포함한 모든 링크 무시 + (url) => { + return url.toLowerCase().includes('ignore') + } + ] +} +``` + +### metaChunk + +- 타입: `boolean` +- 기본값: `false` + +`true`로 설정하면 페이지 메타데이터를 초기 HTML에 인라인으로 삽입하는 대신 별도의 JavaScript 청크로 추출합니다. 이렇게 하면 각 페이지의 HTML 페이로드가 작아지고 페이지 메타데이터를 캐시할 수 있어, 사이트에 많은 페이지가 있을 때 서버 대역폭을 줄일 수 있습니다. + +### mpa + +- 타입: `boolean` +- 기본값: `false` + +`true`로 설정하면 프로덕션 애플리케이션이 [MPA 모드](../guide/mpa-mode)로 빌드됩니다. MPA 모드는 기본적으로 0kb JavaScript를 제공하지만, 클라이언트 사이드 탐색을 비활성화하고 상호작용을 위한 명시적인 옵트인을 필요로 합니다. + +## 테마 {#theming} + +### appearance + +- 타입: `boolean | 'dark' | 'force-dark' | 'force-auto' | import('@vueuse/core').UseDarkOptions` +- 기본값: `true` + +다크 모드를 활성화 여부를 설정합니다 (`.dark` 클래스를 `` 엘리먼트에 추가). + +- `true`: 기본 테마는 유저의 선호 색상 설정에 따라 결정됩니다. +- `dark`: 유저가 수동으로 변경하지 않는 한 기본 테마는 다크 모드가 됩니다. +- `false`: 유저는 테마를 전환할 수 없습니다. +- `'force-dark'`: 테마는 항상 다크 모드가 되며 유저는 이를 전환할 수 없습니다. +- `'force-auto'`: 테마는 항상 유저의 선호 색상 설정에 따라 결정되며 유저는 이를 전환할 수 없습니다. + +이 옵션은 `vitepress-theme-appearance` 키를 사용하여 로컬 스토리지에서 유저 설정을 복원하는 인라인 스크립트를 삽입합니다. 이는 페이지가 렌더링되기 전에 `.dark` 클래스가 적용되어 깜박임을 방지합니다. + +`appearance.initialValue`는 `'dark'` 또는 `undefined`만 가능합니다. Refs 또는 getter는 지원되지 않습니다. + +### lastUpdated + +- 타입: `boolean` +- 기본값: `false` + +각 페이지의 마지막 업데이트 타임스탬프를 Git을 사용하여 가져올지 여부를 설정합니다. 타임스탬프는 각 페이지의 페이지 데이터에 포함되며, [`useData`](./runtime-api#usedata)를 통해 접근할 수 있습니다. + +기본 테마를 사용할 때, 이 옵션을 활성화하면 각 페이지의 마지막 업데이트 시간이 표시됩니다. [`themeConfig.lastUpdatedText`](./default-theme-config#lastupdatedtext) 옵션을 통해 텍스트를 커스터마이징할 수 있습니다. + +## 커스터마이징 {#customization} + +### markdown + +- 타입: `MarkdownOption` + +마크다운 파서 옵션을 구성합니다. VitePress는 파서로 [Markdown-it](https://github.com/markdown-it/markdown-it)을 사용하고, 언어 구문 강조를 위해 [Shiki](https://github.com/shikijs/shiki)를 사용합니다. 이 옵션 내에서 다양한 마크다운 관련 옵션을 전달하여 필요에 맞게 조정할 수 있습니다. + +```js +export default { + markdown: {...} +} +``` + +사용 가능한 모든 옵션에 대해서는 [타입 선언 및 jsdocs](https://github.com/vuejs/vitepress/blob/main/src/node/markdown/markdown.ts)를 참고하세요. + +### vite + +- 타입: `import('vite').UserConfig` + +내부 Vite 개발 서버/번들러에 직접 [Vite 구성](https://vitejs.dev/config/)을 전달합니다. + +```js +export default { + vite: { + // Vite 구성 옵션 + } +} +``` + +### vue + +- 타입: `import('@vitejs/plugin-vue').Options` + +내부 플러그인 인스턴스에 직접 [`@vitejs/plugin-vue` 옵션](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue#options)을 전달합니다. + +```js +export default { + vue: { + // @vitejs/plugin-vue 옵션 + } +} +``` + +## 빌드 훅 {#build-hooks} + +VitePress 빌드 훅은 웹사이트에 새로운 기능과 동작을 추가할 수 있게 합니다: + +- 사이트맵 +- 검색 인덱싱 +- PWA +- 텔레포트 + +### buildEnd + +- 타입: `(siteConfig: SiteConfig) => Awaitable` + +`buildEnd`는 빌드 CLI 훅으로, 빌드(SSG)가 완료된 후 VitePress CLI 프로세스가 종료되기 전에 실행됩니다. + +```ts +export default { + async buildEnd(siteConfig) { + // ... + } +} +``` + +### postRender + +- 타입: `(context: SSGContext) => Awaitable` + +`postRender`는 빌드 훅으로, SSG 렌더링이 완료되었을 때 호출됩니다. 이를 통해 SSG 동안 텔레포트 콘텐츠를 핸들링 할 수 있습니다. + +```ts +export default { + async postRender(context) { + // ... + } +} +``` + +```ts +interface SSGContext { + content: string + teleports?: Record + [key: string]: any +} +``` + +### transformHead + +- 타입: `(context: TransformContext) => Awaitable` + +`transformHead`는 각 페이지를 생성하기 전에 헤드를 변환하는 빌드 훅입니다. VitePress 구성에 정적으로 추가할 수 없는 헤드 항목을 추가할 수 있습니다. 기존 항목과 자동으로 병합되므로 추가 항목만 반환하면 됩니다. + +::: warning +`context` 내부의 어떤 것도 변경하지 마세요. +::: + +```ts +export default { + async transformHead(context) { + // ... + } +} +``` + +```ts +interface TransformContext { + page: string // 예: index.md (srcDir에 상대적) + assets: string[] // js/css가 아닌 모든 에셋을 완전히 처리된 public URL로 표시. + siteConfig: SiteConfig + siteData: SiteData + pageData: PageData + title: string + description: string + head: HeadConfig[] + content: string +} +``` + +이 훅은 사이트를 정적으로 생성할 때만 호출됩니다. 개발 중에는 호출되지 않습니다. 개발 중에 동적 헤드 항목을 추가해야 하는 경우, [`transformPageData`](#transformpagedata) 훅을 대신 사용할 수 있습니다: + +```ts +export default { + transformPageData(pageData) { + pageData.frontmatter.head ??= [] + pageData.frontmatter.head.push([ + 'meta', + { + name: 'og:title', + content: + pageData.frontmatter.layout === 'home' + ? `VitePress` + : `${pageData.title} | VitePress` + } + ]) + } +} +``` + +#### 예제: 표준 URL `` 추가 {#example-adding-a-canonical-url-link} + +```ts +export default { + transformPageData(pageData) { + const canonicalUrl = `https://example.com/${pageData.relativePath}` + .replace(/index\.md$/, '') + .replace(/\.md$/, '.html') + + pageData.frontmatter.head ??= [] + pageData.frontmatter.head.push([ + 'link', + { rel: 'canonical', href: canonicalUrl } + ]) + } +} +``` + +### transformHtml + +- 타입: `(code: string, id: string, context: TransformContext) => Awaitable` + +`transformHtml`은 각 페이지의 내용을 디스크에 저장하기 전에 변환하는 빌드 훅입니다. + +::: warning +`context` 내부의 어떤 것도 변경하지 마세요. HTML 내용을 수정하면 런타임에 하이드레이션 문제가 발생할 수 있습니다. +::: + +```ts +export default { + async transformHtml(code, id, context) { + // ... + } +} +``` + +### transformPageData + +- 타입: `(pageData: PageData, context: TransformPageContext) => Awaitable | { [key: string]: any } | void>` + +`transformPageData`는 각 페이지의 `pageData`를 변환하는 훅입니다. `pageData`를 직접 변경하거나, 변경된 값을 반환하여 페이지 데이터에 병합할 수 있습니다. + +::: warning +`context` 내부의 어떤 것도 변경하지 마세요. 이 훅에서 네트워크 요청이나 이미지 생성과 같은 무거운 연산이 있을 경우 개발 서버의 성능에 영향을 줄 수 있으니 주의하세요. 조건부 로직을 위해 `process.env.NODE_ENV === 'production'`을 확인할 수 있습니다. +::: + +```ts +export default { + async transformPageData(pageData, { siteConfig }) { + pageData.contributors = await getPageContributors(pageData.relativePath) + } + + // 또는 병합할 데이터 반환 + async transformPageData(pageData, { siteConfig }) { + return { + contributors: await getPageContributors(pageData.relativePath) + } + } +} +``` + +```ts +interface TransformPageContext { + siteConfig: SiteConfig +} +``` diff --git a/docs/lunaria.config.json b/docs/lunaria.config.json new file mode 100644 index 00000000..4f93f4dc --- /dev/null +++ b/docs/lunaria.config.json @@ -0,0 +1,51 @@ +{ + "$schema": "./node_modules/@lunariajs/core/config.schema.json", + "repository": { + "name": "vuejs/vitepress", + "rootDir": "docs" + }, + "files": [ + { + "location": "**/config.ts", + "pattern": "@lang/@path", + "type": "universal" + }, + { + "location": "**/*.md", + "pattern": "@lang/@path", + "type": "universal" + } + ], + "defaultLocale": { + "label": "English", + "lang": "en" + }, + "locales": [ + { + "label": "简体中文", + "lang": "zh" + }, + { + "label": "Português", + "lang": "pt" + }, + { + "label": "Русский", + "lang": "ru" + }, + { + "label": "Español", + "lang": "es" + }, + { + "label": "한국어", + "lang": "ko" + }, + { + "label": "فارسی", + "lang": "fa" + } + ], + "outDir": ".vitepress/dist/_translations", + "ignoreKeywords": ["lunaria-ignore"] +} diff --git a/docs/package.json b/docs/package.json index 0aea6117..93f1486f 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,7 +1,21 @@ { + "name": "docs", "private": true, "type": "module", + "scripts": { + "dev": "vitepress dev", + "build": "vitepress build", + "preview": "vitepress preview", + "lunaria:build": "lunaria build", + "lunaria:open": "open-cli .vitepress/dist/_translations/index.html" + }, "devDependencies": { - "vitepress": "workspace:*" + "@lunariajs/core": "^0.1.1", + "markdown-it-mathjax3": "^4.3.2", + "open-cli": "^8.0.0", + "postcss-rtlcss": "^5.7.0", + "vitepress": "workspace:*", + "vitepress-plugin-group-icons": "^1.5.2", + "vitepress-plugin-llms": "^1.1.3" } } diff --git a/docs/pt/config.ts b/docs/pt/config.ts new file mode 100644 index 00000000..4926e697 --- /dev/null +++ b/docs/pt/config.ts @@ -0,0 +1,219 @@ +import { createRequire } from 'module' +import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' + +const require = createRequire(import.meta.url) +const pkg = require('vitepress/package.json') + +export default defineAdditionalConfig({ + lang: 'pt-BR', + description: 'Gerador de Site Estático desenvolvido com Vite e Vue.', + + themeConfig: { + nav: nav(), + + search: { options: searchOptions() }, + + sidebar: { + '/pt/guide/': { base: '/pt/guide/', items: sidebarGuide() }, + '/pt/reference/': { base: '/pt/reference/', items: sidebarReference() } + }, + + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + text: 'Edite esta página no GitHub' + }, + + footer: { + message: 'Lançado sob licença MIT', + copyright: `Direitos reservados © 2019-${new Date().getFullYear()} Evan You` + }, + + docFooter: { + prev: 'Anterior', + next: 'Próximo' + }, + + outline: { + label: 'Nesta página' + }, + + lastUpdated: { + text: 'Atualizado em' + }, + + notFound: { + title: 'PÁGINA NÃO ENCONTRADA', + quote: + 'Mas se você não mudar de direção e continuar procurando, pode acabar onde está indo.', + linkLabel: 'ir para a página inicial', + linkText: 'Me leve para casa' + }, + + langMenuLabel: 'Alterar Idioma', + returnToTopLabel: 'Voltar ao Topo', + sidebarMenuLabel: 'Menu Lateral', + darkModeSwitchLabel: 'Tema Escuro', + lightModeSwitchTitle: 'Mudar para Modo Claro', + darkModeSwitchTitle: 'Mudar para Modo Escuro', + skipToContentLabel: 'Pular para o Conteúdo' + } +}) + +function nav(): DefaultTheme.NavItem[] { + return [ + { + text: 'Guia', + link: '/pt/guide/what-is-vitepress', + activeMatch: '/pt/guide/' + }, + { + text: 'Referência', + link: '/pt/reference/site-config', + activeMatch: '/pt/reference/' + }, + { + text: pkg.version, + items: [ + { + text: 'Registro de Mudanças', + link: 'https://github.com/vuejs/vitepress/blob/main/CHANGELOG.md' + }, + { + text: 'Contribuindo', + link: 'https://github.com/vuejs/vitepress/blob/main/.github/contributing.md' + } + ] + } + ] +} + +function sidebarGuide(): DefaultTheme.SidebarItem[] { + return [ + { + text: 'Introdução', + collapsed: false, + items: [ + { text: 'O que é VitePress?', link: 'what-is-vitepress' }, + { text: 'Iniciando', link: 'getting-started' }, + { text: 'Roteamento', link: 'routing' }, + { text: 'Implantação', link: 'deploy' } + ] + }, + { + text: 'Escrevendo', + collapsed: false, + items: [ + { text: 'Extensões Markdown', link: 'markdown' }, + { text: 'Manipulando Ativos', link: 'asset-handling' }, + { text: 'Frontmatter', link: 'frontmatter' }, + { text: 'Usando Vue em Markdown', link: 'using-vue' }, + { text: 'Internacionalização', link: 'i18n' } + ] + }, + { + text: 'Personalização', + collapsed: false, + items: [ + { text: 'Usando um tema personalizado', link: 'custom-theme' }, + { text: 'Estendendo o tema padrão', link: 'extending-default-theme' }, + { + text: 'Carregamento de dados no momento da compilação', + link: 'data-loading' + }, + { text: 'Compatibilidade SSR', link: 'ssr-compat' }, + { text: 'Conectando a um CMS', link: 'cms' } + ] + }, + { + text: 'Experimental', + collapsed: false, + items: [ + { text: 'Modo MPA', link: 'mpa-mode' }, + { text: 'Geração de Sitemap', link: 'sitemap-generation' } + ] + }, + { + text: 'Configuração e Referência da API', + base: '/pt/reference/', + link: 'site-config' + } + ] +} + +function sidebarReference(): DefaultTheme.SidebarItem[] { + return [ + { + text: 'Referência', + items: [ + { text: 'Configuração do Site', link: 'site-config' }, + { text: 'Configuração Frontmatter', link: 'frontmatter-config' }, + { text: 'API do tempo de execução', link: 'runtime-api' }, + { text: 'CLI', link: 'cli' }, + { + text: 'Tema padrão', + base: '/pt/reference/default-theme-', + items: [ + { text: 'Visão Geral', link: 'config' }, + { text: 'Navegação', link: 'nav' }, + { text: 'Barra Lateral', link: 'sidebar' }, + { text: 'Página Inicial', link: 'home-page' }, + { text: 'Rodapé', link: 'footer' }, + { text: 'Layout', link: 'layout' }, + { text: 'Distintivo', link: 'badge' }, + { text: 'Página da Equipe', link: 'team-page' }, + { text: 'Links Anterior / Próximo', link: 'prev-next-links' }, + { text: 'Editar Link', link: 'edit-link' }, + { text: 'Selo Temporal de Atualização', link: 'last-updated' }, + { text: 'Busca', link: 'search' }, + { text: 'Carbon Ads', link: 'carbon-ads' } + ] + } + ] + } + ] +} + +function searchOptions(): Partial { + return { + placeholder: 'Pesquisar documentos', + translations: { + button: { + buttonText: 'Pesquisar', + buttonAriaLabel: 'Pesquisar' + }, + modal: { + searchBox: { + resetButtonTitle: 'Limpar pesquisa', + resetButtonAriaLabel: 'Limpar pesquisa', + cancelButtonText: 'Cancelar', + cancelButtonAriaLabel: 'Cancelar' + }, + startScreen: { + recentSearchesTitle: 'Histórico de Pesquisa', + noRecentSearchesText: 'Nenhuma pesquisa recente', + saveRecentSearchButtonTitle: 'Salvar no histórico de pesquisas', + removeRecentSearchButtonTitle: 'Remover do histórico de pesquisas', + favoriteSearchesTitle: 'Favoritos', + removeFavoriteSearchButtonTitle: 'Remover dos favoritos' + }, + errorScreen: { + titleText: 'Não foi possível obter resultados', + helpText: 'Verifique a sua conexão de rede' + }, + footer: { + selectText: 'Selecionar', + navigateText: 'Navegar', + closeText: 'Fechar', + searchByText: 'Pesquisa por' + }, + noResultsScreen: { + noResultsText: 'Não foi possível encontrar resultados', + suggestedQueryText: 'Você pode tentar uma nova consulta', + reportMissingResultsText: + 'Deveriam haver resultados para essa consulta?', + reportMissingResultsLinkText: 'Clique para enviar feedback' + } + } + } + } +} diff --git a/docs/pt/guide/asset-handling.md b/docs/pt/guide/asset-handling.md new file mode 100644 index 00000000..9bd66f24 --- /dev/null +++ b/docs/pt/guide/asset-handling.md @@ -0,0 +1,59 @@ +# Manipulação de Ativos {#asset-handling} + +## Referenciando Ativos Estáticos {#referencing-static-assets} + +Todos os arquivos Markdown são compilados em componentes Vue e processados por [Vite](https://vitejs.dev/guide/assets.html). Você pode **e deve** referenciar quaisquer ativos usando URLs relativas: + +```md +![Uma imagem](./imagem.png) +``` + +Você pode referenciar ativos estáticos em seus arquivos markdown, seus componentes `*.vue` no tema, estilos e simples arquivos `.css`, usando caminhos públicos absolutos (com base na raiz do projeto) ou caminhos relativos (com base em seu sistema de arquivos). Este último é semelhante ao comportamento que você está acostumado se já usou Vite, Vue CLI ou o `file-loader` do webpack. + +Tipos comuns de arquivos de imagem, mídia e fonte são detectados e incluídos automaticamente como ativos. + +Todos os ativos referenciados, incluindo aqueles usando caminhos absolutos, serão copiados para o diretório de saída com um nome de arquivo hash na compilação de produção. Ativos nunca referenciados não serão copiados. Ativos de imagem menores que 4KB serão incorporados em base64 - isso pode ser configurado pela opção [`vite`](../reference/site-config#vite) da configuração. + +Todas as referências de caminho **estáticas**, incluindo caminhos absolutos, devem ser baseadas na estrutura do seu diretório de trabalho. + +## O Diretório Público {#the-public-directory} + +Às vezes, pode ser necessário fornecer ativos estáticos que não são referenciados diretamente em nenhum de seus componentes do tema ou Markdown, ou você pode querer servir certos arquivos com o nome de arquivo original. Exemplos de tais arquivos incluem `robots.txt`, favicons e ícones PWA. + +Você pode colocar esses arquivos no diretório `public` sob o [diretório fonte](./routing#source-directory). Por exemplo, se a raiz do seu projeto for `./docs` e estiver usando a localização padrão do diretório fonte, então o diretório público será `./docs/public`. + +Os ativos colocados em `public` serão copiados para a raiz do diretório de saída como são. + +Observe que você deve referenciar arquivos colocados em `public` usando o caminho absoluto da raiz - por exemplo, `public/icon.png` deve sempre ser referenciado no código fonte como `/icon.png`. + +## URL Base {#base-url} + +Se seu site for implantado em uma URL que não seja a raiz, será necessário definir a opção `base` em `.vitepress/config.js`. Por exemplo, se você planeja implantar seu site em `https://foo.github.io/bar/`, então `base` deve ser definido como `'/bar/'` (sempre deve começar e terminar com uma barra). + +Todos os caminhos dos seus ativos estáticos são processados automaticamente para se ajustar aos diferentes valores de configuração `base`. Por exemplo, se você tiver uma referência absoluta a um ativo sob `public` no seu markdown: + +```md +![Uma imagem](/imagem-dentro-de-public.png) +``` + +Você **não** precisa atualizá-lo quando alterar o valor de configuração `base` nesse caso. + +No entanto, se você estiver criando um componente de tema que vincula ativos dinamicamente, por exemplo, uma imagem cujo `src` é baseado em um valor de configuração do tema: + +```vue + +``` + +Nesse caso, é recomendável envolver o caminho com o [`auxiliar withBase`](../reference/runtime-api#withbase) fornecido por VitePress: + +```vue + + + +``` diff --git a/docs/pt/guide/cms.md b/docs/pt/guide/cms.md new file mode 100644 index 00000000..c4593b6d --- /dev/null +++ b/docs/pt/guide/cms.md @@ -0,0 +1,56 @@ +--- +outline: deep +--- + +# Conectando a um CMS {#connecting-to-a-cms} + +## Fluxo de Trabalho Geral {#general-workflow} + +Conectar VitePress a um CMS orbitará majoritariamente sobre [Rotas Dinâmicas](./routing#dynamic-routes). Certifique-se de entender como funcionam antes de proceder. + +Como cada CMS funcionará de forma diferente, aqui podemos fornecer apenas um fluxo de trabalho genérico que precisará ser adaptado para cada cenário específico. + +1. Se seu CMS exige autenticação, crie um arquivo `.env` para armazenar os tokens da API e carregá-los como: + + ```js + // posts/[id].paths.js + import { loadEnv } from 'vitepress' + + const env = loadEnv('', process.cwd()) + ``` + +2. Obtenha os dados necessários do CMS e formate-os em caminhos de dados apropriados: + + ```js + export default { + async paths() { + // use a biblitoca do cliente CMS respectiva se preciso + const data = await (await fetch('https://my-cms-api', { + headers: { + // token se necessário + } + })).json() + + return data.map(entry => { + return { + params: { id: entry.id, /* título, autores, data, etc. */ }, + content: entry.content + } + }) + } + } + ``` + +3. Apresente o conteúdo na página: + + ```md + # {{ $params.title }} + + - por {{ $params.author }} em {{ $params.date }} + + + ``` + +## Guias de Integração {#integration-guides} + +Se você tiver escrito um guia sobre como integrar VitePress com um CMS específico, por favor use o link "Edite esta página" abaixo para enviá-lo para cá! diff --git a/docs/pt/guide/custom-theme.md b/docs/pt/guide/custom-theme.md new file mode 100644 index 00000000..410e325f --- /dev/null +++ b/docs/pt/guide/custom-theme.md @@ -0,0 +1,218 @@ +# Usando um Tema Personalizado {#using-a-custom-theme} + +## Resolução de Tema {#theme-resolving} + +Você pode habilitar um tema personalizado criando um arquivo `.vitepress/theme/index.js` ou `.vitepress/theme/index.ts` (o "arquivo de entrada do tema"): + +``` +. +├─ docs # raiz do projeto +│ ├─ .vitepress +│ │ ├─ theme +│ │ │ └─ index.js # entrada do tema +│ │ └─ config.js # arquivo de configuração +│ └─ index.md +└─ package.json +``` + +VitePress sempre usará o tema personalizado em vez do tema padrão quando detectar a presença de um arquivo de entrada do tema. No entanto, você pode [estender o tema padrão](./extending-default-theme) para realizar personalizações avançadas sobre ele. + +## Interface do Tema {#theme-interface} + +Um tema personalizado do VitePress é definido como um objeto com a seguinte interface: + +```ts +interface Theme { + /** + * Componente raiz de layout para toda página + * @required + */ + Layout: Component + /** + * Aprimora a instância da aplicação Vue + * @optional + */ + enhanceApp?: (ctx: EnhanceAppContext) => Awaitable + /** + * Estende outro tema, chamando seu `enhanceApp` antes do nosso + * @optional + */ + extends?: Theme +} + +interface EnhanceAppContext { + app: App // instância da aplicação Vue + router: Router // instância do roteador VitePress + siteData: Ref // Metadados do nível do site +} +``` + +O arquivo de entrada do tema deve exportar o tema como sua exportação padrão: + +```js [.vitepress/theme/index.js] + +// Você pode importar arquivos Vue diretamente no arquivo de entrada do tema +// VitePress já está pré-configurado com @vitejs/plugin-vue. +import Layout from './Layout.vue' + +export default { + Layout, + enhanceApp({ app, router, siteData }) { + // ... + } +} +``` + +A exportação padrão é o único contrato para um tema personalizado, e apenas a propriedade `Layout` é exigida. Tecnicamente, um tema do VitePress pode ser tão simples quanto um único componente Vue. + +Dentro do seu componente de layout, ele funciona como uma aplicação Vite + Vue 3 normal. Note que o tema também precisa ser [compatível com SSR](./ssr-compat). + +## Construindo um Layout {#building-a-layout} + +O componente de layout mais básico precisa conter um componente [``](../reference/runtime-api#content): + +```vue [.vitepress/theme/Layout.vue] + +``` + +O layout acima simplesmente renderiza o markdown de toda página como HTML. A primeira melhoria que podemos adicionar é lidar com erros 404: + +```vue{1-4,9-12} + + + +``` + +O auxiliar [`useData()`](../reference/runtime-api#usedata) fornece todos os dados em tempo de execução que precisamos para mostrar layouts diferentes. Um dos outros dados que podemos acessar é o frontmatter da página atual. Podemos aproveitar isso para permitir que o usuário final controle o layout em cada página. Por exemplo, o usuário pode indicar que a página deve usar um layout especial de página inicial com: + +```md +--- +layout: home +--- +``` + +E podemos ajustar nosso tema para lidar com isso: + +```vue{3,12-14} + + + +``` + +Você pode, é claro, dividir o layout em mais componentes: + +```vue{3-5,12-15} + + + +``` + +Consulte a [Referência da API em Tempo de Execução](../reference/runtime-api) para tudo que está disponível em componentes de tema. Além disso, você pode aproveitar [Carregamento de Dados em Tempo de Compilação](./data-loading) para gerar layouts orientados por dados - por exemplo, uma página que lista todas as postagens do blog no projeto atual. + +## Distribuindo um Tema Personalizado {#distributing-a-custom-theme} + +A maneira mais fácil de distribuir um tema personalizado é fornecê-lo como um [repositório de modelo no GitHub](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-template-repository). + +Se você deseja distribuir seu tema como um pacote npm, siga estas etapas: + +1. Exporte o objeto do tema como a exportação padrão no seu arquivo de pacote. + +2. Se aplicável, exporte a definição de configuração de tipo do tema como `ThemeConfig`. + +3. Se seu tema exigir ajustes na configuração VitePress, exporte essa configuração em um subdiretório do pacote (por exemplo, `meu-tema/config`) para que o usuário possa estendê-la. + +4. Documente as opções de configuração do tema (tanto via arquivo de configuração quanto em frontmatter). + +5. Forneça instruções claras sobre como consumir seu tema (veja abaixo). + +## Consumindo um Tema Personalizado {#consuming-a-custom-theme} + +Para consumir um tema externo, importe-o e reexporte-o a partir do arquivo de entrada do tema personalizado: + +```js [.vitepress/theme/index.js] +import Theme from 'awesome-vitepress-theme' + +export default Theme +``` + +Se o tema precisar ser estendido: + +```js [.vitepress/theme/index.js] +import Theme from 'awesome-vitepress-theme' + +export default { + extends: Theme, + enhanceApp(ctx) { + // ... + } +} +``` + +Se o tema exigir uma configuração especial do VitePress, você também precisará estendê-lo em sua própria configuração: + +```ts +// .vitepress/theme/config.ts +import baseConfig from 'awesome-vitepress-theme/config' + +export default { + // estenda a configuração base do tema (se preciso) + extends: baseConfig +} +``` + +Finalmente, se o tema fornecer tipos para a configuração do tema: + +```ts +// .vitepress/theme/config.ts +import baseConfig from 'awesome-vitepress-theme/config' +import { defineConfigWithTheme } from 'vitepress' +import type { ThemeConfig } from 'awesome-vitepress-theme' + +export default defineConfigWithTheme({ + extends: baseConfig, + themeConfig: { + // O tipo é `ThemeConfig` + } +}) +``` diff --git a/docs/pt/guide/data-loading.md b/docs/pt/guide/data-loading.md new file mode 100644 index 00000000..bc68554d --- /dev/null +++ b/docs/pt/guide/data-loading.md @@ -0,0 +1,244 @@ +# Carregamento de Dados em Tempo de Compilação {#build-time-data-loading} + +VitePress fornece um recurso chamado **carregadores de dado** que permite carregar dados arbitrários e importá-los de páginas ou de componentes. O carregamento de dados é executado **apenas no tempo da construção**: os dados resultantes serão serializados como JSON no pacote JavaScript final. + +Os carregadores de dados podem ser usados para buscar dados remotos ou gerar metadados com base em arquivos locais. Por exemplo, você pode usar carregadores de dados para processar todas as suas páginas API locais e gerar automaticamente um índice de todas as entradas da API. + +## Uso Básico {#basic-usage} + +Um arquivo de carregador de dados deve terminar com `.data.js` ou `.data.ts`. O arquivo deve fornecer uma exportação padrão de um objeto com o método `load()`: + +```js [example.data.js] +export default { + load() { + return { + hello: 'world' + } + } +} +``` + +O módulo do carregador é avaliado apenas no Node.js, então você pode importar APIs Node e dependências npm conforme necessário. + +Você pode então importar dados deste arquivo em páginas `.md` e componentes `.vue` usando a exportação nomeada `data`: + +```vue + + +
{{ data }}
+``` + +Saída: + +```json +{ + "hello": "world" +} +``` + +Você notará que o próprio carregador de dados não exporta o `data`. É o VitePress chamando o método `load()` nos bastidores e expondo implicitamente o resultado por meio da exportação nomeada `data`. + +Isso funciona mesmo se o carregador for assíncrono: + +```js +export default { + async load() { + // buscar dados remotos + return (await fetch('...')).json() + } +} +``` + +## Dados de Arquivos Locais {#data-from-local-files} + +Quando você precisa gerar dados com base em arquivos locais, você deve usar a opção `watch` no carregador de dados para que as alterações feitas nesses arquivos possam acionar atualizações rápidas. + +A opção `watch` também é conveniente porque você pode usar [padrões glob](https://github.com/mrmlnc/fast-glob#pattern-syntax) para corresponder a vários arquivos. Os padrões podem ser relativos ao próprio arquivo do carregador, e a função `load()` receberá os arquivos correspondentes como caminhos absolutos. + +O exemplo a seguir mostra o carregamento de arquivos CSV e a transformação deles em JSON usando [csv-parse](https://github.com/adaltas/node-csv/tree/master/packages/csv-parse/). Como este arquivo só é executado no tempo da construção, você não enviará o procesador CSV para o cliente! + +```js +import fs from 'node:fs' +import { parse } from 'csv-parse/sync' + +export default { + watch: ['./data/*.csv'], + load(watchedFiles) { + // watchedFiles será um array de caminhos absolutos dos arquivos correspondidos. + // gerar um array de metadados de post que pode ser usada para mostrar + // uma lista no layout do tema + return watchedFiles.map((file) => { + return parse(fs.readFileSync(file, 'utf-8'), { + columns: true, + skip_empty_lines: true + }) + }) + } +} +``` + +## `createContentLoader` + +Ao construir um site focado em conteúdo, frequentemente precisamos criar uma página de "arquivo" ou "índice": uma página onde listamos todas as entradas disponíveis em nossa coleção de conteúdo, por exemplo, artigos de blog ou páginas de API. Nós **podemos** implementar isso diretamente com a API de carregador de dados, mas como este é um caso de uso tão comum, VitePress também fornece um auxiliar `createContentLoader` para simplificar isso: + +```js [posts.data.js] +import { createContentLoader } from 'vitepress' + +export default createContentLoader('posts/*.md', /* opções */) +``` + +O auxiliar aceita um padrão glob relativo ao [diretório fonte](./routing#source-directory) e retorna um objeto de carregador de dados `{ watch, load }` que pode ser usado como exportação padrão em um arquivo de carregador de dados. Ele também implementa cache com base nos selos de data do arquivo para melhorar o desempenho no desenvolvimento. + +Note que o carregador só funciona com arquivos Markdown - arquivos não-Markdown correspondidos serão ignorados. + +Os dados carregados serão um _array_ com o tipo `ContentData[]`: + +```ts +interface ContentData { + // URL mapeada para a página. Ex: /posts/hello.html (não inclui a base) + // itere manualmente ou use `transform` personalizado para normalizar os caminhos + url: string + // dados frontmatter da página + frontmatter: Record + + // os seguintes estão presentes apenas se as opções relevantes estiverem habilitadas + // discutiremos sobre eles abaixo + src: string | undefined + html: string | undefined + excerpt: string | undefined +} +``` + +Por padrão, apenas `url` e `frontmatter` são fornecidos. Isso ocorre porque os dados carregados serão incorporados como JSON no pacote do cliente, então precisamos ser cautelosos com seu tamanho. Aqui está um exemplo de como usar os dados para construir uma página de índice de blog mínima: + +```vue + + + +``` + +### Opções {#options} + +Os dados padrão podem não atender a todas as necessidades - você pode optar por transformar os dados usando opções: + +```js [posts.data.js] +import { createContentLoader } from 'vitepress' + +export default createContentLoader('posts/*.md', { + includeSrc: true, // incluir fonte markdown crua? + render: true, // incluir HTML completo da página apresentada? + excerpt: true, // incluir excerto? + transform(rawData) { + // mapeie, ordene ou filtre os dados crus conforme quiser. + // o resultado final é o que será enviado ao cliente. + return rawData.sort((a, b) => { + return +new Date(b.frontmatter.date) - +new Date(a.frontmatter.date) + }).map((page) => { + page.src // fonte markdown crua + page.html // HTML completo da página apresentada + page.excerpt // HTML do excerto apresentado (conteúdo acima do primeiro `---`) + return {/* ... */} + }) + } +}) +``` + +Veja como é usado no [blog Vue.js](https://github.com/vuejs/blog/blob/main/.vitepress/theme/posts.data.ts). + +A API `createContentLoader` também pode ser usada dentro dos [ganchos de construção](../reference/site-config#build-hooks): + +```js [.vitepress/config.js] +export default { + async buildEnd() { + const posts = await createContentLoader('posts/*.md').load() + // gerar arquivos com base nos metadados dos posts, por exemplo, feed RSS + } +} +``` + +**Tipos** + +```ts +interface ContentOptions { + /** + * Incluir src? + * @default false + */ + includeSrc?: boolean + + /** + * Renderizar src para HTML e incluir nos dados? + * @default false + */ + render?: boolean + + /** + * Se `boolean`, deve-se processar e incluir o resumo? (apresentado como HTML) + * + * Se `function`, controla como o excerto é extraído do conteúdo. + * + * Se `string`, define um separador personalizado a ser usado para extrair o + * excerto. O separador padrão é `---` se `excerpt` for `true`. + * + * @see https://github.com/jonschlinkert/gray-matter#optionsexcerpt + * @see https://github.com/jonschlinkert/gray-matter#optionsexcerpt_separator + * + * @default false + */ + excerpt?: + | boolean + | ((file: { data: { [key: string]: any }; content: string; excerpt?: string }, options?: any) => void) + | string + + /** + * Transforma os dados. Observe que os dados serão incorporados como JSON no pacote do cliente + * se importados de componentes ou arquivos markdown. + */ + transform?: (data: ContentData[]) => T | Promise +} +``` + +## Carregadores de Dados com Tipos {#typed-data-loaders} + +Ao usar TypeScript, você pode tipar seu carregador e exportar `data` da seguinte forma: + +```ts +import { defineLoader } from 'vitepress' + +export interface Data { + // tipo de dado +} + +declare const data: Data +export { data } + +export default defineLoader({ + // opções do carregador verificadas pelo tipo + watch: ['...'], + async load(): Promise { + // ... + } +}) +``` + +## Configuração {#configuration} + +Para obter as informações de configuração dentro de um carregador, você pode usar um código como este: + +```ts +import type { SiteConfig } from 'vitepress' + +const config: SiteConfig = (globalThis as any).VITEPRESS_CONFIG +``` diff --git a/docs/pt/guide/deploy.md b/docs/pt/guide/deploy.md new file mode 100644 index 00000000..b112bf7d --- /dev/null +++ b/docs/pt/guide/deploy.md @@ -0,0 +1,293 @@ +--- +outline: deep +--- + +# Implante seu Site VitePress {#deploy-your-vitepress-site} + +Os guias a seguir são baseados em alguns pressupostos: + +- O site VitePress está dentro do diretório `docs` do seu projeto. +- Você está usando o diretório de saída de compilação padrão (`.vitepress/dist`). +- VitePress está instalado como uma dependência local em seu projeto, e você configurou os seguintes scripts em seu `package.json`: + + ```json [package.json] + { + "scripts": { + "docs:build": "vitepress build docs", + "docs:preview": "vitepress preview docs" + } + } + ``` + +## Compilar e Testar Localmente {#build-and-test-locally} + +1. Execute este comando para compilar a documentação: + + ```sh + $ npm run docs:build + ``` + +2. Após a compilação, veja a prévia local executando: + + ```sh + $ npm run docs:preview + ``` + + O comando `preview` inicializará um servidor web estático local que servirá o diretório de saída `.vitepress/dist` em `http://localhost:4173`. Você pode usar isso para garantir que tudo esteja correto antes de enviar para produção. + +3. Você pode configurar a porta do servidor passando `--port` como argumento. + + ```json + { + "scripts": { + "docs:preview": "vitepress preview docs --port 8080" + } + } + ``` + + Agora o método `docs:preview` implantará o servidor em `http://localhost:8080`. + +## Configurando um Caminho Base Público {#setting-a-public-base-path} + +Por padrão, assumimos que o site será implantado no caminho raiz de um domínio (`/`). Se seu site for servido em um subcaminho, por exemplo, `https://meusite.com/blog/`, você precisa então configurar a opção [`base`](../reference/site-config#base) para `'/blog/'` na configuração VitePress. + +**Exemplo:** Ao usar GitHub Pages (ou GitLab Pages) e implantar em `user.github.io/repo/`, defina seu `base` como `/repo/`. + +## Cabeçalhos de Cache HTTP {#http-cache-headers} + +Se você tiver controle sobre os cabeçalhos HTTP de seu servidor em produção, pode-se configurar cabeçalhos `cache-control` para obter melhor desempenho em visitas repetidas. + +A compilação de produção usa nomes de arquivos com hash para ativos estáticos (JavaScript, CSS e outros ativos importados que não estão em `public`). Se você inspecionar a prévia de produção usando as ferramentas de desenvolvedor do seu nevegador na aba rede, verá arquivos como `app.4f283b18.js`. + +Este hash `4f283b18` é gerado a partir do conteúdo deste arquivo. A mesma URL com hash é garantida para servir o mesmo conteúdo do arquivo - se o conteúdo mudar, as URLs também mudam. Isso significa que você pode usar com segurança os cabeçalhos de cache mais fortes para esses arquivos. Todos esses arquivos serão colocados em `assets/` no diretório de saída, então você pode configurar o seguinte cabeçalho para eles: + +``` +Cache-Control: max-age=31536000,immutable +``` + +::: details Exemplo de arquivo `_headers` do Netlify + +``` +/assets/* + cache-control: max-age=31536000 + cache-control: immutable +``` + +Nota: o arquivo `_headers` deve ser colocado no [diretório public](./asset-handling#the-public-directory) - em nosso caso, `docs/public/_headers` - para que ele seja copiado exatamente para o diretório de saída. + +[Documentação de cabeçalhos personalizados do Netlify](https://docs.netlify.com/routing/headers/) + +::: + +::: details Exemplo de configuração Vercel em `vercel.json` + +```json +{ + "headers": [ + { + "source": "/assets/(.*)", + "headers": [ + { + "key": "Cache-Control", + "value": "max-age=31536000, immutable" + } + ] + } + ] +} +``` + +Nota: o arquivo `vercel.json` deve ser colocado na raiz do seu **repositório**. + +[Documentação Vercel sobre configuração de cabeçalhos](https://vercel.com/docs/concepts/projects/project-configuration#headers) + +::: + +## Guias de Plataforma {#platform-guides} + +### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render + +Configure um novo projeto e altere estas configurações usando seu painel: + +- **Comando de Compilação:** `npm run docs:build` +- **Diretório de Saída:** `docs/.vitepress/dist` +- **Versão do Node:** `18` (ou superior) + +::: warning +Não ative opções como _Auto Minify_ para código HTML. Isso removerá comentários da saída que têm significado para Vue. Haverão erros de incompatibilidade de hidratação se forem removidos. +::: + +### GitHub Pages + +1. Crie um arquivo chamado `deploy.yml` dentro do diretório `.github/workflows` do seu projeto com algum conteúdo como este: + + ```yaml [.github/workflows/deploy.yml] + # Exemplo de fluxo de trabalho para compilar e implantar um site VitePress no GitHub Pages + # + name: Implante o site VitePress no Pages + + on: + # Executa em pushes direcionados à branch `main`. + # Altere para `master` se estiver usando a branch `master` como padrão. + push: + branches: [main] + + # Permite executar manualmente este fluxo de trabalho na guia Actions + workflow_dispatch: + + # Define permissões GITHUB_TOKEN para a implantação no GitHub Pages + permissions: + contents: read + pages: write + id-token: write + + # Permite apenas uma implantação simultânea, pulando execuções em fila entre a execução em andamento e a última da fila. + # No entanto, NÃO cancela execuções em andamento, pois queremos permitir que essas implantações de produção sejam concluídas. + concurrency: + group: pages + cancel-in-progress: false + + jobs: + # Trabalho de compilação + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Não necessário se lastUpdated não estiver habilitado + # - uses: pnpm/action-setup@v3 # Descomente isso se estiver usando pnpm + # with: + # version: 9 + # - uses: oven-sh/setup-bun@v1 # Descomente isso se estiver usando Bun + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm # ou pnpm / yarn + - name: Setup Pages + uses: actions/configure-pages@v4 + - name: Install dependencies + run: npm ci # ou pnpm install / yarn install / bun install + - name: Build with VitePress + run: | + npm run docs:build # ou pnpm docs:build / yarn docs:build / bun run docs:build + touch docs/.vitepress/dist/.nojekyll + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: docs/.vitepress/dist + + # Trabalho de implantação + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + needs: build + runs-on: ubuntu-latest + name: Deploy + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 + ``` + + ::: warning + Certifique-se de que a opção `base` em seu VitePress esteja configurada corretamente. Veja [Configurando um Caminho Base Público](#setting-a-public-base-path) para mais detalhes. + ::: + +2. Nas configurações do seu repositório sob o item do menu "Pages", selecione "GitHub Actions" em "Build and deployment > Source". + +3. Envie suas alterações para a branch `main` e aguarde a conclusão do fluxo de trabalho do GitHub Actions. Você verá seu site implantado em `https://.github.io/[repository]/` ou `https:///` dependendo das suas configurações. Seu site será implantado automaticamente em cada push para a branch `main`. + +### GitLab Pages + +1. Defina `outDir` na configuração VitePress como `../public`. Configure a opção `base` para `'//'` se você deseja implantar em `https://.gitlab.io//`. + +2. Crie um arquivo chamado `.gitlab-ci.yml` na raiz do seu projeto com o conteúdo abaixo. Isso construirá e implantará seu site sempre que você fizer alterações no conteúdo: + + ```yaml [.gitlab-ci.yml] + image: node:18 + pages: + cache: + paths: + - node_modules/ + script: + # - apk add git # Descomente isso se estiver usando imagens pequenas do Docker como o Alpine e tiver lastUpdated habilitado + - npm install + - npm run docs:build + artifacts: + paths: + - public + only: + - main + ``` + +### Azure Static Web Apps {#azure-static-web-apps} + +1. Siga a [documentação oficial](https://docs.microsoft.com/en-us/azure/static-web-apps/build-configuration). + +2. Configure esses valores em seu arquivo de configuração (e remova aqueles que você não precisa, como `api_location`): + + - **`app_location`**: `/` + - **`output_location`**: `docs/.vitepress/dist` + - **`app_build_command`**: `npm run docs:build` + +### Firebase {#firebase} + +1. Crie `firebase.json` e `.firebaserc` na raiz do seu projeto: + + `firebase.json`: + + ```json [firebase.json] + { + "hosting": { + "public": "docs/.vitepress/dist", + "ignore": [] + } + } + ``` + + `.firebaserc`: + + ```json [.firebaserc] + { + "projects": { + "default": "" + } + } + ``` + +2. Após executar `npm run docs:build`, execute este comando para implantar: + + ```sh + firebase deploy + ``` + +### Surge + +1. Após executar `npm run docs:build`, execute este comando para implantar: + + ```sh + npx surge docs/.vitepress/dist + ``` + +### Heroku + +1. Siga a documentação e o guia fornecidos em [`heroku-buildpack-static`](https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-static). + +2. Crie um arquivo chamado `static.json` na raiz do seu projeto com o conteúdo abaixo: + + ```json [static.json] + { + "root": "docs/.vitepress/dist" + } + ``` + +### Edgio + +Consulte [Criar e Implantar um Aplicativo VitePress no Edgio](https://docs.edg.io/guides/vitepress). + +### Kinsta Static Site Hosting {#kinsta-static-site-hosting} + +Você pode implantar seu site VitePress em [Kinsta](https://kinsta.com/static-site-hosting/) seguindo estas [instruções](https://kinsta.com/docs/vitepress-static-site-example/). diff --git a/docs/pt/guide/extending-default-theme.md b/docs/pt/guide/extending-default-theme.md new file mode 100644 index 00000000..aa918b48 --- /dev/null +++ b/docs/pt/guide/extending-default-theme.md @@ -0,0 +1,330 @@ +--- +outline: deep +--- + +# Estendendo o Tema Padrão {#extending-the-default-theme} + +O tema padrão do VitePress é otimizado para documentação e pode ser personalizado. Consulte a [Visão Geral de Configuração do Tema Padrão](../reference/default-theme-config) para uma lista abrangente de opções. + +No entanto, há casos em que apenas a configuração não será suficiente. Por exemplo: + +1. É necessário ajustar a estilização CSS; +2. É necessário modificar a instância da aplicação Vue, por exemplo para registrar componentes globais; +3. É necessário injetar conteúdo personalizado no tema por meio de _slots_ no layout. + +Essas personalizações avançadas exigirão o uso de um tema personalizado que "estende" o tema padrão. + +::: tip +Antes de prosseguir, certifique-se de ler primeiro [Usando um Tema Personalizado](./custom-theme) para entender como temas personalizados funcionam. +::: + +## Personalizando o CSS {#customizing-css} + +O CSS do tema padrão pode ser personalizado substituindo as variáveis CSS no nível raiz: + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme' +import './custom.css' + +export default DefaultTheme +``` + +```css +/* .vitepress/theme/custom.css */ +:root { + --vp-c-brand-1: #646cff; + --vp-c-brand-2: #747bff; +} +``` + +Veja as [variáveis CSS do tema padrão](https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css) que podem ser substituídas. + +## Usando Fontes Diferentes {#using-different-fonts} + +VitePress usa [Inter](https://rsms.me/inter/) como fonte padrão e incluirá as fontes na saída de compilação. A fonte também é pré-carregada automaticamente em produção. No entanto, isso pode não ser desejável se você quiser usar uma fonte principal diferente. + +Para evitar a inclusão de Inter na saída de compilação, importe o tema de `vitepress/theme-without-fonts`: + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme-without-fonts' +import './my-fonts.css' + +export default DefaultTheme +``` + +```css +/* .vitepress/theme/my-fonts.css */ +:root { + --vp-font-family-base: /* fonte de texto normal */ + --vp-font-family-mono: /* fonte de código */ +} +``` + +::: warning +Se estiver usando componentes opcionais como os componentes da [Página da Equipe](../reference/default-theme-team-page), certifique-se de também importá-los de `vitepress/theme-without-fonts`! +::: + +Se a sua fonte é um arquivo local referenciado via `@font-face`, ela será processada como um ativo e incluída em `.vitepress/dist/assets` com um nome de arquivo hash. Para pré-carregar esse arquivo, use o gancho de construção [transformHead](../reference/site-config#transformhead): + +```js [.vitepress/config.js] +export default { + transformHead({ assets }) { + // ajuste o regex para corresponder à sua fonte + const myFontFile = assets.find(file => /font-name\.[\w-]+\.woff2/.test(file)) + if (myFontFile) { + return [ + [ + 'link', + { + rel: 'preload', + href: myFontFile, + as: 'font', + type: 'font/woff2', + crossorigin: '' + } + ] + ] + } + } +} +``` + +## Registrando Componentes Globais {#registering-global-components} + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme' + +/** @type {import('vitepress').Theme} */ +export default { + extends: DefaultTheme, + enhanceApp({ app }) { + // registre seus componentes globais personalizados + app.component('MyGlobalComponent' /* ... */) + } +} +``` + +Se estiver usando TypeScript: +```ts [.vitepress/theme/index.ts] +import type { Theme } from 'vitepress' +import DefaultTheme from 'vitepress/theme' + +export default { + extends: DefaultTheme, + enhanceApp({ app }) { + // registre seus componentes globais personalizados + app.component('MyGlobalComponent' /* ... */) + } +} satisfies Theme +``` + +Como estamos usando Vite, você também pode aproveitar a [funcionalidade de importação glob](https://vitejs.dev/guide/features.html#glob-import) do Vite para registrar automaticamente um diretório de componentes. + +## _Slots_ no Layout {#layout-slots} + +O componente `` do tema padrão possui alguns _slots_ que podem ser usados para injetar conteúdo em locais específicos da página. Aqui está um exemplo de como injetar um componente antes do esquema : + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme' +import MyLayout from './MyLayout.vue' + +export default { + extends: DefaultTheme, + // substitua o Layout por um componente envolvente que + // injeta os slots + Layout: MyLayout +} +``` + +```vue [.vitepress/theme/MyLayout.vue] + + + +``` + +Ou você também pode usar a função _render_. + +```js [.vitepress/theme/index.js] +import { h } from 'vue' +import DefaultTheme from 'vitepress/theme' +import MyComponent from './MyComponent.vue' + +export default { + extends: DefaultTheme, + Layout() { + return h(DefaultTheme.Layout, null, { + 'aside-outline-before': () => h(MyComponent) + }) + } +} +``` + +Lista completa de _slots_ disponíveis no layout do tema padrão: + +- Quando `layout: 'doc'` (padrão) está habilitado via frontmatter: + - `doc-top` + - `doc-bottom` + - `doc-footer-before` + - `doc-before` + - `doc-after` + - `sidebar-nav-before` + - `sidebar-nav-after` + - `aside-top` + - `aside-bottom` + - `aside-outline-before` + - `aside-outline-after` + - `aside-ads-before` + - `aside-ads-after` +- Quando `layout: 'home'` está habilitado via frontmatter: + - `home-hero-before` + - `home-hero-info-before` + - `home-hero-info` + - `home-hero-actions-after` + - `home-hero-image` + - `home-hero-after` + - `home-features-before` + - `home-features-after` +- Quando `layout: 'page'` está habilitado via frontmatter: + - `page-top` + - `page-bottom` +- Na página não encontrada (404): + - `not-found` +- Sempre: + - `layout-top` + - `layout-bottom` + - `nav-bar-title-before` + - `nav-bar-title-after` + - `nav-bar-content-before` + - `nav-bar-content-after` + - `nav-screen-content-before` + - `nav-screen-content-after` + +## Usando a API View Transitions + +### Na Alternância de Aparência {#on-appearance-toggle} + +Você pode estender o tema padrão para fornecer uma transição personalizada quando o modo de cor é alternado. Um exemplo: + +```vue [.vitepress/theme/Layout.vue] + + + + + +``` + +Resultado (**atenção!**: cores piscantes, movimentos súbitos, luzes brilhantes): + +
+Demo + +![Demo de Transição de Alternância de Aparência](/appearance-toggle-transition.webp) + +
+ +Consulte [Chrome Docs](https://developer.chrome.com/docs/web-platform/view-transitions/) para mais detalhes sobre _view transitions_. + +### Na Mudança de Rota {#on-route-change} + +Em breve. + +## Substituindo Componentes Internos {#overriding-internal-components} + +Você pode usar os [aliases](https://vitejs.dev/config/shared-options.html#resolve-alias) Vite para substituir os componentes do tema padrão pelos seus personalizados: + +```ts +import { fileURLToPath, URL } from 'node:url' +import { defineConfig } from 'vitepress' + +export default defineConfig({ + vite: { + resolve: { + alias: [ + { + find: /^.*\/VPNavBar\.vue$/, + replacement: fileURLToPath( + new URL('./components/CustomNavBar.vue', import.meta.url) + ) + } + ] + } + } +}) +``` + +Para saber o nome exato do componente consulte [nosso código fonte](https://github.com/vuejs/vitepress/tree/main/src/client/theme-default/components). Como os componentes são internos, há uma pequena chance de que o nome deles seja atualizado entre lançamentos secundários. diff --git a/docs/pt/guide/frontmatter.md b/docs/pt/guide/frontmatter.md new file mode 100644 index 00000000..0ab4ac51 --- /dev/null +++ b/docs/pt/guide/frontmatter.md @@ -0,0 +1,48 @@ +# Frontmatter + +## Utilização {#usage} + +VitePress suporta frontmatter YAML em todos os arquivos Markdown, processando-os com [gray-matter](https://github.com/jonschlinkert/gray-matter). O frontmatter deve estar no topo do arquivo Markdown (antes de qualquer elemento, incluindo tags ` + + +``` + +## Suporte a RTL (Experimental) {#rtl-support-experimental} + +Para suporte a RTL (Right to Left), especifique `dir: 'rtl'` na configuração e use algum plugin RTLCSS PostCSS como , ou . Você precisará configurar seu plugin PostCSS para usar `:where([dir="ltr"])` e `:where([dir="rtl"])` como prefixos para evitar problemas de especificidade CSS. diff --git a/docs/pt/guide/markdown.md b/docs/pt/guide/markdown.md new file mode 100644 index 00000000..b5245259 --- /dev/null +++ b/docs/pt/guide/markdown.md @@ -0,0 +1,928 @@ +# Extensões Markdown {#markdown-extensions} + +VitePress vem com Extensões Markdown embutidas. + +## Âncoras de Cabeçalho {#header-anchors} + +Cabeçalhos recebem a aplicação automaticamente de links âncora. A apresentação das âncoras pode ser configurada usando a opção `markdown.anchor`. + +### Âncoras personalizadas {#custom-anchors} + +Para especificar uma _tag_ âncora personalizada para um cabeçalho em vez de usar aquela gerada automaticamente, adicione um sufixo ao cabeçalho: + +``` +# Usando âncoras personalizadas {#minha-ancora} +``` + +Isso permite que você tenha um link do cabeçalho como `#minha-ancora` em vez do padrão `#usando-ancoras-personalizadas`. + +## Links {#links} + +Ambos os links internos e externos recebem tratamento especial. + +### Links Internos {#internal-links} + +Os links internos são convertidos em links de roteador para navegação SPA. Além disso, todo arquivo `index.md` contido em cada subdiretório será automaticamente convertido para `index.html`, com a URL correspondente `/`. + +Por exemplo, dada a seguinte estrutura de diretórios: + +``` +. +├─ index.md +├─ foo +│ ├─ index.md +│ ├─ one.md +│ └─ two.md +└─ bar + ├─ index.md + ├─ three.md + └─ four.md +``` + +E supondo que você esteja em `foo/one.md`: + +```md +[Página Inicial](/) +[foo](/foo/) +[foo heading](./#heading) +[bar - three](../bar/three) +[bar - three](../bar/three.md) +[bar - four](../bar/four.html) +``` + +### Sufixo de Página {#page-suffix} + +Páginas e links internos são gerados com o sufixo `.html` por padrão. + +### Links Externos {#external-links} + +Links externos recebem automaticamente `target="_blank" rel="noreferrer"`: + +- [vuejs.org](https://vuejs.org) +- [VitePress no GitHub](https://github.com/vuejs/vitepress) + +## Frontmatter {#frontmatter} + +[YAML frontmatter](https://jekyllrb.com/docs/front-matter/) é suportado por padrão: + +```yaml +--- +título: Escrevendo como um Hacker +idioma: pt-BR +--- +``` + +Esses dados estarão disponíveis para o restante da página, junto com todos os componentes personalizados e de temas. + +Para mais detalhes, veja [Frontmatter](../reference/frontmatter-config). + +## Tabelas ao Estilo GitHub {#github-style-tables} + +**Entrada** + +```md +| Tabelas | São | Legais | +| ------------- | :-----------: | ----: | +| col 3 está | à direita | $1600 | +| col 2 está | centralizada | $12 | +| listras | são legais | $1 | +``` + +**Saída** + +| Tabelas | São | Legais | +| ------------- | :-----------: | -----: | +| col 3 está | à direita | \$1600 | +| col 2 está | centralizada | \$12 | +| listras | são legais | \$1 | + +## Emoji :tada: + +**Entrada** + +``` +:tada: :100: +``` + +**Saída** + +:tada: :100: + +Uma [lista de todos os emojis](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.mjs) está disponível. + +## Tabela de Conteúdo (TOC) + +**Entrada** + +``` +[[toc]] +``` + +**Saída** + +[[toc]] + +A apresentação de TOC (Table of Contents) pode ser configurada usando a opção `markdown.toc`. + +## Recipientes Personalizados {#custom-containers} + +Recipientes personalizados podem ser definidos por seus tipos, títulos e conteúdos. + +### Título Padrão {#default-title} + +**Entrada** + +```md +::: info +Este é um bloco de informações. +::: + +::: tip +Este é um aviso. +::: + +::: warning +Este é um aviso. +::: + +::: danger +Este é um aviso de perigo. +::: + +::: details +Este é um bloco de detalhes. +::: +``` + +**Saída** + +::: info +Este é um bloco de informações. +::: + +::: tip +Este é um aviso. +::: + +::: warning +Este é um aviso. +::: + +::: danger +Este é um aviso de perigo. +::: + +::: details +Este é um bloco de detalhes. +::: + +### Título Personalizado {#custom-title} + +Você pode definir um título personalizado adicionando o texto imediatamente após o "tipo" do recipiente. + +**Entrada** + +````md +::: danger STOP +Zona de perigo, não prossiga +::: + +::: details Clique para ver o código +```js +console.log('Olá, VitePress!') +``` +::: +```` + +**Saída** + +::: danger STOP +Zona de perigo, não prossiga +::: + +::: details Clique para ver o código +```js +console.log('Olá, VitePress!') +``` +::: + +Além disso, você pode definir títulos personalizados globalmente adicionando o seguinte conteúdo no arquivo de configuração do site, útil se não estiver escrevendo em inglês: + +```ts +// config.ts +export default defineConfig({ + // ... + markdown: { + container: { + tipLabel: '提示', + warningLabel: '警告', + dangerLabel: '危险', + infoLabel: '信息', + detailsLabel: '详细信息' + } + } + // ... +}) +``` + +### `raw` + +Este é um recipiente especial que pode ser usado para evitar conflitos de estilo e roteador com VitePress. Isso é especialmente útil ao documentar bibliotecas de componentes. Você também pode verificar [whyframe](https://whyframe.dev/docs/integrations/vitepress) para melhor isolamento. + +**Sintaxe** + +```md +::: raw +Envolve em um `
` +::: +``` + +A classe `vp-raw` também pode ser usada diretamente em elementos. O isolamento de estilo é atualmente opcional: + +- Instale o `postcss` com seu gerenciador de pacotes preferido: + + ```sh + $ npm add -D postcss + ``` + +- Crie um arquivo chamado `docs/postcss.config.mjs` e adicione o seguinte: + + ```js + import { postcssIsolateStyles } from 'vitepress' + + export default { + plugins: [postcssIsolateStyles()] + } + ``` + + Ele utiliza [`postcss-prefix-selector`](https://github.com/postcss/postcss-load-config) internamente. Você pode passar opções assim: + + ```js + postcssIsolateStyles({ + includeFiles: [/vp-doc\.css/] // o padrão é /base\.css/ + }) + ``` + +## Alertas no estilo GitHub {#github-flavored-alerts} + +VitePress também suporta [alertas no estilo 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) para apresentar como um bloco de chamada. Eles serão apresentados da mesma forma que [elementos personalizados](#custom-containers). + +```md +> [!NOTE] +> Destaca informações que os usuários devem levar em consideração, mesmo ao ler rapidamente. + +> [!TIP] +> Informações opcionais para ajudar o usuário a ter mais sucesso. + +> [!IMPORTANT] +> Informações cruciais necessárias para que os usuários tenham sucesso. + +> [!WARNING] +> Conteúdo crítico exigindo atenção imediata do usuário devido a riscos potenciais. + +> [!CAUTION] +> Potenciais consequências negativas de uma ação. +``` + +> [!NOTE] +> Destaca informações que os usuários devem levar em consideração, mesmo ao ler rapidamente. + +> [!TIP] +> Informações opcionais para ajudar o usuário a ter mais sucesso. + +> [!IMPORTANT] +> Informações cruciais necessárias para que os usuários tenham sucesso. + +> [!WARNING] +> Conteúdo crítico exigindo atenção imediata do usuário devido a riscos potenciais. + +> [!CAUTION] +> Potenciais consequências negativas de uma ação. + +## Destaque de Sintaxe em Blocos de Código {#syntax-highlighting-in-code-blocks} + +VitePress utiliza [Shiki](https://github.com/shikijs/shiki) para destacar a sintaxe da linguagem em blocos de código Markdown, usando texto colorido. Shiki suporta uma ampla variedade de linguagens de programação. Tudo o que você precisa fazer é adicionar um _alias_ de linguagem válido após os crases iniciais do bloco de código: + +**Entrada** + +```` +```js +export default { + name: 'MyComponent', + // ... +} +``` +```` + +```` +```html +
    +
  • + {{ todo.text }} +
  • +
+``` +```` + +**Saída** + +```js +export default { + name: 'MyComponent' + // ... +} +``` + +```html +
    +
  • + {{ todo.text }} +
  • +
+``` + +Uma [lista de linguagens válidas](https://shiki.style/languages) está disponível no repositório Shiki. + +Você também pode personalizar o tema de destaque de sintaxe na configuração do aplicativo. Consulte as [opções `markdown`](../reference/site-config#markdown) para mais detalhes. + +## Destaque de Linha em Blocos de Código {#line-highlighting-in-code-blocks} + +**Entrada** + +```` +```js{4} +export default { + data () { + return { + msg: 'Destacado!' + } + } +} +``` +```` + +**Saída** + +```js{4} +export default { + data () { + return { + msg: 'Destacado!' + } + } +} +``` + +Além de uma única linha, você também pode especificar múltiplas linhas únicas, intervalos, ou ambos: + +- Intervalos de linha: por exemplo, `{5-8}`, `{3-10}`, `{10-17}` +- Múltiplas linhas únicas: por exemplo, `{4,7,9}` +- Intervalos de linha e linhas únicas: por exemplo, `{4,7-13,16,23-27,40}` + +**Entrada** + +```` +```js{1,4,6-8} +export default { // Destacado + data () { + return { + msg: `Destacado! + Esta linha não está destacada, + mas esta e as próximas 2 estão.`, + motd: 'VitePress é incrível', + lorem: 'ipsum' + } + } +} +``` +```` + +**Saída** + +```js{1,4,6-8} +export default { // Destacado + data () { + return { + msg: `Destacado! + Esta linha não está destacada, + mas esta e as próximas 2 estão.`, + motd: 'VitePress é incrível', + lorem: 'ipsum', + } + } +} +``` + +Alternativamente, é possível destacar diretamente na linha usando o comentário `// [!code highlight]`. + +**Entrada** + +```` +```js +export default { + data () { + return { + msg: 'Destacado!' // [!!code highlight] + } + } +} +``` +```` + +**Saída** + +```js +export default { + data() { + return { + msg: 'Destacado!' // [!code destaque] + } + } +} +``` + +## Foco em Blocos de Código {#focus-in-code-blocks} + +Adicionando o comentário `// [!code focus]` em uma linha irá destacá-la e desfocar as outras partes do código. + +Além disso, você pode definir o número de linhas para focar usando `// [!code focus:]`. + +**Entrada** + +```` +```js +export default { + data () { + return { + msg: 'Focado!' // [!!code focus] + } + } +} +``` +```` + +**Saída** + +```js +export default { + data() { + return { + msg: 'Focado!' // [!code focus] + } + } +} +``` + +## Diferenças Coloridas em Blocos de Código {#colored-diffs-in-code-blocks} + +Adicionar os comentários `// [!code --]` ou `// [!code ++]` em uma linha criará uma diferença nessa linha, mantendo as cores do bloco de código. + +**Entrada** + +```` +```js +export default { + data () { + return { + msg: 'Removido' // [!!code --] + msg: 'Adicionado' // [!!code ++] + } + } +} +``` +```` + +**Saída** + +```js +export default { + data () { + return { + msg: 'Removido' // [!code --] + msg: 'Adicionado' // [!code ++] + } + } +} +``` + +## Erros e Avisos em Blocos de Código {#errors-and-warnings-in-code-blocks} + +Adicionar os comentários `// [!code warning]` ou `// [!code error]` em uma linha colorirá os blocos conforme apropriado. + +**Entrada** + +```` +```js +export default { + data () { + return { + msg: 'Erro', // [!!code error] + msg: 'Aviso' // [!!code warning] + } + } +} +``` +```` + +**Saída** + +```js +export default { + data() { + return { + msg: 'Erro', // [!code error] + msg: 'Aviso' // [!code warning] + } + } +} +``` + +## Números de Linha {#line-numbers} + +Você pode habilitar números de linha para cada bloco de código através do arquivo de configuração: + +```js +export default { + markdown: { + lineNumbers: true + } +} +``` + +Consulte as [opções markdown](../reference/site-config#markdown) para mais detalhes. + +Você pode adicionar a marca `:line-numbers` / `:no-line-numbers` em seus blocos de código para substituir o valor definido na configuração. + +Você também pode personalizar o número inicial da linha adicionando `=` após `:line-numbers`. Por exemplo, `:line-numbers=2` significa que os números das linhas nos blocos de código começarão a partir de `2`. + +**Entrada** + +````md +```ts {1} +// números de linha desativados por padrão +const line2 = 'Esta é a linha 2' +const line3 = 'Esta é a linha 3' +``` + +```ts:line-numbers {1} +// números de linha ativados +const line2 = 'Esta é a linha 2' +const line3 = 'Esta é a linha 3' +``` + +```ts:line-numbers=2 {1} +// números de linha ativados e começam do 2 +const line3 = 'Esta é a linha 3' +const line4 = 'Esta é a linha 4' +``` +```` + +**Saída** + +```ts {1} +// números de linha desativados por padrão +const line2 = 'Esta é a linha 2' +const line3 = 'Esta é a linha 3' +``` + +```ts:line-numbers {1} +// números de linha ativados +const line2 = 'Esta é a linha 2' +const line3 = 'Esta é a linha 3' +``` + +```ts:line-numbers=2 {1} +// números de linha ativados e começam do 2 +const line3 = 'Esta é a linha 3' +const line4 = 'Esta é a linha 4' +``` + +## Importar _Snippets_ de Código {#import-code-snippets} + +Você pode importar trechos de código de arquivos existentes usando a seguinte sintaxe: + +```md +<<< @/filepath +``` + +Também suporta [destaque de linha](#line-highlighting-in-code-blocks): + +```md +<<< @/filepath{highlightLines} +``` + +**Entrada** + +```md +<<< @/snippets/snippet.js{2} +``` + +**Arquivo de Código** + +<<< @/snippets/snippet.js + +**Saída** + +<<< @/snippets/snippet.js{2} + +::: tip +O valor de `@` corresponde à raiz do código fonte. Por padrão, é a raiz do projeto VitePress, a menos que `srcDir` seja configurado. Alternativamente, você também pode importar de caminhos relativos: + +```md +<<< ../snippets/snippet.js +``` + +::: + +Você também pode usar uma [região VS Code](https://code.visualstudio.com/docs/editor/codebasics#_folding) para incluir apenas a parte correspondente do arquivo de código. Você pode fornecer um nome de região personalizado após um `#` seguindo o caminho do arquivo: + +**Entrada** + +```md +<<< @/snippets/snippet-with-region.js#snippet{1} +``` + +**Arquivo de Código** + +<<< @/snippets/snippet-with-region.js + +**Saída** + +<<< @/snippets/snippet-with-region.js#snippet{1} + +Você também pode especificar o idioma dentro das chaves (`{}`), assim: + +```md +<<< @/snippets/snippet.cs{c#} + + + +<<< @/snippets/snippet.cs{1,2,4-6 c#} + + + +<<< @/snippets/snippet.cs{1,2,4-6 c#:line-numbers} +``` + +Isso é útil se a linguagem original não puder ser inferida pela extensão do arquivo. + +## Grupos de Código {#code-groups} + +Você pode agrupar vários blocos de código assim: + +**Entrada** + +````md +::: code-group + +```js [config.js] +/** + * @type {import('vitepress').UserConfig} + */ +const config = { + // ... +} + +export default config +``` + +```ts [config.ts] +import type { UserConfig } from 'vitepress' + +const config: UserConfig = { + // ... +} + +export default config +``` + +::: +```` + +**Saída** + +::: code-group + +```js [config.js] +/** + * @type {import('vitepress').UserConfig} + */ +const config = { + // ... +} + +export default config +``` + +```ts [config.ts] +import type { UserConfig } from 'vitepress' + +const config: UserConfig = { + // ... +} + +export default config +``` + +::: + +Você também pode [importar _snippets_ de código](#import-code-snippets) em grupos de código: + +**Entrada** + +```md +::: code-group + + + +<<< @/snippets/snippet.js + + + +<<< @/snippets/snippet-with-region.js#snippet{1,2 ts:line-numbers} [snippet with region] + +::: +``` + +**Output** + +::: code-group + +<<< @/snippets/snippet.js + +<<< @/snippets/snippet-with-region.js#snippet{1,2 ts:line-numbers} [snippet with region] + +::: + +## Inclusão de Arquivo Markdown {#markdown-file-inclusion} + +Você pode incluir um arquivo markdown em outro arquivo markdown, mesmo aninhado. + +::: tip +Você também pode prefixar o caminho do markdown com `@`, ele atuará como a raiz de origem. Por padrão, é a raiz do projeto VitePress, a menos que `srcDir` seja configurado. +::: + +Por exemplo, você pode incluir um arquivo markdown relativo usando isto: + +**Entrada** + +```md +# Documentação + +## Conceitos Básicos + + +``` + +**Arquivo da Parte** (`parts/basics.md`) + +```md +Algumas coisas básicas. + +### Configuração + +Pode ser criada usando `.foorc.json`. +``` + +**Código Equivalente** + +```md +# Documentação + +## Conceitos Básicos + +Algumas coisas básicas. + +### Configuração + +Pode ser criada usando `.foorc.json`. +``` + +Também suporta a seleção de um intervalo de linhas: + +**Entrada** + +```md +# Documentação + +## Conceitos Básicos + + +``` + +**Arquivo da Parte** (`parts/basics.md`) + +```md +Algumas coisas básicas. + +### Configuração + +Pode ser criada usando `.foorc.json`. +``` + +**Código Equivalente** + +```md +# Documentação + +## Conceitos Básicos + +### Configuração + +Pode ser criada usando `.foorc.json`. +``` + +O formato do intervalo de linhas selecionado pode ser: `{3,}`, `{,10}`, `{1,10}` + +::: warning +Observe que isso não gera erros se o arquivo não estiver presente. Portanto, ao usar esse recurso, certifique-se de que o conteúdo está sendo mostrado como esperado. +::: + +## Equações Matemáticas {#math-equations} + +Isso é atualmente opcional. Para ativá-lo, você precisa instalar `markdown-it-mathjax3` e definir `markdown.math` como `true` no seu arquivo de configuração: + +```sh +npm add -D markdown-it-mathjax3 +``` + +```ts [.vitepress/config.ts] +export default { + markdown: { + math: true + } +} +``` + +**Entrada** + +```md +Quando $a \ne 0$, existem duas soluções para $(ax^2 + bx + c = 0)$ e elas são +$$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ + +**Equações de Maxwell:** + +| equação | descrição | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | +| $\nabla \cdot \vec{\mathbf{B}} = 0$ | a divergência de $\vec{\mathbf{B}}$ é zero | +| $\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | a rotacional de $\vec{\mathbf{E}}$ é proporcional à taxa de variação de $\vec{\mathbf{B}}$ | +| $\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | _hã?_ | + +**Saída** + +Quando $a \ne 0$, existem duas soluções para $(ax^2 + bx + c = 0)$ e são +$$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ + +**Equações de Maxwell:** + +| equação | descrição | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | +| $\nabla \cdot \vec{\mathbf{B}} = 0$ | a divergência de $\vec{\mathbf{B}}$ é zero | +| $\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | a rotacional de $\vec{\mathbf{E}}$ é proporcional à taxa de variação de $\vec{\mathbf{B}}$ | +| $\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | _hã?_ | + +## _Lazy Loading_ de Imagens {#image-lazy-loading} + +Você pode ativar o "carregamento folgado" para cada imagem adicionada via markdown definindo `lazyLoading` como `true` no seu arquivo de configuração: + +```js +export default { + markdown: { + image: { + // o carregamento folgado de imagens está desativado por padrão + lazyLoading: true + } + } +} +``` + +## Configuração Avançada {#advanced-configuration} + +VitePress usa [markdown-it](https://github.com/markdown-it/markdown-it) como interpretador Markdown. Muitas das extensões acima são implementadas por meio de _plugins_ personalizados. Você pode personalizar ainda mais a instância `markdown-it` usando a opção `markdown` em `.vitepress/config.js`: + +```js +import { defineConfig } from 'vitepress' +import markdownItAnchor from 'markdown-it-anchor' +import markdownItFoo from 'markdown-it-foo' + +export default defineConfig({ + markdown: { + // opções para markdown-it-anchor + // https://github.com/valeriangalliat/markdown-it-anchor#usage + anchor: { + permalink: markdownItAnchor.permalink.headerLink() + }, + + // opções para @mdit-vue/plugin-toc + // https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-toc#options + toc: { level: [1, 2] }, + + config: (md) => { + // use mais plugins markdown-it! + md.use(markdownItFoo) + } + } +}) +``` + +Consulte a lista completa de propriedades configuráveis em [Referência de Configuração: Configuração da Aplicação](../reference/site-config#markdown). diff --git a/docs/pt/guide/mpa-mode.md b/docs/pt/guide/mpa-mode.md new file mode 100644 index 00000000..28aabae1 --- /dev/null +++ b/docs/pt/guide/mpa-mode.md @@ -0,0 +1,23 @@ +# Modo MPA {#mpa-mode} + +O modo MPA (Aplicação Multipáginas) pode ser habilitado pela linha de comando com `vitepress build --mpa`, ou através da configuração pela opção `mpa: true`. + +No modo MPA, todas as páginas são apresentadas por padrão sem qualquer JavaScript incluído. Como resultado, o site em produção provavelmente terá uma nota de desempenho de visita inicial superior com ferramentas de auditoria. + +Entretanto, devido a ausência de navegação SPA, links entre páginas acarretarão em recarregamentos de página completos. Navegações pós-carregamento no modo MPA não parecerão tão instantâneas quanto no modo SPA. + +Também note que não ter JavaScript por padrão significa que você está essencialmente utilizando Vue como modelo de linguagem no lado do servidor. Nenhum manipulador de evento será embutido no navegador, então não haverá interatividade. Para carregar JavaScript no lado do cliente, você precisará usar a tag especial ` + +# Olá +``` + +` +``` + +### Apresentando Conteúdo Cru {#rendering-raw-content} + +Parâmetros passados para a página serão serializados na carga JavaScript do cliente, portanto, evite passar dados pesados nos parâmetros, como Markdown cru ou conteúdo HTML obtido de um CMS remoto. + +Em vez disso, você pode passar tal conteúdo para cada página usando a propriedade `content` em cada objeto de caminho: + +```js +export default { + async paths() { + const posts = await (await fetch('https://my-cms.com/blog-posts')).json() + + return posts.map((post) => { + return { + params: { id: post.id }, + content: post.content // Markdown ou HTML cru + } + }) + } +} +``` + +Em seguida, use a seguinte sintaxe especial para apresentar o conteúdo como parte do próprio arquivo Markdown: + +```md + +``` diff --git a/docs/pt/guide/sitemap-generation.md b/docs/pt/guide/sitemap-generation.md new file mode 100644 index 00000000..c6f8d9b8 --- /dev/null +++ b/docs/pt/guide/sitemap-generation.md @@ -0,0 +1,53 @@ +# Geração de Sitemap {#sitemap-generation} + +VitePress vem com suporte embutido para gerar um arquivo `sitemap.xml` para seu site. Para habilitar, adicione o seguinte ao seu `.vitepress/config.js`: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + sitemap: { + hostname: 'https://example.com' + } +}) +``` + +Para ter tags `` em seu `sitemap.xml`, você pode habilitar a opção [`lastUpdated`](../reference/default-theme-last-updated). + +## Opções {#options} + +O suporte de Sietmap é alimentado pelo módulo [`sitemap`](https://www.npmjs.com/package/sitemap). Você pode passar qualquer uma das opções suportadas por ele na opção `sitemap` do seu arquivo de configuração. Esses serão passados diretamente ao construtor `SitemapStream`. Refira-se a [documentação `sitemap`](https://www.npmjs.com/package/sitemap#options-you-can-pass) para mais detalhes. Exemplo: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + sitemap: { + hostname: 'https://example.com', + lastmodDateOnly: false + } +}) +``` + +## Gancho `transformItems` + +Você pode usar o gancho `sitemap.transformItems` para modificar os itens do sitemap antes de eles serem escritos no arquivo `sitemap.xml`. Este gancho é chamado com um _array_ de itens sitemap e espera um _array_ de itens sitemap como retorno. Exemplo: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + sitemap: { + hostname: 'https://example.com', + transformItems: (items) => { + // adiciona novos itens ou modifica/filtra itens existentes + items.push({ + url: '/extra-page', + changefreq: 'monthly', + priority: 0.8 + }) + return items + } + } +}) +``` diff --git a/docs/pt/guide/ssr-compat.md b/docs/pt/guide/ssr-compat.md new file mode 100644 index 00000000..87bd0408 --- /dev/null +++ b/docs/pt/guide/ssr-compat.md @@ -0,0 +1,134 @@ +--- +outline: deep +--- + +# Compatibilidade SSR {#ssr-compatibility} + +VitePress pré-interpreta a aplicação no Node.js durante a compilação de produção, utilizando as capacidades de Interpretação do Lado do Servidor (SSR) do Vue. Isso significa que todo o código personalizado nos componentes do tema está sujeito à Compatibilidade SSR. + +A [seção SSR na documentação Vue oficial](https://vuejs.org/guide/scaling-up/ssr.html) fornece mais contexto sobre o que é SSR, a relação entre SSR / SSG e notas comuns sobre escrever código amigável a SSR. A regra geral é acessar apenas APIs do navegador / DOM nos gatilhos `beforeMount` ou `mounted` dos componentes Vue. + +## `` + +Se você estiver usando ou demonstrando componentes que não são compatíveis com SSR (por exemplo, contêm diretivas personalizadas), você pode envolvê-los no componente embutido ``: + +```md + + + +``` + +## Bibliotecas que Acessam a API do Navegador na Importação {#libraries-that-access-browser-api-on-import} + +Alguns componentes ou bibliotecas acessam APIs do navegador **na importação**. Para usar código que assume um ambiente de navegador na importação, você precisa importá-los dinamicamente. + +### Importando no Gatilho `mounted` {#importing-in-mounted-hook} + +```vue + +``` + +### Importação Condicional {#conditional-import} + +Você também pode importar condicionalmente uma dependência usando o sinalizador `import.meta.env.SSR` (parte das [variáveis de ambiente Vite](https://vitejs.dev/guide/env-and-mode.html#env-variables)): + +```js +if (!import.meta.env.SSR) { + import('./lib-que-acessa-window-na-importacao').then((module) => { + // usar código + }) +} +``` + +Como [`Theme.enhanceApp`](./custom-theme#theme-interface) pode ser assíncrono, você pode importar condicionalmente e registrar plugins Vue que acessam APIs do navegador na importação: + +```js [.vitepress/theme/index.js] +/** @type {import('vitepress').Theme} */ +export default { + // ... + async enhanceApp({ app }) { + if (!import.meta.env.SSR) { + const plugin = await import('plugin-que-acessa-window-na-importacao') + app.use(plugin.default) + } + } +} +``` + +Se estiver usando TypeScript: +```ts [.vitepress/theme/index.ts] +import type { Theme } from 'vitepress' + +export default { + // ... + async enhanceApp({ app }) { + if (!import.meta.env.SSR) { + const plugin = await import('plugin-que-acessa-window-na-importacao') + app.use(plugin.default) + } + } +} satisfies Theme +``` + +### `defineClientComponent` + +VitePress fornece um auxiliar de conveniência para importar componentes Vue que acessam APIs do navegador na importação. + +```vue + + + +``` + +Você também pode passar propriedades/filhos/_slots_ para o componente alvo: + +```vue + + + +``` + +O componente alvo só será importado no gatilho `mounted` do componente que o envolve. diff --git a/docs/pt/guide/using-vue.md b/docs/pt/guide/using-vue.md new file mode 100644 index 00000000..226d90d2 --- /dev/null +++ b/docs/pt/guide/using-vue.md @@ -0,0 +1,255 @@ +# Usando Vue em Markdown {#using-vue-in-markdown} + +Em VitePress, cada arquivo Markdown é compilado para HTML e então processado como um [Componente de Arquivo Único Vue](https://vuejs.org/guide/scaling-up/sfc.html). Isso significa que você pode usar qualquer funcionalidade Vue dentro do Markdown, incluindo a interpolação dinâmica, usar componentes Vue ou lógica arbitrária de componentes Vue dentro da página adicionando uma tag ` + +## Conteúdo Markdown + +A contagem é: {{ count }} + + + + +``` + +::: warning Evite ` +``` + +## Usando _Teleports_ {#using-teleports} + +VitePress atualmente oferece suporte a SSG para _teleports_ apenas para o corpo. Para outros alvos, você pode envolvê-los dentro do componente embutido `` ou injetar a marcação de _teleport_ na localização correta em sua página final HTML por meio do [gancho `postRender`](../reference/site-config#postrender). + + + +::: details +<<< @/components/ModalDemo.vue +::: + +```md + + +
+ // ... +
+
+
+``` + + + + diff --git a/docs/pt/guide/what-is-vitepress.md b/docs/pt/guide/what-is-vitepress.md new file mode 100644 index 00000000..734cd417 --- /dev/null +++ b/docs/pt/guide/what-is-vitepress.md @@ -0,0 +1,57 @@ +# O que é VitePress? {#what-is-vitepress} + +O VitePress é um [Gerador de Site Estático](https://en.wikipedia.org/wiki/Static_site_generator) (SSG) projetado para criar sites rápidos e centrados em conteúdo. Em suma, VitePress utiliza seu conteúdo-fonte escrito em [Markdown](https://en.wikipedia.org/wiki/Markdown), aplica um tema a ele e gera páginas HTML estáticas que podem ser facilmente implantadas em qualquer lugar. + +
+ +Quer apenas experimentar? Pule para o [Início Rápido](./getting-started). + +
+ +## Casos de Uso {#use-cases} + +- **Documentação** + + VitePress vem com um tema padrão projetado para documentação técnica. Ele alimenta esta página que você está lendo agora, juntamente com a documentação [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/) e [muitos outros](https://www.vuetelescope.com/explore?framework.slug=vitepress). + + A [documentação oficial Vue.js](https://vuejs.org/) também é baseada em VitePress, mas usa um tema personalizado compartilhado entre várias traduções. + +- **Blogs, Portfólios e Sites de Marketing** + + VitePress suporta [temas totalmente personalizáveis](./custom-theme), com a experiência de desenvolvedor padrão de uma aplicação Vite + Vue. A construção com Vite significa que você pode aproveitar diretamente plugins Vite de seu rico ecossistema. Adicionalmente, VitePress fornece APIs flexíveis para [carregar dados](./data-loading) (locais ou remotos) e [gerar rotas dinamicamente](./routing#dynamic-routes). Você pode usá-lo para construir praticamente qualquer coisa desde que os dados possam ser determinados no momento da construção. + + O [blog oficial Vue.js](https://blog.vuejs.org/) é um blog simples que gera sua página inicial baseada em conteúdo local. + +## Experiência de Desenvolvedor {#developer-experience} + +VitePress visa proporcionar excelente Experiência de Desenvolvedor (DX) ao trabalhar com conteúdo em Markdown. + +- **[Alimentado por Vite:](https://vitejs.dev/)** inicialização instantânea do servidor, com edições sempre refletidas instantaneamente (<100ms) sem recarregamento de página. + +- **[Extensões Markdown Integradas:](./markdown)** Frontmatter, tabelas, destaque de sintaxe... você escolhe. Especificamente, VitePress fornece muitos recursos avançados para trabalhar com blocos de código, tornando-o ideal para documentação altamente técnica. + +- **[Markdown Aprimorado por Vue:](./using-vue)** cada página Markdown é também um [Componente de Arquivo Único Vue](https://pt.vuejs.org/guide/scaling-up/sfc.html), graças à compatibilidade de sintaxe de 100% do template Vue com HTML. Você pode incorporar interatividade em seu conteúdo estático usando recursos de template Vue ou componentes Vue importados. + +## Desempenho {#performance} + +Ao contrário de muitos SSGs tradicionais, um site gerado pelo VitePress é na verdade uma [Aplicação de Página Única](https://en.wikipedia.org/wiki/Single-page_application) (SPA). + +- **Carregamento Inicial Rápido** + + A visita inicial a qualquer página será servida com o HTML estático pré-renderizado para velocidade de carregamento rápida e SEO otimizado. A página então carrega um pacote JavaScript que transforma a página em uma SPA Vue ("hidratação"). O processo de hidratação é extremamente rápido: no [PageSpeed Insights](https://pagespeed.web.dev/report?url=https%3A%2F%2Fvitepress.dev%2F), sites típicos VitePress alcançam pontuações de desempenho quase perfeitas, mesmo em dispositivos móveis de baixo desempenho com uma rede lenta. + +- **Navegação Rápida pós-carregamento** + + Mais importante ainda, o modelo SPA leva a uma melhor experiência do usuário **após** o carregamento inicial. A navegação subsequente dentro do site não causará mais uma recarga completa da página. Em vez disso, o conteúdo da página de entrada será buscado e atualizado dinamicamente. VitePress também pré-carrega automaticamente pedaços de página para links que estão dentro do viewport. Na maioria dos casos, a navegação pós-carregamento parecerá instantânea. + +- **Interatividade Sem Penalidades** + + Para ser capaz de hidratar as partes dinâmicas Vue incorporadas dentro do Markdown estático, cada página Markdown é processada como um componente Vue e compilada em JavaScript. Isso pode parecer ineficiente, mas o compilador Vue é inteligente o suficiente para separar as partes estáticas e dinâmicas, minimizando tanto o custo de hidratação quanto o tamanho da carga. Para o carregamento inicial da página, as partes estáticas são automaticamente eliminadas da carga JavaScript e puladas durante a hidratação. + +## E o VuePress? {#what-about-vuepress} + +VitePress é o sucessor espiritual de VuePress. VuePress era orginalmente baseado em Vue 2 e webpack. Com Vue 3 e Vite, VitePress oferece uma experiência de desenvolvedor significativamente melhor, melhor desempenho em produção, um tema padrão mais polido e uma API de personalização mais flexível. + +A diferença da API entre VitePress e VuePress reside principalmente em temas e personalização. Se você estiver usando VuePress 1 com o tema padrão, a migração para VitePress deve ser relativamente simples. + +Também houve esforço investido em VuePress 2, que também suporta Vue 3 e Vite com melhor compatibilidade do que VuePress 1. No entanto, manter dois SSGs em paralelo não é sustentável, então a equipe Vue decidiu focar em VitePress como o principal SSG recomendado a longo prazo. diff --git a/docs/pt/index.md b/docs/pt/index.md new file mode 100644 index 00000000..67cab365 --- /dev/null +++ b/docs/pt/index.md @@ -0,0 +1,35 @@ +--- +layout: home + +hero: + name: VitePress + text: Gerador de Site Estático Vite & Vue + tagline: Markdown para Lindos Documentos em Minutos + actions: + - theme: brand + text: O que é VitePress? + link: /pt/guide/what-is-vitepress + - theme: alt + text: Iniciar + link: /pt/guide/getting-started + - theme: alt + text: GitHub + link: https://github.com/vuejs/vitepress + image: + src: /vitepress-logo-large.svg + alt: VitePress + +features: + - icon: 📝 + title: Foco no seu conteúdo + details: Cria sites de documentação belos e sem esforço apenas com markdown. + - icon: + title: Aproveite a experiência Vite + details: Início de servidor instantâneo, atualizações ultrarrápidas, e plugins do ecossistema Vite. + - icon: + title: Personalize com Vue + details: Use sintaxe e componentes Vue diretamente em markdown, ou construa temas personalizados com Vue. + - icon: 🚀 + title: Entregue Sites Rápidos + details: Carregamento inicial rápido com HTML estático, navegação rápida com roteamento no lado do cliente. +--- diff --git a/docs/pt/reference/cli.md b/docs/pt/reference/cli.md new file mode 100644 index 00000000..6d7f0006 --- /dev/null +++ b/docs/pt/reference/cli.md @@ -0,0 +1,74 @@ +# Interface de Linha de Comando {#command-line-interface} + +## `vitepress dev` + +Inicia o servidor de desenvolvimento VitePress com o diretório designado como raiz. Por padrão usa o diretório atual. O comando `dev` pode também ser omitido ao rodar no diretório atual. + +### Uso + +```sh +# inicia no diretório atual, omitindo `dev` +vitepress + +# inicia em um subdiretório +vitepress dev [root] +``` + +### Opções {#options} + +| Opção | Descrição | +| --------------- | ----------------------------------------------------------------- | +| `--open [path]` | Abre o navegador na inicialização (`boolean \| string`) | +| `--port ` | Especifica porta (`number`) | +| `--base ` | Caminho base público (padrão: `/`) (`string`) | +| `--cors` | Habilita CORS | +| `--strictPort` | Interrompe se a porta especificada já está em uso (`boolean`) | +| `--force` | Força o otimizador a ignorar o cache e reempacotar (`boolean`) | + +## `vitepress build` + +Compila o site VitePress para produção. + +### Uso + +```sh +vitepress build [root] +``` + +### Opções + +| Opção | Descrição | +| ------------------------------ | ------------------------------------------------------------------------------------------------------------------- | +| `--mpa` (experimental) | Compila no [Modo MPA](../guide/mpa-mode) sem hidratação no lado do cliente (`boolean`) | +| `--base ` | Caminho base público (padrão: `/`) (`string`) | +| `--target ` | Transpila o alvo (padrão: `"modules"`) (`string`) | +| `--outDir ` | Diretório de saída relativo ao **cwd** (padrão: `/.vitepress/dist`) (`string`) | +| `--minify [minifier]` | Habilita/desabilita minificação, ou especifica um minificador para usar (padrão: `"esbuild"`) (`boolean \| "terser" \| "esbuild"`) | +| `--assetsInlineLimit ` | Limite em bytes para alinhar ativos em base64 (padrão: `4096`) (`number`) | + +## `vitepress preview` + +Prevê localmente a compilação de produção. + +### Uso + +```sh +vitepress preview [root] +``` + +### Opções + +| Opção | Descrição | +| --------------- | ------------------------------------------ | +| `--base ` | Caminho base público (padrão: `/`) (`string`) | +| `--port ` | Especifica porta (`number`) | + +## `vitepress init` + +Inicia o [Assistente de Instalação](../guide/getting-started#setup-wizard) no diretório atual. + +### Uso + +```sh +vitepress init +``` diff --git a/docs/pt/reference/default-theme-badge.md b/docs/pt/reference/default-theme-badge.md new file mode 100644 index 00000000..2fe79aa3 --- /dev/null +++ b/docs/pt/reference/default-theme-badge.md @@ -0,0 +1,69 @@ +# Emblema {#badge} + +O emblema permite adicionar status aos seus cabeçalhos. Por exemplo, pode ser útil especificar o tipo da seção ou a versão suportada. + +## Uso {#usage} + +Você pode usar o componente `Badge` que está disponível globalmente. + +```html +### Title +### Title +### Title +### Title +``` + +O código acima é apresentado como: + +### Title +### Title +### Title +### Title + +## Filiação Personalizada {#custom-children} + +`` aceita `children` (filhos), que serão exibidos no emblema. + +```html +### Title custom element +``` + +### Title custom element + +## Personalize o Tipo de Cor {#customize-type-color} + +Você pode personalizar o estilo dos emblemas sobrepondo variáveis CSS. Os seguintes são os valores padrão: + +```css +:root { + --vp-badge-info-border: transparent; + --vp-badge-info-text: var(--vp-c-text-2); + --vp-badge-info-bg: var(--vp-c-default-soft); + + --vp-badge-tip-border: transparent; + --vp-badge-tip-text: var(--vp-c-brand-1); + --vp-badge-tip-bg: var(--vp-c-brand-soft); + + --vp-badge-warning-border: transparent; + --vp-badge-warning-text: var(--vp-c-warning-1); + --vp-badge-warning-bg: var(--vp-c-warning-soft); + + --vp-badge-danger-border: transparent; + --vp-badge-danger-text: var(--vp-c-danger-1); + --vp-badge-danger-bg: var(--vp-c-danger-soft); +} +``` + +## `` + +O componente `` aceita as seguintes propriedades: + +```ts +interface Props { + // Quando `` é passado, esse valor é ignorado. + text?: string + + // O padrão é `tip`. + type?: 'info' | 'tip' | 'warning' | 'danger' +} +``` diff --git a/docs/pt/reference/default-theme-carbon-ads.md b/docs/pt/reference/default-theme-carbon-ads.md new file mode 100644 index 00000000..1c4d4e60 --- /dev/null +++ b/docs/pt/reference/default-theme-carbon-ads.md @@ -0,0 +1,22 @@ +# Carbon Ads {#carbon-ads} + +VitePress tem suporte embutido para [Carbon Ads](https://www.carbonads.net/). Ao definir as credenciais Carbon Ads na configuração, VitePress mostrará anúncios na página. + +```js +export default { + themeConfig: { + carbonAds: { + code: 'seu-código-carbon', + placement: 'sua-veiculação-carbon' + } + } +} +``` + +Esses valores são usados para chamar o sript em CDN do carbon como mostrado abaixo. + +```js +`//cdn.carbonads.com/carbon.js?serve=${code}&placement=${placement}` +``` + +Para aprender mais sobre a configuração Carbon Ads, por favor visite [Site Carbon Ads](https://www.carbonads.net/). diff --git a/docs/pt/reference/default-theme-config.md b/docs/pt/reference/default-theme-config.md new file mode 100644 index 00000000..54e53e4a --- /dev/null +++ b/docs/pt/reference/default-theme-config.md @@ -0,0 +1,438 @@ +# Configuração do Tema Padrão {#default-theme-config} + +A configuração do tema permite que você personalize seu tema. Você pode definir a configuração do tema através da opção `themeConfig` no arquivo de configuração: + +```ts +export default { + lang: 'pt-BR', + title: 'VitePress', + description: 'Gerador de site estático Vite & Vue.', + + // Configurações relacionadas ao tema. + themeConfig: { + logo: '/logo.svg', + nav: [...], + sidebar: { ... } + } +} +``` + +**As opções documentadas nesta página se aplicam apenas ao tema padrão.** Temas diferentes esperam configurações de tema diferentes. Ao usar um tema personalizado, o objeto de configuração do tema será passado para o tema para que se possam definir comportamentos condicionais. + +## i18nRouting + +- Tipo: `boolean` + +Alterar o local para, por exemplo, `zh` alterará a URL de `/foo` (ou `/en/foo/`) para `/zh/foo`. Você pode desativar esse comportamento definindo `themeConfig.i18nRouting` como `false`. + +## logo + +- Tipo: `ThemeableImage` + +Arquivo de logo a ser exibido na barra de navegação, logo antes do título do site. Aceita um caminho em string, ou um objeto para definir um logo diferente para os modos claro/escuro. + +```ts +export default { + themeConfig: { + logo: '/logo.svg' + } +} +``` + +```ts +type ThemeableImage = + | string + | { src: string; alt?: string } + | { light: string; dark: string; alt?: string } +``` + +## siteTitle + +- Tipo: `string | false` + +Você pode personalizar este item para substituir o título padrão do site (`title` na configuração da aplicação) na navegação. Quando definido como `false`, o título na navegação será desativado. Útil quando você tem um `logo` que já contém o título do site. + +```ts +export default { + themeConfig: { + siteTitle: 'Olá Mundo' + } +} +``` + +## nav + +- Tipo: `NavItem` + +A configuração para o item do menu de navegação. Mais detalhes em [Tema Padrão: Navegação](./default-theme-nav#navigation-links). + +```ts +export default { + themeConfig: { + nav: [ + { text: 'Guia', link: '/guide' }, + { + text: 'Menu Dropdown', + items: [ + { text: 'Item A', link: '/item-1' }, + { text: 'Item B', link: '/item-2' }, + { text: 'Item C', link: '/item-3' } + ] + } + ] + } +} +``` + +```ts +type NavItem = NavItemWithLink | NavItemWithChildren + +interface NavItemWithLink { + text: string + link: string + activeMatch?: string + target?: string + rel?: string + noIcon?: boolean +} + +interface NavItemChildren { + text?: string + items: NavItemWithLink[] +} + +interface NavItemWithChildren { + text?: string + items: (NavItemChildren | NavItemWithLink)[] + activeMatch?: string +} +``` + +## sidebar + +- Tipo: `Sidebar` + +A configuração para o item do menu da barra lateral. Mais detalhes em [Tema Padrão: Barra Lateral](./default-theme-sidebar). + +```ts +export default { + themeConfig: { + sidebar: [ + { + text: 'Guia', + items: [ + { text: 'Introdução', link: '/introduction' }, + { text: 'Começando', link: '/getting-started' }, + ... + ] + } + ] + } +} +``` + +```ts +export type Sidebar = SidebarItem[] | SidebarMulti + +export interface SidebarMulti { + [path: string]: SidebarItem[] +} + +export type SidebarItem = { + /** + * O rótulo de texto do item. + */ + text?: string + + /** + * O link do item. + */ + link?: string + + /** + * Os filhos do item. + */ + items?: SidebarItem[] + + /** + * Se não especificado, o grupo não é retrátil. + * + * Se `true`, o grupo é retrátil e é colapsado por padrão. + * + * Se `false`, o grupo é retrátil, mas expandido por padrão. + */ + collapsed?: boolean +} +``` + +## aside + +- Tipo: `boolean | 'left'` +- Padrão: `true` +- Pode ser anulado por página via [frontmatter](./frontmatter-config#aside) + +Definir este valor como `false` impede a apresentação do elemento aside.\ +Definir este valor como `true` apresenta o aside à direita.\ +Definir este valor como `left` apresenta o aside à esquerda. + +Se você quiser desativá-lo para todas as visualizações, você deve usar `outline: false` em vez disso. + +## outline + +- Tipo: `Outline | Outline['level'] | false` +- O nível pode ser sobreposto por página via [frontmatter](./frontmatter-config#outline) + +Definir este valor como `false` impede a apresentação do elemento _outline_. Consulte a interface para obter mais detalhes: + +```ts +interface Outline { + /** + * Os níveis de títulos a serem exibidos na outline. + * Um único número significa que apenas os títulos desse nível serão exibidos. + * Se uma tupla for passada, o primeiro número é o nível mínimo e o segundo número é o nível máximo. + * `'deep'` é o mesmo que `[2, 6]`, o que significa que todos os títulos de `

` a `

` serão exibidos. + * + * @default 2 + */ + level?: number | [number, number] | 'deep' + + /** + * O título a ser exibido na outline. + * + * @default 'On this page' + */ + label?: string +} +``` + +## socialLinks + +- Tipo: `SocialLink[]` + +Você pode definir esta opção para mostrar os links de redes sociais com ícones na navegação. + +```ts +export default { + themeConfig: { + socialLinks: [ + { icon: 'github', link: 'https://github.com/vuejs/vitepress' }, + { icon: 'twitter', link: '...' }, + // Você também pode adicionar ícones personalizados passando SVG como string: + { + icon: { + svg: 'Dribbble' + }, + link: '...', + // Você também pode incluir um rótulo personalizado para acessibilidade (opcional mas recomendado): + ariaLabel: 'cool link' + } + ] + } +} +``` + +```ts +interface SocialLink { + icon: string | { svg: string } + link: string + ariaLabel?: string +} +``` + +## footer + +- Tipo: `Footer` +- Pode ser sobreposto por página via [frontmatter](./frontmatter-config#footer) + +Configuração do rodapé. Você pode adicionar uma mensagem ou texto de direitos autorais no rodapé, no entanto, ela só será exibida quando a página não contiver uma barra lateral. Isso se deve a preocupações de design. + +```ts +export default { + themeConfig: { + footer: { + message: 'Lançado sob a Licença MIT.', + copyright: 'Direitos autorais © 2019-presente Evan You' + } + } +} +``` + +```ts +export interface Footer { + message?: string + copyright?: string +} +``` + +## editLink + +- Tipo: `EditLink` +- Pode ser sobreposto por página via [frontmatter](./frontmatter-config#editlink) + +O _EditLink_ permite exibir um link para editar a página em serviços de gerenciamento Git, como GitHub ou GitLab. Consulte [Tema Padrão: Editar Link](./default-theme-edit-link) para mais detalhes. + +```ts +export default { + themeConfig: { + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + text: 'Editar esta página no GitHub' + } + } +} +``` + +```ts +export interface EditLink { + pattern: string + text?: string +} +``` + +## lastUpdated + +- Tipo: `LastUpdatedOptions` + +Permite personalização para o texto de última atualização e o formato de data. + +```ts +export default { + themeConfig: { + lastUpdated: { + text: 'Atualizado em', + formatOptions: { + dateStyle: 'full', + timeStyle: 'medium' + } + } + } +} +``` + +```ts +export interface LastUpdatedOptions { + /** + * @default 'Last updated' + */ + text?: string + + /** + * @default + * { dateStyle: 'short', timeStyle: 'short' } + */ + formatOptions?: Intl.DateTimeFormatOptions & { forceLocale?: boolean } +} +``` + +## algolia + +- Tipo: `AlgoliaSearch` + +Uma opção para dar suporte à pesquisa em seu site de documentação usando [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch). Saiba mais em [Tema Padrão: Pesquisa](./default-theme-search). + +```ts +export interface AlgoliaSearchOptions extends DocSearchProps { + locales?: Record> +} +``` + +Veja todas as opções [aqui](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts). + +## carbonAds {#carbon-ads} + +- Tipo: `CarbonAdsOptions` + +Uma opção para mostrar [Carbon Ads](https://www.carbonads.net/). + +```ts +export default { + themeConfig: { + carbonAds: { + code: 'seu-código-carbon', + placement: 'sua-veiculação-carbon' + } + } +} +``` + +```ts +export interface CarbonAdsOptions { + code: string + placement: string +} +``` + +Saiba mais em [Tema Padrão: Carbon Ads](./default-theme-carbon-ads). + +## docFooter + +- Tipo: `DocFooter` + +Pode ser usado para personalizar o texto que aparece acima dos links anterior e próximo. Útil se não estiver escrevendo documentação em inglês. Também pode ser usado para desabilitar globalmente os links anterior/próximo. Se você quiser ativar/desativar seletivamente os links anterior/próximo, pode usar [frontmatter](./default-theme-prev-next-links). + +```ts +export default { + themeConfig: { + docFooter: { + prev: 'Página anterior', + next: 'Próxima página' + } + } +} +``` + +```ts +export interface DocFooter { + prev?: string | false + next?: string | false +} +``` + +## darkModeSwitchLabel + +- Tipo: `string` +- Padrão: `Appearance` + +Pode ser usado para personalizar o rótulo do botão de modo escuro. Esse rótulo é exibido apenas na visualização móvel. + +## lightModeSwitchTitle + +- Tipo: `string` +- Padrão: `Switch to light theme` + +Pode ser usado para personalizar o título do botão de modo claro que aparece ao passar o mouse. + +## darkModeSwitchTitle + +- Tipo: `string` +- Padrão: `Switch to dark theme` + +Pode ser usado para personalizar o título do botão de modo escuro que aparece ao passar o mouse. + +## sidebarMenuLabel + +- Tipo: `string` +- Padrão: `Menu` + +Pode ser usado para personalizar o rótulo do menu da barra lateral. Esse rótulo é exibido apenas na visualização móvel. + +## returnToTopLabel + +- Tipo: `string` +- Padrão: `Return to top` + +Pode ser usado para personalizar o rótulo do botão de retorno ao topo. Esse rótulo é exibido apenas na visualização móvel. + +## langMenuLabel + +- Tipo: `string` +- Padrão: `Change language` + +Pode ser usado para personalizar o aria-label do botão de idioma na barra de navegação. Isso é usado apenas se você estiver usando [i18n](../guide/i18n). + +## externalLinkIcon + +- Tipo: `boolean` +- Padrão: `false` + +Se deve mostrar um ícone de link externo ao lado de links externos no markdown. diff --git a/docs/pt/reference/default-theme-edit-link.md b/docs/pt/reference/default-theme-edit-link.md new file mode 100644 index 00000000..6b1e8793 --- /dev/null +++ b/docs/pt/reference/default-theme-edit-link.md @@ -0,0 +1,60 @@ +# Editar Link {#edit-link} + +## Configuração a nível de Site {#site-level-config} + +Editar Link permite que você mostre um link para editar a página com serviços de gerenciamento Git, como GitHub ou GitLab. Para habilitar, adicione a opção `themeConfig.editLink` na sua configuração. + +```js +export default { + themeConfig: { + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path' + } + } +} +``` + +A opção `pattern` define a estrutura da URL para o link, e `:path` será substituído com o mesmo caminho de página. + +Você também pode colocar uma função pura que aceita [`PageData`](./runtime-api#usedata) como argumento e retorna uma URL em string. + +```js +export default { + themeConfig: { + editLink: { + pattern: ({ filePath }) => { + if (filePath.startsWith('packages/')) { + return `https://github.com/acme/monorepo/edit/main/${filePath}` + } else { + return `https://github.com/acme/monorepo/edit/main/docs/${filePath}` + } + } + } + } +} +``` + +Isso não deve gerar efeitos colaterais ou acessar qualquer coisa fora do seu escopo, uma vez que será serializado e executado no navegador. + +Por padrão, isso irá adicionar o link com texto "Edite essa página" no final da página de documentação. Você pode personalizar esse texto ao definir a opção `text`. + +```js +export default { + themeConfig: { + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + text: 'Edite essa página no GitHub' + } + } +} +``` + +## Configuração Frontmatter {#frontmatter-config} + +A funcionalidade pode ser desabilitada por página usando a opção `editLink` no frontmatter: + +```yaml +--- +editLink: false +--- +``` diff --git a/docs/pt/reference/default-theme-footer.md b/docs/pt/reference/default-theme-footer.md new file mode 100644 index 00000000..138531e7 --- /dev/null +++ b/docs/pt/reference/default-theme-footer.md @@ -0,0 +1,53 @@ +# Rodapé {#footer} + +VitePress irá mostrar o rodapé global na parte inferior da página quando `themeConfig.footer` está presente. + +```ts +export default { + themeConfig: { + footer: { + message: 'Lançado sob Licença MIT.', + copyright: 'Direitos Reservados © 2019-present Evan You' + } + } +} +``` + +```ts +export interface Footer { + // A mensagem mostrada logo antes do copyright. + message?: string + + // O próprio texto de copyright. + copyright?: string +} +``` + +A configuração acima também suporta strings HTML. Então, por exemplo, se você quiser configurar o texto de rodapé para ter alguns links, você pode ajustar a configuração como o seguinte: + +```ts +export default { + themeConfig: { + footer: { + message: 'Lançado sob Licença MIT.', + copyright: 'Direitos Reservados © 2019-present Evan You' + } + } +} +``` + +::: warning +Apenas elementos _inline_ serão usados em `message` e `copyright` conforme eles são apresentados dentro do elemento `

`. Se você quiser adicionar elementos de tipo _block_, considere usar o _slot_ [`layout-bottom`](../guide/extending-default-theme#layout-slots). +::: + +Note que o rodapé não será mostrado quando a [Barra Lateral](./default-theme-sidebar) estiver visível. + +## Configuração Frontmatter {#frontmatter-config} + +Isso pode ser desabilitado por página usando a opção `footer` em frontmatter: + +```yaml +--- +footer: false +--- +``` diff --git a/docs/pt/reference/default-theme-home-page.md b/docs/pt/reference/default-theme-home-page.md new file mode 100644 index 00000000..460c55bf --- /dev/null +++ b/docs/pt/reference/default-theme-home-page.md @@ -0,0 +1,168 @@ +# Página Inicial {#home-page} + +O tema padrão VitePress fornece um layout de página inicial, que você também pode ver em uso [na página inicial deste site](../). Você pode usá-lo em qualquer uma de suas páginas especificando `layout: home` em [frontmatter](./frontmatter-config). + +```yaml +--- +layout: home +--- +``` + +No entanto, essa opção sozinha não faz muito. Você pode adicionar várias "seções" diferentes pré-modeladas à página inicial definindo opções adicionais como `hero` e `features`. + +## Seção Hero {#hero-section} + +A seção _Hero_ fica no topo da página inicial. Aqui segue como você pode configurar a seção _Hero_. + +```yaml +--- +layout: home + +hero: + name: VitePress + text: Gerador de site estático com Vite & Vue. + tagline: Lorem ipsum... + image: + src: /logo.png + alt: VitePress + actions: + - theme: brand + text: Iniciar + link: /guide/what-is-vitepress + - theme: alt + text: Ver no GitHub + link: https://github.com/vuejs/vitepress +--- +``` + +```ts +interface Hero { + // A string mostrada acima de `text`. Vem com a cor da marca + // e espera-se que seja curta, como o nome do produto. + name?: string + + // O texto principal para a seção hero. + // Isso será definido como uma tag `h1`. + text: string + + // Slogan exibido abaixo de `text`. + tagline?: string + + // A imagem é exibida ao lado da área de texto e slogan. + image?: ThemeableImage + + // Botões acionáveis para exibir na seção hero da página inicial. + actions?: HeroAction[] +} + +type ThemeableImage = + | string + | { src: string; alt?: string } + | { light: string; dark: string; alt?: string } + +interface HeroAction { + // Tema de cor do botão. Padrão: `brand`. + theme?: 'brand' | 'alt' + + // Rótulo do botão. + text: string + + // Destino do link do botão. + link: string + + // Atributo target do link. + target?: string + + // Atributo rel do link. + rel?: string +} +``` + +### Personalizando a cor do nome {#customizing-the-name-color} + +VitePress usa a cor da marca (`--vp-c-brand-1`) para `name`. No entanto, você pode personalizar essa cor sobrescrevendo a variável `--vp-home-hero-name-color`. + +```css +:root { + --vp-home-hero-name-color: blue; +} +``` + +Você também pode personalizá-la ainda mais combinando `--vp-home-hero-name-background` para dar ao `name` uma cor degradê. + +```css +:root { + --vp-home-hero-name-color: transparent; + --vp-home-hero-name-background: -webkit-linear-gradient(120deg, #bd34fe, #41d1ff); +} +``` + +## Seção de Funcionalidades {#features-section} + +Na seção de funcionalidades, você pode listar qualquer número de funcionalidades que deseja mostrar imediatamente após a seção _Hero_. Para configurá-la, passe a opção `features` para o frontmatter. + +Você pode fornecer um ícone para cada funcionalidade, que pode ser um emoji ou qualquer tipo de imagem. Quando o ícone configurado é uma imagem (svg, png, jpeg...), você deve fornecer o ícone com a largura e altura apropriadas; você também pode fornecer a descrição, seu tamanho intrínseco, bem como suas variantes para temas escuros e claros quando necessário. + +```yaml +--- +layout: home + +features: + - icon: 🛠️ + title: Simples e minimalista, sempre + details: Lorem ipsum... + - icon: + src: /cool-feature-icon.svg + title: Outro recurso legal + details: Lorem ipsum... + - icon: + dark: /dark-feature-icon.svg + light: /light-feature-icon.svg + title: Outro recurso legal + details: Lorem ipsum... +--- +``` + +```ts +interface Feature { + // Mostra ícone em cada bloco de funcionalide. + icon?: FeatureIcon + + // Título da funcionalidade. + title: string + + // Detalhes da funcionalidade. + details: string + + // Link quando clicado no componente de funcionalidade. + // O link pode ser interno ou externo. + // + // ex. `guide/reference/default-theme-home-page` ou `https://example.com` + link?: string + + // Texto do link a ser exibido dentro do componente de funcionalidade. + // Melhor usado com a opção `link`. + // + // ex. `Saiba mais`, `Visitar página`, etc. + linkText?: string + + // Atributo rel do link para a opção `link`. + // + // ex. `external` + rel?: string + + // Atributo target do link para a opção `link`. + target?: string +} + +type FeatureIcon = + | string + | { src: string; alt?: string; width?: string; height: string } + | { + light: string + dark: string + alt?: string + width?: string + height: string + } +``` diff --git a/docs/pt/reference/default-theme-last-updated.md b/docs/pt/reference/default-theme-last-updated.md new file mode 100644 index 00000000..5bc782e1 --- /dev/null +++ b/docs/pt/reference/default-theme-last-updated.md @@ -0,0 +1,27 @@ +# Última Atualização {#last-updated} + +O tempo em que o conteúdo foi atualizado pela última vez será mostrado no canto inferior direito da página. Para habilitar, adicione a opção `lastUpdated` na sua configuração. + +::: tip +Você precisa fazer _commit_ no arquivo markdown para ver o tempo atualizado. +::: + +## Configuração a nível de Site {#site-level-config} + +```js +export default { + lastUpdated: true +} +``` + +## Configuração Frontmatter {#frontmatter-config} + +Isso pode ser desabilitado por página usando a opção `lastUpdated` no frontmatter: + +```yaml +--- +lastUpdated: false +--- +``` + +Refira-se ao [Tema Padrão: Última Atualização](./default-theme-config#lastupdated) para mais detalhes. Qualquer valor positivo a nível de tema também habilitará a funcionalidade a não ser que esteja explicitamente desabilitada a nível de página ou de site. diff --git a/docs/pt/reference/default-theme-layout.md b/docs/pt/reference/default-theme-layout.md new file mode 100644 index 00000000..0e4d0162 --- /dev/null +++ b/docs/pt/reference/default-theme-layout.md @@ -0,0 +1,62 @@ +# Layout {#layout} + +Você pode escolher o layout da página definindo a opção de `layout` para o [frontmatter](./frontmatter-config) da página. Há três opções de layout: `doc`, `page` e `home`. Se nada for especificado, a página será tratada como página `doc`. + +```yaml +--- +layout: doc +--- +``` + +## Layout do documento {#doc-layout} + +A opção `doc` é o layout padrão e estiliza todo o conteúdo Markdown com o visual de "documentação". Ela funciona agrupando todo o conteúdo na classe CSS `vp-doc`, e aplicando os estilos aos elementos abaixo dela. + +Quase todos os elementos genéricos, como `p` ou `h2`, recebem um estilo especial. Portanto, lembre-se de que se você adicionar qualquer HTML personalizado dentro de um conteúdo Markdown, ele também será afetado por esses estilos. + +Ele também fornece recursos específicos de documentação listados abaixo. Esses recursos estão habilitados apenas neste layout. + +- Editar link +- Links Anterior e Próximo +- _Outline_ +- [Carbon Ads](./default-theme-carbon-ads) + +## Layout da Página {#page-layout} + +A opção `page` é tratada como "página em branco". O Markdown ainda será processado e todas as [Extensões Markdown](../guide/markdown) funcionarão da mesma forma que o layout `doc`, mas este não receberá nenhum estilo padrão. + +O layout da página permitirá que você estilize tudo sem que o tema VitePress afete a marcação. Isso é útil quando você deseja criar sua própria página personalizada. + +Observe que mesmo neste layout, a barra lateral ainda aparecerá se a página tiver uma configuração de barra lateral correspondente. + +## Layout da Home {#home-layout} + +A opção `home` gerará um modelo de _"Homepage"_. Nesse layout você pode definir opções extras, como `hero` e `features`, para personalizar ainda mais o conteúdo. Visite [Tema padrão: Página Inicial](./default-theme-home-page) para obter mais detalhes. + +## Sem Layout {#no-layout} + +Se você não quiser nenhum layout, pode passar `layout: false` pelo frontmatter. Esta opção é útil se você deseja uma página de destino totalmente personalizável (sem barra lateral, barra de navegação ou rodapé por padrão). + +## Layout Personalizado {#custom-layout} + +Você também pode usar um layout personalizado: + +```md +--- +layout: foo +--- +``` + +Isto irá procurar um componente chamado `foo` registrado no contexto. Por exemplo, você pode registrar seu componente globalmente em `.vitepress/theme/index.ts`: + +```ts +import DefaultTheme from 'vitepress/theme' +import Foo from './Foo.vue' + +export default { + extends: DefaultTheme, + enhanceApp({ app }) { + app.component('foo', Foo) + } +} +``` diff --git a/docs/pt/reference/default-theme-nav.md b/docs/pt/reference/default-theme-nav.md new file mode 100644 index 00000000..5f0d2399 --- /dev/null +++ b/docs/pt/reference/default-theme-nav.md @@ -0,0 +1,162 @@ +# Navegação {#nav} + +Referente a barra de navegação exibida no topo da página. Ela contém o título do site, links do menu global, e etc. + +## Título do Site e Logo {#site-title-and-logo} + +Por padrão, a navegação mostra o título do site referenciando o valor de [`config.title`](./site-config#title). Se desejar alterar o que é exibido na navegação, você pode definir um texto personalizado na opção `themeConfig.siteTitle`. + +```js +export default { + themeConfig: { + siteTitle: 'Meu Título Personalizado' + } +} +``` + +Se você tiver um logo para seu site, pode mostrá-lo passando o caminho para a imagem. Você deve colocar o logo diretamente dentro da pasta `public`, e definir o caminho absoluto para ele. + +```js +export default { + themeConfig: { + logo: '/my-logo.svg' + } +} +``` + +Ao adicionar um logo, ele é mostrado juntamente com o título do site. Se seu logo tem tudo o que você precisa e se você desejar ocultar o texto do título, defina `false` na opção `siteTitle`. + +```js +export default { + themeConfig: { + logo: '/my-logo.svg', + siteTitle: false + } +} +``` + +Você também pode passar um objeto como logo se quiser adicionar um atributo `alt` ou personalizá-lo com base no modo claro/escuro. Consulte [`themeConfig.logo`](./default-theme-config#logo) para obter detalhes. + +## Links de Navegação {#navigation-links} + +Você pode definir a opção `themeConfig.nav` para adicionar links à sua navegação. + +```js +export default { + themeConfig: { + nav: [ + { text: 'Guia', link: '/guide' }, + { text: 'Configuração', link: '/config' }, + { text: 'Registro de Alterações', link: 'https://github.com/...' } + ] + } +} +``` + +`text` é o próprio texto mostrado na navegação, e o `link` é o link para o qual será navegado quando o texto for clicado. Para o link, defina o caminho para o próprio arquivo sem o prefixo `.md` e sempre comece com `/`. + +Links de navegação também podem ser menus _dropdown_. Para fazer isso, defina a chave `items` na opção do link. + +```js +export default { + themeConfig: { + nav: [ + { text: 'Guia', link: '/guide' }, + { + text: 'Menu Dropdown', + items: [ + { text: 'Item A', link: '/item-1' }, + { text: 'Item B', link: '/item-2' }, + { text: 'Item C', link: '/item-3' } + ] + } + ] + } +} +``` + +Note que o título do menu _dropdown_ (`Menu Dropdown` no exemplo acima) não pode ter a propriedade `link`, pois ele se torna um botão para abrir o diálogo dropdown. + +Você também pode adicionar "seções" aos itens do menu _dropdown_ passando mais itens aninhados. + +```js +export default { + themeConfig: { + nav: [ + { text: 'Guia', link: '/guia' }, + { + text: 'Menu Dropdown', + items: [ + { + // Título da seção. + text: 'Título da Seção A', + items: [ + { text: 'Item A da Seção A', link: '...' }, + { text: 'Item B da Seção B', link: '...' } + ] + } + ] + }, + { + text: 'Menu Dropdown', + items: [ + { + // Você também pode omitir o título. + items: [ + { text: 'Item A da Seção A', link: '...' }, + { text: 'Item B da Seção B', link: '...' } + ] + } + ] + } + ] + } +} +``` + +### Personalizar o estado "ativo" do link {#customize-link-s-active-state} + +Os itens do menu de navegação serão destacados quando a página atual estiver no caminho correspondente. Se desejar personalizar o caminho a ser correspondido, defina a propriedade `activeMatch` e regex como um valor em string. + +```js +export default { + themeConfig: { + nav: [ + // Este link fica no estado ativo quando + // o usuário está no caminho `/config/`. + { + text: 'Guia', + link: '/guide', + activeMatch: '/config/' + } + ] + } +} +``` + +::: warning +`activeMatch` deve ser uma string regex, mas você deve defini-la como uma string. Não podemos usar um objeto RegExp real aqui porque ele não é serializável durante o momento de construção. +::: + +### Personalizar os atributos "target" e "rel" de links {#customize-link-s-target-and-rel-attributes} + +Por padrão, VitePress determina automaticamente os atributos `target` e `rel` baseado em um link externo ou não. Mas se você quiser, também pode personalizá-los. + +```js +export default { + themeConfig: { + nav: [ + { + text: 'Merchandise', + link: 'https://www.thegithubshop.com/', + target: '_self', + rel: 'sponsored' + } + ] + } +} +``` + +## Links Sociais {#social-links} + +Consulte [`socialLinks`](./default-theme-config#sociallinks). diff --git a/docs/pt/reference/default-theme-prev-next-links.md b/docs/pt/reference/default-theme-prev-next-links.md new file mode 100644 index 00000000..c9472a24 --- /dev/null +++ b/docs/pt/reference/default-theme-prev-next-links.md @@ -0,0 +1,43 @@ +# Links Anterior e Próximo {#prev-next-links} + +Você pode personalizar o texto e o link para os botões de Anterior e Próximo mostrados ao fim da página. Isso é útil quando você quer mostrar um texto diferente daquele que você tem na barra lateral. Além disso, você pode achar útil desabilitar o rodapé ou link para a página para ela não ser incluída na sua barra lateral. + +## prev + +- Tipo: `string | false | { text?: string; link?: string }` + +- Detalhes: + + Especifica o texto/link para mostrar no link para a página anterior. Se você não ver isso no frontmatter, o texto/link será inferido da configuração da barra lateral. + +- Exemplos: + + - Para personalizar apenas o texto: + + ```yaml + --- + prev: 'Iniciar | Markdown' + --- + ``` + + - Para personalizar ambos texto e link: + + ```yaml + --- + prev: + text: 'Markdown' + link: '/guide/markdown' + --- + ``` + + - Para esconder a página anterior: + + ```yaml + --- + prev: false + --- + ``` + +## next + +O mesmo que `prev` mas para a próxima página. diff --git a/docs/pt/reference/default-theme-search.md b/docs/pt/reference/default-theme-search.md new file mode 100644 index 00000000..c16406cb --- /dev/null +++ b/docs/pt/reference/default-theme-search.md @@ -0,0 +1,372 @@ +--- +outline: deep +--- + +# Pesquisa {#search} + +## Pesquisa Local {#local-search} + +VitePress oferece suporte à pesquisa de texto completa usando um índice no navegador graças ao [minisearch](https://github.com/lucaong/minisearch/). Para habilitar esse recurso, basta definir a opção `themeConfig.search.provider` como `'local'` no arquivo `.vitepress/config.ts`: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local' + } + } +}) +``` + +Exemplo de resultado: + +![captura de tela do modal de pesquisa](/search.png) + +Alternativamente, você pode usar [Algolia DocSearch](#algolia-search) ou alguns plugins da comunidade como ou . + +### i18n {#local-search-i18n} + +Você pode usar uma configuração como esta para usar a pesquisa multilínguas: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + locales: { + zh: { + translations: { + button: { + buttonText: '搜索文档', + buttonAriaLabel: '搜索文档' + }, + modal: { + noResultsText: '无法找到相关结果', + resetButtonTitle: '清除查询条件', + footer: { + selectText: '选择', + navigateText: '切换' + } + } + } + } + } + } + } + } +}) +``` + +### Opções MiniSearch {#mini-search-options} + +Você pode configurar o MiniSearch assim: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + miniSearch: { + /** + * @type {Pick} + */ + options: { + /* ... */ + }, + /** + * @type {import('minisearch').SearchOptions} + * @default + * { fuzzy: 0.2, prefix: true, boost: { title: 4, text: 2, titles: 1 } } + */ + searchOptions: { + /* ... */ + } + } + } + } + } +}) +``` + +Saiba mais na [documentação do MiniSearch](https://lucaong.github.io/minisearch/classes/MiniSearch.MiniSearch.html). + +### Apresentador de Conteúdo Personalizado {#custom-content-renderer} + +Você pode personalizar a função usada para apresentar o conteúdo markdown antes de indexá-lo: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + /** + * @param {string} src + * @param {import('vitepress').MarkdownEnv} env + * @param {import('markdown-it-async')} md + */ + async _render(src, env, md) { + // retorne a string HTML + } + } + } + } +}) +``` + +Essa função será removida dos dados do site no lado do cliente, então você pode usar APIs do Node.js nela. + +#### Exemplo: Excluindo páginas da pesquisa {#example-excluding-pages-from-search} + +Você pode excluir páginas da pesquisa adicionando `search: false` ao frontmatter da página. Alternativamente: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + async _render(src, env, md) { + const html = await md.renderAsync(src, env) + if (env.frontmatter?.search === false) return '' + if (env.relativePath.startsWith('algum/caminho')) return '' + return html + } + } + } + } +}) +``` + +::: warning Nota +No caso uma função `_render` personalizada ser fornecida, você precisa manipular o `search: false` do frontmatter por conta própria. Além disso, o objeto `env` não estará completamente populado antes que `md.renderAsync` seja chamado, então verificações em propriedades opcionais `env`, como `frontmatter`, devem ser feitas após isso. +::: + +#### Exemplo: Transformando conteúdo - adicionando âncoras {#example-transforming-content-adding-anchors} + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + async _render(src, env, md) { + const html = await md.renderAsync(src, env) + if (env.frontmatter?.title) + return await md.renderAsync(`# ${env.frontmatter.title}`) + html + return html + } + } + } + } +}) +``` + +## Pesquisa Algolia {#algolia-search} + +VitePress oferece suporte à pesquisa em seu site de documentação usando [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch). Consulte o guia de início deles. Em seu arquivo `.vitepress/config.ts`, você precisará fornecer pelo menos o seguinte para que funcione: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'algolia', + options: { + appId: '...', + apiKey: '...', + indexName: '...' + } + } + } +}) +``` + +### i18n {#algolia-search-i18n} {#algolia-search-i18n} + +Você pode usar uma configuração como esta para usar a pesquisa multilínguas: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'algolia', + options: { + appId: '...', + apiKey: '...', + indexName: '...', + locales: { + zh: { + placeholder: '搜索文档', + translations: { + button: { + buttonText: '搜索文档', + buttonAriaLabel: '搜索文档' + }, + modal: { + searchBox: { + resetButtonTitle: '清除查询条件', + resetButtonAriaLabel: '清除查询条件', + cancelButtonText: '取消', + cancelButtonAriaLabel: '取消' + }, + startScreen: { + recentSearchesTitle: '搜索历史', + noRecentSearchesText: '没有搜索历史', + saveRecentSearchButtonTitle: '保存至搜索历史', + removeRecentSearchButtonTitle: '从搜索历史中移除', + favoriteSearchesTitle: '收藏', + removeFavoriteSearchButtonTitle: '从收藏中移除' + }, + errorScreen: { + titleText: '无法获取结果', + helpText: '你可能需要检查你的网络连接' + }, + footer: { + selectText: '选择', + navigateText: '切换', + closeText: '关闭', + searchByText: '搜索提供者' + }, + noResultsScreen: { + noResultsText: '无法找到相关结果', + suggestedQueryText: '你可以尝试查询', + reportMissingResultsText: '你认为该查询应该有结果?', + reportMissingResultsLinkText: '点击反馈' + } + } + } + } + } + } + } + } +}) +``` + +[Essas opções](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts) podem ser sobrepostas. Consulte a documentação oficial Algolia para obter mais informações sobre elas. + +### Configuração _Crawler_ {#crawler-config} + +Aqui está um exemplo de configuração baseado na qual este site usa: + +```ts +new Crawler({ + appId: '...', + apiKey: '...', + rateLimit: 8, + startUrls: ['https://vitepress.dev/'], + renderJavaScript: false, + sitemaps: [], + exclusionPatterns: [], + ignoreCanonicalTo: false, + discoveryPatterns: ['https://vitepress.dev/**'], + schedule: 'at 05:10 on Saturday', + actions: [ + { + indexName: 'vitepress', + pathsToMatch: ['https://vitepress.dev/**'], + recordExtractor: ({ $, helpers }) => { + return helpers.docsearch({ + recordProps: { + lvl1: '.content h1', + content: '.content p, .content li', + lvl0: { + selectors: 'section.has-active div h2', + defaultValue: 'Documentation' + }, + lvl2: '.content h2', + lvl3: '.content h3', + lvl4: '.content h4', + lvl5: '.content h5' + }, + indexHeadings: true + }) + } + } + ], + initialIndexSettings: { + vitepress: { + attributesForFaceting: ['type', 'lang'], + attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'], + attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'], + attributesToSnippet: ['content:10'], + camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'], + searchableAttributes: [ + 'unordered(hierarchy_radio_camel.lvl0)', + 'unordered(hierarchy_radio.lvl0)', + 'unordered(hierarchy_radio_camel.lvl1)', + 'unordered(hierarchy_radio.lvl1)', + 'unordered(hierarchy_radio_camel.lvl2)', + 'unordered(hierarchy_radio.lvl2)', + 'unordered(hierarchy_radio_camel.lvl3)', + 'unordered(hierarchy_radio.lvl3)', + 'unordered(hierarchy_radio_camel.lvl4)', + 'unordered(hierarchy_radio.lvl4)', + 'unordered(hierarchy_radio_camel.lvl5)', + 'unordered(hierarchy_radio.lvl5)', + 'unordered(hierarchy_radio_camel.lvl6)', + 'unordered(hierarchy_radio.lvl6)', + 'unordered(hierarchy_camel.lvl0)', + 'unordered(hierarchy.lvl0)', + 'unordered(hierarchy_camel.lvl1)', + 'unordered(hierarchy.lvl1)', + 'unordered(hierarchy_camel.lvl2)', + 'unordered(hierarchy.lvl2)', + 'unordered(hierarchy_camel.lvl3)', + 'unordered(hierarchy.lvl3)', + 'unordered(hierarchy_camel.lvl4)', + 'unordered(hierarchy.lvl4)', + 'unordered(hierarchy_camel.lvl5)', + 'unordered(hierarchy.lvl5)', + 'unordered(hierarchy_camel.lvl6)', + 'unordered(hierarchy.lvl6)', + 'content' + ], + distinct: true, + attributeForDistinct: 'url', + customRanking: [ + 'desc(weight.pageRank)', + 'desc(weight.level)', + 'asc(weight.position)' + ], + ranking: [ + 'words', + 'filters', + 'typo', + 'attribute', + 'proximity', + 'exact', + 'custom' + ], + highlightPreTag: '', + highlightPostTag: '', + minWordSizefor1Typo: 3, + minWordSizefor2Typos: 7, + allowTyposOnNumericTokens: false, + minProximity: 1, + ignorePlurals: true, + advancedSyntax: true, + attributeCriteriaComputedByMinProximity: true, + removeWordsIfNoResults: 'allOptional' + } + } +}) +``` diff --git a/docs/pt/reference/default-theme-sidebar.md b/docs/pt/reference/default-theme-sidebar.md new file mode 100644 index 00000000..0d8baf8d --- /dev/null +++ b/docs/pt/reference/default-theme-sidebar.md @@ -0,0 +1,182 @@ +# Barra Lateral {#sidebar} + +A barra lateral é o bloco principal de navegação da sua documentação. Você pode configurar o menu da barra lateral em [`themeConfig.sidebar`](./default-theme-config#sidebar). + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Guia', + items: [ + { text: 'Introdução', link: '/introduction' }, + { text: 'Iniciando', link: '/getting-started' }, + ... + ] + } + ] + } +} +``` + +## O Básico {#the-basics} + +A forma mais simples do menu da barra lateral é passar um único _array_ de links. O item do primeiro nível define a "seção" da barra lateral. Ele deve conter `text`, que é o título da seção, e `items` que são os próprios links de navegação. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Título da Seção A', + items: [ + { text: 'Item A', link: '/item-a' }, + { text: 'Item B', link: '/item-b' }, + ... + ] + }, + { + text: 'Título da Seção B', + items: [ + { text: 'Item C', link: '/item-c' }, + { text: 'Item D', link: '/item-d' }, + ... + ] + } + ] + } +} +``` + +Cada `link` deve especificar o caminho para o próprio arquivo começando com `/`. Se você adicionar uma barra no final do link, será mostrado o `index.md` do diretório correspondente. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Guia', + items: [ + // Isso mostra a página `/guide/index.md`. + { text: 'Introdução', link: '/guide/' } + ] + } + ] + } +} +``` + +Você pode aninhar ainda mais os itens da barra lateral até 6 níveis de profundidade contando a partir do nível raiz. Note que níveis mais profundos que 6 serão ignorados e não serão exibidos na barra lateral. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Nível 1', + items: [ + { + text: 'Nível 2', + items: [ + { + text: 'Nível 3', + items: [ + ... + ] + } + ] + } + ] + } + ] + } +} +``` + +## Múltiplas Barras Laterais {#multiple-sidebars} + +Você pode mostrar uma barra lateral diferente dependendo do caminho da página. Por exemplo, como mostrado neste site, você pode querer criar seções separadas de conteúdo em sua documentação, como a página "Guia" e a página "Configuração". + +Para fazer isso, primeiro organize suas páginas em diretórios para cada seção desejada: + +``` +. +├─ guide/ +│ ├─ index.md +│ ├─ one.md +│ └─ two.md +└─ config/ + ├─ index.md + ├─ three.md + └─ four.md +``` + +Em seguida, atualize sua configuração para definir sua barra lateral para cada seção. Desta vez, você deve passar um objeto em vez de um array. + +```js +export default { + themeConfig: { + sidebar: { + // Esta barra lateral é exibida quando um usuário + // está no diretório `guide`. + '/guide/': [ + { + text: 'Guia', + items: [ + { text: 'Índice', link: '/guide/' }, + { text: 'Um', link: '/guide/one' }, + { text: 'Dois', link: '/guide/two' } + ] + } + ], + + // Esta barra lateral é exibida quando um usuário + // está no diretório `config`. + '/config/': [ + { + text: 'Configuração', + items: [ + { text: 'Índice', link: '/config/' }, + { text: 'Três', link: '/config/three' }, + { text: 'Quatro', link: '/config/four' } + ] + } + ] + } + } +} +``` + +## Grupos Retráteis na Barra Lateral {#collapsible-sidebar-groups} + +Adicionando a opção `collapsed` ao grupo da barra lateral, ela mostra um botão para ocultar/mostrar cada seção. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Título da Seção A', + collapsed: false, + items: [...] + } + ] + } +} +``` + +Todas as seções são "abertas" por padrão. Se você deseja que elas estejam "fechadas" na carga inicial da página, defina a opção `collapsed` como `true`. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Título da Seção A', + collapsed: true, + items: [...] + } + ] + } +} +``` diff --git a/docs/pt/reference/default-theme-team-page.md b/docs/pt/reference/default-theme-team-page.md new file mode 100644 index 00000000..32a9db0d --- /dev/null +++ b/docs/pt/reference/default-theme-team-page.md @@ -0,0 +1,256 @@ + + +# Página da Equipe {#team-page} + +Se você quiser apresentar sua equipe, você pode usar componentes de equipe para construir a Página da Equipe. Existem duas maneiras de usar esses componentes. Uma é incorporá-lo na página de documento, e outra é criar uma Página de Equipe completa. + +## Mostrar membros da equipe em uma página {#show-team-members-in-a-page} + +Você pode usar o componente `` exposto em `vitepress/theme` para exibir uma lista de membros da equipe em qualquer página. + +```html + + +# Nosso time + +Diga olá à nossa equipe incrível. + + +``` + +O código acima exibirá um membro da equipe em um elemento tipo cartão. Ele deve exibir algo semelhante ao abaixo. + + + +O componente `` vem em 2 tamanhos diferentes, pequeno `small` e médio `medium`. Enquanto é uma questão de preferência, geralmente o tamanho `small` deve encaixar melhor quando usado na página de documento. Além disso, você pode adicionar mais propriedades a cada membro, como adicionar o botão "descrição" ou "patrocinador". Saiba mais sobre em [``](#vpteammembers). + +Incorporar membros da equipe na página de documento é bom para equipes de pequeno porte, onde ter uma página de equipe inteira dedicada pode ser demais, ou introduzir membros parciais como uma referência ao contexto da documentação. + +Se você tiver um grande número de membros, ou simplesmente quiser ter mais espaço para mostrar os membros da equipe, considere [criar uma página de equipe completa.](#create-a-full-team-page) + +## Criando uma página de equipe completa {#create-a-full-team-page} + +Em vez de adicionar membros da equipe à página de documento, você também pode criar uma Página de Equipe completa, da mesma forma que pode criar uma [Página Inicial](./default-theme-home-page) personalizada. + +Para criar uma página de equipe, primeiro crie um novo arquivo md. O nome do arquivo não importa, mas aqui vamos chamá-lo de `team.md`. Neste arquivo, defina a opção `layout: page` do frontmatter, e então você poderá compor a estrutura da sua página usando componentes `TeamPage`. + +```html +--- +layout: page +--- + + + + + + + + + +``` + +Ao criar uma página de equipe completa, lembre-se de agrupar todos os componentes com o componente ``. Este componente garantirá que todos os componentes aninhados relacionados à equipe obtenham a estrutura de layout adequada, como espaçamentos. + +O componente `` adiciona a seção de título da página. O título é `

`. Use os _slots_ `#title` e `#lead`para documentar sobre sua equipe. + +`` funciona da mesma forma que quando usado em uma página de documento. Ele exibirá a lista de membros. + +### Adicione seções para dividir os membros da equipe {#add-sections-to-divide-team-members} + +Você pode adicionar "seções" à página da equipe. Por exemplo, você pode ter diferentes tipos de membros da equipe, como membros da Equipe Principal e Parceiros da Comunidade. Você pode dividir esses membros em seções para explicar melhor os papéis de cada grupo. + +Para fazer isso, adicione o componente `` ao arquivo `team.md` que criamos anteriormente. + +```html +--- +layout: page +--- + + + + + + + + + + + + + + +``` + +O componente `` pode ter os _slots_ `#title` e `#lead` similar ao componente `VPTeamPageTitle`, e também o _slot_ `#members` para exibir os membros da equipe. + +Lembre-se de colocar o componente `` dentro do _slot_ `#members`. + +## `` + +O componente `` exibe uma determinada lista de membros. + +```html + +``` + +```ts +interface Props { + // Tamanho de cada membro. O padrão é `medium`. + size?: 'small' | 'medium' + + // Lista de membros a serem exibidos. + members: TeamMember[] +} + +interface TeamMember { + // Imagem avatar do membro + avatar: string + + // Nome do membro. + name: string + + // Título a ser mostrado abaixo do nome do membro. + // Ex.: Desenvolvedor, Engenheiro de Software, etc. + title?: string + + // Organização a qual o membro pertence. + org?: string + + // URL da organização. + orgLink?: string + + // Descrição do membro. + desc?: string + + // Links sociais, por exemplo, GitHub, Twitter, etc. + // Você pode passar o objeto de Links Sociais aqui. + // Veja: https://vitepress.dev/reference/default-theme-config.html#sociallinks + links?: SocialLink[] + + // URL da página de patrocinador do membro. + sponsor?: string + + // Texto para o link do patrocinador. O padrão é 'Sponsor'. + actionText?: string +} +``` + +## `` + +O componente raiz ao criar uma página de equipe completa. Ele aceita apenas um único _slot_. Ele estilizará todos os componentes relacionados à equipe passados. + +## `` + +Adiciona a seção "título" da página. Melhor usar logo no início sob ``. Aceita os _slots_ `#title` e `#lead`. + +```html + + + + + + +``` + +## `` + +Cria uma "seção" na página da equipe. Aceita os _slots_ `#title`, `#lead` e `#members`. Você pode adicionar quantas seções quiser dentro de ``. + +```html + + ... + + + + + + +``` diff --git a/docs/pt/reference/frontmatter-config.md b/docs/pt/reference/frontmatter-config.md new file mode 100644 index 00000000..41904d1a --- /dev/null +++ b/docs/pt/reference/frontmatter-config.md @@ -0,0 +1,221 @@ +--- +outline: deep +--- + +# Configuração Frontmatter {#frontmatter-config} + +Frontmatter permite a configuração baseada em páginas. Em cada arquivo markdown, você pode usar a configuração frontmatter para sobrepor opções de configuração a nível de site ou de tema. Além disso, existem opções de configuração que só podem ser definidas em frontmatter. + +Exemplo de uso: + +```md +--- +title: Documentação com VitePress +editLink: true +--- +``` + +Você pode acessar os dados do frontmatter através da variável global `$frontmatter` em expressões Vue: + +```md +{{ $frontmatter.title }} +``` + +## title + +- Tipo: `string` + +Título para a página. É o mesmo que [config.title](./site-config#title), e sobrepõe a configuração a nível de site. + +```yaml +--- +title: VitePress +--- +``` + +## titleTemplate + +- Tipo: `string | boolean` + +O sufixo para o título. É o mesmo que [config.titleTemplate](./site-config#titletemplate), e sobrepõe a configuração a nível de site. + +```yaml +--- +title: VitePress +titleTemplate: Gerador de site estático com Vite & Vue +--- +``` + +## description + +- Tipo: `string` + +Descrição para a página. É o mesmo que [config.description](./site-config#description), e sobrepõe a configuração a nível de site. + +```yaml +--- +description: VitePress +--- +``` + +## head + +- Tipo: `HeadConfig[]` + +Especifica tags head adicionais a serem injetadas na página atual. Elas serão acrescentadas após as tags head injetadas pela configuração a nível de site. + +```yaml +--- +head: + - - meta + - name: description + content: hello + - - meta + - name: keywords + content: super duper SEO +--- +``` + +```ts +type HeadConfig = + | [string, Record] + | [string, Record, string] +``` + +## Somente no Tema Padrão {#default-theme-only} + +As seguintes opções frontmatter são aplicáveis apenas ao usar o tema padrão. + +### layout + +- Tipo: `doc | home | page` +- Padrão: `doc` + +Determina o layout da página. + +- `doc` - Aplica estilos de documentação padrão ao conteúdo markdown. +- `home` - Layout especial para a "Página Inicial". Você pode adicionar opções extras como `hero` e `features` para criar rapidamente uma bela página inicial. +- `page` - Comporta-se de maneira semelhante a `doc`, mas não aplica estilos ao conteúdo. Útil quando você deseja criar uma página totalmente personalizada. + +```yaml +--- +layout: doc +--- +``` + +### hero + +Define o conteúdo da seção _hero_ na página inicial quando `layout` está definido como `home`. Mais detalhes em [Tema Padrão: Página Inicial](./default-theme-home-page). + +### features + +Define os itens a serem exibidos na seção de funcionalidades quando `layout` está definido como `home`. Mais detalhes em [Tema Padrão: Página Inicial](./default-theme-home-page). + +### navbar + +- Tipo: `boolean` +- Padrão: `true` + +Se deve exibir a [barra de navegação](./default-theme-nav). + +```yaml +--- +navbar: false +--- +``` + +### sidebar + +- Tipo: `boolean` +- Padrão: `true` + +Se deve exibir a [barra lateral](./default-theme-sidebar). + +```yaml +--- +sidebar: false +--- +``` + +### aside + +- Tipo: `boolean | 'left'` +- Padrão: `true` + +Define a localização do componente aside no layout `doc`. + +Configurar este valor como `false` impede a apresentação do elemento aside.\ +Configurar este valor como `true` apresenta o aside à direita.\ +Configurar este valor como `'left'` apresenta o aside à esquerda. + +```yaml +--- +aside: false +--- +``` + +### outline + +- Tipo: `number | [number, number] | 'deep' | false` +- Padrão: `2` + +Os níveis do cabeçalho no _outline_ a serem exibidos para a página. É o mesmo que [config.themeConfig.outline.level](./default-theme-config#outline), e sobrepõe o valor definido na configuração no nível do site. + +### lastUpdated + +- Tipo: `boolean | Date` +- Padrão: `true` + +Se deve mostrar o texto de [última atualização](./default-theme-last-updated) no rodapé da página atual. Se uma data e hora específica forem especificadas, ela será exibida em vez do último horário de modificação do git. + +```yaml +--- +lastUpdated: false +--- +``` + +### editLink + +- Tipo: `boolean` +- Padrão: `true` + +Se deve exibir o [link de edição](./default-theme-edit-link) no rodapé da página atual. + +```yaml +--- +editLink: false +--- +``` + +### footer + +- Tipo: `boolean` +- Padrão: `true` + +Se deve exibir o [rodapé](./default-theme-footer). + +```yaml +--- +footer: false +--- +``` + +### pageClass + +- Tipo: `string` + +Adiciona um nome de classe extra a uma página específica. + +```yaml +--- +pageClass: custom-page-class +--- +``` + +Em seguida, você pode personalizar os estilos desta página específica no arquivo `.vitepress/theme/custom.css`: + +```css +.custom-page-class { + /* estilos específicos da página */ +} +``` diff --git a/docs/pt/reference/runtime-api.md b/docs/pt/reference/runtime-api.md new file mode 100644 index 00000000..ed6476ac --- /dev/null +++ b/docs/pt/reference/runtime-api.md @@ -0,0 +1,165 @@ +# API em Tempo de Execução {#runtime-api} + +VitePress oferece várias APIs embutidas para permitir o acesso aos dados da aplicação. VitePress vem também com alguns componentes embutidos que podem ser usados globalmente. + +Os métodos auxiliares são importáveis globais de `vitepress` e geralmente são usados em componentes Vue de temas personalizados. No entanto, eles também podem ser usados dentro de páginas `.md` porque os arquivos markdown são compilados em [Componentes de Arquivo Único Vue (SFC)](https://vuejs.org/guide/scaling-up/sfc.html). + +Métodos que começam com `use*` indicam que é uma função da [API de Composição Vue 3](https://vuejs.org/guide/introduction.html#composition-api) ("Composable") que só pode ser usada dentro de `setup()` ou ` + + +``` + +## `useRoute` + +Retorna o objeto de rota atual com o seguinte tipo: + +```ts +interface Route { + path: string + data: PageData + component: Component | null +} +``` + +## `useRouter` + +Retorna a instância do roteador VitePress para que você possa navegar programaticamente para outra página. + +```ts +interface Router { + /** + * Rota atual. + */ + route: Route + /** + * Navegar para uma nova URL. + */ + go: (to?: string) => Promise + /** + * Chamado antes da mudança de rota. Retorne `false` para cancelar a navegação. + */ + onBeforeRouteChange?: (to: string) => Awaitable + /** + * Chamado antes do carregamento do componente da página (depois que o estado do histórico é + * atualizado). Retorne `false` para cancelar a navegação. + */ + onBeforePageLoad?: (to: string) => Awaitable + /** + * Chamado após a mudança de rota. + */ + onAfterRouteChange?: (to: string) => Awaitable +} +``` + +## `withBase` + +- **Tipo**: `(path: string) => string` + +Anexa o [`base`](./site-config#base) configurado a um caminho de URL fornecido. Veja também [Base URL](../guide/asset-handling#base-url). + +## `` + +O componente `` exibe o conteúdo markdown renderizado. Útil [ao criar seu próprio tema](../guide/custom-theme). + +```vue + +``` + +## `` + +O componente `` revela seu _slot_ apenas no lado do cliente. + +Como as aplicações VitePress são interpretadas no lado do servidor em Node.js ao gerar builds estáticos, qualquer uso do Vue deve seguir os requisitos de código universal. Em resumo, certifique-se de acessar apenas APIs do Navegador / DOM em ganchos `beforeMount` ou `mounted`. + +Se você estiver usando ou demonstrando componentes que não são compatíveis com SSR (por exemplo, contêm diretivas personalizadas), você pode envolvê-los dentro do componente `ClientOnly`. + +```vue-html + + + +``` + +- Relacionado: [Compatibilidade SSR](../guide/ssr-compat) + +## `$frontmatter` + +Acesse diretamente os dados [frontmatter](../guide/frontmatter) da página atual em expressões Vue. + +```md +--- +title: Olá +--- + +# {{ $frontmatter.title }} +``` + +## `$params` + +Acesse diretamente os [parâmetros de rota dinâmica](../guide/routing#dynamic-routes) da página atual em expressões Vue. + +```md +- nome do pacote: {{ $params.pkg }} +- versão: {{ $params.version }} +``` diff --git a/docs/pt/reference/site-config.md b/docs/pt/reference/site-config.md new file mode 100644 index 00000000..09281901 --- /dev/null +++ b/docs/pt/reference/site-config.md @@ -0,0 +1,705 @@ +--- +outline: deep +--- + +# Configuração do Site {#site-config} + +A configuração do site é onde você pode definir as configurações globais do site. As opções de configuração do aplicativo definem configurações que se aplicam a todos os sites VitePress, independentemente do tema que estão usando. Por exemplo, o diretório base ou o título do site. + +## Visão geral {#overview} + +### Resolução de Configuração {#config-resolution} + +O arquivo de configuração é sempre resolvido a partir de `/.vitepress/config.[ext]`, onde `` é a [raiz do projeto](../guide/routing#root-and-source-directory) VitePress e `[ext]` é uma das extensões de arquivo suportadas. O TypeScript é suportado de fábrica. As extensões suportadas incluem `.js`, `.ts`, `.mjs` e `.mts`. + +Recomenda-se usar a sintaxe de módulos ES nos arquivos de configuração. O arquivo de configuração deve exportar por padrão um objeto: + +```ts +export default { + // opções de configuração de nível da aplicação + lang: 'pt-BR', + title: 'VitePress', + description: 'Gerador de site estático Vite & Vue.', + ... +} +``` + +:::details Configuração Dinâmica (Assíncrona) + +Se você precisar gerar dinamicamente a configuração, também pode exportar por padrão uma função. Por exemplo: + +```ts +import { defineConfig } from 'vitepress' + +export default async () => { + const posts = await (await fetch('https://my-cms.com/blog-posts')).json() + + return defineConfig({ + // opções de configuração de nível da aplicação + lang: 'pt-BR', + title: 'VitePress', + description: 'Gerador de site estático Vite & Vue.', + + // opções de configuração de nível do tema + themeConfig: { + sidebar: [ + ...posts.map((post) => ({ + text: post.name, + link: `/posts/${post.name}` + })) + ] + } + }) +} +``` + +Você também pode usar o `await` no nível superior. Como: + +```ts +import { defineConfig } from 'vitepress' + +const posts = await (await fetch('https://my-cms.com/blog-posts')).json() + +export default defineConfig({ + // opções de configuração de nível da aplicação + lang: 'pt-BR', + title: 'VitePress', + description: 'Gerador de site estático Vite & Vue.', + + // opções de configuração de nível do tema + themeConfig: { + sidebar: [ + ...posts.map((post) => ({ + text: post.name, + link: `/posts/${post.name}` + })) + ] + } +}) +``` + +::: + +### Configuração Intellisense {#config-intellisense} + +Usar o auxiliar `defineConfig` fornecerá Intellisense alimentado por TypeScript para as opções de configuração. Supondo que seu IDE o suporte, isso deve funcionar tanto em JavaScript quanto em TypeScript. + +```js +import { defineConfig } from 'vitepress' + +export default defineConfig({ + // ... +}) +``` + +### Configuração de Tema Tipada {#typed-theme-config} + +Por padrão, o auxiliar `defineConfig` espera o tipo de configuração de tema do tema padrão: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + // O tipo é `DefaultTheme.Config` + } +}) +``` + +Se você estiver usando um tema personalizado e desejar verificações de tipo para a configuração do tema, será necessário usar `defineConfigWithTheme` em vez disso, e passar o tipo de configuração para o seu tema personalizado por meio de um argumento genérico: + +```ts +import { defineConfigWithTheme } from 'vitepress' +import type { ThemeConfig } from 'your-theme' + +export default defineConfigWithTheme({ + themeConfig: { + // O tipo é `ThemeConfig` + } +}) +``` + +### Configuração Vite, Vue & Markdown + +- **Vite** + + Você pode configurar a instância subjacente do Vite usando a opção [vite](#vite) em sua configuração VitePress. Não é necessário criar um arquivo de configuração Vite separado. + +- **Vue** + + VitePress já inclui o plugin Vue oficial para Vite ([@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue)). Você pode configurar suas opções usando a opção [vue](#vue) em sua configuração VitePress. + +- **Markdown** + + Você pode configurar a instância subjacente de [Markdown-It](https://github.com/markdown-it/markdown-it) usando a opção [markdown](#markdown) em sua configuração VitePress. + +## Metadados do Site {#site-metadata} + +### title + +- Tipo: `string` +- Padrão: `VitePress` +- Pode ser substituído por página via [frontmatter](./frontmatter-config#title) + +Título do site. Ao usar o tema padrão, isso será exibido na barra de navegação. + +Ele também será usado como o sufixo padrão para todos os títulos individuais das páginas, a menos que [`titleTemplate`](#titletemplate) seja definido. O título final de uma página individual será o conteúdo textual do seu primeiro cabeçalho `

`, combinado com o título global como sufixo. Por exemplo, com a seguinte configuração e conteúdo da página: + +```ts +export default { + title: 'Meu Site Incrível' +} +``` + +```md +# Olá +``` + +O título da página será `Olá | Meu Site Incrível`. + +### titleTemplate + +- Tipo: `string | boolean` +- Pode ser substituído por página via [frontmatter](./frontmatter-config#titletemplate) + +Permite personalizar o sufixo do título de cada página ou o título inteiro. Por exemplo: + +```ts +export default { + title: 'Meu Site Incrível', + titleTemplate: 'Sufixo Personalizado' +} +``` + +```md +# Olá +``` + +O título da página será `Olá | Sufixo Personalizado`. + +Para personalizar completamente como o título deve ser renderizado, você pode usar o símbolo `:title` em `titleTemplate`: + +```ts +export default { + titleTemplate: ':title - Sufixo Personalizado' +} +``` + +Aqui, `:title` será substituído pelo texto inferido do primeiro cabeçalho `

` da página. O título do exemplo anterior da página será `Olá - Sufixo Personalizado`. + +A opção pode ser definida como `false` para desativar sufixos de título. + +### description + +- Tipo: `string` +- Padrão: `Um site VitePress` +- Pode ser substituído por página via [frontmatter](./frontmatter-config#descrição) + +Descrição para o site. Isso será apresentado como uma tag `` na página HTML. + +```ts +export default { + descrição: 'Um site VitePress' +} +``` + +### head + +- Tipo: `HeadConfig[]` +- Padrão: `[]` +- Pode ser acrescentado por página via [frontmatter](./frontmatter-config#head) + +Elementos adicionais para adicionar na tag `` da página HTML. As tags adicionadas pelo usuário são mostradas antes da tag `head` de fechamento, após as tags VitePress. + +```ts +type HeadConfig = + | [string, Record] + | [string, Record, string] +``` + +#### Exemplo: Adicionando um favicon {#example-adding-a-favicon} + +```ts +export default { + cabeça: [['link', { rel: 'icon', href: '/favicon.ico' }]] +} // coloque o favicon.ico no diretório public, se a base estiver definida, use /base/favicon.ico + +/* Mostraria: + +*/ +``` + +#### Exemplo: Adicionando Fontes do Google {#example-adding-google-fonts} + +```ts +export default { + head: [ + [ + 'link', + { rel: 'preconnect', href: 'https://fonts.googleapis.com' } + ], + [ + 'link', + { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: '' } + ], + [ + 'link', + { href: 'https://fonts.googleapis.com/css2?family=Roboto&display=swap', rel: 'stylesheet' } + ] + ] +} + +/* Mostraria: + + + +*/ +``` + +#### Exemplo: Registrando um _service worker_ {#example-registering-a-service-worker} + +```ts +export default { + head: [ + [ + 'script', + { id: 'register-sw' }, + `;(() => { + if ('serviceWorker' in navigator) { + navigator.serviceWorker.register('/sw.js') + } + })()` + ] + ] +} + +/* Mostraria: + +*/ +``` + +#### Exemplo: Usando o Google Analytics {#example-using-google-analytics} + +```ts +export default { + head: [ + [ + 'script', + { async: '', src: 'https://www.googletagmanager.com/gtag/js?id=TAG_ID' } + ], + [ + 'script', + {}, + `window.dataLayer = window.dataLayer || []; + function gtag(){dataLayer.push(arguments);} + gtag('js', new Date()); + gtag('config', 'TAG_ID');` + ] + ] +} + +/* Mostraria: + + +*/ +``` + +### lang + +- Tipo: `string` +- Padrão: `en-US` + +O atributo de idioma para o site. Isso será mostrado como uma tag `` na página HTML. + +```ts +export default { + lang: 'en-US' +} +``` + +### base + +- Tipo: `string` +- Padrão: `/` + +A URL base em que o site será implantado. Você precisará definir isso se planeja implantar seu site em um subdiretório, por exemplo, no GitHub pages. Se você planeja implantar seu site em `https://foo.github.io/bar/` então você deve definir a base como `'/bar/'`. Deve sempre começar e terminar com uma barra. + +A base é automaticamente adicionada a todos as URLs que começam com / em outras opções, então você só precisa especificá-la uma vez. + +```ts +export default { + base: '/base/' +} +``` + +## Roteamento {#routing} + +### cleanUrls + +- Tipo: `boolean` +- Padrão: `false` + +Quando definido como `true`, VitePress removerá o `.html` no final dos URLs. Veja também [Gerando URL Limpa](../guide/routing#generating-clean-url). + +::: warning Suporte do Servidor Necessário +Ativar isso pode exigir configurações adicionais em sua plataforma de hospedagem. Para funcionar, seu servidor deve ser capaz de servir `/foo.html` ao visitar `/foo` **sem redirecionamento**. +::: + +### rewrites + +- Tipo: `Record` + +Define mapeamentos personalizados de diretório <-> URL. Veja [Roteamento: Reescrever Rotas](../guide/routing#route-rewrites) para mais detalhes. + +```ts +export default { + rewrites: { + 'source/:page': 'destination/:page' + } +} +``` + +## Construção {#build} + +### srcDir + +- Tipo: `string` +- Padrão: `.` + +O diretório onde suas páginas de markdown são armazenadas, relativo à raiz do projeto. Veja também [Diretório Raiz e Fonte](../guide/routing#root-and-source-directory). + +```ts +export default { + srcDir: './src' +} +``` + +### srcExclude + +- Tipo: `string` +- Padrão: `undefined` + +Um [padrão glob](https://github.com/mrmlnc/fast-glob#pattern-syntax) para corresponder a arquivos markdown que devem ser excluídos como conteúdo fonte. + +```ts +export default { + srcExclude: ['**/README.md', '**/TODO.md'] +} +``` + +### outDir + +- Tipo: `string` +- Padrão: `./.vitepress/dist` + +A localização da saída da compilação para o site, relativa à [raiz do projeto](../guide/routing#root-and-source-directory). + +```ts +export default { + outDir: '../public' +} +``` + +### assetsDir + +- Tipo: `string` +- Padrão: `assets` + +Especifica o diretório para aninhar ativos gerados. O caminho deve estar dentro de [`outDir`](#outdir) e é resolvido em relação a ele. + +```ts +export default { + assetsDir: 'static' +} +``` + +### cacheDir + +- Tipo: `string` +- Padrão: `./.vitepress/cache` + +O diretório para arquivos de cache, relativo à [raiz do projeto](../guide/routing#root-and-source-directory). Veja também: [cacheDir](https://vitejs.dev/config/shared-options.html#cachedir). + +```ts +export default { + cacheDir: './.vitepress/.vite' +} +``` + +### ignoreDeadLinks + +- Tipo: `boolean | 'localhostLinks' | (string | RegExp | ((link: string) => boolean))[]` +- Padrão: `false` + +Quando definido como `true`, VitePress não falhará na compilação devido a links quebrados. + +Quando definido como `'localhostLinks'`, a compilação falhará em links quebrados, mas não verificará links `localhost`. + +```ts +export default { + ignoreDeadLinks: true +} +``` + +Também pode ser um _array_ de uma exata URL em string, padrões regex, ou funções de filtro personalizadas. + +```ts +export default { + ignoreDeadLinks: [ + // ignora URL exata "/playground" + '/playground', + // ignora todos os links localhost + /^https?:\/\/localhost/, + // ignora todos os links incluindo "/repl/"" + /\/repl\//, + // função personalizada, ignora todos os links incluindo "ignore" + (url) => { + return url.toLowerCase().includes('ignore') + } + ] +} +``` + +### mpa + +- Tipo: `boolean` +- Padrão: `false` + +Quando definido como `true`, a aplicação em produção será compilada no [Modo MPA](../guide/mpa-mode). O modo MPA envia 0kb de JavaScript por padrão, às custas de desabilitar a navegação no lado do cliente e exigir permissão explícita para interatividade. + +## Tematização {#theming} + +### appearance + +- Tipo: `boolean | 'dark' | 'force-dark' | import('@vueuse/core').UseDarkOptions` +- Padrão: `true` + +Se habilitar o modo escuro (adicionando a classe `.dark` ao elemento ``). + +- Se a opção estiver definida como `true` o tema padrão é determinado pelo esquema de cores preferido do usuário. +- Se a opção estiver definida como `dark` o tema é escuro por padrão, a menos que o usuário mude manualmente. +- Se a opção estiver definida como `false` os usuários não poderão mudar o tema. + +Esta opção injeta um script em linha que restaura as configurações dos usuários do armazenamento local (_local storage_) usando a chave `vitepress-theme-appearance`. Isso garante que a classe `.dark` seja aplicada antes de a página ser mostrada para evitar oscilações. + +`appearance.initialValue` só pode ser `'dark' | undefined`. Refs ou getters não são suportados. + +### lastUpdated + +- Tipo: `boolean` +- Padrão: `false` + +Para obter o selo de tempo da última atualização para cada página usando o Git. O selo de data será incluído nos dados de cada página, acessíveis via [`useData`](./runtime-api#usedata). + +Ao usar o tema padrão, habilitar esta opção exibirá o horário da última atualização de cada página. Você pode personalizar o texto via opção [`themeConfig.lastUpdatedText`](./default-theme-config#lastupdatedtext). + +## Personalização {#customization} + +### markdown + +- Tipo: `MarkdownOption` + +Configure as opções do processador Markdown. VitePress usa [Markdown-it](https://github.com/markdown-it/markdown-it) como processador e [Shiki](https://github.com/shikijs/shiki) para destacar sintaxe de linguagem. Dentro desta opção, você pode passar várias opções Markdown relacionadas para atender às suas necessidades. + +```js +export default { + markdown: {...} +} +``` + +Verifique a [declaração de tipo e jsdocs](https://github.com/vuejs/vitepress/blob/main/src/node/markdown/markdown.ts) para todas as opções disponíveis. + +### vite + +- Tipo: `import('vite').UserConfig` + +Passe a [Configuração Vite](https://vitejs.dev/config/) crua para o servidor interno / empacotador Vite. + +```js +export default { + vite: { + // Opções de configuração Vite + } +} +``` + +### vue + +- Tipo: `import('@vitejs/plugin-vue').Options` + +Passe as opções [`@vitejs/plugin-vue`](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue#options) cruas para a instância interna do plugin. + +```js +export default { + vue: { + // Opções @vitejs/plugin-vue + } +} +``` + +## Ganchos de Compilação {#build-hooks} + +Os ganchos de compilação VitePress permitem adicionar novas funcionalidades ao seu site: + +- Sitemap +- Indexação de Pesquisa +- PWA +- _Teleports_ + +## buildEnd +- Tipo: `(siteConfig: SiteConfig) => Awaitable` +`buildEnd` é um gancho de compilação CLI (Interface de Linha de Comando), ele será executado após a conclusão da compilação (SSG), mas antes que o processo VitePress CLI termine. + +```ts +export default { + async buildEnd(siteConfig) { + // ... + } +} +``` + +## postRender +- Tipo: `(context: SSGContext) => Awaitable` +- `postRender` é um gancho de compilação, chamado quando a interpretação SSG é concluída. Ele permitirá que você manipule o conteúdo de _teleports_ durante a geração de site estático. + + ```ts + export default { + async postRender(context) { + // ... + } + } + ``` + + ```ts + interface SSGContext { + content: string + teleports?: Record + [key: string]: any + } + ``` + +## transformHead +- Tipo: `(context: TransformContext) => Awaitable` + +`transformHead` é um gancho de compilação para transformar o cabeçalho antes de gerar cada página. Isso permite adicionar entradas no cabeçalho que não podem ser adicionadas estaticamente à configuração VitePress. Você só precisa retornar entradas extras, que serão mescladas automaticamente com as existentes. + +:::warning +Não faça mutações em qualquer item dentro de `context`. +::: + +```ts +export default { + async transformHead(context) { + // ... + } +} +``` + +```ts +interface TransformContext { + page: string // e.g. index.md (relativo a srcDir) + assets: string[] // todos os ativos não-js/css com URL pública completamente resolvida + siteConfig: SiteConfig + siteData: SiteData + pageData: PageData + title: string + description: string + head: HeadConfig[] + content: string +} +``` + +Note que este gancho só é chamado ao gerar o site estaticamente. Não é chamado durante o desenvolvimento. Se você precisar adicionar entradas de cabeçalho dinâmicas durante o desenvolvimento, pode usar o gancho [`transformPageData`](#transformpagedata) em seu lugar. + + ```ts + export default { + transformPageData(pageData) { + pageData.frontmatter.head ??= [] + pageData.frontmatter.head.push([ + 'meta', + { + name: 'og:title', + content: + pageData.frontmatter.layout === 'home' + ? `VitePress` + : `${pageData.title} | VitePress` + } + ]) + } + } + ``` + +#### Exemplo: Adicionar URL canônica `` {#example-adding-a-canonical-url-link} + +```ts +export default { + transformPageData(pageData) { + const canonicalUrl = `https://example.com/${pageData.relativePath}` + .replace(/index\.md$/, '') + .replace(/\.md$/, '.html') + + pageData.frontmatter.head ??= [] + pageData.frontmatter.head.push([ + 'link', + { rel: 'canonical', href: canonicalUrl } + ]) + } +} +``` + +### transformHtml +- Tipo: `(code: string, id: string, context: TransformContext) => Awaitable` +`transformHtml` é um gancho de compilação para transformar o conteúdo de cada página antes de salvá-lo no disco. + +:::warning +Não faça mutações em qualquer item dentro de `context`. Além disso, modificar o conteúdo HTML pode causar problemas de hidratação em tempo de execução. +::: + +```ts +export default { + async transformHtml(code, id, context) { + // ... + } +} +``` + +### transformPageData +- Tipo: `(pageData: PageData, context: TransformPageContext) => Awaitable | { [key: string]: any } | void>` + +`transformPageData` é um gancho para transformar os dados de cada página. Você pode fazer mutações diretamente em `pageData` ou retornar valores alterados que serão mesclados nos dados da página. + +:::warning +Não faça mutações em qualquer item dentro de `context` e tenha cuidado pois isso pode impactar no desempenho do servidor de desenvolvimento, especialmente se você tiver algumas solicitações de rede ou computações pesadas (como gerar imagens) no gancho. Você pode verificar `process.env.NODE_ENV === 'production'` para lógica condicional. +::: + +```ts +export default { + async transformPageData(pageData, { siteConfig }) { + pageData.contributors = await getPageContributors(pageData.relativePath) + } + + // ou retorne dados a serem mesclados + async transformPageData(pageData, { siteConfig }) { + return { + contributors: await getPageContributors(pageData.relativePath) + } + } +} +``` + +```ts +interface TransformPageContext { + siteConfig: SiteConfig +} +``` diff --git a/docs/public/_headers b/docs/public/_headers deleted file mode 100644 index f7fa3afc..00000000 --- a/docs/public/_headers +++ /dev/null @@ -1,3 +0,0 @@ -/assets/* - cache-control: max-age=31536000 - cache-control: immutable \ No newline at end of file diff --git a/docs/public/_redirects b/docs/public/_redirects deleted file mode 100644 index 45c59465..00000000 --- a/docs/public/_redirects +++ /dev/null @@ -1 +0,0 @@ -https://vitepress.vuejs.org/* https://vitepress.dev/:splat 301! diff --git a/docs/public/appearance-toggle-transition.webp b/docs/public/appearance-toggle-transition.webp new file mode 100644 index 00000000..7c2a8d7a Binary files /dev/null and b/docs/public/appearance-toggle-transition.webp differ diff --git a/docs/public/pure.html b/docs/public/pure.html index 0d0ecb5a..91fd6630 100644 --- a/docs/public/pure.html +++ b/docs/public/pure.html @@ -1,4 +1,4 @@ - + Plain HTML page | VitePress diff --git a/docs/public/vitepress-logo-large.svg b/docs/public/vitepress-logo-large.svg new file mode 120000 index 00000000..59e331aa --- /dev/null +++ b/docs/public/vitepress-logo-large.svg @@ -0,0 +1 @@ +../../art/vitepress-logo.svg \ No newline at end of file diff --git a/docs/public/vitepress-logo-large.webp b/docs/public/vitepress-logo-large.webp new file mode 100644 index 00000000..2e47b155 Binary files /dev/null and b/docs/public/vitepress-logo-large.webp differ diff --git a/docs/public/vitepress-logo-mini.png b/docs/public/vitepress-logo-mini.png new file mode 100644 index 00000000..db8521e2 Binary files /dev/null and b/docs/public/vitepress-logo-mini.png differ diff --git a/docs/public/vitepress-logo-mini.svg b/docs/public/vitepress-logo-mini.svg new file mode 120000 index 00000000..f7c9b3af --- /dev/null +++ b/docs/public/vitepress-logo-mini.svg @@ -0,0 +1 @@ +../../art/vitepress-logo-mini.svg \ No newline at end of file diff --git a/docs/public/vitepress-og.jpg b/docs/public/vitepress-og.jpg new file mode 100644 index 00000000..ea97e47f Binary files /dev/null and b/docs/public/vitepress-og.jpg differ diff --git a/docs/reference/cli.md b/docs/reference/cli.md deleted file mode 100644 index 0df6da0e..00000000 --- a/docs/reference/cli.md +++ /dev/null @@ -1,74 +0,0 @@ -# Command Line Interface - -## `vitepress dev` - -Start VitePress dev server using designated directory as root. Defaults to current directory. The `dev` command can also be omitted when running in current directory. - -### Usage - -```sh -# start in current directory, omitting `dev` -vitepress - -# start in sub directory -vitepress dev [root] -``` - -### Options - -| Option | Description | -| - | - | -| `--open [path]` | Open browser on startup (`boolean \| string`) | -| `--port ` | Specify port (`number`) | -| `--base ` | Public base path (default: `/`) (`string`) | -| `--cors` | Enable CORS | -| `--strictPort` | Exit if specified port is already in use (`boolean`) | -| `--force` | Force the optimizer to ignore the cache and re-bundle (`boolean`) | - -## `vitepress build` - -Build the VitePress site for production. - -### Usage - -```sh -vitepress build [root] -``` - -### Options - -| Option | Description | -| - | - | -| `--mpa` (experimental) | Build in [MPA mode](../guide/mpa-mode) without client-side hydration (`boolean`) | -| `--base ` | Public base path (default: `/`) (`string`) | -| `--target ` | Transpile target (default: `"modules"`) (`string`) | -| `--outDir ` | Output directory (default: `.vitepress/dist`) (`string`) | -| `--minify [minifier]` | Enable/disable minification, or specify minifier to use (default: `"esbuild"`) (`boolean \| "terser" \| "esbuild"`) | -| `--assetsInlineLimit ` | Static asset base64 inline threshold in bytes (default: `4096`) (`number`) | - -## `vitepress preview` - -Locally preview the production build. - -### Usage - -```sh -vitepress preview [root] -``` - -### Options - -| Option | Description | -| - | - | -| `--base ` | Public base path (default: `/`) (`string`) | -| `--port ` | Specify port (`number`) | - -## `vitepress init` - -Start the [Setup Wizard](../guide/getting-started#setup-wizard) in current directory. - -### Usage - -```sh -vitepress init -``` diff --git a/docs/reference/default-theme-search.md b/docs/reference/default-theme-search.md deleted file mode 100644 index 6f5925ca..00000000 --- a/docs/reference/default-theme-search.md +++ /dev/null @@ -1,153 +0,0 @@ -# Search - -## Local Search - -VitePress supports fuzzy full-text search using a in-browser index thanks to [minisearch](https://github.com/lucaong/minisearch/). To enable this feature, simply set the `themeConfig.search.provider` option to `'local'` in your `.vitepress/config.ts` file: - -```ts -import { defineConfig } from 'vitepress' - -export default defineConfig({ - themeConfig: { - search: { - provider: 'local' - } - } -}) -``` - -Example result: - -![screenshot of the search modal](/search.png) - -Alternatively, you can use [Algolia DocSearch](#algolia-search) or some community plugins like or . - -### i18n {#local-search-i18n} - -You can use a config like this to use multilingual search: - -```ts -import { defineConfig } from 'vitepress' - -export default defineConfig({ - themeConfig: { - search: { - provider: 'local', - options: { - locales: { - zh: { - translations: { - button: { - buttonText: '搜索文档', - buttonAriaLabel: '搜索文档' - }, - modal: { - noResultsText: '无法找到相关结果', - resetButtonTitle: '清除查询条件', - footer: { - selectText: '选择', - navigateText: '切换' - } - } - } - } - } - } - } - } -}) -``` - -## Algolia Search - -VitePress supports searching your docs site using [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch). Refer their getting started guide. In your `.vitepress/config.ts` you'll need to provide at least the following to make it work: - -```ts -import { defineConfig } from 'vitepress' - -export default defineConfig({ - themeConfig: { - search: { - provider: 'algolia', - options: { - appId: '...', - apiKey: '...', - indexName: '...' - } - } - } -}) -``` - -### i18n {#algolia-search-i18n} - -You can use a config like this to use multilingual search: - -```ts -import { defineConfig } from 'vitepress' - -export default defineConfig({ - themeConfig: { - search: { - provider: 'algolia', - options: { - appId: '...', - apiKey: '...', - indexName: '...', - locales: { - zh: { - placeholder: '搜索文档', - translations: { - button: { - buttonText: '搜索文档', - buttonAriaLabel: '搜索文档' - }, - modal: { - searchBox: { - resetButtonTitle: '清除查询条件', - resetButtonAriaLabel: '清除查询条件', - cancelButtonText: '取消', - cancelButtonAriaLabel: '取消' - }, - startScreen: { - recentSearchesTitle: '搜索历史', - noRecentSearchesText: '没有搜索历史', - saveRecentSearchButtonTitle: '保存至搜索历史', - removeRecentSearchButtonTitle: '从搜索历史中移除', - favoriteSearchesTitle: '收藏', - removeFavoriteSearchButtonTitle: '从收藏中移除' - }, - errorScreen: { - titleText: '无法获取结果', - helpText: '你可能需要检查你的网络连接' - }, - footer: { - selectText: '选择', - navigateText: '切换', - closeText: '关闭', - searchByText: '搜索提供者' - }, - noResultsScreen: { - noResultsText: '无法找到相关结果', - suggestedQueryText: '你可以尝试查询', - reportMissingResultsText: '你认为该查询应该有结果?', - reportMissingResultsLinkText: '点击反馈' - } - } - } - } - } - } - } - } -}) -``` - -[These options](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts) can be overridden. Refer official Algolia docs to learn more about them. - - diff --git a/docs/ru/components/ModalDemo.vue b/docs/ru/components/ModalDemo.vue new file mode 100644 index 00000000..85c9dec1 --- /dev/null +++ b/docs/ru/components/ModalDemo.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/docs/ru/config.ts b/docs/ru/config.ts new file mode 100644 index 00000000..739cfbf2 --- /dev/null +++ b/docs/ru/config.ts @@ -0,0 +1,219 @@ +import { createRequire } from 'module' +import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' + +const require = createRequire(import.meta.url) +const pkg = require('vitepress/package.json') + +export default defineAdditionalConfig({ + lang: 'ru-RU', + description: 'Генератор статических сайтов на основе Vite и Vue.', + + themeConfig: { + nav: nav(), + + search: { options: searchOptions() }, + + sidebar: { + '/ru/guide/': { base: '/ru/guide/', items: sidebarGuide() }, + '/ru/reference/': { base: '/ru/reference/', items: sidebarReference() } + }, + + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + text: 'Редактировать страницу' + }, + + footer: { + message: 'Опубликовано под лицензией MIT.', + copyright: '© 2019 – настоящее время, Эван Ю' + }, + + outline: { label: 'Содержание страницы' }, + + docFooter: { + prev: 'Предыдущая страница', + next: 'Следующая страница' + }, + + lastUpdated: { + text: 'Обновлено' + }, + + notFound: { + title: 'СТРАНИЦА НЕ НАЙДЕНА', + quote: + 'Но если ты не изменишь направление и продолжишь искать, ты можешь оказаться там, куда направляешься.', + linkLabel: 'перейти на главную', + linkText: 'Отведи меня домой' + }, + + darkModeSwitchLabel: 'Оформление', + lightModeSwitchTitle: 'Переключить на светлую тему', + darkModeSwitchTitle: 'Переключить на тёмную тему', + sidebarMenuLabel: 'Меню', + returnToTopLabel: 'Вернуться к началу', + langMenuLabel: 'Изменить язык', + skipToContentLabel: 'Перейти к содержимому' + } +}) + +function nav(): DefaultTheme.NavItem[] { + return [ + { + text: 'Руководство', + link: '/ru/guide/what-is-vitepress', + activeMatch: '/ru/guide/' + }, + { + text: 'Справочник', + link: '/ru/reference/site-config', + activeMatch: '/ru/reference/' + }, + { + text: pkg.version, + items: [ + { + text: 'Изменения', + link: 'https://github.com/vuejs/vitepress/blob/main/CHANGELOG.md' + }, + { + text: 'Вклад', + link: 'https://github.com/vuejs/vitepress/blob/main/.github/contributing.md' + } + ] + } + ] +} + +function sidebarGuide(): DefaultTheme.SidebarItem[] { + return [ + { + text: 'Введение', + collapsed: false, + items: [ + { text: 'Что такое VitePress?', link: 'what-is-vitepress' }, + { text: 'Первые шаги', link: 'getting-started' }, + { text: 'Маршрутизация', link: 'routing' }, + { text: 'Развёртывание', link: 'deploy' } + ] + }, + { + text: 'Написание', + collapsed: false, + items: [ + { text: 'Расширения Markdown', link: 'markdown' }, + { text: 'Обработка ресурсов', link: 'asset-handling' }, + { text: 'Метаданные', link: 'frontmatter' }, + { text: 'Использование Vue в Markdown', link: 'using-vue' }, + { text: 'Интернационализация', link: 'i18n' } + ] + }, + { + text: 'Настройка', + collapsed: false, + items: [ + { text: 'Пользовательская тема', link: 'custom-theme' }, + { + text: 'Расширение темы по умолчанию', + link: 'extending-default-theme' + }, + { + text: 'Загрузка данных в режиме реального времени', + link: 'data-loading' + }, + { text: 'Совместимость с SSR', link: 'ssr-compat' }, + { text: 'Подключение к CMS', link: 'cms' } + ] + }, + { + text: 'Экспериментально', + collapsed: false, + items: [ + { text: 'Режим MPA', link: 'mpa-mode' }, + { text: 'Генерация карты сайта', link: 'sitemap-generation' } + ] + }, + { text: 'Конфигурация и API', base: '/ru/reference/', link: 'site-config' } + ] +} + +function sidebarReference(): DefaultTheme.SidebarItem[] { + return [ + { + text: 'Справочник', + items: [ + { text: 'Конфигурация сайта', link: 'site-config' }, + { text: 'Конфигурация метаданных', link: 'frontmatter-config' }, + { text: 'Runtime API', link: 'runtime-api' }, + { text: 'Командная строка', link: 'cli' }, + { + text: 'Тема по умолчанию', + base: '/ru/reference/default-theme-', + items: [ + { text: 'Обзор', link: 'config' }, + { text: 'Навигация', link: 'nav' }, + { text: 'Сайдбар', link: 'sidebar' }, + { text: 'Главная страница', link: 'home-page' }, + { text: 'Футер', link: 'footer' }, + { text: 'Макет', link: 'layout' }, + { text: 'Значки', link: 'badge' }, + { text: 'Страница команды', link: 'team-page' }, + { + text: 'Предыдущая и следующая страницы', + link: 'prev-next-links' + }, + { text: 'Ссылка для редактирования', link: 'edit-link' }, + { text: 'Последнее обновление', link: 'last-updated' }, + { text: 'Поиск', link: 'search' }, + { text: 'Carbon Ads (реклама)', link: 'carbon-ads' } + ] + } + ] + } + ] +} + +function searchOptions(): Partial { + return { + placeholder: 'Поиск в документации', + translations: { + button: { + buttonText: 'Поиск', + buttonAriaLabel: 'Поиск' + }, + modal: { + searchBox: { + resetButtonTitle: 'Сбросить поиск', + resetButtonAriaLabel: 'Сбросить поиск', + cancelButtonText: 'Отменить поиск', + cancelButtonAriaLabel: 'Отменить поиск' + }, + startScreen: { + recentSearchesTitle: 'История поиска', + noRecentSearchesText: 'Нет истории поиска', + saveRecentSearchButtonTitle: 'Сохранить в истории поиска', + removeRecentSearchButtonTitle: 'Удалить из истории поиска', + favoriteSearchesTitle: 'Избранное', + removeFavoriteSearchButtonTitle: 'Удалить из избранного' + }, + errorScreen: { + titleText: 'Невозможно получить результаты', + helpText: 'Вам может потребоваться проверить подключение к Интернету' + }, + footer: { + selectText: 'выбрать', + navigateText: 'перейти', + closeText: 'закрыть', + searchByText: 'поставщик поиска' + }, + noResultsScreen: { + noResultsText: 'Нет результатов для', + suggestedQueryText: 'Вы можете попытаться узнать', + reportMissingResultsText: + 'Считаете, что поиск даёт ложные результаты?', + reportMissingResultsLinkText: 'Нажмите на кнопку «Обратная связь»' + } + } + } + } +} diff --git a/docs/ru/guide/asset-handling.md b/docs/ru/guide/asset-handling.md new file mode 100644 index 00000000..7236e32d --- /dev/null +++ b/docs/ru/guide/asset-handling.md @@ -0,0 +1,63 @@ +# Обработка ресурсов {#asset-handling} + +## Ссылки на статические ресурсы {#referencing-static-assets} + +Все файлы Markdown компилируются в компоненты Vue и обрабатываются [Vite](https://vitejs.dev/guide/assets.html). Вы можете, **и должны**, ссылаться на любые ресурсы, используя относительные URL: + +```md +![Изображение](./image.png) +``` + +Вы можете ссылаться на статические ресурсы в ваших файлах разметки, ваших компонентах `*.vue` в теме, стилях и обычных файлах `.css`, используя абсолютные пути (основанные на корне проекта) или относительные пути (основанные на вашей файловой системе). Последнее похоже на поведение, к которому вы привыкли, если использовали Vite, Vue CLI или `file-loader` в webpack. + +Распространённые типы файлов изображений, мультимедиа и шрифтов определяются и включаются в качестве ресурсов автоматически. + +::: tip Связанные файлы не рассматриваются как ресурсы +PDF-файлы или другие документы, на которые есть ссылки в файлах с разметкой, не рассматриваются автоматически как ресурсы. Чтобы сделать связанные файлы доступными, вы должны вручную поместить их в каталог [`public`](#the-public-directory) вашего проекта. +::: + +Все ссылающиеся ресурсы, включая те, которые используют абсолютные пути, будут скопированы в выходной каталог с хэшированным именем файла в производственной сборке. Ресурсы, на которые никогда не ссылались, не будут скопированы. Изображения размером менее 4 КБ будут вставляться в формате base64 — это можно настроить с помощью опции конфигурации [`vite`](../reference/site-config#vite). + +Все **статические** ссылки на пути, включая абсолютные пути, должны быть основаны на структуре ваших рабочих каталогов. + +## Директория `public` {#the-public-directory} + +Иногда вам может понадобиться предоставить статические ресурсы, на которые нет прямых ссылок ни в одном из компонентов Markdown или темы, или вы можете захотеть предоставить определённые файлы с оригинальным именем. Примерами таких файлов являются `robots.txt`, `favicon.ico` и иконки PWA. + +Вы можете поместить эти файлы в директорию `public` в [директории с исходными файлами](./routing#source-directory). Например, если корень вашего проекта — `./docs`, и вы используете стандартное расположение исходного каталога, то ваш публичный каталог будет `./docs/public`. + +Ресурсы, размещённые в `public`, будут скопированы в корень выходного каталога как есть. + +Обратите внимание, что вы должны ссылаться на файлы, размещённые в `public`, используя корневой абсолютный путь — например, `public/icon.png` всегда должен упоминаться в исходном коде как `/icon.png`. + +## Базовый URL {#base-url} + +Если ваш сайт развёрнут на URL-адресе, не являющемся корневым, вам нужно установить параметр `base` в файле `.vitepress/config.js`. Например, если вы планируете развернуть свой сайт на `https://foo.github.io/bar/`, то параметр `base` следует установить на `'/bar/'` (он всегда должен начинаться и заканчиваться слэшем). + +Все пути к статическим ресурсам автоматически обрабатываются с учётом различных значений конфигурации `base`. Например, если в вашей разметке есть абсолютная ссылка на ресурс в директории `public`: + +```md +![Изображение](/image-inside-public.png) +``` + +В этом случае вам **не** нужно обновлять его при изменении значения конфигурации `base`. + +Однако если вы создаете компонент темы, который динамически ссылается на активы, например, изображение, атрибут `src` которого основан на значении конфигурации темы: + +```vue + +``` + +В этом случае рекомендуется обернуть путь с помощью [хелпера `withBase`](../reference/runtime-api#withbase), предоставляемого VitePress: + +```vue + + + +``` diff --git a/docs/ru/guide/cms.md b/docs/ru/guide/cms.md new file mode 100644 index 00000000..81542d2b --- /dev/null +++ b/docs/ru/guide/cms.md @@ -0,0 +1,58 @@ +--- +outline: deep +--- + +# Подключение к CMS {#connecting-to-a-cms} + +## Общий рабочий процесс {#general-workflow} + +Подключение VitePress к CMS в значительной степени зависит от [динамических маршрутов](./routing#dynamic-routes). Прежде чем приступить к работе, убедитесь, что вы понимаете, как это работает. + +Поскольку каждая CMS работает по-своему, здесь мы можем предоставить лишь общую схему работы, которую вам нужно будет адаптировать под свой конкретный сценарий. + +1. Если ваша CMS требует аутентификации, создайте файл `.env` для хранения токенов API и загрузите его таким образом: + + ```js + // posts/[id].paths.js + import { loadEnv } from 'vitepress' + + const env = loadEnv('', process.cwd()) + ``` + +2. Получите необходимые данные из CMS и преобразуйте их в соответствующие пути: + + ```js + export default { + async paths() { + // при необходимости используйте соответствующую клиентскую библиотеку CMS + const data = await ( + await fetch('https://my-cms-api', { + headers: { + // токен, если необходимо + } + }) + ).json() + + return data.map((entry) => { + return { + params: { id: entry.id /* заголовок, автор, дата и т. д. */ }, + content: entry.content + } + }) + } + } + ``` + +3. Отрисуйте содержимое страницы: + + ```md + # {{ $params.title }} + + - Автор: {{ $params.author }}, {{ $params.date }} + + + ``` + +## Руководства по интеграции {#integration-guides} + +Если вы написали руководство по интеграции VitePress с конкретной CMS, воспользуйтесь ссылкой «Редактировать эту страницу», чтобы добавить его сюда! diff --git a/docs/ru/guide/custom-theme.md b/docs/ru/guide/custom-theme.md new file mode 100644 index 00000000..7c30ce94 --- /dev/null +++ b/docs/ru/guide/custom-theme.md @@ -0,0 +1,216 @@ +# Пользовательская тема {#using-a-custom-theme} + +## Разрешение темы {#theme-resolving} + +Вы можете включить пользовательскую тему, создав файл `.vitepress/theme/index.js` или `.vitepress/theme/index.ts` («файл входа темы»): + +``` +. +├─ docs # корень проекта +│ ├─ .vitepress +│ │ ├─ theme +│ │ │ └─ index.js # файл входа темы +│ │ └─ config.js # файл конфигурации +│ └─ index.md +└─ package.json +``` + +VitePress всегда будет использовать пользовательскую тему вместо темы по умолчанию, если обнаружит наличие входного файла темы. Однако вы можете [расширить тему по умолчанию](./extending-default-theme), чтобы выполнить расширенные настройки поверх нее. + +## Интерфейс темы {#theme-interface} + +Пользовательская тема VitePress определяется как объект со следующим интерфейсом: + +```ts +interface Theme { + /** + * Корневой компонент макета для каждой страницы + * @required + */ + Layout: Component + /** + * Улучшение экземпляра приложения Vue + * @optional + */ + enhanceApp?: (ctx: EnhanceAppContext) => Awaitable + /** + * Расширяем другую тему, вызывая её `enhanceApp` перед нашей + * @optional + */ + extends?: Theme +} + +interface EnhanceAppContext { + app: App // Экземпляр приложения Vue + router: Router // Экземпляр маршрутизатора VitePress + siteData: Ref // Метаданные на уровне сайта +} +``` + +Файл входа темы должен экспортировать тему по умолчанию: + +```js [.vitepress/theme/index.js] + +// Вы можете напрямую импортировать файлы Vue в файле входа темы. +// VitePress предварительно настроен с помощью @vitejs/plugin-vue. +import Layout from './Layout.vue' + +export default { + Layout, + enhanceApp({ app, router, siteData }) { + // ... + } +} +``` + +Экспорт по умолчанию является единственным контрактом для пользовательской темы, и только свойство `Layout` является обязательным. Таким образом, технически тема VitePress может быть простой, как один компонент Vue. + +Внутри компонент макета работает так же, как и обычное приложение Vite + Vue 3. Обратите внимание, что тема также должна быть [SSR-совместимой](./ssr-compat). + +## Создание макета {#building-a-layout} + +Самый базовый компонент макета должен содержать компонент [``](../reference/runtime-api#content): + +```vue [.vitepress/theme/Layout.vue] + +``` + +Приведённая выше схема просто отображает разметку каждой страницы в виде HTML. Добавим обработку 404 ошибки в качестве первого улучшения: + +```vue{1-4,9-12} + + + +``` + +Хелпер [`useData()`](../reference/runtime-api#usedata) предоставляет нам все данные во время выполнения, необходимые для условной отрисовки различных макетов. Среди различных данных, к которым мы можем получить доступ, являются метаданные текущей страницы. Мы можем использовать это, чтобы позволить конечному пользователю управлять макетом на каждой странице. Например, пользователь может указать, что страница должна использовать специальный макет главной страницы: + +```md +--- +layout: home +--- +``` + +И мы можем настроить нашу тему, чтобы справиться с этим: + +```vue{3,12-14} + + + +``` + +Конечно, вы можете разделить макет на большее количество компонентов: + +```vue{3-5,12-15} + + + +``` + +Обратитесь к [Справочнику Runtime API](../reference/runtime-api), чтобы узнать обо всём, что доступно в компонентах темы. Кроме того, вы можете использовать [загрузку данных в режиме реального времени](./data-loading) для создания макета, управляемого данными — например, страницы со списком всех записей в блоге текущего проекта. + +## Распространение пользовательской темы {#distributing-a-custom-theme} + +Самый простой способ распространить пользовательскую тему — предоставить её в виде [репозитория шаблонов на GitHub](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-template-repository). + +Если вы хотите распространить тему в виде пакета npm, выполните следующие действия: + +1. Экспортируйте объект темы в качестве экспорта по умолчанию в записи пакета. + +2. Если есть возможность, экспортируйте определение типа конфигурации темы как `ThemeConfig`. + +3. Если ваша тема требует настройки конфигурации VitePress, экспортируйте эту конфигурацию в подпапку пакета (например. `my-theme/config`), чтобы пользователь мог расширить её. + +4. Документируйте параметры конфигурации темы (как через файл конфигурации, так и через метаданные). + +5. Предоставьте чёткие инструкции по использованию вашей темы (см. ниже). + +## Использование пользовательской темы {#consuming-a-custom-theme} + +Чтобы использовать внешнюю тему, импортируйте и реэкспортируйте её из элемента пользовательской темы: + +```js [.vitepress/theme/index.js] +import Theme from 'awesome-vitepress-theme' + +export default Theme +``` + +Если тема требует расширения: + +```js [.vitepress/theme/index.js] +import Theme from 'awesome-vitepress-theme' + +export default { + extends: Theme, + enhanceApp(ctx) { + // ... + } +} +``` + +Если тема требует специальных настроек VitePress, вам нужно будет также расширить их в своем собственном конфиге: + +```ts [.vitepress/config.ts] +import baseConfig from 'awesome-vitepress-theme/config' + +export default { + // расширить базовый конфиг темы (если необходимо) + extends: baseConfig +} +``` + +Наконец, если тема предоставляет типы для своего конфига темы: + +```ts [.vitepress/config.ts] +import baseConfig from 'awesome-vitepress-theme/config' +import { defineConfigWithTheme } from 'vitepress' +import type { ThemeConfig } from 'awesome-vitepress-theme' + +export default defineConfigWithTheme({ + extends: baseConfig, + themeConfig: { + // Тип `ThemeConfig` + } +}) +``` diff --git a/docs/ru/guide/data-loading.md b/docs/ru/guide/data-loading.md new file mode 100644 index 00000000..3588fa84 --- /dev/null +++ b/docs/ru/guide/data-loading.md @@ -0,0 +1,254 @@ +# Загрузка данных в режиме реального времени {#build-time-data-loading} + +VitePress предоставляет функцию **загрузчиков данных**, которая позволяет загружать произвольные данные и импортировать их со страниц или компонентов. Загрузка данных выполняется **только во время сборки**: Полученные данные будут сериализованы в виде JSON в финальной сборке JavaScript. + +Загрузчики данных могут использоваться для получения удалённых данных или генерирования метаданных на основе локальных файлов. Например, вы можете использовать загрузчики данных для анализа всех локальных страниц API и автоматического создания индекса всех записей API. + +## Пример использования {#basic-usage} + +Файл загрузчика данных должен заканчиваться либо `.data.js`, либо `.data.ts`. Файл должен предоставлять экспорт объекта по умолчанию с помощью метода `load()`: + +```js [example.data.js] +export default { + load() { + return { + hello: 'мир' + } + } +} +``` + +Модуль загрузчика выполняется только в Node.js, поэтому вы можете импортировать любые API Node и зависимости npm по мере необходимости. + +Затем вы можете импортировать данные из этого файла в страницы `.md` и компоненты `.vue` с помощью экспорта с именем `data`: + +```vue + + +
{{ data }}
+``` + +Результат: + +```json +{ + "hello": "мир" +} +``` + +Вы заметите, что сам загрузчик данных не экспортирует `data`. Это VitePress вызывает метод `load()` за кулисами и неявно раскрывает результат через именованный экспорт `data`. + +Это работает, даже если загрузчик асинхронный: + +```js +export default { + async load() { + // получение удалённых данных + return (await fetch('...')).json() + } +} +``` + +## Данные из локальных файлов {#data-from-local-files} + +Если вам нужно генерировать данные на основе локальных файлов, используйте опцию `watch` в загрузчике данных, чтобы изменения, внесённые в эти файлы, вызывали горячие обновления. + +Опция `watch` удобна ещё и тем, что вы можете использовать [шаблоны glob](https://github.com/mrmlnc/fast-glob#pattern-syntax) для соответствия нескольким файлам. Шаблоны могут быть относительными к самому файлу загрузчика, а функция `load()` будет получать совпадающие файлы в виде абсолютных путей. + +В следующем примере показана загрузка CSV-файлов и их преобразование в JSON с помощью [csv-parse](https://github.com/adaltas/node-csv/tree/master/packages/csv-parse/). Поскольку этот файл выполняется только во время сборки, вы не будете передавать CSV-парсер клиенту! + +```js +import fs from 'node:fs' +import { parse } from 'csv-parse/sync' + +export default { + watch: ['./data/*.csv'], + load(watchedFiles) { + // watchedFiles будет представлять собой массив абсолютных путей к найденным файлам. + // Формируем массив метаданных записи блога, которые можно использовать для визуализации списка в макете темы + return watchedFiles.map((file) => { + return parse(fs.readFileSync(file, 'utf-8'), { + columns: true, + skip_empty_lines: true + }) + }) + } +} +``` + +## `createContentLoader` {#createcontentloader} + +При создании сайта, ориентированного на контент, нам часто приходится создавать страницы типа «архив», или «индекс», на которых мы перечисляем все доступные записи в нашей коллекции контента. Например, записи в блоге или страницы API. Мы **можем** реализовать это напрямую с помощью API загрузчика данных, но поскольку это очень распространённый случай использования, VitePress также предоставляет функцию `createContentLoader`, чтобы упростить эту задачу: + +```js [posts.data.js] +import { createContentLoader } from 'vitepress' + +export default createContentLoader('posts/*.md' /* параметры */) +``` + +Эта функция принимает шаблон glob относительно [исходного каталога](./routing#source-directory) и возвращает объект `{ watch, load }` загрузчика данных, который может быть использован в качестве экспорта по умолчанию в файле загрузчика данных. В нем также реализовано кэширование на основе временных меток изменения файлов для повышения производительности dev. + +Обратите внимание, что загрузчик работает только с файлами Markdown — совпадающие файлы, не относящиеся к Markdown, будут пропущены. + +Загруженные данные будут представлять собой массив с типом `ContentData[]`: + +```ts +interface ContentData { + // отображаемый URL-адрес страницы, например: /posts/hello.html (не включает `base`) + // выполните итерацию вручную или используйте пользовательскую `трансформацию` для нормализации путей + url: string + // метаданные страницы + frontmatter: Record + + // следующие параметры присутствуют только в том случае, если соответствующие опции включены + // мы рассмотрим их ниже + src: string | undefined + html: string | undefined + excerpt: string | undefined +} +``` + +По умолчанию указываются только `url` и `frontmatter`. Это связано с тем, что загруженные данные будут вложены в клиентский пакет в виде JSON, поэтому нам нужно быть осторожными с их размером. Вот пример использования этих данных для создания минимальной индексной страницы блога: + +```vue + + + +``` + +### Параметры {#options} + +Данные по умолчанию могут не соответствовать всем требованиям — вы можете изменить данные с помощью параметров: + +```js [posts.data.js] +import { createContentLoader } from 'vitepress' + +export default createContentLoader('posts/*.md', { + includeSrc: true, // включить исходный текст в формате Markdown? + render: true, // включать в себя полный HTML страницы? + excerpt: true, // включить отрывок? + transform(rawData) { + // составляйте карты, сортируйте или фильтруйте исходные данные по своему усмотрению. + // конечный результат — это то, что будет отправлено клиенту. + return rawData + .sort((a, b) => { + return +new Date(b.frontmatter.date) - +new Date(a.frontmatter.date) + }) + .map((page) => { + page.src // исходный текст в формате Markdown + page.html // отображение полной страницы HTML + page.excerpt // отображаемый отрывок HTML (содержимое выше первого `---`) + return { + /* ... */ + } + }) + } +}) +``` + +Посмотрите, как он используется в [блоге Vue.js](https://github.com/vuejs/blog/blob/main/.vitepress/theme/posts.data.ts). + +API `createContentLoader` также можно использовать внутри [хуков сборки](../reference/site-config#build-hooks): + +```js [.vitepress/config.js] +export default { + async buildEnd() { + const posts = await createContentLoader('posts/*.md').load() + // генерируем файлы на основе метаданных сообщений, например, RSS-канал + } +} +``` + +**Типы** + +```ts +interface ContentOptions { + /** + * Включаем src? + * @default false + */ + includeSrc?: boolean + + /** + * Преобразовываем src в HTML и включаем в данные? + * @default false + */ + render?: boolean + + /** + * Если `boolean`, то следует ли разбирать и включать отрывок? (отображается как HTML) + * + * Если `function`, то управляйте тем, как отрывок извлекается из содержимого. + * + * Если `string`, определите пользовательский разделитель, который будет использоваться для извлечения + * отрывка. Разделителем по умолчанию является `---`, если `excerpt` имеет значение `true`. + * + * @see https://github.com/jonschlinkert/gray-matter#optionsexcerpt + * @see https://github.com/jonschlinkert/gray-matter#optionsexcerpt_separator + * + * @default false + */ + excerpt?: + | boolean + | (( + file: { + data: { [key: string]: any } + content: string + excerpt?: string + }, + options?: any + ) => void) + | string + + /** + * Преобразуйте данные. Обратите внимание, что при импорте из компонентов или файлов + * с разметкой данные будут вложены в клиентский пакет в виде JSON. + */ + transform?: (data: ContentData[]) => T | Promise +} +``` + +## Загрузчики типизированных данных {#typed-data-loaders} + +При использовании TypeScript можно ввести свой загрузчик и экспортировать `data` следующим образом: + +```ts +import { defineLoader } from 'vitepress' + +export interface Data { + // тип данных +} + +declare const data: Data +export { data } + +export default defineLoader({ + // тип проверенных опций загрузчика + watch: ['...'], + async load(): Promise { + // ... + } +}) +``` + +## Конфигурация {#configuration} + +Чтобы получить информацию о конфигурации внутри загрузчика, вы можете использовать код, подобный этому: + +```ts +import type { SiteConfig } from 'vitepress' + +const config: SiteConfig = (globalThis as any).VITEPRESS_CONFIG +``` diff --git a/docs/ru/guide/deploy.md b/docs/ru/guide/deploy.md new file mode 100644 index 00000000..ff12be6c --- /dev/null +++ b/docs/ru/guide/deploy.md @@ -0,0 +1,339 @@ +--- +outline: deep +--- + +# Развёртывание вашего сайта VitePress {#deploy-your-vitepress-site} + +Следующие инструкции основаны на некоторых общих предположениях: + +- Сайт VitePress находится в директории `docs` вашего проекта. +- Вы используете выходной каталог сборки по умолчанию (`.vitepress/dist`). +- VitePress установлен как локальная зависимость в вашем проекте, и вы установили следующие скрипты в вашем `package.json`: + + ```json [package.json] + { + "scripts": { + "docs:build": "vitepress build docs", + "docs:preview": "vitepress preview docs" + } + } + ``` + +## Сборка и локальное тестирование {#build-and-test-locally} + +1. Выполните эту команду, чтобы собрать документацию: + + ```sh + $ npm run docs:build + ``` + +2. После сборки просмотрите её локально, запустив команду: + + ```sh + $ npm run docs:preview + ``` + + Команда `preview` загрузит локальный статический веб-сервер, который будет обслуживать выходной каталог `.vitepress/dist` по адресу `http://localhost:4173`. Вы можете использовать его для теста, чтобы убедиться, что всё выглядит хорошо, прежде чем отправлять в производство. + +3. Можно указать порт сервера, передав `--port` в качестве аргумента. + + ```json + { + "scripts": { + "docs:preview": "vitepress preview docs --port 8080" + } + } + ``` + + Теперь метод `docs:preview` запустит сервер по адресу `http://localhost:8080`. + +## Установка публичного базового пути {#setting-a-public-base-path} + +По умолчанию предполагается, что сайт будет развёрнут по корневому пути домена (`/`). Если ваш сайт будет обслуживаться по подпути, например, `https://mywebsite.com/blog/`, то в конфигурации VitePress необходимо установить для опции [`base`](../reference/site-config#base) значение `'/blog/'`. + +**Пример:** Если вы используете Github (или GitLab) Pages и развёртываете на `user.github.io/repo/`, то установите `base` на `/repo/`. + +## Заголовки кэша HTTP {#http-cache-headers} + +Если вы контролируете HTTP-заголовки на своем рабочем сервере, можно настроить заголовки `cache-control` для достижения лучшей производительности при повторных посещениях. + +В производственной сборке используются хэшированные имена файлов для статических ресурсов (JavaScript, CSS и другие импортированные ресурсы, не находящиеся в `public`). Если вы просмотрите предварительную версию с помощью вкладки «Network» («Сеть») инструментов разработчика вашего браузера, вы увидите файлы типа `app.4f283b18.js`. + +Этот хэш `4f283b18` генерируется из содержимого этого файла. Один и тот же хэшированный URL гарантированно обслуживает одно и то же содержимое файла — если содержимое меняется, то и URL тоже. Это означает, что можно смело использовать самые сильные настройки кэширования для этих файлов. Все такие файлы будут помещены в каталог `assets/` в выходном каталоге, поэтому вы можете настроить для них следующий заголовок: + +``` +Cache-Control: max-age=31536000,immutable +``` + +::: details Пример файла Netlify `_headers` + +``` +/assets/* + cache-control: max-age=31536000 + cache-control: immutable +``` + +Примечание: файл `_headers` должен быть помещён в [директорию `public`](./asset-handling#the-public-directory) — в нашем случае `docs/public/_headers` — так, чтобы он был скопирован в выходной каталог. + +[Netlify custom headers documentation](https://docs.netlify.com/routing/headers/) + +::: + +::: details Пример конфигурации Vercel в файле `vercel.json` + +```json +{ + "headers": [ + { + "source": "/assets/(.*)", + "headers": [ + { + "key": "Cache-Control", + "value": "max-age=31536000, immutable" + } + ] + } + ] +} +``` + +Примечание: Файл `vercel.json` должен быть помещен в корень вашего **репозитория**. + +[Документация Vercel по конфигурации заголовков](https://vercel.com/docs/concepts/projects/project-configuration#headers) + +::: + +## Руководства по платформам {#platform-guides} + +### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render {#netlify-vercel-cloudflare-pages-aws-amplify-render} + +Создайте новый проект и измените эти настройки с помощью панели управления: + +- **Build Command:** `npm run docs:build` +- **Output Directory:** `docs/.vitepress/dist` +- **Node Version:** `20` (или выше) + +::: warning ПРЕДУПРЕЖДЕНИЕ +Не включайте такие опции, как _Auto Minify_ для HTML-кода. Он удалит из вывода комментарии, которые имеют значение для Vue. При их удалении могут возникать ошибки несоответствия гидратации. +::: + +### GitHub Pages {#github-pages} + +1. Создайте файл с именем `deploy.yml` в директории `.github/workflows` вашего проекта с примерно таким содержанием: + + ```yaml [.github/workflows/deploy.yml] + # Пример рабочего процесса для создания и развёртывания сайта VitePress на GitHub Pages + # + name: Deploy VitePress site to Pages + + on: + # Выполняется при пушах, направленных в ветку `main`. Измените это значение на `master`, если вы + # используете ветку `master` в качестве ветки по умолчанию. + push: + branches: [main] + + # Позволяет запустить этот рабочий процесс вручную на вкладке «Actions». + workflow_dispatch: + + # Устанавливает разрешения GITHUB_TOKEN, чтобы разрешить развёртывание на страницах GitHub. + permissions: + contents: read + pages: write + id-token: write + + # Разрешите только одно одновременное развёртывание, пропуская запуски, стоящие в очереди. + # Однако НЕ отменяйте текущие запуски, поскольку мы хотим дать возможность завершить производственные развёртывания. + concurrency: + group: pages + cancel-in-progress: false + + jobs: + # Сборка + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Не требуется, если функция lastUpdated не включена + # - uses: pnpm/action-setup@v3 # Раскомментируйте, если вы используете pnpm + # with: + # version: 9 + # - uses: oven-sh/setup-bun@v1 # Раскомментируйте, если вы используете Bun + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm # или pnpm / yarn + - name: Setup Pages + uses: actions/configure-pages@v4 + - name: Install dependencies + run: npm ci # или pnpm install / yarn install / bun install + - name: Build with VitePress + run: npm run docs:build # или pnpm docs:build / yarn docs:build / bun run docs:build + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: docs/.vitepress/dist + + # Развёртывание + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + needs: build + runs-on: ubuntu-latest + name: Deploy + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 + ``` + + ::: warning ПРЕДУПРЕЖДЕНИЕ + Убедитесь, что опция `base` в вашем VitePress настроена правильно. Дополнительные сведения см. в секции [Установка публичного базового пути](#setting-a-public-base-path). + ::: + +2. В настройках вашего репозитория в разделе «Pages» выберите пункт меню «GitHub Actions» в секции «Build and deployment > Source». + +3. Внесите свои изменения в ветку `main` и дождитесь завершения процесса GitHub Actions. Вы должны увидеть, что ваш сайт развёрнут по адресу `https://.github.io/[repository]/` или `https:///` в зависимости от ваших настроек. Ваш сайт будет автоматически разворачиваться при каждом внесении изменений в ветке `main`. + +### GitLab Pages {#gitlab-pages} + +1. Установите значение `../public` для параметра `outDir` в конфигурации VitePress. Настройте опцию `base` на `'/<репозиторий>/'`, если вы хотите развернуть ваш проект по адресу `https://<имя пользователя>.gitlab.io/<репозиторий>/`. Вам не нужна опция `base`, если вы выполняете развёртывание на личном домене, страницах пользователя или группы, или если в GitLab включен параметр «Использовать уникальный домен». + +2. Создайте файл с именем `.gitlab-ci.yml` в корне вашего проекта с приведённым ниже содержимым. Это позволит создавать и развёртывать ваш сайт каждый раз, когда вы вносите изменения в его содержимое: + + ```yaml [.gitlab-ci.yml] + image: node:18 + pages: + cache: + paths: + - node_modules/ + script: + # - apk add git # Отметьте это, если вы используете небольшие докер-образы, такие как alpine, и у вас включен lastUpdated + - npm install + - npm run docs:build + artifacts: + paths: + - public + only: + - main + ``` + +### Статические веб-приложения Azure {#azure-static-web-apps} + +1. Следуйте [официальной документации](https://docs.microsoft.com/ru-ru/azure/static-web-apps/build-configuration). + +2. Установите эти значения в вашем конфигурационном файле (и удалите те, которые вам не нужны, например, `api_location`): + + - **`app_location`**: `/` + - **`output_location`**: `docs/.vitepress/dist` + - **`app_build_command`**: `npm run docs:build` + +### Firebase {#firebase} + +1. Создайте `firebase.json` и `.firebaserc` в корне вашего проекта: + + `firebase.json`: + + ```json [firebase.json] + { + "hosting": { + "public": "docs/.vitepress/dist", + "ignore": [] + } + } + ``` + + `.firebaserc`: + + ```json [.firebaserc] + { + "projects": { + "default": "" + } + } + ``` + +2. После запуска `npm run docs:build` выполните эту команду для развёртывания: + + ```sh + firebase deploy + ``` + +### Surge {#surge} + +1. После запуска `npm run docs:build` выполните эту команду для развёртывания: + + ```sh + npx surge docs/.vitepress/dist + ``` + +### Heroku {#heroku} + +1. Следуйте документации и руководству, приведённому в [`heroku-buildpack-static`](https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-static). + +2. Создайте файл `static.json` в корне вашего проекта со следующим содержимым: + + ```json [static.json] + { + "root": "docs/.vitepress/dist" + } + ``` + +### Edgio {#edgio} + +См. [Создание и развёртывание приложения VitePress в Edgio](https://docs.edg.io/applications/v6/sites_frameworks/getting_started/vitepress). + +### Хостинг статических файлов Kinsta {#kinsta-static-site-hosting} + +Вы можете развернуть свой сайт VitePress на [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). + +### Nginx + +Вот пример конфигурации блока сервера Nginx. Эта настройка включает сжатие gzip для общих текстовых ресурсов, правила обслуживания статических файлов вашего сайта VitePress с правильными заголовками кэширования и обработку параметра `cleanUrls: true`. + +```nginx +server { + gzip on; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + + listen 80; + server_name _; + index index.html; + + location / { + # расположение контента + root /app; + + # точные совпадения -> обратные чистые URL-адреса -> папки -> не найдены + try_files $uri $uri.html $uri/ =404; + + # несуществующие страницы + error_page 404 /404.html; + + # папка без index.html вызывает ошибку 403 в этой настройке + error_page 403 /404.html; + + # настройка заголовков кэширования + # файлы в папке с ресурсами имеют хэши имён файлов + location ~* ^/assets/ { + expires 1y; + add_header Cache-Control "public, immutable"; + } + } +} +``` + +Эта конфигурация предполагает, что ваш собранный сайт VitePress находится в директории `/app`. При необходимости измените директиву `root`, если файлы вашего сайта расположены в другом месте. + +::: warning Не используйте index.html по умолчанию +Разрешение try_files не должно использовать index.html, как это делается в других приложениях Vue. Это может привести к недопустимому состоянию страницы. +::: + +Дополнительную информацию можно найти в официальной документации [Nginx](https://nginx.org/ru/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). diff --git a/docs/ru/guide/extending-default-theme.md b/docs/ru/guide/extending-default-theme.md new file mode 100644 index 00000000..4443b882 --- /dev/null +++ b/docs/ru/guide/extending-default-theme.md @@ -0,0 +1,332 @@ +--- +outline: deep +--- + +# Расширение темы по умолчанию {#extending-the-default-theme} + +Тема VitePress по умолчанию оптимизирована для документации и может быть настроена по вашему усмотрению. Полный список опций можно найти в главе [Настройки темы по умолчанию](../reference/default-theme-config). + +Однако есть ряд случаев, когда одной лишь конфигурации будет недостаточно. Например: + +1. Вам нужно изменить стили CSS; +2. Вам нужно изменить экземпляр приложения Vue, например, чтобы зарегистрировать глобальные компоненты; +3. Вам нужно внедрить пользовательский контент в тему через слоты макета. + +Эти расширенные настройки потребуют использования пользовательской темы, которая «расширяет» тему по умолчанию. + +::: tip СОВЕТ +Прежде чем приступить к работе, обязательно прочитайте главу [Пользовательская тема](./custom-theme), чтобы понять, как работают пользовательские темы. +::: + +## Настройка CSS {#customizing-css} + +CSS темы по умолчанию можно настроить, переопределив переменные CSS корневого уровня: + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme' +import './custom.css' + +export default DefaultTheme +``` + +```css +/* .vitepress/theme/custom.css */ +:root { + --vp-c-brand-1: #646cff; + --vp-c-brand-2: #747bff; +} +``` + +См. [переменные CSS темы по умолчанию](https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css), которые можно переопределить. + +## Использование различных шрифтов {#using-different-fonts} + +VitePress использует [Inter](https://rsms.me/inter/) в качестве шрифта по умолчанию, и будет включать шрифты в вывод сборки. Шрифт также автоматически загружается в производство. Однако это может быть нежелательно, если вы хотите использовать другой основной шрифт. + +Чтобы не включать Inter в вывод сборки, импортируйте тему из `vitepress/theme-without-fonts`: + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme-without-fonts' +import './my-fonts.css' + +export default DefaultTheme +``` + +```css +/* .vitepress/theme/my-fonts.css */ +:root { + --vp-font-family-base: /* normal text font */ --vp-font-family-mono: + /* code font */; +} +``` + +::: warning ПРЕДУПРЕЖДЕНИЕ +Если вы используете дополнительные компоненты, такие как [Страница команды](../reference/default-theme-team-page), убедитесь, что они также импортированы из `vitepress/theme-without-fonts`! +::: + +Если ваш шрифт — это локальный файл, на который ссылаются через `@font-face`, он будет обработан как ресурс и включён в каталог `.vitepress/dist/assets` с хэшированным именем файла. Чтобы предварительно загрузить этот файл, используйте хук сборки [transformHead](../reference/site-config#transformhead): + +```js [.vitepress/config.js] +export default { + transformHead({ assets }) { + // настраиваем regex соответствующим образом, чтобы он соответствовал вашему шрифту + const myFontFile = assets.find(file => /font-name\.[\w-]+\.woff2/.test(file)) + if (myFontFile) { + return [ + [ + 'link', + { + rel: 'preload', + href: myFontFile, + as: 'font', + type: 'font/woff2', + crossorigin: '' + } + ] + ] + } + } +} +``` + +## Регистрация глобальных компонентов {#registering-global-components} + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme' + +/** @type {import('vitepress').Theme} */ +export default { + extends: DefaultTheme, + enhanceApp({ app }) { + // регистрируем пользовательские глобальные компоненты + app.component('MyGlobalComponent' /* ... */) + } +} +``` + +Если вы используете TypeScript: + +```ts [.vitepress/theme/index.ts] +import type { Theme } from 'vitepress' +import DefaultTheme from 'vitepress/theme' + +export default { + extends: DefaultTheme, + enhanceApp({ app }) { + // регистрируем пользовательские глобальные компоненты + app.component('MyGlobalComponent' /* ... */) + } +} satisfies Theme +``` + +Поскольку мы используем Vite, можно применять [глобальную функцию импорта](https://vitejs.dev/guide/features.html#glob-import) Vite для автоматической регистрации каталога компонентов. + +## Слоты макета {#layout-slots} + +Компонент `` темы по умолчанию имеет несколько слотов, которые можно использовать для вставки содержимого в определённые места страницы. Вот пример внедрения компонента перед оглавлением: + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme' +import MyLayout from './MyLayout.vue' + +export default { + extends: DefaultTheme, + // переопределяем макет с помощью компонента-обёртки, + // который внедряет слоты + Layout: MyLayout +} +``` + +```vue [.vitepress/theme/MyLayout.vue] + + + +``` + +Также можно использовать функцию рендеринга. + +```js [.vitepress/theme/index.js] +import { h } from 'vue' +import DefaultTheme from 'vitepress/theme' +import MyComponent from './MyComponent.vue' + +export default { + extends: DefaultTheme, + Layout() { + return h(DefaultTheme.Layout, null, { + 'aside-outline-before': () => h(MyComponent) + }) + } +} +``` + +Полный список слотов, доступных в макете темы по умолчанию: + +- Когда `layout: 'doc'` (по умолчанию) включен через метаданные: + - `doc-top` + - `doc-bottom` + - `doc-footer-before` + - `doc-before` + - `doc-after` + - `sidebar-nav-before` + - `sidebar-nav-after` + - `aside-top` + - `aside-bottom` + - `aside-outline-before` + - `aside-outline-after` + - `aside-ads-before` + - `aside-ads-after` +- Когда `layout: 'home'` включен через метаданные: + - `home-hero-before` + - `home-hero-info-before` + - `home-hero-info` + - `home-hero-info-after` + - `home-hero-actions-after` + - `home-hero-image` + - `home-hero-after` + - `home-features-before` + - `home-features-after` +- Когда `layout: 'page'` включен через метаданные: + - `page-top` + - `page-bottom` +- На странице «Не найдено (404)»: + - `not-found` +- Всегда: + - `layout-top` + - `layout-bottom` + - `nav-bar-title-before` + - `nav-bar-title-after` + - `nav-bar-content-before` + - `nav-bar-content-after` + - `nav-screen-content-before` + - `nav-screen-content-after` + +## Использование View Transitions API {#using-view-transitions-api} + +### Переключение внешнего вида {#on-appearance-toggle} + +Вы можете расширить стандартную тему, чтобы обеспечить пользовательский переход при переключении цветового режима. Пример: + +```vue [.vitepress/theme/Layout.vue] + + + + + +``` + +Результат (**предупреждение!**: мигающие цвета, резкие движения, яркий свет): + +
+Демонстрация + +![Демонстрация переходов](/appearance-toggle-transition.webp) + +
+ +Более подробно о переходах между представлениями читайте в [документации Chrome](https://developer.chrome.com/docs/web-platform/view-transitions/). + +### Изменение маршрута {#on-route-change} + +Скоро будет. + +## Переопределение внутренних компонентов {#overriding-internal-components} + +Вы можете использовать [псевдонимы](https://vitejs.dev/config/shared-options.html#resolve-alias) Vite, чтобы заменить стандартные компоненты темы на свои собственные: + +```ts +import { fileURLToPath, URL } from 'node:url' +import { defineConfig } from 'vitepress' + +export default defineConfig({ + vite: { + resolve: { + alias: [ + { + find: /^.*\/VPNavBar\.vue$/, + replacement: fileURLToPath( + new URL('./components/CustomNavBar.vue', import.meta.url) + ) + } + ] + } + } +}) +``` + +Чтобы узнать точное название компонента, обратитесь к [нашему исходному коду](https://github.com/vuejs/vitepress/tree/main/src/client/theme-default/components). Поскольку компоненты являются внутренними, есть небольшая вероятность того, что их название будет обновлено между минорными выпусками. diff --git a/docs/ru/guide/frontmatter.md b/docs/ru/guide/frontmatter.md new file mode 100644 index 00000000..b09693f7 --- /dev/null +++ b/docs/ru/guide/frontmatter.md @@ -0,0 +1,48 @@ +# Метаданные {#frontmatter} + +## Использование {#usage} + +VitePress поддерживает метаданные YAML во всех Markdown-файлах, разбирая их с помощью [gray-matter](https://github.com/jonschlinkert/gray-matter). Метаданные должны находиться в верхней части Markdown-файла (перед любыми элементами, включая теги ` + + +``` + +## Поддержка RTL (экспериментально) {#rtl-support-experimental} + +Для поддержки языков с написанием справа налево укажите `dir: 'rtl'` в конфиге и используйте какой-нибудь плагин RTLCSS PostCSS, например , или . Вам нужно настроить плагин PostCSS на использование `:where([dir="ltr"])` и `:where([dir="rtl"])` в качестве префиксов, чтобы избежать проблем со спецификой CSS. diff --git a/docs/ru/guide/markdown.md b/docs/ru/guide/markdown.md new file mode 100644 index 00000000..b67e1355 --- /dev/null +++ b/docs/ru/guide/markdown.md @@ -0,0 +1,1037 @@ +# Расширения Markdown {#markdown-extensions} + +VitePress поставляется со встроенными расширениями Markdown. + +## Якоря заголовков {#header-anchors} + +К заголовкам автоматически применяются якорные ссылки. Отрисовку якорей можно настроить с помощью опции `markdown.anchor`. + +### Пользовательские якоря {#custom-anchors} + +Чтобы указать пользовательский тег якоря для заголовка, а не использовать автоматически сгенерированный, добавьте суффикс к заголовку: + +``` +# Использование пользовательских якорей {#мой-якорь} +``` + +Это позволит вам ссылаться на заголовок как `#мой-якорь` вместо стандартного `#использование-пользовательских-якорей`. + +## Ссылки {#links} + +Особое внимание уделяется как внутренним, так и внешним ссылкам. + +### Внутренние ссылки {#internal-links} + +Внутренние ссылки преобразуются в ссылки маршрутизатора для навигации SPA. Кроме того, каждый `index.md`, содержащийся в каждом подкаталоге, будет автоматически преобразован в `index.html`, с соответствующим URL `/`. + +Например, при следующей структуре каталогов: + +``` +. +├─ index.md +├─ foo +│ ├─ index.md +│ ├─ one.md +│ └─ two.md +└─ bar + ├─ index.md + ├─ three.md + └─ four.md +``` + +И при условии, что вы находитесь в `foo/one.md`: + +```md +[Home](/) +[foo](/foo/) +[foo heading](./#heading) +[bar - three](../bar/three) +[bar - three](../bar/three.md) +[bar - four](../bar/four.html) +``` + +### Суффикс страницы {#page-suffix} + +Страницы и внутренние ссылки по умолчанию генерируются с суффиксом `.html`. + +### Внешние ссылки {#external-links} + +Исходящие ссылки автоматически получают значение `target="_blank" rel="noreferrer"`: + +- [vuejs.org](https://vuejs.org) +- [VitePress on GitHub](https://github.com/vuejs/vitepress) + +## Метаданные {#frontmatter} + +[Метаданные YAML](https://jekyllrb.com/docs/front-matter/) поддерживаются из коробки: + +```yaml +--- +title: Веду блог как хакер +lang: ru-RU +--- +``` + +Эти данные будут доступны остальной части страницы, а также всем пользовательским и тематическим компонентам. + +Более подробную информацию можно найти в главе [Метаданные](../reference/frontmatter-config). + +## Таблицы в стиле GitHub {#github-style-tables} + +**Разметка** + +```md +| Таблицы | это | круто | +| ---------------- | :----------------------: | ----: | +| столбец 3 | выровнен по правому краю | $1600 | +| столбец 2 | отцентрован | $12 | +| полосатые строки | как полоски у зебры | $1 | +``` + +**Результат** + +| Таблицы | это | круто | +| ---------------- | :----------------------: | -----: | +| столбец 3 | выровнен по правому краю | \$1600 | +| столбец 2 | отцентрован | \$12 | +| полосатые строки | как полоски у зебры | \$1 | + +## Эмодзи :tada: {#emoji} + +**Разметка** + +``` +:tada: :100: +``` + +**Результат** + +:tada: :100: + +[Список всех эмодзи](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.mjs). + +## Оглавление {#table-of-contents} + +**Разметка** + +``` +[[toc]] +``` + +**Результат** + +[[toc]] + +Отрисовка TOC может быть настроена с помощью опции `markdown.toc`. + +## Пользовательские контейнеры {#custom-containers} + +Пользовательские контейнеры можно определить по их типам, заголовкам и содержимому. + +### Заголовок по умолчанию {#default-title} + +**Разметка** + +```md +::: info +Это информация. +::: + +::: tip +Это совет. +::: + +::: warning +Это предупреждение. +::: + +::: danger +Это сигнал об опасности. +::: + +::: details +Это блок-спойлер. +::: +``` + +**Результат** + +::: info +Это информация. +::: + +::: tip +Это совет. +::: + +::: warning +Это предупреждение. +::: + +::: danger +Это сигнал об опасности. +::: + +::: details +Это блок-спойлер. +::: + +### Пользовательский заголовок {#custom-title} + +Вы можете задать собственный заголовок, добавив текст сразу после «типа» контейнера. + +**Разметка** + +````md +::: danger СТОП +Опасная зона, остановитесь +::: + +::: details Нажмите на меня, чтобы переключить код + +```js +console.log('Привет, VitePress!') +``` + +::: +```` + +**Результат** + +::: danger СТОП +Опасная зона, остановитесь +::: + +::: details Нажмите на меня, чтобы переключить код + +```js +console.log('Привет, VitePress!') +``` + +::: + +Кроме того, можно установить пользовательские заголовки глобально, добавив следующее содержимое в конфигурацию сайта, полезное, если вы пишете не на английском языке: + +```ts +// config.ts +export default defineConfig({ + // ... + markdown: { + container: { + tipLabel: 'СОВЕТ', + warningLabel: 'ПРЕДУПРЕЖДЕНИЕ', + dangerLabel: 'ОПАСНОСТЬ', + infoLabel: 'ИНФОРМАЦИЯ', + detailsLabel: 'Подробная информация' + } + } + // ... +}) +``` + +### Дополнительные атрибуты {#additional-attributes} + +Вы можете добавить дополнительные атрибуты к пользовательским контейнерам. Мы используем [markdown-it-attrs](https://github.com/arve0/markdown-it-attrs) для этой функции, и она поддерживается почти для всех элементов Markdown. Например, можно установить атрибут `open`, чтобы сделать блок подробностей открытым по умолчанию: + +**Разметка** + +````md +::: details Нажмите на меня, чтобы переключить код {open} +```js +console.log('Привет, VitePress!') +``` +::: +```` + +**Результат** + +::: details Нажмите на меня, чтобы переключить код {open} +```js +console.log('Привет, VitePress!') +``` +::: + +### `raw` {#raw} + +Это специальный контейнер, который можно использовать для предотвращения конфликтов стилей и маршрутизаторов с VitePress. Это особенно полезно при документировании библиотек компонентов. Вы также можете посмотреть [whyframe](https://whyframe.dev/docs/integrations/vitepress) для лучшей изоляции. + +**Синтаксис** + +```md +::: raw +Заворачивается в `
` +::: +``` + +Класс `vp-raw` можно использовать и непосредственно на элементах. Изоляция стиля в настоящее время осуществляется по желанию: + +- Установите `postcss` с помощью предпочитаемого менеджера пакетов: + + ```sh + $ npm add -D postcss + ``` + +- Создайте файл с именем `docs/postcss.config.mjs` и добавьте в него следующее: + + ```js + import { postcssIsolateStyles } from 'vitepress' + + export default { + plugins: [postcssIsolateStyles()] + } + ``` + + Он использует [`postcss-prefix-selector`](https://github.com/postcss/postcss-load-config) под капотом. Вы можете передать ему параметры следующим образом: + + ```js + postcssIsolateStyles({ + includeFiles: [/vp-doc\.css/] // по умолчанию /base\.css/ + }) + ``` + +## Оповещения в стиле 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). + +```md +> [!NOTE] +> Выделяет информацию, на которую пользователи должны обратить внимание, даже при беглом просмотре. + +> [!TIP] +> Дополнительная информация, которая поможет пользователю добиться большего успеха. + +> [!IMPORTANT] +> Важнейшая информация, необходимая пользователям для достижения успеха. + +> [!WARNING] +> Критический контент, требующий немедленного внимания пользователей из-за потенциальных рисков. + +> [!CAUTION] +> Негативные потенциальные последствия того или иного действия. +``` + +> [!NOTE] +> Выделяет информацию, на которую пользователи должны обратить внимание, даже при беглом просмотре. + +> [!TIP] +> Дополнительная информация, которая поможет пользователю добиться большего успеха. + +> [!IMPORTANT] +> Важнейшая информация, необходимая пользователям для достижения успеха. + +> [!WARNING] +> Критический контент, требующий немедленного внимания пользователей из-за потенциальных рисков. + +> [!CAUTION] +> Негативные потенциальные последствия того или иного действия. + +## Подсветка синтаксиса в блоках кода {#syntax-highlighting-in-code-blocks} + +VitePress использует [Shiki](https://github.com/shikijs/shiki) для выделения синтаксиса языка в блоках кода Markdown с помощью цветного текста. Shiki поддерживает широкий спектр языков программирования. Всё, что вам нужно сделать, это добавить правильный псевдоним языка к начальным обратным кавычкам блока кода: + +**Разметка** + +```` +```js +export default { + name: 'MyComponent', + // ... +} +``` +```` + +```` +```html +
    +
  • + {{ todo.text }} +
  • +
+``` +```` + +**Результат** + +```js +export default { + name: 'MyComponent' + // ... +} +``` + +```html +
    +
  • {{ todo.text }}
  • +
+``` + +[Список всех поддерживаемых языков](https://shiki.style/languages). + +Вы также можете настроить тему подсветки синтаксиса в конфигурации приложения. Более подробную информацию см. в секции [`markdown`](../reference/site-config#markdown). + +## Выделение строк в блоках кода {#line-highlighting-in-code-blocks} + +**Разметка** + +```` +```js{4} +export default { + data () { + return { + msg: 'Подсвечено!' + } + } +} +``` +```` + +**Результат** + +```js{4} +export default { + data () { + return { + msg: 'Подсвечено!' + } + } +} +``` + +Помимо одной строки, можно указать несколько отдельных строк, диапазонов или и то, и другое: + +- Диапазоны строк, например: `{5-8}`, `{3-10}`, `{10-17}` +- Несколько одиночных строк, например: `{4,7,9}` +- Диапазоны строк и отдельные строки, например: `{4,7-13,16,23-27,40}` + +**Разметка** + +```` +```js{1,4,6-8} +export default { // Подсвечено + data () { + return { + msg: `Подсвечено! + Эта строка не выделена, + но эта и две следующих - да.`, + motd: 'VitePress - это потрясающе', + lorem: 'ipsum' + } + } +} +``` +```` + +**Результат** + +```js{1,4,6-8} +export default { // Подсвечено + data () { + return { + msg: `Подсвечено! + Эта строка не выделена, + но эта и две следующих - да.`, + motd: 'VitePress - это потрясающе', + lorem: 'ipsum', + } + } +} +``` + +Кроме того, можно выделять непосредственно в строке, используя комментарий `// [!code highlight]`. + +**Разметка** + +```` +```js +export default { + data () { + return { + msg: 'Подсвечено!' // [!!code highlight] + } + } +} +``` +```` + +**Результат** + +```js +export default { + data() { + return { + msg: 'Подсвечено!' // [!code highlight] + } + } +} +``` + +## Фокус в блоках кода {#focus-in-code-blocks} + +Добавление комментария `// [!code focus]` к строке сфокусирует её и размоет остальные части кода. + +Кроме того, вы можете задать количество строк для фокусировки с помощью `// [!code focus:]`. + +**Разметка** + +```` +```js +export default { + data () { + return { + msg: 'Фокус!' // [!!code focus] + } + } +} +``` +```` + +**Результат** + +```js +export default { + data() { + return { + msg: 'Фокус!' // [!code focus] + } + } +} +``` + +## Подсветка различий в блоках кода {#colored-diffs-in-code-blocks} + +Добавление в строку комментариев `// [!code --]` или `// [!code ++]` подсветит различие этой строки от другой, сохраняя цвета блока кода. + +**Разметка** + +```` +```js +export default { + data () { + return { + msg: 'Удалено' // [!!code --] + msg: 'Добавлено' // [!!code ++] + } + } +} +``` +```` + +**Результат** + +```js +export default { + data () { + return { + msg: 'Удалено' // [!code --] + msg: 'Добавлено' // [!code ++] + } + } +} +``` + +## Ошибки и предупреждения в блоках кода {#errors-and-warnings-in-code-blocks} + +Добавление в строку комментариев `// [!code warning]` или `// [!code error]` окрасит её соответствующим образом. + +**Разметка** + +```` +```js +export default { + data () { + return { + msg: 'Ошибка', // [!!code error] + msg: 'Предупреждение' // [!!code warning] + } + } +} +``` +```` + +**Результат** + +```js +export default { + data() { + return { + msg: 'Ошибка', // [!code error] + msg: 'Предупреждение' // [!code warning] + } + } +} +``` + +## Номера строк {#line-numbers} + +Вы можете включить нумерацию строк для каждого блока кода в конфигурации: + +```js +export default { + markdown: { + lineNumbers: true + } +} +``` + +Более подробную информацию см. в секции [`markdown`](../reference/site-config#markdown). + +Вы можете добавить метки `:line-numbers` / `:no-line-numbers` в ваши изолированные блоки кода, чтобы переопределить значение, установленное в конфиге. + +Вы также можете настроить номер начальной строки, добавив `=` после `:line-numbers`. Например, `:line-numbers=2` означает, что нумерация строк в блоках кода будет начинаться с `2`. + +**Разметка** + +````md +```ts {1} +// опция line-numbers по умолчанию отключена +const line2 = 'Строка 2' +const line3 = 'Строка 3' +``` + +```ts:line-numbers {1} +// опция line-numbers включена +const line2 = 'Строка 2' +const line3 = 'Строка 3' +``` + +```ts:line-numbers=2 {1} +// опция line-numbers включена, нумерация начинается с 2 +const line3 = 'Строка 3' +const line4 = 'Строка 4' +``` +```` + +**Результат** + +```ts {1} +// опция line-numbers по умолчанию отключена +const line2 = 'Строка 2' +const line3 = 'Строка 3' +``` + +```ts:line-numbers {1} +// опция line-numbers включена +const line2 = 'Строка 2' +const line3 = 'Строка 3' +``` + +```ts:line-numbers=2 {1} +// опция line-numbers включена, нумерация начинается с 2 +const line3 = 'Строка 3' +const line4 = 'Строка 4' +``` + +## Импорт фрагментов кода {#import-code-snippets} + +Вы можете импортировать фрагменты кода из существующих файлов, используя следующий синтаксис: + +```md +<<< @/filepath +``` + +[Выделение строк](#line-highlighting-in-code-blocks) тоже поддерживается: + +```md +<<< @/filepath{highlightLines} +``` + +**Разметка** + +```md +<<< @/snippets/snippet.js{2} +``` + +**Файл с кодом** + +<<< @/snippets/snippet.js + +**Результат** + +<<< @/snippets/snippet.js{2} + +::: tip СОВЕТ +Значение `@` соответствует корню источника. По умолчанию это корень проекта VitePress, если не настроен параметр `srcDir`. Альтернативно вы также можете импортировать из относительных путей: + +```md +<<< ../snippets/snippet.js +``` + +::: + +Вы также можете использовать [регион VS Code](https://code.visualstudio.com/docs/editor/codebasics#_folding), чтобы включить только соответствующую часть файла кода. Имя пользовательского региона начинается с `#` после пути к файлу: + +**Разметка** + +```md +<<< @/snippets/snippet-with-region.js#snippet{1} +``` + +**Файл с кодом** + +<<< @/snippets/snippet-with-region.js + +**Результат** + +<<< @/snippets/snippet-with-region.js#snippet{1} + +Кроме того, можно указать язык внутри фигурных скобок (`{}`) следующим образом: + +```md +<<< @/snippets/snippet.cs{c#} + + + +<<< @/snippets/snippet.cs{1,2,4-6 c#} + + + +<<< @/snippets/snippet.cs{1,2,4-6 c#:line-numbers} +``` + +Это полезно, если исходный язык нельзя определить по расширению вашего файла. + +## Группы кодов {#code-groups} + +Можно сгруппировать несколько блоков кода следующим образом: + +**Разметка** + +````md +::: code-group + +```js [config.js] +/** + * @type {import('vitepress').UserConfig} + */ +const config = { + // ... +} + +export default config +``` + +```ts [config.ts] +import type { UserConfig } from 'vitepress' + +const config: UserConfig = { + // ... +} + +export default config +``` + +::: +```` + +**Результат** + +::: code-group + +```js [config.js] +/** + * @type {import('vitepress').UserConfig} + */ +const config = { + // ... +} + +export default config +``` + +```ts [config.ts] +import type { UserConfig } from 'vitepress' + +const config: UserConfig = { + // ... +} + +export default config +``` + +::: + +Вы также можете [импортировать фрагменты](#import-code-snippets) в группы кода: + +**Разметка** + +```md +::: code-group + + + +<<< @/snippets/snippet.js + + + +<<< @/snippets/snippet-with-region.js#snippet{1,2 ts:line-numbers} [фрагмент с регионом] + +::: +``` + +**Результат** + +::: code-group + +<<< @/snippets/snippet.js + +<<< @/snippets/snippet-with-region.js#snippet{1,2 ts:line-numbers} [фрагмент с регионом] + +::: + +## Включение файла Markdown {#markdown-file-inclusion} + +Вы можете включить файл Markdown в другой файл Markdown, даже вложенный. + +::: tip СОВЕТ +Вы также можете добавить в префикс пути к Markdown символ `@`, он будет выступать в качестве корня источника. По умолчанию это корень проекта VitePress, если не настроена опция `srcDir`. +::: + +Например, вы можете включить относительный файл Markdown следующим образом: + +**Разметка** + +```md +# Документация + +## Основы + + +``` + +**Файл части** (`parts/basics.md`) + +```md +Некоторые вещи для начала. + +### Конфигурация + +Может быть создана с помощью `.foorc.json`. +``` + +**Эквивалентный код** + +```md +# Документация + +## Основы + +Некоторые вещи для начала. + +### Конфигурация + +Может быть создана с помощью `.foorc.json`. +``` + +Он также поддерживает выбор диапазона строк: + +**Разметка** + +```md +# Документация + +## Основы + + +``` + +**Файл части** (`parts/basics.md`) + +```md +Некоторые вещи для начала. + +### Конфигурация + +Может быть создана с помощью `.foorc.json`. +``` + +**Соответствующий код** + +```md +# Документация + +## Основы + +### Конфигурация + +Может быть создана с помощью `.foorc.json`. +``` + +Формат выбранного диапазона строк может быть следующим: `{3,}`, `{,10}`, `{1,10}` + +Вы также можете использовать [блоки кода VS Code](https://code.visualstudio.com/docs/editor/codebasics#_folding), чтобы включить только соответствующую часть файла. Можно указать пользовательское имя блока после `#`, следующего за путём к файлу: + +**Разметка** + +```md +# Документация + +## Основы + + + +``` + +**Часть файла** (`parts/basics.md`) + +```md + +## Используемая строка 1 + +## Используемая строка 2 + +## Используемая строка 3 + +``` + +**Соответствующий код** + +```md +# Документация + +## Основы + +## Используемая строка 1 + +## Используемая строка 3 +``` + +::: warning ПРЕДУПРЕЖДЕНИЕ +Обратите внимание, что это не приводит к ошибкам, если ваш файл отсутствует. Поэтому при использовании этой функции убедитесь, что содержимое отображается так, как ожидается. +::: + +Вместо регионов VS Code вы также можете использовать якоря заголовков, чтобы включить определённый раздел файла. Например, если у вас есть заголовок в вашем markdown-файле, например: + +```md +## Мой основной раздел + +Какой-то контент здесь. + +### Мой подраздел + +Ещё немного контента здесь. + +## Другой раздел + +Контент вне `Моего основного раздела`. +``` + +Вы можете включить раздел `Мой основной раздел` следующим образом: + +```md +## Мой дополнительный раздел + +``` + +**Соответствующий код** + +```md +## Мой дополнительный раздел + +Какой-то контент здесь. + +### Мой подраздел + +Ещё немного контента здесь. +``` + +Здесь `мои-основнои-раздел` — это сгенерированный идентификатор элемента заголовка. Если его нелегко угадать, вы можете открыть файл в браузере и нажать на якорь заголовка (символ `#` слева от заголовка при наведении), чтобы увидеть идентификатор в адресной строке. Или используйте инструменты разработчика браузера для проверки элемента. Кроме того, вы также можете указать идентификатор для файла части следующим образом: + +```md +## Мой основной раздел {#custom-id} +``` + +и включить его следующим образом: + +```md + +``` + +## Математические уравнения {#math-equations} + +В настоящее время эта фича предоставляется по желанию. Чтобы включить её, вам нужно установить `markdown-it-mathjax3` и установить значение `true` для опции `markdown.math` в вашем файле конфигурации: + +```sh +npm add -D markdown-it-mathjax3 +``` + +```ts [.vitepress/config.ts] +export default { + markdown: { + math: true + } +} +``` + +**Разметка** + +```md +Когда $a \ne 0$, существует два решения $(ax^2 + bx + c = 0)$: +$$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ + +**Уравнения Максвелла:** + +| уравнение | описание | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | +| $\nabla \cdot \vec{\mathbf{B}} = 0$ | дивергенция $\vec{\mathbf{B}}$ равна нулю | +| $\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | искривление $\vec{\mathbf{E}}$ пропорционально скорости изменения $\vec{\mathbf{B}}$ | +| $\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | _что?_ | +``` + +**Результат** + +Когда $a \ne 0$, существует два решения $(ax^2 + bx + c = 0)$: +$$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ + +**Уравнения Максвелла:** + +| уравнение | описание | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | +| $\nabla \cdot \vec{\mathbf{B}} = 0$ | дивергенция $\vec{\mathbf{B}}$ равна нулю | +| $\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | искривление $\vec{\mathbf{E}}$ пропорционально скорости изменения $\vec{\mathbf{B}}$ | +| $\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | _что?_ | + +## Ленивая загрузка изображений {#image-lazy-loading} + +Вы можете включить ленивую загрузку для каждого изображения, добавленного через markdown, установив значение `true` для опции `lazyLoading` в вашем файле конфигурации: + +```js +export default { + markdown: { + image: { + // ленивая загрузка изображений отключена по умолчанию + lazyLoading: true + } + } +} +``` + +## Расширенная конфигурация {#advanced-configuration} + +VitePress использует [markdown-it](https://github.com/markdown-it/markdown-it) для отрисовки Markdown. Многие из вышеперечисленных расширений реализованы с помощью пользовательских плагинов. Вы можете дополнительно настроить экземпляр `markdown-it` с помощью опции `markdown` в файле `.vitepress/config.js`: + +```js +import { defineConfig } from 'vitepress' +import markdownItAnchor from 'markdown-it-anchor' +import markdownItFoo from 'markdown-it-foo' + +export default defineConfig({ + markdown: { + // опции для markdown-it-anchor + // https://github.com/valeriangalliat/markdown-it-anchor#usage + anchor: { + permalink: markdownItAnchor.permalink.headerLink() + }, + + // опции для @mdit-vue/plugin-toc + // https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-toc#options + toc: { level: [1, 2] }, + + config: (md) => { + // используйте любые плагины для markdown-it! + md.use(markdownItFoo) + } + } +}) +``` + +Полный список настраиваемых свойств см. в секции [`markdown`](../reference/site-config#markdown). diff --git a/docs/ru/guide/migration-from-vitepress-0.md b/docs/ru/guide/migration-from-vitepress-0.md new file mode 100644 index 00000000..4d5c7426 --- /dev/null +++ b/docs/ru/guide/migration-from-vitepress-0.md @@ -0,0 +1,23 @@ +# Переход с VitePress 0.x + +Если вы переходите с версии VitePress 0.x, то в ней есть несколько изменений, связанных с новыми функциями и улучшениями. Следуйте этому руководству, чтобы узнать, как перенести ваше приложение на последнюю версию VitePress. + +## Конфигурация приложения + +- Функция интернационализации ещё не реализована. + +## Конфигурация темы + +- Опция `sidebar` изменила свою структуру. + - Ключ `children` теперь называется `items`. + - Элемент верхнего уровня может не содержать `link` в данный момент. Мы планируем вернуть его обратно. +- `repo`, `repoLabel`, `docsDir`, `docsBranch`, `editLinks`, `editLinkText` удалены в пользу более гибкого api. + - Для добавления ссылки GitHub с иконкой в навигацию используйте функцию [Социальные ссылки](../reference/default-theme-nav#navigation-links). + - Для добавления ссылки «Редактировать эту страницу» используйте функцию [Ссылка для редактирования](../reference/default-theme-edit-link). +- Опция `lastUpdated` теперь разделена на `config.lastUpdated` и `themeConfig.lastUpdatedText`. +- Опция `carbonAds.carbon` заменена на `carbonAds.code`. + +## Конфигурация метаданных + +- Опция `home: true` заменена на `layout: home`. Кроме того, многие настройки, связанные с главной страницей, были изменены для обеспечения дополнительных возможностей. Подробности см. в разделе [Главная страница](../reference/default-theme-home-page). +- Опция `footer` перенесена в [`themeConfig.footer`](../reference/default-theme-config#footer). diff --git a/docs/ru/guide/migration-from-vuepress.md b/docs/ru/guide/migration-from-vuepress.md new file mode 100644 index 00000000..afacc630 --- /dev/null +++ b/docs/ru/guide/migration-from-vuepress.md @@ -0,0 +1,30 @@ +# Переход с VuePress + +## Конфигурация + +### Сайдбар + +Боковая панель больше не заполняется автоматически из метаданных. Вы можете [самостоятельно прочитать вступление](https://github.com/vuejs/vitepress/issues/572#issuecomment-1170116225), чтобы научиться динамически заполнять боковую панель. [Дополнительные утилиты для этого](https://github.com/vuejs/vitepress/issues/96) могут быть предоставлены в будущем. + +## Markdown + +### Изображения + +В отличие от VuePress, VitePress автоматически обрабатывает опцию [`base`](./asset-handling#base-url) вашего конфига, когда вы используете статическое изображение. + +Таким образом, теперь вы можете выводить изображения без тега `img`. + +```diff +- foo ++ ![foo](/foo.png) +``` + +::: warning ПРЕДУПРЕЖДЕНИЕ +Для динамических изображений вам всё ещё нужно использовать `withBase`, как показано в [Руководстве по базовому URL](./asset-handling#base-url). +::: + +Используйте регулярное выражение `` для поиска всех изображений с синтаксисом `![](...)` и замены на `![$2]($1)`. + +--- + +продолжение следует... diff --git a/docs/ru/guide/mpa-mode.md b/docs/ru/guide/mpa-mode.md new file mode 100644 index 00000000..f3d32537 --- /dev/null +++ b/docs/ru/guide/mpa-mode.md @@ -0,0 +1,23 @@ +# Режим MPA {#mpa-mode} + +Режим MPA (Multi-Page Application — «Многостраничное приложение») можно включить через командную строку с помощью команды `vitepress build --mpa`, или через конфигурацию с помощью опции `mpa: true`. + +В режиме MPA все страницы по умолчанию отображаются без включенного JavaScript. В результате производственный сайт, скорее всего, получит более высокую оценку эффективности первых посещений с помощью инструментов аудита. + +Однако из-за отсутствия навигации SPA межстраничные ссылки будут приводить к полной перезагрузке страницы. После загрузки навигация в режиме MPA будет не такой мгновенной, как в режиме SPA. + +Также обратите внимание, что «no-JS-by-default» («без JS по умолчанию») означает, что вы используете Vue исключительно как серверный язык шаблонов. Никаких обработчиков событий в браузере не будет, как и интерактивности. Чтобы загрузить JavaScript со стороны клиента, вам нужно использовать специальный тег ` + +# Привет +``` + +` +``` + +### Рендеринг необработанного содержимого {#rendering-raw-content} + +Параметры, передаваемые странице, будут сериализованы в полезной нагрузке клиентского JavaScript, поэтому вам следует избегать передачи в параметрах больших объемов данных, например, необработанного Markdown или HTML-контента, полученного из удалённой CMS. + +Вместо этого вы можете передавать такое содержимое на каждую страницу с помощью свойства `content` каждого объекта path: + +```js +export default { + async paths() { + const posts = await (await fetch('https://my-cms.com/blog-posts')).json() + + return posts.map((post) => { + return { + params: { id: post.id }, + content: post.content // необработанный Markdown или HTML + } + }) + } +} +``` + +Затем используйте следующий специальный синтаксис, чтобы отобразить содержимое как часть самого файла Markdown: + +```md + +``` diff --git a/docs/ru/guide/sitemap-generation.md b/docs/ru/guide/sitemap-generation.md new file mode 100644 index 00000000..6e933c90 --- /dev/null +++ b/docs/ru/guide/sitemap-generation.md @@ -0,0 +1,58 @@ +# Генерация карты сайта {#sitemap-generation} + +VitePress поставляется с готовой поддержкой генерации файла `sitemap.xml` для вашего сайта. Чтобы включить её, добавьте следующее в файл `.vitepress/config.js`: + +```ts +export default { + sitemap: { + hostname: 'https://example.com' + } +} +``` + +Чтобы теги `` присутствовали в вашем файле `sitemap.xml`, вы можете включить опцию [`lastUpdated`](../reference/default-theme-last-updated). + +## Параметры {#options} + +Поддержка карты сайта осуществляется с помощью модуля [`sitemap`](https://www.npmjs.com/package/sitemap). Вы можете передать любые поддерживаемые им параметры в опцию `sitemap` в вашем конфигурационном файле. Они будут переданы непосредственно в конструктор `SitemapStream`. Более подробную информацию см. в документации [`sitemap`](https://www.npmjs.com/package/sitemap#options-you-can-pass). Пример: + +```ts +export default { + sitemap: { + hostname: 'https://example.com', + lastmodDateOnly: false + } +} +``` + +При использовании параметра `base` в своей конфигурации обязательно добавьте его в адрес `hostname`: + +```ts +export default { + base: '/my-site/', + sitemap: { + hostname: 'https://example.com/my-site/' + } +} +``` + +## Хук `transformItems` {#transformitems-hook} + +Вы можете использовать хук `sitemap.transformItems` для изменения элементов карты сайта перед их записью в файл `sitemap.xml`. Этот хук вызывается с массивом элементов sitemap и ожидает возвращения массива элементов sitemap. Пример: + +```ts +export default { + sitemap: { + hostname: 'https://example.com', + transformItems: (items) => { + // добавляем новые элементы или изменяем/фильтруем существующие + items.push({ + url: '/extra-page', + changefreq: 'monthly', + priority: 0.8 + }) + return items + } + } +} +``` diff --git a/docs/ru/guide/ssr-compat.md b/docs/ru/guide/ssr-compat.md new file mode 100644 index 00000000..a2afb8fa --- /dev/null +++ b/docs/ru/guide/ssr-compat.md @@ -0,0 +1,135 @@ +--- +outline: deep +--- + +# Совместимость с SSR {#ssr-compatibility} + +VitePress предварительно рендерит приложение в Node.js во время производственной сборки, используя возможности Vue по рендерингу на стороне сервера (SSR). Это означает, что весь пользовательский код в компонентах темы подлежит проверке на совместимость с SSR. + +Глава [Рендеринг на стороне сервера](https://ru.vuejs.org/guide/scaling-up/ssr.html) в документации Vue содержит более подробную информацию о том, что такое SSR, взаимосвязь между SSR и SSG, а также общие указания по написанию кода, дружественного к SSR. Правило заключается в том, чтобы обращаться к API браузера / DOM только в хуках `beforeMount` или `mounted` компонентов Vue. + +## `` {#clientonly} + +Если вы используете или демонстрируете компоненты, которые не являются SSR-дружественными (например, содержат пользовательские директивы), вы можете обернуть их внутри встроенного компонента ``: + +```md + + + +``` + +## Библиотеки, обращающиеся к API браузера при импорте {#libraries-that-access-browser-api-on-import} + +Некоторые компоненты или библиотеки получают доступ к API браузера **при импорте**. Чтобы использовать код, предполагающий наличие среды браузера при импорте, необходимо динамически импортировать их. + +### Импорт в хуке `onMounted` {#importing-in-mounted-hook} + +```vue + +``` + +### Условный импорт {#conditional-import} + +Вы также можете условно импортировать зависимость с помощью флага `import.meta.env.SSR` (часть [env-переменных Vite](https://vitejs.dev/guide/env-and-mode.html#env-variables)): + +```js +if (!import.meta.env.SSR) { + import('./lib-that-access-window-on-import').then((module) => { + // используем код + }) +} +``` + +Поскольку [`Theme.enhanceApp`](./custom-theme#theme-interface) может быть асинхронным, вы можете условно импортировать и регистрировать плагины Vue, которые получают доступ к API браузера при импорте: + +```js [.vitepress/theme/index.js] +/** @type {import('vitepress').Theme} */ +export default { + // ... + async enhanceApp({ app }) { + if (!import.meta.env.SSR) { + const plugin = await import('plugin-that-access-window-on-import') + app.use(plugin.default) + } + } +} +``` + +Если вы используете TypeScript: + +```ts [.vitepress/theme/index.ts] +import type { Theme } from 'vitepress' + +export default { + // ... + async enhanceApp({ app }) { + if (!import.meta.env.SSR) { + const plugin = await import('plugin-that-access-window-on-import') + app.use(plugin.default) + } + } +} satisfies Theme +``` + +### `defineClientComponent` {#defineclientcomponent} + +VitePress предоставляет удобный помощник для импорта компонентов Vue, которые получают доступ к API браузера при импорте. + +```vue + + + +``` + +Вы также можете передавать параметры/дочерние элементы/слоты целевому компоненту: + +```vue + + + +``` + +Целевой компонент будет импортирован только в смонтированный хук компонента-обёртки. diff --git a/docs/ru/guide/using-vue.md b/docs/ru/guide/using-vue.md new file mode 100644 index 00000000..e031c3f7 --- /dev/null +++ b/docs/ru/guide/using-vue.md @@ -0,0 +1,323 @@ +# Использование Vue в Markdown {#using-vue-in-markdown} + +В VitePress каждый Markdown-файл компилируется в HTML, а затем обрабатывается как [однофайловый компонент Vue](https://ru.vuejs.org/guide/scaling-up/sfc.html). Это означает, что вы можете использовать любые возможности Vue внутри Markdown, включая динамический шаблонизатор, использование компонентов Vue или произвольную логику компонентов Vue на странице, добавив тег ` + +## Содержание в формате Markdown. Счётчик: {{ count }} + + + + +``` + +::: warning Избегайте ` +``` + +## Использование телепортов {#using-teleports} + +В настоящее время VitePress поддерживает SSG только для телепортов к элементу `body`. Для других целей вы можете обернуть их внутри встроенного компонента `` или внедрить разметку телепортации в нужное место HTML конечной страницы через [хук `postRender`](../reference/site-config#postrender). + + + +::: details Исходный код +<<< @/ru/components/ModalDemo.vue +::: + +```md + + +
+ // ... +
+
+
+``` + + + + + + +## Поддержка VS Code IntelliSense + + + +Vue предоставляет поддержку IntelliSense из коробки через [официальный плагин Vue для VS Code](https://marketplace.visualstudio.com/items?itemName=Vue.volar). Однако, чтобы включить её для файлов `.md`, вам нужно внести некоторые изменения в файлы конфигурации. + +1. Добавьте шаблон `.md` в параметры `include` и `vueCompilerOptions.vitePressExtensions` в файле tsconfig/jsconfig: + +::: code-group +```json [tsconfig.json] +{ + "include": [ + "docs/**/*.ts", + "docs/**/*.vue", + "docs/**/*.md", + ], + "vueCompilerOptions": { + "vitePressExtensions": [".md"], + }, +} +``` +::: + +2. Добавьте `markdown` в параметр `vue.server.includeLanguages` в настройках VS Code: + +::: code-group +```json [.vscode/settings.json] +{ + "vue.server.includeLanguages": ["vue", "markdown"] +} +``` +::: diff --git a/docs/ru/guide/what-is-vitepress.md b/docs/ru/guide/what-is-vitepress.md new file mode 100644 index 00000000..1bcc3e18 --- /dev/null +++ b/docs/ru/guide/what-is-vitepress.md @@ -0,0 +1,57 @@ +# Что такое VitePress? {#what-is-vitepress} + +VitePress — это [Генератор статических сайтов](https://en.wikipedia.org/wiki/Static_site_generator) (ГСС), предназначенный для быстрого создания сайтов, ориентированных на контент. В двух словах, VitePress берёт ваш исходный контент, написанный в [Markdown](https://ru.wikipedia.org/wiki/Markdown), применяет к нему тему и генерирует статические HTML-страницы, которые можно легко развернуть в любом месте. + +
+ +Хотите попробовать прямо сейчас? Перейдите к главе [Первые шаги](./getting-started). + +
+ +## Примеры использования {#use-cases} + +- **Документация** + + 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, но использует пользовательскую тему, разделяемую между несколькими переводами. + +- **Блоги, портфолио и маркетинговые сайты** + + VitePress поддерживает [полностью кастомизированные темы](./custom-theme), при этом разработчики могут использовать стандартное приложение Vite + Vue. То, что он построен на базе Vite, также означает, что вы можете напрямую использовать плагины Vite из его богатой экосистемы. Кроме того, VitePress предоставляет гибкие API для [загрузки данных](./data-loading) (локальной или удаленной) и [динамической генерации маршрутов](./routing#dynamic-routes). С его помощью можно построить практически всё, что угодно, если данные могут быть определены во время сборки. + + Официальный [блог Vue.js](https://blog.vuejs.org/) — это простой блог, который генерирует свою индексную страницу на основе локального контента. + +## Опыт разработчика {#developer-experience} + +VitePress стремится обеспечить отличные возможности для разработчиков при работе с содержимым в формате Markdown. + +- **[На базе Vite:](https://vitejs.dev/)** мгновенный запуск сервера, правки всегда отражаются мгновенно (<100 мс) без перезагрузки страницы. + +- **[Встроенные расширения Markdown:](./markdown)** Frontmatter, таблицы, подсветка синтаксиса... называйте как хотите. В частности, VitePress предоставляет множество расширенных возможностей для работы с блоками кода, что делает его идеальным для создания технической документации. + +- **[Markdown с возможностями Vue:](./using-vue)** каждая Markdown-страница также является [однофайловым компонентом](https://ru.vuejs.org/guide/scaling-up/sfc.html) Vue, благодаря 100% синтаксической совместимости шаблона Vue с HTML. Вы можете внедрить интерактивность в статический контент, используя шаблонизаторы Vue или импортированные компоненты Vue. + +## Производительность {#performance} + +В отличие от многих традиционных ГСС, где каждая навигация приводит к полной перезагрузке страницы, сайт, созданный VitePress, обслуживает статический HTML при первом посещении, но становится [Одностраничным приложением](https://ru.wikipedia.org/wiki/%D0%9E%D0%B4%D0%BD%D0%BE%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%87%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5) (SPA) для последующей навигации по сайту. Эта модель, на наш взгляд, обеспечивает оптимальный баланс производительности: + +- **Быстрая начальная загрузка** + + При первом посещении любой страницы будет использоваться статичный, предварительно отрендеренный HTML для быстрой загрузки и оптимального SEO. Затем на страницу загружается пакет JavaScript, который превращает страницу в Vue SPA («гидратация»). Вопреки распространённому мнению о медленной гидратации SPA, этот процесс на самом деле чрезвычайно быстр благодаря высокой производительности Vue 3 и оптимизациям компилятора. По данным [PageSpeed Insights](https://pagespeed.web.dev/report?url=https%3A%2F%2Fvitepress.dev%2F), типичные сайты VitePress достигают почти идеальных показателей производительности даже на мобильных устройствах с низкой скоростью передачи данных. + +- **Быстрая навигация после загрузки** + + Что ещё более важно, модель SPA приводит к улучшению пользовательского опыта **после** первоначальной загрузки. Последующая навигация по сайту больше не будет приводить к полной перезагрузке страницы. Вместо этого содержимое входящей страницы будет получено и динамически обновлено. VitePress также автоматически выполняет предварительную выборку фрагментов страницы для ссылок, которые находятся в пределах области просмотра. В большинстве случаев навигация после загрузки будет ощущаться мгновенно. + +- **Интерактивность без штрафов** + + Для того чтобы динамические части Vue, встроенные в статический Markdown, могли работать в режиме гидратации, каждая страница Markdown обрабатывается как компонент Vue и компилируется в JavaScript. Это может показаться неэффективным, но компилятор Vue достаточно умён, чтобы разделить статическую и динамическую части, минимизируя как стоимость гидратации, так и размер полезной нагрузки. При первоначальной загрузке страницы статические части автоматически исключаются из полезной нагрузки JavaScript и пропускаются во время гидратации. + +## Что насчёт VuePress? {#what-about-vuepress} + +VitePress — это духовный наследник VuePress. Оригинальный VuePress был основан на Vue 2 и webpack. Благодаря Vue 3 и Vite под капотом, VitePress обеспечивает значительно лучший опыт разработки, лучшую производительность, более отточенную тему по умолчанию и более гибкий API для настройки. + +Разница в API между VitePress и VuePress заключается в основном в тематическом оформлении и настройке. Если вы используете VuePress 1 с темой по умолчанию, то переход на VitePress будет относительно простым. + +Также были приложены усилия для создания VuePress 2, который также поддерживает Vue 3 и Vite с большей совместимостью с VuePress 1. Однако поддерживать два генератора параллельно не представляется возможным, поэтому команда Vue решила сосредоточиться на VitePress как основном рекомендуемом генераторе статических сайтов в долгосрочной перспективе. diff --git a/docs/ru/index.md b/docs/ru/index.md new file mode 100644 index 00000000..e5bc7732 --- /dev/null +++ b/docs/ru/index.md @@ -0,0 +1,35 @@ +--- +layout: home + +hero: + name: VitePress + text: Генератор статических сайтов на основе Vite и Vue + tagline: Преобразуйте Markdown в красивую документацию за минуты + actions: + - theme: brand + text: Что такое VitePress? + link: /ru/guide/what-is-vitepress + - theme: alt + text: Первые шаги + link: /ru/guide/getting-started + - theme: alt + text: GitHub + link: https://github.com/vuejs/vitepress + image: + src: /vitepress-logo-large.svg + alt: VitePress + +features: + - icon: 📝 + title: Сосредоточьтесь на своем контенте + details: Легко создавайте красивые сайты с документацией, используя только Markdown. + - icon: + title: Наслаждайтесь опытом разработчиков Vite + details: Мгновенный запуск сервера, молниеносные горячие обновления и использование плагинов экосистемы Vite. + - icon: + title: Настройка с помощью Vue + details: Используйте синтаксис Vue и компоненты прямо в Markdown или создавайте собственные темы с помощью Vue. + - icon: 🚀 + title: Быстрый запуск веб-сайтов + details: Быстрая начальная загрузка с помощью статического HTML, быстрая навигация после загрузки с помощью маршрутизации на стороне клиента. +--- diff --git a/docs/ru/reference/cli.md b/docs/ru/reference/cli.md new file mode 100644 index 00000000..93954da2 --- /dev/null +++ b/docs/ru/reference/cli.md @@ -0,0 +1,74 @@ +# Интерфейс командной строки {#command-line-interface} + +## `vitepress dev` {#vitepress-dev} + +Запуск сервера разработки VitePress, с использованием указанного каталога в качестве корневого. По умолчанию используется текущий каталог. Команду `dev` также можно опустить при работе в текущем каталоге. + +### Использование {#usage} + +```sh +# запуск в текущем каталоге, опускаем `dev` +vitepress + +# запуск в подкаталоге +vitepress dev [root] +``` + +### Параметры {#options} + +| Параметр | Описание | +| --------------- | ------------------------------------------------------------------------------ | +| `--open [path]` | Открытие браузера при запуске (`boolean \| string`) | +| `--port ` | Номер порта (`number`) | +| `--base ` | Публичный базовый путь (по умолчанию: `/`) (`string`) | +| `--cors` | Включить CORS | +| `--strictPort` | Выйти, если указанный порт уже используется (`boolean`) | +| `--force` | Заставить оптимизатор игнорировать кэш и повторно объединять файлы (`boolean`) | + +## `vitepress build` {#vitepress-build} + +Создание производственной сборки текущего сайта VitePress. + +### Использование {#usage-1} + +```sh +vitepress build [root] +``` + +### Параметры {#options-1} + +| Параметр | Описание | +| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- | +| `--mpa` (экспериментально) | Сборка в режиме [MPA](../guide/mpa-mode) без гидратации на стороне клиента (`boolean`) | +| `--base ` | Публичный базовый путь (по умолчанию: `/`) (`string`) | +| `--target ` | Транспилировать цель (по умолчанию: `"modules"`) (`string`) | +| `--outDir ` | Выходной каталог относительно **cwd** (по умолчанию: `/.vitepress/dist`) (`string`) | +| `--minify [minifier]` | Включить/выключить минификацию или задать используемый минификатор (по умолчанию: `"esbuild"`) (`boolean \| "terser" \| "esbuild"`) | +| `--assetsInlineLimit ` | Статический встроенный порог ресурса base64 в байтах (по умолчанию: `4096`) (`number`) | + +## `vitepress preview` {#vitepress-preview} + +Локальный предварительный просмотр производственной сборки. + +### Использование {#usage-2} + +```sh +vitepress preview [root] +``` + +### Параметры {#options-2} + +| Параметр | Описание | +| --------------- | ----------------------------------------------------- | +| `--base ` | Публичный базовый путь (по умолчанию: `/`) (`string`) | +| `--port ` | Номер порта (`number`) | + +## `vitepress init` {#vitepress-init} + +Запуск [Мастера настройки](../guide/getting-started#setup-wizard) в текущем каталоге. + +### Использование {#usage-3} + +```sh +vitepress init +``` diff --git a/docs/ru/reference/default-theme-badge.md b/docs/ru/reference/default-theme-badge.md new file mode 100644 index 00000000..fc546436 --- /dev/null +++ b/docs/ru/reference/default-theme-badge.md @@ -0,0 +1,72 @@ +# Значки {#badge} + +С помощью значков удобно добавлять статус к заголовкам. Например, может быть полезно указать тип раздела или поддерживаемую версию. + +## Использование {#usage} + +Вы можете использовать компонент `Badge`, который доступен глобально. + +```html +### Заголовок ### Заголовок + ### Заголовок + ### Заголовок + +``` + +Приведённый выше код даёт такой результат: + +### Заголовок {#title} + +### Заголовок {#title-1} + +### Заголовок {#title-2} + +### Заголовок {#title-3} + +## Дочерние элементы {#custom-children} + +`` принимает параметр `children`, который будет отображаться внутри значка. + +```html +### Заголовок вложенный элемент +``` + +### Заголовок вложенный элемент + +## Настройка стиля значков {#customize-type-color} + +Вы можете настроить стиль значков, переопределив переменные CSS. Ниже приведены значения по умолчанию: + +```css +:root { + --vp-badge-info-border: transparent; + --vp-badge-info-text: var(--vp-c-text-2); + --vp-badge-info-bg: var(--vp-c-default-soft); + + --vp-badge-tip-border: transparent; + --vp-badge-tip-text: var(--vp-c-brand-1); + --vp-badge-tip-bg: var(--vp-c-brand-soft); + + --vp-badge-warning-border: transparent; + --vp-badge-warning-text: var(--vp-c-warning-1); + --vp-badge-warning-bg: var(--vp-c-warning-soft); + + --vp-badge-danger-border: transparent; + --vp-badge-danger-text: var(--vp-c-danger-1); + --vp-badge-danger-bg: var(--vp-c-danger-soft); +} +``` + +## `` {#badge-1} + +Компонент `` принимает следующие параметры: + +```ts +interface Props { + // Когда передается ``, это значение игнорируется. + text?: string + + // По умолчанию: `tip`. + type?: 'info' | 'tip' | 'warning' | 'danger' +} +``` diff --git a/docs/ru/reference/default-theme-carbon-ads.md b/docs/ru/reference/default-theme-carbon-ads.md new file mode 100644 index 00000000..7988a7b0 --- /dev/null +++ b/docs/ru/reference/default-theme-carbon-ads.md @@ -0,0 +1,22 @@ +# Carbon Ads {#carbon-ads} + +VitePress имеет встроенную поддержку [Carbon Ads](https://www.carbonads.net/). Определив в конфиге учётные данные Carbon Ads, VitePress будет отображать рекламу на странице. + +```js +export default { + themeConfig: { + carbonAds: { + code: 'код-рекламы', + placement: 'место-размещения-рекламы' + } + } +} +``` + +Эти значения используются для вызова сценария Carbon CDN, как показано ниже: + +```js +;`//cdn.carbonads.com/carbon.js?serve=${code}&placement=${placement}` +``` + +Чтобы узнать больше о настройке Carbon Ads, посетите [веб-сайт Carbon Ads](https://www.carbonads.net/). diff --git a/docs/ru/reference/default-theme-config.md b/docs/ru/reference/default-theme-config.md new file mode 100644 index 00000000..2eb95570 --- /dev/null +++ b/docs/ru/reference/default-theme-config.md @@ -0,0 +1,494 @@ +# Настройка темы по умолчанию {#default-theme-config} + +Конфигурация темы позволяет настроить её под себя. Вы можете настроить тему с помощью опции `themeConfig` в файле конфигурации: + +```ts +export default { + lang: 'ru-RU', + title: 'VitePress', + description: 'Генератор статического сайта на базе Vite и Vue.', + + // Конфигурации, связанные с темой. + themeConfig: { + logo: '/logo.svg', + nav: [...], + sidebar: { ... } + } +} +``` + +**Параметры, описанные на этой странице, применимы только к теме по умолчанию.** Разные темы предполагают разные конфигурации темы. При использовании пользовательской темы объект конфигурации темы будет передан теме, чтобы она могла определить условное поведение на его основе. + +## i18nRouting + +- Тип: `boolean` + +При смене локали на `ru` URL изменится с `/foo` (или `/en/foo/`) на `/ru/foo`. Вы можете отключить это поведение, установив для параметра `themeConfig.i18nRouting` значение `false`. + +## logo + +- Тип: `ThemeableImage` + +Файл логотипа для отображения в навигационной панели, прямо перед заголовком сайта. Принимает строку пути или объект, чтобы установить другой логотип для светлого/тёмного режима. + +```ts +export default { + themeConfig: { + logo: '/logo.svg' + } +} +``` + +```ts +type ThemeableImage = + | string + | { src: string; alt?: string } + | { light: string; dark: string; alt?: string } +``` + +## siteTitle + +- Тип: `string | false` + +Вы можете настроить этот элемент для замены стандартного заголовка сайта (`title` в конфигурации приложения) в nav. При установке значения `false` заголовок в панели навигации будет отключен. Пригодится, если у вас есть `logo`, который уже содержит текст названия сайта. + +```ts +export default { + themeConfig: { + siteTitle: 'Привет, мир' + } +} +``` + +## nav + +- Тип: `NavItem` + +Конфигурация для пункта навигационного меню. Подробнее в главе [Тема по умолчанию: Навигация](./default-theme-nav#navigation-links). + +```ts +export default { + themeConfig: { + nav: [ + { text: 'Руководство', link: '/guide' }, + { + text: 'Выпадающее меню', + items: [ + { text: 'Пункт A', link: '/item-1' }, + { text: 'Пункт B', link: '/item-2' }, + { text: 'Пункт C', link: '/item-3' } + ] + } + ] + } +} +``` + +```ts +type NavItem = NavItemWithLink | NavItemWithChildren + +interface NavItemWithLink { + text: string + link: string + activeMatch?: string + target?: string + rel?: string + noIcon?: boolean +} + +interface NavItemChildren { + text?: string + items: NavItemWithLink[] +} + +interface NavItemWithChildren { + text?: string + items: (NavItemChildren | NavItemWithLink)[] + activeMatch?: string +} +``` + +## sidebar + +- Тип: `Sidebar` + +Конфигурация для пунктов меню боковой панели. Подробнее в главе [Тема по умолчанию: Сайдбар](./default-theme-sidebar). + +```ts +export default { + themeConfig: { + sidebar: [ + { + text: 'Руководство', + items: [ + { text: 'Введение', link: '/introduction' }, + { text: 'Первые шаги', link: '/getting-started' }, + ... + ] + } + ] + } +} +``` + +```ts +export type Sidebar = SidebarItem[] | SidebarMulti + +export interface SidebarMulti { + [path: string]: SidebarItem[] | { items: SidebarItem[]; base: string } +} + +export type SidebarItem = { + /** + * Текстовая метка элемента + */ + text?: string + + /** + * Ссылка на элемент + */ + link?: string + + /** + * Потомки элемента + */ + items?: SidebarItem[] + + /** + * Если не указано, группа не будет сворачиваться + * + * Если `true`, то группа будет сворачиваться и разворачиваться по умолчанию + * + * Если `false`, группа сворачивается, но по умолчанию разворачивается + */ + collapsed?: boolean + + /** + * Базовый путь для дочерних элементов + */ + base?: string + + /** + * Настройте текст, который отображается в футере предыдущей/следующей страницы + */ + docFooterText?: string + + rel?: string + target?: string +} +``` + +## aside + +- Тип: `boolean | 'left'` +- По умолчанию: `true` +- Можно переопределить для каждой страницы с помощью [метаданных](./frontmatter-config#aside) + +Установка этого значения в `false` предотвращает отрисовку контейнера сайдбара.\ +Установка этого значения в `true` приведёт к отображению сайдбара справа.\ +Установка этого значения в `left` приведёт к отображению сайдбара слева. + +Если вы хотите отключить его для всех режимов просмотра, используйте `aside: false`. + +## outline + +- Тип: `Outline | Outline['level'] | false` +- Уровень можно переопределить для каждой страницы с помощью [метаданных](./frontmatter-config#outline) + +Установка этого значения в `false` предотвращает отрисовку оглавления. Для получения более подробной информации обратитесь к этому интерфейсу: + +```ts +interface Outline { + /** + * Уровни заголовков, которые будут отображаться в оглавлении. + * Одиночное число означает, что будут отображаться только заголовки этого уровня. + * Если передается кортеж, то первое число — это минимальный уровень, а второе — максимальный. + * `'deep'` то же самое, что `[2, 6]`, что означает, что будут отображены все заголовки от `

` до `

`. + * + * @default 2 + */ + level?: number | [number, number] | 'deep' + + /** + * Заголовок, который будет отображаться в оглавлении. + * + * @default 'На этой странице' + */ + label?: string +} +``` + +## socialLinks + +- Тип: `SocialLink[]` + +Вы можете задать эту опцию, чтобы показывать ссылки на ваши социальные аккаунты с помощью иконок в панели навигации. + +```ts +export default { + themeConfig: { + socialLinks: [ + // Можно добавить любую иконку из simple-icons (https://simpleicons.org/): + { icon: 'github', link: 'https://github.com/vuejs/vitepress' }, + { icon: 'twitter', link: '...' }, + // Можно добавить пользовательские иконки, передав SVG в виде строки: + { + icon: { + svg: 'Dribbble' + }, + link: '...', + // Можно включить пользовательский ярлык для доступности (необязательно, но рекомендуется): + ariaLabel: 'классная ссылка' + } + ] + } +} +``` + +```ts +interface SocialLink { + icon: string | { svg: string } + link: string + ariaLabel?: string +} +``` + +## footer + +- Тип: `Footer` +- Можно переопределить для каждой страницы с помощью [метаданных](./frontmatter-config#footer) + +Настройка футера. Вы можете разместить в футере сообщение или текст об авторских правах, однако он будет отображаться только в том случае, если страница не содержит боковой панели. Это объясняется соображениями дизайна. + +```ts +export default { + themeConfig: { + footer: { + message: 'Опубликовано под лицензией MIT.', + copyright: '© 2019 – настоящее время, Эван Ю' + } + } +} +``` + +```ts +export interface Footer { + message?: string + copyright?: string +} +``` + +## editLink + +- Тип: `EditLink` +- Можно переопределить для каждой страницы с помощью [метаданных](./frontmatter-config#editlink) + +Ссылка для редактирования позволяет отобразить ссылку для редактирования страницы на сервисах управления Git, таких как GitHub или GitLab. См. секцию [Тема по умолчанию: Ссылка для редактирования](./default-theme-edit-link) для получения более подробной информации. + +```ts +export default { + themeConfig: { + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + text: 'Редактировать эту страницу на GitHub' + } + } +} +``` + +```ts +export interface EditLink { + pattern: string + text?: string +} +``` + +## lastUpdated + +- Тип: `LastUpdatedOptions` + +Позволяет настраивать текст и формат даты последнего обновления. + +```ts +export default { + themeConfig: { + lastUpdated: { + text: 'Обновлено', + formatOptions: { + dateStyle: 'full', + timeStyle: 'medium' + } + } + } +} +``` + +```ts +export interface LastUpdatedOptions { + /** + * @default 'Last updated' + */ + text?: string + + /** + * @default + * { dateStyle: 'short', timeStyle: 'short' } + */ + formatOptions?: Intl.DateTimeFormatOptions & { forceLocale?: boolean } +} +``` + +## algolia + +- Тип: `AlgoliaSearch` + +Опция для поддержки поиска на вашем сайте документации с помощью [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch). Подробнее в главе [Тема по умолчанию: Поиск](./default-theme-search) + +```ts +export interface AlgoliaSearchOptions extends DocSearchProps { + locales?: Record> +} +``` + +Посмотреть все доступные опции можно [здесь](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts). + +## carbonAds {#carbon-ads} + +- Тип: `CarbonAdsOptions` + +Возможность отображения [Carbon Ads](https://www.carbonads.net/). + +```ts +export default { + themeConfig: { + carbonAds: { + code: 'код-рекламы', + placement: 'место-размещения-рекламы' + } + } +} +``` + +```ts +export interface CarbonAdsOptions { + code: string + placement: string +} +``` + +Подробнее в главе [Тема по умолчанию: Carbon Ads](./default-theme-carbon-ads) + +## docFooter + +- Тип: `DocFooter` + +Можно использовать для настройки текста, отображаемого над ссылками на предыдущую и следующую страницы. Полезно, если вы не пишете документы только на английском языке. Также можно использовать для глобального отключения подобных ссылок. Если вы хотите выборочно включить/выключить эти ссылки на отдельной странице, воспользуйтесь [метаданными](./default-theme-prev-next-links). + +```ts +export default { + themeConfig: { + docFooter: { + prev: 'Предыдущая страница', + next: 'Следующая страница' + } + } +} +``` + +```ts +export interface DocFooter { + prev?: string | false + next?: string | false +} +``` + +## darkModeSwitchLabel + +- Тип: `string` +- По умолчанию: `Appearance` + +Можно использовать для настройки надписи переключателя тёмного режима. Этот ярлык отображается только в мобильном представлении. + +## lightModeSwitchTitle + +- Тип: `string` +- По умолчанию: `Switch to light theme` + +Может использоваться для настройки заголовка переключателя светлого режима, который появляется при наведении курсора. + +## darkModeSwitchTitle + +- Тип: `string` +- По умолчанию: `Switch to dark theme` + +Можно использовать для настройки заголовка переключателя тёмного режима, который появляется при наведении курсора. + +## sidebarMenuLabel + +- Тип: `string` +- По умолчанию: `Menu` + +Может использоваться для настройки метки бокового меню. Эта метка отображается только в мобильном представлении. + +## returnToTopLabel + +- Тип: `string` +- По умолчанию: `Return to top` + +Может использоваться для настройки метки кнопки возврата наверх. Эта метка отображается только в мобильном представлении. + +## langMenuLabel + +- Тип: `string` +- По умолчанию: `Change language` + +Можно использовать для настройки aria-метки кнопки переключения языка в панели навигации. Применяется только в том случае, если вы используете [i18n](../guide/i18n). + +## skipToContentLabel + +- Тип: `string` +- По умолчанию: `Skip to content` + +Можно использовать для настройки метки ссылки перехода к содержимому. Эта ссылка отображается, когда пользователь перемещается по сайту с помощью клавиатуры. + +## externalLinkIcon + +- Тип: `boolean` +- По умолчанию: `false` + +Отображать ли значок внешней ссылки рядом с внешними ссылками в Markdown. + +## `useLayout` + +Возвращает данные, относящиеся к макету. Возвращаемый объект имеет следующий тип: + +```ts +interface { + isHome: ComputedRef + + sidebar: Readonly> + sidebarGroups: ComputedRef + hasSidebar: ComputedRef + isSidebarEnabled: ComputedRef + + hasAside: ComputedRef + leftAside: ComputedRef + + headers: Readonly> + hasLocalNav: ComputedRef +} +``` + +**Пример:** + +```vue + + + +``` diff --git a/docs/ru/reference/default-theme-edit-link.md b/docs/ru/reference/default-theme-edit-link.md new file mode 100644 index 00000000..a2cd6b00 --- /dev/null +++ b/docs/ru/reference/default-theme-edit-link.md @@ -0,0 +1,60 @@ +# Ссылка для редактирования {#edit-link} + +## Настройка в файле конфигурации {#site-level-config} + +Ссылка на редактирование позволяет отобразить ссылку для редактирования страницы на сервисах управления Git, таких как GitHub или GitLab. Чтобы включить её, добавьте опции `themeConfig.editLink` в свой конфиг: + +```js +export default { + themeConfig: { + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path' + } + } +} +``` + +Параметр `pattern` задает структуру URL для ссылки, а `:path` будет заменён на путь к странице. + +Вы также можете поместить чистую функцию, которая принимает [`PageData`](./runtime-api#usedata) в качестве аргумента и возвращает строку URL. + +```js +export default { + themeConfig: { + editLink: { + pattern: ({ filePath }) => { + if (filePath.startsWith('packages/')) { + return `https://github.com/acme/monorepo/edit/main/${filePath}` + } else { + return `https://github.com/acme/monorepo/edit/main/docs/${filePath}` + } + } + } + } +} +``` + +Она не должна иметь побочных эффектов или доступа к чему-либо за пределами своей области, поскольку будет сериализована и выполнена в браузере. + +По умолчанию это добавит текст ссылки «Редактировать страницу» в нижней части документа. Вы можете настроить этот текст, определив опцию `text`. + +```js +export default { + themeConfig: { + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + text: 'Редактировать эту страницу на GitHub' + } + } +} +``` + +## Настройка в метаданных {#frontmatter-config} + +Эту ссылку можно отключить на конкретной странице с помощью опции `editLink` в метаданных: + +```yaml +--- +editLink: false +--- +``` diff --git a/docs/ru/reference/default-theme-footer.md b/docs/ru/reference/default-theme-footer.md new file mode 100644 index 00000000..99840b3c --- /dev/null +++ b/docs/ru/reference/default-theme-footer.md @@ -0,0 +1,55 @@ +# Футер {#footer} + +VitePress будет отображать блок футера внизу страницы, если присутствует объект `themeConfig.footer`. + +```ts +export default { + themeConfig: { + footer: { + message: 'Опубликовано под лицензией MIT.', + copyright: '© 2019 – настоящее время, Эван Ю' + } + } +} +``` + +```ts +export interface Footer { + // Сообщение, отображаемое прямо перед копирайтом. + message?: string + + // Уведомление об авторских правах. + copyright?: string +} +``` + +Приведённая выше конфигурация также поддерживает строки HTML. Так, например, если вы хотите разместить в футере несколько ссылок, можно настроить конфигурацию следующим образом: + +```ts +export default { + themeConfig: { + footer: { + message: + 'Опубликовано под лицензией MIT.', + copyright: + '© 2019 – настоящее время, Эван Ю' + } + } +} +``` + +::: warning ПРЕДУПРЕЖДЕНИЕ +В `message` и `copyright` можно использовать только встроенные элементы, поскольку они отображаются внутри элемента `

`. Если вы хотите добавить блочные элементы, рассмотрите возможность использования слота [`layout-bottom`](../guide/extending-default-theme#layout-slots). +::: + +Обратите внимание, что футер не будет отображаться, если виден [Сайдбар](./default-theme-sidebar). + +## Настройка в метаданных {#frontmatter-config} + +Отображение футера можно отключить на конкретной странице с помощью опции `footer` в метаданных: + +```yaml +--- +footer: false +--- +``` diff --git a/docs/ru/reference/default-theme-home-page.md b/docs/ru/reference/default-theme-home-page.md new file mode 100644 index 00000000..fedf2b53 --- /dev/null +++ b/docs/ru/reference/default-theme-home-page.md @@ -0,0 +1,196 @@ +# Главная страница {#home-page} + +Тема VitePress по умолчанию предоставляет макет главной страницы, который вы также можете увидеть на [главной странице этого сайта](../). Вы можете использовать его на любой из своих страниц, указав `layout: home` в [метаданных](./frontmatter-config) страницы. + +```yaml +--- +layout: home +--- +``` + +Однако сам по себе этот вариант мало что даст. Вы можете добавить несколько различных готовых «секций» на главную страницу, установив дополнительные опции, такие как `hero` и `features`. + +## Секция `hero` {#hero-section} + +Секция `hero` находится в верхней части главной страницы. Вот как можно её настроить: + +```yaml +--- +layout: home + +hero: + name: VitePress + text: Генератор статических сайтов на основе Vite и Vue. + tagline: Lorem ipsum... + image: + src: /logo.png + alt: VitePress + actions: + - theme: brand + text: Начать + link: /guide/what-is-vitepress + - theme: alt + text: Посмотреть на GitHub + link: https://github.com/vuejs/vitepress +--- +``` + +```ts +interface Hero { + // Строка, отображаемая поверх `text`. Поставляется в фирменном цвете и, + // как ожидается, будет короткой — например, название продукта + name?: string + + // Основной текст секции. Будет использоваться внутри тега `h1` + text: string + + // Заголовок, отображаемый под `text` + tagline?: string + + // Изображение отображается рядом с `text` и `tagline` + image?: ThemeableImage + + // Кнопки действий для отображения в секции + actions?: HeroAction[] +} + +type ThemeableImage = + | string + | { src: string; alt?: string } + | { light: string; dark: string; alt?: string } + +interface HeroAction { + // Цветовая тема кнопки. По умолчанию принимает значение `brand`. + theme?: 'brand' | 'alt' + + // Метка кнопки. + text: string + + // Ссылка назначения кнопки. + link: string + + // Атрибут цели ссылки. + target?: string + + // Атрибут rel ссылки. + rel?: string +} +``` + +### Настройка цвета заголовка секции {#customizing-the-name-color} + +VitePress использует фирменный цвет (`--vp-c-brand-1`) для атрибута `name` в секции `hero`. Однако вы можете настроить этот цвет, переопределив переменную `--vp-home-hero-name-color`. + +```css +:root { + --vp-home-hero-name-color: blue; +} +``` + +Также вы можете настроить его ещё больше, комбинируя `--vp-home-hero-name-background`, чтобы придать `name` градиентный цвет. + +```css +:root { + --vp-home-hero-name-color: transparent; + --vp-home-hero-name-background: -webkit-linear-gradient( + 120deg, + #bd34fe, + #41d1ff + ); +} +``` + +## Секция `features` {#features-section} + +В секции `features` можно перечислить любое количество функций, которые вы хотели бы показать сразу после секции `hero`. Чтобы настроить её, передайте опцию `features` в метаданных страницы. + +Для каждой функции можно указать иконку, который может быть эмодзи или любым другим изображением. Если настраиваемая иконка представляет собой изображение (svg, png, jpeg...), вы должны предоставить ей соответствующую ширину и высоту. При необходимости можно указать описание, собственный размер, а также варианты для тёмной и светлой темы. + +```yaml +--- +layout: home + +features: + - icon: 🛠️ + title: Просто и минималистично, всегда + details: Lorem ipsum... + - icon: + src: /cool-feature-icon.svg + title: Ещё одна интересная функция + details: Lorem ipsum... + - icon: + dark: /dark-feature-icon.svg + light: /light-feature-icon.svg + title: Ещё одна интересная функция + details: Lorem ipsum... +--- +``` + +```ts +interface Feature { + // Иконка + icon?: FeatureIcon + + // Заголовок фичи + title: string + + // Описание фичи + details: string + + // Ссылка при нажатии на компонент функции. Ссылка может быть как внутренней, так и внешней. + // + // например, `guide/reference/default-theme-home-page` или `https://example.com` + link?: string + + // Текст ссылки, который будет отображаться внутри компонента функции. Лучше всего использовать с опцией `link`. + // + // например, `Узнать подробнее`, `Посетить страницу` и т. д. + linkText?: string + + // Атрибут rel для опции `link` + // + // например, `external` + rel?: string + + // Атрибут target для опции `link` + target?: string +} + +type FeatureIcon = + | string + | { src: string; alt?: string; width?: string; height: string } + | { + light: string + dark: string + alt?: string + width?: string + height: string + } +``` + +## Содержимое Markdown {#markdown-content} + +Вы можете добавить дополнительный контент на главную страницу вашего сайта, просто добавив Markdown под разделителем `---`. + +````md +--- +layout: home + +hero: + name: VitePress + text: Генератор статических сайтов на основе Vite и Vue. +--- + +## Начало работы + +Вы можете начать использовать VitePress прямо сейчас, используя `npx`! + +```sh +npm init +npx vitepress init +``` +```` + +::: info ПРИМЕЧАНИЕ +VitePress не всегда автоматически стилизовал дополнительный контент страницы с макетом `layout: home`. Чтобы вернуться к старому поведению, добавьте `markdownStyles: false` в метаданных. +::: diff --git a/docs/ru/reference/default-theme-last-updated.md b/docs/ru/reference/default-theme-last-updated.md new file mode 100644 index 00000000..7d926dc5 --- /dev/null +++ b/docs/ru/reference/default-theme-last-updated.md @@ -0,0 +1,27 @@ +# Последнее обновление {#last-updated} + +Время последнего обновления содержимого будет отображаться в правом нижнем углу страницы. Чтобы включить его, добавьте опцию `lastUpdated` в свой конфиг. + +::: tip Совет +Чтобы увидеть обновленное время, необходимо зафиксировать файл Markdown. +::: + +## Настройка в файле конфигурации {#site-level-config} + +```js +export default { + lastUpdated: true +} +``` + +## Настройка в метаданных {#frontmatter-config} + +Эту информацию можно отключить на конкретной странице с помощью опции `lastUpdated` в метаданных: + +```yaml +--- +lastUpdated: false +--- +``` + +Также смотрите [Тема по умолчанию: `lastUpdated`](./default-theme-config#lastupdated) для получения более подробной информации. Любое истинное значение на уровне темы также включит функцию, если только она не будет явно отключена на уровне сайта или страницы. diff --git a/docs/ru/reference/default-theme-layout.md b/docs/ru/reference/default-theme-layout.md new file mode 100644 index 00000000..346569a1 --- /dev/null +++ b/docs/ru/reference/default-theme-layout.md @@ -0,0 +1,62 @@ +# Макет {#layout} + +Вы можете выбрать макет страницы, установив опцию `layout` в [метаданных](./frontmatter-config). Изначально есть 3 макета: `doc`, `page` и `home`. Если ничего не указано, то страница будет использовать макет `doc`. + +```yaml +--- +layout: doc +--- +``` + +## Макет `doc` {#doc-layout} + +Вариант `doc` — это макет по умолчанию, который стилизует всё содержимое Markdown в виде «документации». Он работает, оборачивая весь контент в CSS-класс `vp-doc` и применяя стили к вложенным элементам. + +Почти все общие элементы, такие как `p` или `h2`, получают специальную стилизацию. Поэтому имейте в виду, что если вы добавите какой-либо пользовательский HTML внутри Markdown-контента, то он также будет подвержен влиянию этих стилей. + +Кроме того, в нём предусмотрены специальные функции, перечисленные ниже. Эти функции включены только в данном макете. + +- Ссылка «Редактировать» +- Ссылки предыдущая/следующая +- Оглавление +- Реклама [Carbon Ads](./default-theme-carbon-ads) + +## Макет `page` {#page-layout} + +Вариант `page` сгенерирует «пустую страницу». Markdown всё равно будет разобран, и все [расширения Markdown](../guide/markdown) будут работать так же, как и с макетом `doc`, но никаких стилей по умолчанию применено не будет. + +Макет `page` позволит вам оформить всё самостоятельно, без влияния темы VitePress на разметку. Это удобно, когда вы хотите создать свою собственную страницу. + +Обратите внимание, что даже при таком раскладе сайдбар всё равно будет отображаться, если у страницы есть соответствующая конфигурация сайдбара. + +## Макет `home` {#home-layout} + +Вариант `home` сгенерирует шаблонную «домашнюю страницу». В этом макете вы можете установить дополнительные параметры, такие как `hero` и `features`, для дальнейшей настройки контента. Посетите секцию [Тема по умолчанию: Домашняя страница](./default-theme-home-page) для получения более подробной информации. + +## Без макета {#no-layout} + +Если вам не нужен макет, вы можете указать `layout: false` в метаданных. Этот параметр полезен, если вам нужна полностью настраиваемая целевая страница (по умолчанию без сайдбара, панели навигации или футера). + +## Свой макет {#custom-layout} + +Вы также можете использовать собственный макет: + +```md +--- +layout: foo +--- +``` + +Будет выполнен поиск компонента с именем `foo`, зарегистрированного в контексте. Например, вы можете зарегистрировать свой компонент глобально в `.vitepress/theme/index.ts`: + +```ts +import DefaultTheme from 'vitepress/theme' +import Foo from './Foo.vue' + +export default { + extends: DefaultTheme, + enhanceApp({ app }) { + app.component('foo', Foo) + } +} +``` diff --git a/docs/ru/reference/default-theme-nav.md b/docs/ru/reference/default-theme-nav.md new file mode 100644 index 00000000..41257de8 --- /dev/null +++ b/docs/ru/reference/default-theme-nav.md @@ -0,0 +1,214 @@ +# Навигация {#nav} + +Ключ `nav` в конфигурации — это панель навигации, отображаемая в верхней части страницы. Она содержит заголовок сайта, ссылки глобального меню и т. д. + +## Название и логотип сайта {#site-title-and-logo} + +По умолчанию навигация отображает название сайта, ссылаясь на значение [`config.title`](./site-config#title). Если вы хотите изменить то, что отображается в панели навигации, задайте пользовательский текст в опции `themeConfig.siteTitle`. + +```js +export default { + themeConfig: { + siteTitle: 'Мой заголовок' + } +} +``` + +Если у вас есть логотип для вашего сайта, вы можете отобразить его, передав путь к изображению. Вы должны поместить логотип непосредственно в директорию `public` и указать абсолютный путь к нему. + +```js +export default { + themeConfig: { + logo: '/my-logo.svg' + } +} +``` + +При добавлении логотипа он отображается вместе с названием сайта. Если вам нужен только логотип и вы хотите скрыть текст заголовка сайта, установите `false` для параметра `SiteTitle`. + +```js +export default { + themeConfig: { + logo: '/my-logo.svg', + siteTitle: false + } +} +``` + +Вы также можете передать объект в качестве логотипа, если хотите добавить атрибут `alt` или настроить его в зависимости от тёмного/светлого режима. Подробности смотрите в [`themeConfig.logo`](./default-theme-config#logo). + +## Навигационные ссылки {#navigation-links} + +Вы можете определить опцию `themeConfig.nav`, чтобы добавить ссылки в панель навигации: + +```js +export default { + themeConfig: { + nav: [ + { text: 'Руководство', link: '/guide' }, + { text: 'Настройка', link: '/config' }, + { text: 'Изменения', link: 'https://github.com/...' } + ] + } +} +``` + +`text` — это текст, отображаемый в навигации, а `link` — это ссылка, на которую будет осуществлён переход при нажатии на текст. Для ссылки задайте путь к фактическому файлу без префикса `.md` и всегда начинайте с `/`. + +Навигационные ссылки также могут быть выпадающими меню. Для этого установите ключ `items` вместо ключа `link`: + +```js +export default { + themeConfig: { + nav: [ + { text: 'Руководство', link: '/guide' }, + { + text: 'Выпадающее меню', + items: [ + { text: 'Пункт A', link: '/item-1' }, + { text: 'Пункт B', link: '/item-2' }, + { text: 'Пункт C', link: '/item-3' } + ] + } + ] + } +} +``` + +Обратите внимание, что заголовок выпадающего меню (`Выпадающее меню` в примере выше) не может иметь свойство `link`, так как он становится кнопкой для открытия выпадающего диалога. + +Вы можете добавить «секции» в пункты выпадающего меню, передавая больше вложенных элементов: + +```js +export default { + themeConfig: { + nav: [ + { text: 'Руководство', link: '/guide' }, + { + text: 'Выпадающее меню', + items: [ + { + // Заголовок секции + text: 'Секция A', + items: [ + { text: 'Пункт A в секции A', link: '...' }, + { text: 'Пункт B в секции A', link: '...' } + ] + } + ] + }, + { + text: 'Выпадающее меню', + items: [ + { + // Заголовок можно опустить + items: [ + { text: 'Пункт A в секции A', link: '...' }, + { text: 'Пункт B в секции A', link: '...' } + ] + } + ] + } + ] + } +} +``` + +### Настройка «активного» состояния ссылки {#customize-link-s-active-state} + +Пункты меню навигации будут выделены, если текущая страница находится под соответствующим путём. Если вы хотите настроить сопоставление путей, определите свойство `activeMatch` и регулярное выражение в качестве строкового значения. + +```js +export default { + themeConfig: { + nav: [ + // Эта ссылка получает активное состояние, когда пользователь + // переходит по пути `/config/`. + { + text: 'Руководство', + link: '/guide', + activeMatch: '/config/' + } + ] + } +} +``` + +::: warning ПРЕДУПРЕЖДЕНИЕ +Ожидается, что `activeMatch` будет регулярным выражением, но вы должны определить его как строку. Мы не можем использовать здесь реальный объект RegExp, потому что он не сериализуется во время сборки. +::: + +### Настройка атрибутов «target» и «rel» {#customize-link-s-target-and-rel-attributes} + +По умолчанию VitePress автоматически определяет атрибуты `target` и `rel` в зависимости от того, является ли ссылка внешней. Но при желании их можно настроить и вручную. + +```js +export default { + themeConfig: { + nav: [ + { + text: 'Товары', + link: 'https://www.thegithubshop.com/', + target: '_self', + rel: 'sponsored' + } + ] + } +} +``` + +## Социальные ссылки {#social-links} + +См. [`socialLinks`](./default-theme-config#sociallinks). + +## Пользовательские компоненты + +Вы можете добавить пользовательские компоненты в панель навигации с помощью опции `component`. Ключ `component` должен быть именем компонента Vue и должен быть зарегистрирован глобально с помощью [Theme.enhanceApp](../guide/custom-theme#theme-interface). + +```js [.vitepress/config.js] +export default { + themeConfig: { + nav: [ + { + text: 'Мое меню', + items: [ + { + component: 'MyCustomComponent', + // Необязательные параметры для передачи компоненту + props: { + title: 'Мой пользовательский компонент' + } + } + ] + }, + { + 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 предоставляет следующие дополнительные параметры компонента: + +- `screenMenu`: необязательное булево значение, указывающее, находится ли компонент внутри мобильного навигационного меню + +Пример можно посмотреть в тестах e2e [здесь](https://github.com/vuejs/vitepress/tree/main/__tests__/e2e/.vitepress). diff --git a/docs/ru/reference/default-theme-prev-next-links.md b/docs/ru/reference/default-theme-prev-next-links.md new file mode 100644 index 00000000..e25bab8f --- /dev/null +++ b/docs/ru/reference/default-theme-prev-next-links.md @@ -0,0 +1,43 @@ +# Предыдущая и следующая страницы {#prev-next-links} + +Вы можете настроить текст и ссылку для предыдущей и следующей страниц (отображаются в нижней части страницы). Это полезно, если вы хотите, чтобы текст отличался от того, что находится в сайдбаре. Кроме того, вы можете счесть полезным отключить футер или ссылку на страницу, которая не включена в сайдбар. + +## prev {#prev} + +- Тип: `string | false | { text?: string; link?: string }` + +- Подробности: + + Указывает текст/ссылку, который должен отображаться при переходе на предыдущую страницу. Если вы не зададите это в метаданных, текст/ссылка будет определяться из конфигурации сайдбара. + +- Примеры: + + - Для настройки только текста: + + ```yaml + --- + prev: 'Начать | Markdown' + --- + ``` + + - Для настройки текста и ссылки: + + ```yaml + --- + prev: + text: 'Markdown' + link: '/guide/markdown' + --- + ``` + + - Для скрытия предыдущей страницы: + + ```yaml + --- + prev: false + --- + ``` + +## next {#next} + +Аналогично параметру `prev`, но для следующей страницы. diff --git a/docs/ru/reference/default-theme-search.md b/docs/ru/reference/default-theme-search.md new file mode 100644 index 00000000..bab3fa9e --- /dev/null +++ b/docs/ru/reference/default-theme-search.md @@ -0,0 +1,386 @@ +--- +outline: deep +--- + +# Поиск {#search} + +## Локальный поиск {#local-search} + +VitePress поддерживает нечёткий полнотекстовый поиск с использованием внутрибраузерного индекса благодаря [MiniSearch](https://github.com/lucaong/minisearch/). Чтобы включить эту функцию, просто установите значение `'local'` для опции `themeConfig.search.provider` в файле `.vitepress/config.ts`: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local' + } + } +}) +``` + +Пример результата: + +![скриншот модального окна поиска](/search.png) + +В качестве альтернативы можно использовать [Algolia DocSearch](#algolia-search) или некоторые плагины сообщества, например: + +- +- +- + +### i18n {#local-search-i18n} + +Пример конфигурации для использования многоязычного поиска: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + locales: { + ru: { // используйте ключ `root`, если хотите перевести локаль по умолчанию + translations: { + button: { + buttonText: 'Поиск', + buttonAriaLabel: 'Поиск' + }, + modal: { + displayDetails: 'Отобразить подробный список', + resetButtonTitle: 'Сбросить поиск', + backButtonTitle: 'Закрыть поиск', + noResultsText: 'Нет результатов по запросу', + footer: { + selectText: 'выбрать', + selectKeyAriaLabel: 'выбрать', + navigateText: 'перейти', + navigateUpKeyAriaLabel: 'стрелка вверх', + navigateDownKeyAriaLabel: 'стрелка вниз', + closeText: 'закрыть', + closeKeyAriaLabel: 'esc' + } + } + } + } + } + } + } + } +}) +``` + +### Параметры MiniSearch {#minisearch-options} + +Вы можете настроить MiniSearch следующим образом: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + miniSearch: { + /** + * @type {Pick} + */ + options: { + /* ... */ + }, + /** + * @type {import('minisearch').SearchOptions} + * @default + * { fuzzy: 0.2, prefix: true, boost: { title: 4, text: 2, titles: 1 } } + */ + searchOptions: { + /* ... */ + } + } + } + } + } +}) +``` + +Подробнее в [документации MiniSearch](https://lucaong.github.io/minisearch/classes/MiniSearch.MiniSearch.html). + +### Пользовательский рендерер содержимого {#custom-content-renderer} + +Вы можете настроить функцию, используемую для отображения содержимого в формате Markdown перед его индексацией: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + /** + * @param {string} src + * @param {import('vitepress').MarkdownEnv} env + * @param {import('markdown-it-async')} md + */ + async _render(src, env, md) { + // возвращаем html + } + } + } + } +}) +``` + +Эта функция будет очищена от данных сайта на стороне клиента, поэтому вы можете использовать в ней API Node.js. + +#### Пример: Исключение страниц из поиска {#example-excluding-pages-from-search} + +Вы можете исключить страницы из поиска, добавив `search: false` в блок метаданных страницы. Альтернативный вариант: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + async _render(src, env, md) { + const html = await md.renderAsync(src, env) + if (env.frontmatter?.search === false) return '' + if (env.relativePath.startsWith('some/path')) return '' + return html + } + } + } + } +}) +``` + +::: warning ПРИМЕЧАНИЕ +В случае, если предоставляется пользовательская функция `_render`, вам нужно самостоятельно обработать заголовок `search: false`. Кроме того, объект `env` не будет полностью заполнен до вызова `md.renderAsync`, поэтому любые проверки необязательных свойств `env`, таких как `frontmatter`, должны быть выполнены после этого. +::: + +#### Пример: Преобразование содержимого - добавление якорей {#example-transforming-content-adding-anchors} + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + async _render(src, env, md) { + const html = await md.renderAsync(src, env) + if (env.frontmatter?.title) + return await md.renderAsync(`# ${env.frontmatter.title}`) + html + return html + } + } + } + } +}) +``` + +## Поиск Algolia {#algolia-search} + +VitePress поддерживает поиск в вашей документации с помощью [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch). Обратитесь к руководству по началу работы. В файле `.vitepress/config.ts` вам нужно будет указать, по крайней мере, следующее, чтобы всё работало: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'algolia', + options: { + appId: '...', + apiKey: '...', + indexName: '...' + } + } + } +}) +``` + +### i18n {#algolia-search-i18n} + +Пример конфигурации для использования многоязычного поиска: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'algolia', + options: { + appId: '...', + apiKey: '...', + indexName: '...', + locales: { + ru: { + placeholder: 'Поиск в документации', + translations: { + button: { + buttonText: 'Поиск', + buttonAriaLabel: 'Поиск' + }, + modal: { + searchBox: { + resetButtonTitle: 'Сбросить поиск', + resetButtonAriaLabel: 'Сбросить поиск', + cancelButtonText: 'Отменить поиск', + cancelButtonAriaLabel: 'Отменить поиск' + }, + startScreen: { + recentSearchesTitle: 'История поиска', + noRecentSearchesText: 'Нет истории поиска', + saveRecentSearchButtonTitle: 'Сохранить в истории поиска', + removeRecentSearchButtonTitle: 'Удалить из истории поиска', + favoriteSearchesTitle: 'Избранное', + removeFavoriteSearchButtonTitle: 'Удалить из избранного' + }, + errorScreen: { + titleText: 'Невозможно получить результаты', + helpText: + 'Вам может потребоваться проверить подключение к Интернету' + }, + footer: { + selectText: 'выбрать', + navigateText: 'перейти', + closeText: 'закрыть', + searchByText: 'поставщик поиска' + }, + noResultsScreen: { + noResultsText: 'Нет результатов для', + suggestedQueryText: 'Вы можете попытаться узнать', + reportMissingResultsText: + 'Считаете, что поиск даёт ложные результаты?', + reportMissingResultsLinkText: + 'Нажмите на кнопку «Обратная связь»' + } + } + } + } + } + } + } + } +}) +``` + +[Эти параметры](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts) можно переопределить. Чтобы узнать о них больше, обратитесь к официальной документации Algolia. + +### Конфигурация поискового робота {#crawler-config} + +Вот пример конфигурации, основанной на той, что используется на этом сайте: + +```ts +new Crawler({ + appId: '...', + apiKey: '...', + rateLimit: 8, + startUrls: ['https://vitepress.dev/'], + renderJavaScript: false, + sitemaps: [], + exclusionPatterns: [], + ignoreCanonicalTo: false, + discoveryPatterns: ['https://vitepress.dev/**'], + schedule: 'at 05:10 on Saturday', + actions: [ + { + indexName: 'vitepress', + pathsToMatch: ['https://vitepress.dev/**'], + recordExtractor: ({ $, helpers }) => { + return helpers.docsearch({ + recordProps: { + lvl1: '.content h1', + content: '.content p, .content li', + lvl0: { + selectors: 'section.has-active div h2', + defaultValue: 'Documentation' + }, + lvl2: '.content h2', + lvl3: '.content h3', + lvl4: '.content h4', + lvl5: '.content h5' + }, + indexHeadings: true + }) + } + } + ], + initialIndexSettings: { + vitepress: { + attributesForFaceting: ['type', 'lang'], + attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'], + attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'], + attributesToSnippet: ['content:10'], + camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'], + searchableAttributes: [ + 'unordered(hierarchy_radio_camel.lvl0)', + 'unordered(hierarchy_radio.lvl0)', + 'unordered(hierarchy_radio_camel.lvl1)', + 'unordered(hierarchy_radio.lvl1)', + 'unordered(hierarchy_radio_camel.lvl2)', + 'unordered(hierarchy_radio.lvl2)', + 'unordered(hierarchy_radio_camel.lvl3)', + 'unordered(hierarchy_radio.lvl3)', + 'unordered(hierarchy_radio_camel.lvl4)', + 'unordered(hierarchy_radio.lvl4)', + 'unordered(hierarchy_radio_camel.lvl5)', + 'unordered(hierarchy_radio.lvl5)', + 'unordered(hierarchy_radio_camel.lvl6)', + 'unordered(hierarchy_radio.lvl6)', + 'unordered(hierarchy_camel.lvl0)', + 'unordered(hierarchy.lvl0)', + 'unordered(hierarchy_camel.lvl1)', + 'unordered(hierarchy.lvl1)', + 'unordered(hierarchy_camel.lvl2)', + 'unordered(hierarchy.lvl2)', + 'unordered(hierarchy_camel.lvl3)', + 'unordered(hierarchy.lvl3)', + 'unordered(hierarchy_camel.lvl4)', + 'unordered(hierarchy.lvl4)', + 'unordered(hierarchy_camel.lvl5)', + 'unordered(hierarchy.lvl5)', + 'unordered(hierarchy_camel.lvl6)', + 'unordered(hierarchy.lvl6)', + 'content' + ], + distinct: true, + attributeForDistinct: 'url', + customRanking: [ + 'desc(weight.pageRank)', + 'desc(weight.level)', + 'asc(weight.position)' + ], + ranking: [ + 'words', + 'filters', + 'typo', + 'attribute', + 'proximity', + 'exact', + 'custom' + ], + highlightPreTag: '', + highlightPostTag: '', + minWordSizefor1Typo: 3, + minWordSizefor2Typos: 7, + allowTyposOnNumericTokens: false, + minProximity: 1, + ignorePlurals: true, + advancedSyntax: true, + attributeCriteriaComputedByMinProximity: true, + removeWordsIfNoResults: 'allOptional' + } + } +}) +``` diff --git a/docs/ru/reference/default-theme-sidebar.md b/docs/ru/reference/default-theme-sidebar.md new file mode 100644 index 00000000..bdc6e338 --- /dev/null +++ b/docs/ru/reference/default-theme-sidebar.md @@ -0,0 +1,180 @@ +# Сайдбар {#sidebar} + +Сайдбар (боковая панель) — основной навигационный блок вашей документации. Меню боковой панели можно настроить в секции [`themeConfig.sidebar`](./default-theme-config#sidebar). + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Руководство', + items: [ + { text: 'Введение', link: '/ru/introduction' }, + { text: 'Первые шаги', link: '/ru/getting-started' }, + ... + ] + } + ] + } +} +``` + +## Основы {#the-basics} + +Простейшая форма сайдбара — это передача массива ссылок. Элемент первого уровня определяет «секцию» сайдбара. Он должен содержать `text`, который является заголовком секции, и `items`, которые являются фактическими навигационными ссылками. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Заголовок секции A', + items: [ + { text: 'Пункт A', link: '/item-a' }, + { text: 'Пункт B', link: '/item-b' }, + ... + ] + }, + { + text: 'Заголовок секции B', + items: [ + { text: 'Пункт C', link: '/item-c' }, + { text: 'Пункт D', link: '/item-d' }, + ... + ] + } + ] + } +} +``` + +Каждый элемент `link` должен указывать путь к фактическому файлу, начинающийся с `/`. Если добавить в конец ссылки косую черту, то будет показан `index.md` соответствующего каталога. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Руководство', + items: [ + // Ссылка на страницу `/ru/guide/index.md` + { text: 'Введение', link: '/ru/guide/' } + ] + } + ] + } +} +``` + +Вы можете вложить элементы боковой панели на 6 уровней вглубь, считая от корневого уровня. Обратите внимание, что более 6 уровней вложенных элементов будут игнорироваться и не отображаться на боковой панели. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Уровень 1', + items: [ + { + text: 'Уровень 2', + items: [ + { + text: 'Уровень 3', + items: [ + ... + ] + } + ] + } + ] + } + ] + } +} +``` + +## Несколько сайдбаров {#multiple-sidebars} + +Вы можете показывать разные боковые панели в зависимости от текущего маршрута. Например, как показано на этом сайте, вы можете создать в документации отдельные разделы, например, «Руководство» и «Настройка». + +Для этого сначала организуйте страницы в каталоги для каждого нужного раздела: + +``` +. +├─ guide/ +│ ├─ index.md +│ ├─ one.md +│ └─ two.md +└─ config/ + ├─ index.md + ├─ three.md + └─ four.md +``` + +Затем обновите конфигурацию, чтобы определить боковую панель для каждого раздела. На этот раз вместо массива нужно передать объект. + +```js +export default { + themeConfig: { + sidebar: { + // Эта боковая панель отображается, когда пользователь находится в директории `guide` + '/guide/': [ + { + text: 'Руководство', + items: [ + { text: 'Index', link: '/guide/' }, + { text: 'One', link: '/guide/one' }, + { text: 'Two', link: '/guide/two' } + ] + } + ], + + // Эта боковая панель отображается, когда пользователь находится в директории `config` + '/config/': [ + { + text: 'Настройка', + items: [ + { text: 'Index', link: '/config/' }, + { text: 'Three', link: '/config/three' }, + { text: 'Four', link: '/config/four' } + ] + } + ] + } + } +} +``` + +## Сворачиваемые группы {#collapsible-sidebar-groups} + +Добавив опцию `collapsed` внутри группы `sidebar`, вы увидите кнопку переключения для скрытия/показа каждой секции. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Заголовок секции A', + collapsed: false, + items: [...] + } + ] + } +} +``` + +Все секции «развёрнуты» по умолчанию. Если вы хотите, чтобы они были «свёрнуты» при первоначальной загрузке страницы, установите для опции `collapsed` значение `true`. + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Заголовок секции A', + collapsed: true, + items: [...] + } + ] + } +} +``` diff --git a/docs/ru/reference/default-theme-team-page.md b/docs/ru/reference/default-theme-team-page.md new file mode 100644 index 00000000..615692bb --- /dev/null +++ b/docs/ru/reference/default-theme-team-page.md @@ -0,0 +1,252 @@ + + +# Страница команды {#team-page} + +Если вы хотите представить свою команду, вы можете использовать компоненты Team для создания страницы команды. Есть два варианта использования этих компонентов. Один из вариантов — встроить их в страницу с макетом `doc`, а другой — создать полноценную страницу команды. + +## Отображение членов команды на странице {#show-team-members-in-a-page} + +Вы можете использовать компонент ``, доступный из `vitepress/theme`, для отображения списка членов команды на любой странице. + +```html + + +# Поприветствуйте нашу замечательную команду + + +``` + +Вышеуказанное отобразит члена команды в виде карточки. Должно отобразиться что-то похожее на то, что показано ниже. + + + +Компонент `` поставляется в двух различных размерах, `small` и `medium`. Хотя это зависит от ваших предпочтений, обычно размер `small` лучше подходит для использования на странице с макетом `doc`. Кроме того, вы можете добавить дополнительные свойства для карточки члена команды, например, добавить «описание» или кнопку «спонсировать». Подробнее об этом в секции [``](#vpteammembers). + +Встраивание членов команды в страницу документа хорошо подходит для небольших команд, где наличие полной страницы команды может быть слишком большим, или для представления частичных членов команды в качестве ссылки на контекст документации. + +Если у вас большое количество участников или вы просто хотите иметь больше места для отображения членов команды, подумайте о [создании отдельной страницы команды](#create-a-full-team-page). + +## Создание отдельной страницы команды {#create-a-full-team-page} + +Вместо того чтобы добавлять членов команды на страницу с макетом `doc`, вы можете создать полноценную страницу команды, подобно созданию пользовательской [главной страницы](./default-theme-home-page). + +Чтобы создать страницу команды, сначала создайте новый md-файл. Имя файла не имеет значения, но здесь мы назовем его `team.md`. В этом файле установите в блоке метаданных параметр `layout: page`, а затем вы можете организовать структуру страницы, используя компоненты `TeamPage`. + +```html +--- +layout: page +--- + + + + + + + + + + +``` + +При создании полной страницы команды не забудьте обернуть все компоненты компонентом ``. Этот компонент обеспечит всем вложенным компонентам, связанным с командой, правильную структуру макета, например, расстояние между ними. + +Компонент `` добавляет блок заголовка страницы. Заголовок — это тег `

`. Используйте слоты `#title` и `#lead`, чтобы рассказать о своей команде. + +`` работает так же, как и при использовании в doc-странице. Отобразится список участников. + +### Добавление секций для разделения членов команды {#add-sections-to-divide-team-members} + +Вы можете добавить «секции» на страницу команды. Например, у вас могут быть разные типы членов команды, такие как члены основной команды и партнёры сообщества. Вы можете разделить этих членов на секции, чтобы лучше объяснить роли каждой группы. + +Для этого добавьте компонент `` в файл `team.md`, который мы создали ранее. + +```html +--- +layout: page +--- + + + + + + + + + + + + + + + +``` + +Компонент `` может иметь слоты `#title` и `#lead`, аналогичные компоненту `VPTeamPageTitle`, а также слот `#members` для отображения членов команды. + +Не забудьте поместить компонент `` в слот `#members`. + +## `` {#vpteammembers} + +Компонент `` отображает заданный список членов команды. + +```html + +``` + +```ts +interface Props { + // Размер карточки каждого члена команды. По умолчанию `medium`. + size?: 'small' | 'medium' + + // Список членов команды для отображения. + members: TeamMember[] +} + +interface TeamMember { + // Изображение аватара. + avatar: string + + // Имя члена команды. + name: string + + // Заголовок, отображаемый под именем члена команды. + // например: разработчик, инженер-программист и т. д. + title?: string + + // Организация, в которой состоит текущий член команды. + org?: string + + // URL-адрес сайта организации. + orgLink?: string + + // Описание члена команды. + desc?: string + + // Социальные ссылки: GitHub, Twitter и т. д. + // Могут быть переданы в виде объекта. + // См. https://vitepress.dev/reference/default-theme-config.html#sociallinks + links?: SocialLink[] + + // URL-адрес спонсорской страницы члена команды. + sponsor?: string + + // Текст спонсорской ссылки. По умолчанию 'Sponsor'. + actionText?: string +} +``` + +## `` {#vpteampage} + +Корневой компонент при создании отдельной страницы команды. Принимает только один слот. Он будет стилизовать все передаваемые компоненты, связанные с командой. + +## `` {#vpteampagetitle} + +Добавляет блок «заголовка» страницы. Лучше всего использовать в самом начале внутри ``. Принимает слоты `#title` и `#lead`. + +```html + + + + + + +``` + +## `` {#vpteampagesection} + +Создает «секцию» на странице команды. Принимает слоты `#title`, `#lead` и `#members`. Внутри `` вы можете добавить столько секций, сколько захотите. + +```html + + ... + + + + + + +``` diff --git a/docs/ru/reference/frontmatter-config.md b/docs/ru/reference/frontmatter-config.md new file mode 100644 index 00000000..70151fd7 --- /dev/null +++ b/docs/ru/reference/frontmatter-config.md @@ -0,0 +1,240 @@ +--- +outline: deep +--- + +# Конфигурация метаданных {#frontmatter-config} + +Метаданные обеспечивают настройку отдельных страниц. В каждом файле Markdown можно использовать метаданные, чтобы переопределить параметры конфигурации сайта или темы. Кроме того, есть параметры конфигурации, которые можно задать только через метаданные. + +Пример использования: + +```md +--- +title: Документация с VitePress +editLink: true +--- +``` + +Вы можете получить доступ к метаданным через глобальный объект `$frontmatter` в выражениях Vue: + +```md +{{ $frontmatter.title }} +``` + +## title + +- Тип: `string` + +Заголовок страницы. Это то же самое, что [config.title](./site-config#title), и оно переопределяет конфигурацию сайта. + +```yaml +--- +title: VitePress +--- +``` + +## titleTemplate + +- Тип: `string | boolean` + +Суффикс для названия. Это то же самое, что и [config.titleTemplate](./site-config#titletemplate), и оно переопределяет конфигурацию сайта. + +```yaml +--- +title: VitePress +titleTemplate: Генератор статических сайтов на основе Vite и Vue +--- +``` + +## description + +- Тип: `string` + +Описание для страницы. Это то же самое, что и [config.description](./site-config#description), и оно переопределяет конфигурацию сайта. + +```yaml +--- +description: VitePress +--- +``` + +## head + +- Тип: `HeadConfig[]` + +Укажите дополнительные теги, которые будут выводиться для текущей страницы. Они будут добавляться после других тегов внутри блока head, введённых в конфигурации сайта. + +```yaml +--- +head: + - - meta + - name: description + content: привет + - - meta + - name: keywords + content: супер-пупер SEO +--- +``` + +```ts +type HeadConfig = + | [string, Record] + | [string, Record, string] +``` + +## Только для темы по умолчанию {#default-theme-only} + +Следующие параметры метаданных применимы только при использовании темы по умолчанию. + +### layout + +- Тип: `doc | home | page` +- По умолчанию: `doc` + +Определяет макет страницы. + +- `doc` - Применяет стили документации по умолчанию к содержимому Markdown. +- `home` - Вы можете добавить дополнительные параметры, такие как `hero` и `features`, чтобы быстро создать красивую целевую страницу. +- `page` - Ведет себя аналогично `doc`, но не применяет стили к содержимому. Полезно, если вы хотите создать полностью настраиваемую страницу. + +```yaml +--- +layout: doc +--- +``` + +### hero + +Определяет содержимое секции `hero`, когда `layout` имеет значение `home`. Подробнее в главе [Тема по умолчанию: Главная страница](./default-theme-home-page). + +### features + +Определяет элементы для отображения в секции `features`, когда `layout` имеет значение `home`. Подробнее в главе [Тема по умолчанию: Главная страница](./default-theme-home-page). + +### navbar + +- Тип: `boolean` +- По умолчанию: `true` + +Отображать ли [панель навигации](./default-theme-nav). + +```yaml +--- +navbar: false +--- +``` + +### sidebar + +- Тип: `boolean` +- По умолчанию: `true` + +Отображать ли [сайдбар](./default-theme-sidebar). + +```yaml +--- +sidebar: false +--- +``` + +### aside + +- Тип: `boolean | 'left'` +- По умолчанию: `true` + +Определяет расположение компонента aside в макете `doc`. + +Установка этого значения в `false` предотвращает отрисовку контейнера сайдбара.\ +Установка этого значения в `true` приведёт к отображению сайдбара справа.\ +Установка этого значения в `left` приведёт к отображению сайдбара слева. + +```yaml +--- +aside: false +--- +``` + +### outline + +- Тип: `number | [number, number] | 'deep' | false` +- По умолчанию: `2` + +Уровни заголовков в оглавлении для отображения на странице. Это то же самое, что и [config.themeConfig.outline.level](./default-theme-config#outline), и оно переопределяет значение, установленное в конфигурации сайта. + +```yaml +--- +outline: [2, 4] +--- +``` + +### lastUpdated + +- Тип: `boolean | Date` +- По умолчанию: `true` + +Отображать ли текст [Обновлено](./default-theme-last-updated) в футере текущей страницы. Если указано время даты, оно будет отображаться вместо временной метки последнего изменения git. + +```yaml +--- +lastUpdated: false +--- +``` + +### editLink + +- Тип: `boolean` +- По умолчанию: `true` + +Отображать ли [ссылку для редактирования](./default-theme-edit-link) в футере текущей страницы. + +```yaml +--- +editLink: false +--- +``` + +### footer + +- Тип: `boolean` +- По умолчанию: `true` + +Отображать ли [футер](./default-theme-footer). + +```yaml +--- +footer: false +--- +``` + +### pageClass + +- Тип: `string` + +Добавьте дополнительное имя класса на определённую страницу. + +```yaml +--- +pageClass: custom-page-class +--- +``` + +Вы также можете настроить стили этой конкретной страницы в файле `.vitepress/theme/custom.css`: + +```css +.custom-page-class { + /* стили для конкретной страницы */ +} +``` + +### isHome + +- Тип: `boolean` + +Стандартная тема полагается на проверки типа `frontmatter.layout === 'home'`, чтобы определить, является ли текущая страница домашней (главной).\ +Это полезно, когда вы хотите принудительно показывать элементы домашней страницы в пользовательском макете. + +```yaml +--- +isHome: true +--- +``` diff --git a/docs/ru/reference/runtime-api.md b/docs/ru/reference/runtime-api.md new file mode 100644 index 00000000..f1bfe6d8 --- /dev/null +++ b/docs/ru/reference/runtime-api.md @@ -0,0 +1,165 @@ +# Runtime API {#runtime-api} + +VitePress предлагает несколько встроенных API, позволяющих получить доступ к данным приложения. VitePress также поставляется с несколькими встроенными компонентами, которые можно использовать глобально. + +Вспомогательные методы глобально импортируются из `vitepress` и обычно используются в компонентах Vue для пользовательских тем. Однако их можно использовать и внутри страниц `.md`, так как файлы markdown компилируются в [однофайловые компоненты](https://ru.vuejs.org/guide/scaling-up/sfc.html) Vue. + +Методы, начинающиеся с `use*`, указывают на то, что это функция [Vue 3 Composition API](https://ru.vuejs.org/guide/introduction.html#composition-api) («композабл»), которая может быть использована только внутри `setup()` или ` + + +``` + +## `useRoute` {#useroute} + +Возвращает текущий объект маршрута со следующим типом: + +```ts +interface Route { + path: string + data: PageData + component: Component | null +} +``` + +## `useRouter` {#userouter} + +Возвращает экземпляр маршрутизатора VitePress, чтобы вы могли программно перейти на другую страницу. + +```ts +interface Router { + /** + * Текущий маршрут. + */ + route: Route + /** + * Переход к новому URL-адресу. + */ + go: (to?: string) => Promise + /** + * Вызывается перед изменением маршрута. Верните `false`, чтобы отменить навигацию. + */ + onBeforeRouteChange?: (to: string) => Awaitable + /** + * Вызывается перед загрузкой компонента страницы (после того, как состояние истории + * обновлено). Верните `false`, чтобы отменить навигацию. + */ + onBeforePageLoad?: (to: string) => Awaitable + /** + * Вызывается после изменения маршрута. + */ + onAfterRouteChange?: (to: string) => Awaitable +} +``` + +## `withBase` {#withbase} + +- **Тип**: `(path: string) => string` + +Добавляет настроенный [`base`](./site-config#base) к заданному URL-пути. Также смотрите секцию [Базовый URL](../guide/asset-handling#base-url). + +## `` {#content} + +Компонент `` отображает отрисованное содержимое Markdown. Полезно [при создании собственной темы](../guide/custom-theme). + +```vue + +``` + +## `` {#clientonly} + +Компонент `` отображает свой слот только на стороне клиента. + +Поскольку приложения VitePress при генерации статических сборок рендерятся в Node.js, любое использование Vue должно соответствовать универсальным требованиям к коду. Короче говоря, убедитесь, что доступ к API Browser / DOM осуществляется только в хуках `beforeMount` или `mounted`. + +Если вы используете или демонстрируете компоненты, которые не являются SSR-дружественными (например, содержат пользовательские директивы), вы можете обернуть их внутри компонента `ClientOnly`. + +```vue-html + + + +``` + +- См. также: [Совместимость с SSR](../guide/ssr-compat) + +## `$frontmatter` {#frontmatter} + +Прямой доступ к [метаданным](../guide/frontmatter) текущей страницы в выражениях Vue. + +```md +--- +title: Привет +--- + +# {{ $frontmatter.title }} +``` + +## `$params` {#params} + +Прямой доступ к параметрам [динамических маршрутов](../guide/routing#dynamic-routes) текущей страницы в выражениях Vue. + +```md +- имя пакета: {{ $params.pkg }} +- версия: {{ $params.version }} +``` diff --git a/docs/ru/reference/site-config.md b/docs/ru/reference/site-config.md new file mode 100644 index 00000000..50bd132c --- /dev/null +++ b/docs/ru/reference/site-config.md @@ -0,0 +1,722 @@ +--- +outline: deep +--- + +# Конфигурация сайта {#site-config} + +Конфигурация сайта — это место, где вы можете определить глобальные настройки сайта. Параметры конфигурации приложения определяют настройки, которые применяются к каждому сайту VitePress, независимо от того, какая тема на нем используется. Например, базовый каталог или название сайта. + +## Обзор {#overview} + +### Разрешение конфигурации {#config-resolution} + +Конфигурация всегда считывается из файла `/.vitepress/config.[ext]`, где `` — это корень вашего [проекта](../guide/routing#root-and-source-directory) VitePress, а `[ext]` — одно из поддерживаемых расширений файла. TypeScript поддерживается из коробки. Поддерживаемые расширения включают `.js`, `.ts`, `.mjs` и `.mts`. + +В файлах конфигурации рекомендуется использовать синтаксис ES-модулей. Файл конфигурации должен по умолчанию экспортировать объект: + +```ts +export default { + // параметры конфигурации на уровне приложения + lang: 'ru-RU', + title: 'VitePress', + description: 'Генератор статических сайтов на основе Vite и Vue.', + ... +} +``` + +:::details Динамическая (асинхронная) конфигурация + +Если вам нужно генерировать конфигурацию динамически, вы также можете экспортировать функцию по умолчанию. Например: + +```ts +import { defineConfig } from 'vitepress' + +export default async () => { + const posts = await (await fetch('https://my-cms.com/blog-posts')).json() + + return defineConfig({ + // параметры конфигурации на уровне приложения + lang: 'ru-RU', + title: 'VitePress', + description: 'Генератор статических сайтов на основе Vite и Vue.', + + // параметры конфигурации на уровне темы + themeConfig: { + sidebar: [ + ...posts.map((post) => ({ + text: post.name, + link: `/posts/${post.name}` + })) + ] + } + }) +} +``` + +Вы также можете использовать `await` верхнего уровня. Например: + +```ts +import { defineConfig } from 'vitepress' + +const posts = await (await fetch('https://my-cms.com/blog-posts')).json() + +export default defineConfig({ + // параметры конфигурации на уровне приложения + lang: 'ru-RU', + title: 'VitePress', + description: 'Генератор статических сайтов на основе Vite и Vue.', + + // параметры конфигурации на уровне темы + themeConfig: { + sidebar: [ + ...posts.map((post) => ({ + text: post.name, + link: `/posts/${post.name}` + })) + ] + } +}) +``` + +::: + +### Интеллектуальная настройка {#config-intellisense} + +Использование помощника `defineConfig` обеспечит интеллектуальный анализ опций конфигурации на основе TypeScript. Если ваша IDE поддерживает эту функцию, она должна работать как в JavaScript, так и в TypeScript. + +```js +import { defineConfig } from 'vitepress' + +export default defineConfig({ + // ... +}) +``` + +### Типизированная конфигурация темы {#typed-theme-config} + +По умолчанию помощник `defineConfig` ожидает тип конфигурации темы из темы по умолчанию: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + // Тип `DefaultTheme.Config` + } +}) +``` + +Если вы используете пользовательскую тему и хотите проверять типы для конфигурации темы, вам нужно использовать `defineConfigWithTheme`, и передавать тип конфигурации для вашей пользовательской темы через общий аргумент: + +```ts +import { defineConfigWithTheme } from 'vitepress' +import type { ThemeConfig } from 'your-theme' + +export default defineConfigWithTheme({ + themeConfig: { + // Tип `ThemeConfig` + } +}) +``` + +### Настройка Vite, Vue и Markdown {#vite-vue-markdown-config} + +- **Vite** + + Вы можете настроить базовый экземпляр Vite с помощью опции [vite](#vite) в конфигурации VitePress. Нет необходимости создавать отдельный файл конфигурации Vite. + +- **Vue** + + VitePress уже включает в себя официальный плагин Vue для Vite ([@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue)). Вы можете настроить его параметры с помощью опции [vue](#vue) в конфигурации VitePress. + +- **Markdown** + + Вы можете настроить базовый экземпляр [Markdown-It](https://github.com/markdown-it/markdown-it) с помощью опции [markdown](#markdown) в конфигурации VitePress. + +## Метаданные сайта {#site-metadata} + +### title {#title} + +- Тип: `string` +- По умолчанию: `VitePress` +- Можно переопределить для каждой страницы с помощью [метаданных](./frontmatter-config#title) + +Название для сайта. При использовании темы по умолчанию оно будет отображаться в панели навигации. + +Оно также будет использоваться в качестве суффикса по умолчанию для всех заголовков отдельных страниц, если не определен [`titleTemplate`](#titletemplate). Окончательный заголовок отдельной страницы будет представлять собой текстовое содержимое её первого заголовка `

`, объединённое с глобальным `title` в качестве суффикса. Например, со следующей конфигурацией и содержимым страницы: + +```ts +export default { + title: 'Мой замечательный сайт' +} +``` + +```md +# Привет +``` + +Заголовок страницы будет таким: `Привет | Мой замечательный сайт`. + +### titleTemplate {##titletemplate} + +- Тип: `string | boolean` +- Можно переопределить для каждой страницы с помощью [метаданных](./frontmatter-config#titletemplate) + +Позволяет настраивать суффикс заголовка каждой страницы или весь заголовок. Например: + +```ts +export default { + title: 'Мой замечательный сайт', + titleTemplate: 'Пользовательский суффикс' +} +``` + +```md +# Привет +``` + +Заголовок страницы будет таким: `Привет | Пользовательский суффикс`. + +Чтобы полностью настроить отображение заголовка, вы можете использовать символ `:title` в `titleTemplate`: + +```ts +export default { + titleTemplate: ':title - Пользовательский суффикс' +} +``` + +Здесь `:title` будет заменён текстом, выведенным из первого заголовка страницы `

`. Заголовок страницы предыдущего примера будет `Привет - Пользовательский суффикс`. + +Опция может быть установлена в значение `false`, чтобы отключить суффиксы заголовков. + +### description {#description} + +- Тип: `string` +- По умолчанию: `A VitePress site` +- Можно переопределить для каждой страницы с помощью [метаданных](./frontmatter-config#description) + +Описание для сайта. Это будет отображаться как тег `` в HTML-странице. + +```ts +export default { + description: 'A VitePress site' +} +``` + +### head {#head} + +- Тип: `HeadConfig[]` +- По умолчанию: `[]` +- Можно добавлять на страницу через [метаданные](./frontmatter-config#head) + +Дополнительные элементы для отображения в теге `` в HTML-странице. Добавленные пользователем теги выводятся перед закрывающим тегом `head`, после тегов VitePress. + +```ts +type HeadConfig = + | [string, Record] + | [string, Record, string] +``` + +#### Пример: Добавление значка сайта {#example-adding-a-favicon} + +```ts +export default { + head: [['link', { rel: 'icon', href: '/favicon.ico' }]] +} // поместите favicon.ico в публичную директорию; если установлен параметр base, используйте /base/favicon.ico + +/* Отрисуется так: + +*/ +``` + +#### Пример: Добавление шрифтов Google {#example-adding-google-fonts} + +```ts +export default { + head: [ + ['link', { rel: 'preconnect', href: 'https://fonts.googleapis.com' }], + [ + 'link', + { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: '' } + ], + [ + 'link', + { + href: 'https://fonts.googleapis.com/css2?family=Roboto&display=swap', + rel: 'stylesheet' + } + ] + ] +} + +/* Отрисуется так: + + + +*/ +``` + +#### Пример: Регистрация сервис-воркера {#example-registering-a-service-worker} + +```ts +export default { + head: [ + [ + 'script', + { id: 'register-sw' }, + `;(() => { + if ('serviceWorker' in navigator) { + navigator.serviceWorker.register('/sw.js') + } + })()` + ] + ] +} + +/* Отрисуется так: + +*/ +``` + +#### Пример: Использование Google Analytics {#example-using-google-analytics} + +```ts +export default { + head: [ + [ + 'script', + { async: '', src: 'https://www.googletagmanager.com/gtag/js?id=TAG_ID' } + ], + [ + 'script', + {}, + `window.dataLayer = window.dataLayer || []; + function gtag(){dataLayer.push(arguments);} + gtag('js', new Date()); + gtag('config', 'TAG_ID');` + ] + ] +} + +/* Отрисуется так: + + +*/ +``` + +### lang {#lang} + +- Тип: `string` +- По умолчанию: `en-US` + +Атрибут lang для сайта. Будет выглядеть как тег `` в HTML-странице. + +```ts +export default { + lang: 'en-US' +} +``` + +### base {#base} + +- Тип: `string` +- По умолчанию: `/` + +Базовый URL-адрес, по которому будет развёрнут сайт. Этот параметр необходимо задать, если вы планируете развернуть свой сайт по подпути, например, для страниц GitHub. Если вы планируете развернуть свой сайт на `https://foo.github.io/bar/`, то вам следует установить base на `'/bar/'`. Он всегда должен начинаться и заканчиваться косой чертой. + +Параметр `base` автоматически добавляется ко всем URL, которые начинаются с `/` в других опциях, поэтому вам нужно указать его только один раз. + +```ts +export default { + base: '/base/' +} +``` + +## Маршрутизация {#routing} + +### cleanUrls {#cleanurls} + +- Тип: `boolean` +- По умолчанию: `false` + +Если установить значение `true`, VitePress будет удалять из URL-адресов завершающий `.html`. Также смотрите [Создание чистого URL-адреса](../guide/routing#generating-clean-url). + +::: warning Требуется поддержка сервера +Для включения этой функции может потребоваться дополнительная настройка на вашей хостинговой платформе. Чтобы это сработало, ваш сервер должен быть способен обслуживать `/foo.html` при посещении `/foo` **без редиректа**. +::: + +### rewrites {#rewrites} + +- Тип: `Record` + +Определяет сопоставление пользовательских каталогов с URL-адресами. Дополнительную информацию см. в секции [Маршрутизация: перезапись маршрутов](../guide/routing#route-rewrites). + +```ts +export default { + rewrites: { + 'source/:page': 'destination/:page' + } +} +``` + +## Сборка {#build} + +### srcDir {#srcdir} + +- Тип: `string` +- По умолчанию: `.` + +Каталог, в котором хранятся ваши страницы в формате Markdown, относительно корня проекта. Также смотрите [Корневая директория и директория с исходными файлами](../guide/routing#root-and-source-directory). + +```ts +export default { + srcDir: './src' +} +``` + +### srcExclude {#srcexclude} + +- Тип: `string[]` +- По умолчанию: `undefined` + +[Шаблон](https://github.com/mrmlnc/fast-glob#pattern-syntax) для поиска файлов, которые должны быть исключены из исходного содержимого. + +```ts +export default { + srcExclude: ['**/README.md', '**/TODO.md'] +} +``` + +### outDir {#outdir} + +- Тип: `string` +- По умолчанию: `./.vitepress/dist` + +Расположение вывода сборки для сайта, относительно [корня проекта](../guide/routing#root-and-source-directory). + +```ts +export default { + outDir: '../public' +} +``` + +### assetsDir {#assetsdir} + +- Тип: `string` +- По умолчанию: `assets` + +Укажите каталог, в котором будут храниться сгенерированные ресурсы. Путь должен находиться внутри [`outDir`](#outdir) и разрешается относительно него. + +```ts +export default { + assetsDir: 'static' +} +``` + +### cacheDir {#cachedir} + +- Тип: `string` +- По умолчанию: `./.vitepress/cache` + +Каталог для файлов кэша, относительно [корня проекта](../guide/routing#root-and-source-directory). См. также: [cacheDir](https://vitejs.dev/config/shared-options.html#cachedir). + +```ts +export default { + cacheDir: './.vitepress/.vite' +} +``` + +### ignoreDeadLinks {#ignoredeadlinks} + +- Тип: `boolean | 'localhostLinks' | (string | RegExp | ((link: string) => boolean))[]` +- По умолчанию: `false` + +Если установлено значение `true`, VitePress не будет завершать сборку из-за неработающих ссылок. + +Если установить значение `'localhostLinks'`, сборка будет завершаться при наличии неработающих ссылок, но не будет проверять ссылки `localhost`. + +```ts +export default { + ignoreDeadLinks: true +} +``` + +Это также может быть массив точных строк url, шаблонов regex или пользовательских функций фильтрации. + +```ts +export default { + ignoreDeadLinks: [ + // игнорировать url "/playground" + '/playground', + // игнорировать все ссылки на localhost + /^https?:\/\/localhost/, + // игнорировать все ссылки, включающие "/repl/"" + /\/repl\//, + // пользовательская функция, игнорирует все ссылки, включающие "ignore" + (url) => { + return url.toLowerCase().includes('ignore') + } + ] +} +``` + +### metaChunk {#metachunk} + +- Тип: `boolean` +- По умолчанию: `false` + +Если установлено значение `true`, метаданные страницы извлекаются в отдельный фрагмент JavaScript, а не вставляются в исходный HTML. Это уменьшает полезную нагрузку HTML каждой страницы и делает метаданные страниц кэшируемыми, что позволяет снизить пропускную способность сервера при наличии большого количества страниц на сайте. + +### mpa {#mpa} + +- Тип: `boolean` +- По умолчанию: `false` + +Если установлено значение `true`, производственное приложение будет создано в [режиме MPA](../guide/mpa-mode). В режиме MPA по умолчанию используется 0 КБ JavaScript, что приводит к отключению навигации на стороне клиента и требует явного согласия на интерактивность. + +## Тема {#theming} + +### appearance {#appearance} + +- Тип: `boolean | 'dark' | 'force-dark' | 'force-auto' | import('@vueuse/core').UseDarkOptions` +- По умолчанию: `true` + +Включать ли тёмный режим (путём добавления класса `.dark` к элементу ``). + +- Если опция имеет значение `true`, тема по умолчанию будет определяться цветовой гаммой, предпочитаемой пользователем. +- Если опция имеет значение `dark`, тема по умолчанию будет тёмной, если пользователь не переключит её вручную. +- Если установить значение `false`, пользователи не смогут переключать тему. +- Если для опции установлено значение `force-dark`, тема всегда будет темной, и пользователи не смогут её переключать. +- Если для опции установлено значение `force-auto`, тема всегда будет определяться предпочитаемой пользователем цветовой схемой, и пользователи не смогут её переключать. + +Эта опция вставляет встроенный скрипт, который восстанавливает настройки пользователей из локального хранилища с помощью ключа `vitepress-theme-appearance`. Это гарантирует, что класс `.dark` будет применён до отрисовки страницы, чтобы избежать мерцания. + +`appearance.initialValue` может быть только `'dark' | undefined`. Ссылки или геттеры не поддерживаются. + +### lastUpdated {#lastupdated} + +- Тип: `boolean` +- По умолчанию: `false` + +Получать ли временную метку последнего обновления для каждой страницы с помощью Git. Временная метка будет включена в данные каждой страницы, доступные через [`useData`](./runtime-api#usedata). + +При использовании темы по умолчанию включение этой опции приведёт к отображению времени последнего обновления каждой страницы. Вы можете настроить текст с помощью опции [`themeConfig.lastUpdatedText`](./default-theme-config#lastupdatedtext). + +## Кастомизация {#customization} + +### markdown {#markdown} + +- Тип: `MarkdownOption` + +Настройте параметры парсера Markdown. VitePress использует [Markdown-it](https://github.com/markdown-it/markdown-it) в качестве парсера и [Shiki](https://github.com/shikijs/shiki) для подсветки синтаксиса языка. Внутри этой опции вы можете передать различные параметры, связанные с Markdown, в соответствии с вашими потребностями. + +```js +export default { + markdown: {...} +} +``` + +Проверьте [объявление типа и jsdocs](https://github.com/vuejs/vitepress/blob/main/src/node/markdown/markdown.ts) на наличие всех доступных опций. + +### vite {#vite} + +- Тип: `import('vite').UserConfig` + +Передаёт необработанную [конфигурацию Vite](https://vitejs.dev/config/) внутреннему серверу разработки / сборщику Vite. + +```js +export default { + vite: { + // параметры конфигурации Vite + } +} +``` + +### vue {#vue} + +- Тип: `import('@vitejs/plugin-vue').Options` + +Передаёт необработанные [параметры `@vitejs/plugin-vue`](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue#options) внутреннему экземпляру плагина. + +```js +export default { + vue: { + // параметры @vitejs/plugin-vue + } +} +``` + +## Хуки сборки {#build-hooks} + +Хуки для сборки VitePress позволяют добавлять на сайт новую функциональность и поведение: + +- Карта сайта +- Поисковая индексация +- PWA +- Телепорты + +### buildEnd {#buildend} + +- Тип: `(siteConfig: SiteConfig) => Awaitable` + +`buildEnd` — это хук CLI сборки, который будет запущен после завершения сборки (SSG), но до выхода из процесса VitePress CLI. + +```ts +export default { + async buildEnd(siteConfig) { + // ... + } +} +``` + +### postRender {#postrender} + +- Тип: `(context: SSGContext) => Awaitable` + +`postRender` — это хук сборки, вызываемый после завершения рендеринга SSG. Это позволит вам обрабатывать содержимое телепортов во время SSG. + +```ts +export default { + async postRender(context) { + // ... + } +} +``` + +```ts +interface SSGContext { + content: string + teleports?: Record + [key: string]: any +} +``` + +### transformHead {#transformhead} + +- Тип: `(context: TransformContext) => Awaitable` + +`transformHead` — это хук сборки для преобразования заголовка перед генерацией каждой страницы. Это позволит вам добавить в конфигурацию VitePress записи, которые не могут быть добавлены статически. Вам нужно только вернуть дополнительные записи, они будут автоматически объединены с существующими. + +::: warning ПРЕДУПРЕЖДЕНИЕ +Не мутируйте ничего внутри `context`. +::: + +```ts +export default { + async transformHead(context) { + // ... + } +} +``` + +```ts +interface TransformContext { + page: string // например, index.md (относительно srcDir) + assets: string[] // все ресурсы, не относящиеся к js/css, в виде полностью разрешённых публичных URL-адресов + siteConfig: SiteConfig + siteData: SiteData + pageData: PageData + title: string + description: string + head: HeadConfig[] + content: string +} +``` + +Обратите внимание, что этот хук вызывается только при статической генерации сайта. Он не вызывается во время разработки. Если вам нужно добавить динамические записи в голову во время разработки, вместо этого вы можете использовать хук [`transformPageData`](#transformpagedata): + +```ts +export default { + transformPageData(pageData) { + pageData.frontmatter.head ??= [] + pageData.frontmatter.head.push([ + 'meta', + { + name: 'og:title', + content: + pageData.frontmatter.layout === 'home' + ? `VitePress` + : `${pageData.title} | VitePress` + } + ]) + } +} +``` + +#### Пример: Добавление канонического URL-адреса `` {#example-adding-a-canonical-url-link} + +```ts +export default { + transformPageData(pageData) { + const canonicalUrl = `https://example.com/${pageData.relativePath}` + .replace(/index\.md$/, '') + .replace(/\.md$/, '.html') + + pageData.frontmatter.head ??= [] + pageData.frontmatter.head.push([ + 'link', + { rel: 'canonical', href: canonicalUrl } + ]) + } +} +``` + +### transformHtml {#transformhtml} + +- Тип: `(code: string, id: string, context: TransformContext) => Awaitable` + +`transformHtml` — это хук сборки для преобразования содержимого каждой страницы перед сохранением на диск. + +::: warning ПРЕДУПРЕЖДЕНИЕ +Не мутируйте ничего внутри `контекста`. Кроме того, изменение html-содержимого может вызвать проблемы с гидратацией во время выполнения. +::: + +```ts +export default { + async transformHtml(code, id, context) { + // ... + } +} +``` + +### transformPageData {#transformpagedata} + +- Тип: `(pageData: PageData, context: TransformPageContext) => Awaitable | { [key: string]: any } | void>` + +`transformPageData` — это хук для преобразования `pageData` каждой страницы. Вы можете напрямую изменять `pageData` или возвращать изменённые значения, которые будут объединены с данными страницы. + +::: warning ПРЕДУПРЕЖДЕНИЕ +Не мутируйте ничего внутри `context` и будьте осторожны, это может повлиять на производительность dev-сервера, особенно если у вас есть некоторые сетевые запросы или тяжёлые вычисления (например, генерация изображений) в хуке. Вы можете проверить `process.env.NODE_ENV === 'production'` для условной логики. +::: + +```ts +export default { + async transformPageData(pageData, { siteConfig }) { + pageData.contributors = await getPageContributors(pageData.relativePath) + } + + // или возвращаем данные для объединения + async transformPageData(pageData, { siteConfig }) { + return { + contributors: await getPageContributors(pageData.relativePath) + } + } +} +``` + +```ts +interface TransformPageContext { + siteConfig: SiteConfig +} +``` diff --git a/docs/snippets/init.ansi b/docs/snippets/init.ansi new file mode 100644 index 00000000..5421a3e6 --- /dev/null +++ b/docs/snippets/init.ansi @@ -0,0 +1,30 @@ +┌ Welcome to VitePress! +│ +◇ Where should VitePress initialize the config? +│ ./docs +│ +◇ Where should VitePress look for your markdown files? +│ ./docs +│ +◇ Site title: +│ My Awesome Project +│ +◇ Site description: +│ A VitePress Site +│ +◇ Theme: +│ Default Theme +│ +◇ Use TypeScript for config and theme files? +│ Yes +│ +◇ Add VitePress npm scripts to package.json? +│ Yes +│ +◇ Add a prefix for VitePress npm scripts? +│ Yes +│ +◇ Prefix for VitePress npm scripts: +│ docs +│ +└ Done! Now run pnpm run docs:dev and start writing. \ No newline at end of file diff --git a/docs/zh/config.ts b/docs/zh/config.ts new file mode 100644 index 00000000..22fb8b95 --- /dev/null +++ b/docs/zh/config.ts @@ -0,0 +1,211 @@ +import { createRequire } from 'module' +import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' + +const require = createRequire(import.meta.url) +const pkg = require('vitepress/package.json') + +export default defineAdditionalConfig({ + lang: 'zh-Hans', + description: '由 Vite 和 Vue 驱动的静态站点生成器', + + themeConfig: { + nav: nav(), + + search: { options: searchOptions() }, + + sidebar: { + '/zh/guide/': { base: '/zh/guide/', items: sidebarGuide() }, + '/zh/reference/': { base: '/zh/reference/', items: sidebarReference() } + }, + + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + text: '在 GitHub 上编辑此页面' + }, + + footer: { + message: '基于 MIT 许可发布', + copyright: `版权所有 © 2019-${new Date().getFullYear()} 尤雨溪` + }, + + docFooter: { + prev: '上一页', + next: '下一页' + }, + + outline: { + label: '页面导航' + }, + + lastUpdated: { + text: '最后更新于' + }, + + notFound: { + title: '页面未找到', + quote: + '但如果你不改变方向,并且继续寻找,你可能最终会到达你所前往的地方。', + linkLabel: '前往首页', + linkText: '带我回首页' + }, + + langMenuLabel: '多语言', + returnToTopLabel: '回到顶部', + sidebarMenuLabel: '菜单', + darkModeSwitchLabel: '主题', + lightModeSwitchTitle: '切换到浅色模式', + darkModeSwitchTitle: '切换到深色模式', + skipToContentLabel: '跳转到内容' + } +}) + +function nav(): DefaultTheme.NavItem[] { + return [ + { + text: '指南', + link: '/zh/guide/what-is-vitepress', + activeMatch: '/zh/guide/' + }, + { + text: '参考', + link: '/zh/reference/site-config', + activeMatch: '/zh/reference/' + }, + { + text: pkg.version, + items: [ + { + text: '更新日志', + link: 'https://github.com/vuejs/vitepress/blob/main/CHANGELOG.md' + }, + { + text: '参与贡献', + link: 'https://github.com/vuejs/vitepress/blob/main/.github/contributing.md' + } + ] + } + ] +} + +function sidebarGuide(): DefaultTheme.SidebarItem[] { + return [ + { + text: '简介', + collapsed: false, + items: [ + { text: '什么是 VitePress?', link: 'what-is-vitepress' }, + { text: '快速开始', link: 'getting-started' }, + { text: '路由', link: 'routing' }, + { text: '部署', link: 'deploy' } + ] + }, + { + text: '写作', + collapsed: false, + items: [ + { text: 'Markdown 扩展', link: 'markdown' }, + { text: '资源处理', link: 'asset-handling' }, + { text: 'frontmatter', link: 'frontmatter' }, + { text: '在 Markdown 使用 Vue', link: 'using-vue' }, + { text: '国际化', link: 'i18n' } + ] + }, + { + text: '自定义', + collapsed: false, + items: [ + { text: '自定义主题', link: 'custom-theme' }, + { text: '扩展默认主题', link: 'extending-default-theme' }, + { text: '构建时数据加载', link: 'data-loading' }, + { text: 'SSR 兼容性', link: 'ssr-compat' }, + { text: '连接 CMS', link: 'cms' } + ] + }, + { + text: '实验性功能', + collapsed: false, + items: [ + { text: 'MPA 模式', link: 'mpa-mode' }, + { text: 'sitemap 生成', link: 'sitemap-generation' } + ] + }, + { text: '配置和 API 参考', base: '/zh/reference/', link: 'site-config' } + ] +} + +function sidebarReference(): DefaultTheme.SidebarItem[] { + return [ + { + text: '参考', + items: [ + { text: '站点配置', link: 'site-config' }, + { text: 'frontmatter 配置', link: 'frontmatter-config' }, + { text: '运行时 API', link: 'runtime-api' }, + { text: 'CLI', link: 'cli' }, + { + text: '默认主题', + base: '/zh/reference/default-theme-', + items: [ + { text: '概览', link: 'config' }, + { text: '导航栏', link: 'nav' }, + { text: '侧边栏', link: 'sidebar' }, + { text: '主页', link: 'home-page' }, + { text: '页脚', link: 'footer' }, + { text: '布局', link: 'layout' }, + { text: '徽章', link: 'badge' }, + { text: '团队页', link: 'team-page' }, + { text: '上下页链接', link: 'prev-next-links' }, + { text: '编辑链接', link: 'edit-link' }, + { text: '最后更新时间戳', link: 'last-updated' }, + { text: '搜索', link: 'search' }, + { text: 'Carbon Ads', link: 'carbon-ads' } + ] + } + ] + } + ] +} + +function searchOptions(): Partial { + return { + placeholder: '搜索文档', + translations: { + button: { + buttonText: '搜索文档', + buttonAriaLabel: '搜索文档' + }, + modal: { + searchBox: { + resetButtonTitle: '清除查询条件', + resetButtonAriaLabel: '清除查询条件', + cancelButtonText: '取消', + cancelButtonAriaLabel: '取消' + }, + startScreen: { + recentSearchesTitle: '搜索历史', + noRecentSearchesText: '没有搜索历史', + saveRecentSearchButtonTitle: '保存至搜索历史', + removeRecentSearchButtonTitle: '从搜索历史中移除', + favoriteSearchesTitle: '收藏', + removeFavoriteSearchButtonTitle: '从收藏中移除' + }, + errorScreen: { + titleText: '无法获取结果', + helpText: '你可能需要检查你的网络连接' + }, + footer: { + selectText: '选择', + navigateText: '切换', + closeText: '关闭', + searchByText: '搜索提供者' + }, + noResultsScreen: { + noResultsText: '无法找到相关结果', + suggestedQueryText: '你可以尝试查询', + reportMissingResultsText: '你认为该查询应该有结果?', + reportMissingResultsLinkText: '点击反馈' + } + } + } + } +} diff --git a/docs/zh/guide/asset-handling.md b/docs/zh/guide/asset-handling.md new file mode 100644 index 00000000..69259a6a --- /dev/null +++ b/docs/zh/guide/asset-handling.md @@ -0,0 +1,63 @@ +# 资源处理 {#asset-handling} + +## 引用静态资源 {#referencing-static-assets} + +所有的 Markdown 文件都会被编译成 Vue 组件,并由 [Vite](https://cn.vitejs.dev/guide/assets.html) 处理。可以**并且应该**使用相对路径来引用资源: + +```md +![An image](./image.png) +``` + +可以在 Markdown 文件、主题中的 `*.vue` 组件、样式和普通的 `.css` 文件中引用静态资源,可以使用绝对路径 (基于项目根目录) 或者相对路径 (基于文件系统)。后者类似于 Vite、Vue CLI 或者 webpack 的 `file-loader` 的行为。 + +常见的图像,媒体和字体文件会被自动检测并视作资源。 + +::: tip 通过链接引用的文件不会视作资源 +在 Markdown 内,通过链接引用的 PDF 或者其他文档不会被自动视作资源。要使这些文件可用,你必须手动将其放在项目的 [`public`](#the-public-directory) 目录内。 +::: + +所有引用的资源,包括那些使用绝对路径的,都会在生产构建过程中被复制到输出目录,并使用哈希文件名。从未使用过的资源将不会被复制。小于 4kb 的图像资源将会采用 base64 内联——这可以通过 [`vite`](../reference/site-config#vite) 配置选项进行配置。 + +所有**静态**路径引用,包括绝对路径,都应基于你的工作目录的结构。 + +## public 目录 {#the-public-directory} + +有时可能需要一些静态资源,但这些资源没有直接被 Markdown 或主题组件直接引用,或者你可能想以原始文件名提供某些文件,像 `robots.txt`,favicons 和 PWA 图标这样的文件。 + +可以将这些文件放置在[源目录](./routing#source-directory)的 `public` 目录中。例如,如果项目根目录是 `./docs`,并且使用默认源目录位置,那么 public 目录将是 `./docs/public`。 + +放置在 `public` 中的资源将按原样复制到输出目录的根目录中。 + +请注意,应使用根绝对路径来引用放置在 `public` 中的文件——例如,`public/icon.png` 应始终在源代码中使用 `/icon.png` 引用。 + +## 根 URL {#base-url} + +如果站点没有部署在根 URL 上,则需要在 `.vitepress/config.js` 中设置 `base` 选项。例如,如果计划将站点部署到 `https://foo.github.io/bar/`,则 `base` 应设置为 `'/bar/'`(它应始终以斜杠开头和结尾)。 + +所有静态资源路径都会被自动处理,来适应不同的 `base` 配置值。例如,如果 markdown 中有一个对 `public` 中的资源的绝对引用: + +```md +![An image](/image-inside-public.png) +``` + +在这种情况下,更改 `base` 配置值时,**无需**更新该引用。 + +但是如果你正在编写一个主题组件,它动态地链接到资源,例如一个图片,它的 `src` 基于主题配置: + +```vue + +``` + +在这种情况下,建议使用 VitePress 提供的 [`withBase` helper](../reference/runtime-api#withbase) 来包括路径: + +```vue + + + +``` diff --git a/docs/zh/guide/cms.md b/docs/zh/guide/cms.md new file mode 100644 index 00000000..916ba050 --- /dev/null +++ b/docs/zh/guide/cms.md @@ -0,0 +1,56 @@ +--- +outline: deep +--- + +# 连接到 CMS {#connecting-to-a-cms} + +## 一般的工作流 {#general-workflow} + +将 VitePress 连接到 CMS 主要围绕[动态路由](./routing#dynamic-routes)展开。在继续阅读之前,请确保了解它的工作原理。 + +由于每个 CMS 的工作方式都不同,因此我们只能提供一个通用的工作流,你需要根据具体情况进行调整。 + +1. 如果你的 CMS 需要身份验证,请创建一个 `.env` 文件来存储你的 API token: + + ```js + // posts/[id].paths.js + import { loadEnv } from 'vitepress' + + const env = loadEnv('', process.cwd()) + ``` + +2. 从 CMS 获取必要的数据并将其格式调整为合适的路径数据: + + ```js + export default { + async paths() { + // 如有需要,使用相应的 CMS 客户端库 + const data = await (await fetch('https://my-cms-api', { + headers: { + // 如有必要,可使用 token + } + })).json() + + return data.map(entry => { + return { + params: { id: entry.id, /* title, authors, date 等 */ }, + content: entry.content + } + }) + } + } + ``` + +3. 在页面中渲染内容: + + ```md + # {{ $params.title }} + + - by {{ $params.author }} on {{ $params.date }} + + + ``` + +## 整合指南 {#integration-guides} + +如果你已经写了一篇关于如何将 VitePress 与特定的 CMS 集成的指南,请点击下面的“在 GitHub 上编辑此页面”链接将它提交到这里! diff --git a/docs/zh/guide/custom-theme.md b/docs/zh/guide/custom-theme.md new file mode 100644 index 00000000..6600f522 --- /dev/null +++ b/docs/zh/guide/custom-theme.md @@ -0,0 +1,216 @@ +# 自定义主题 {#using-a-custom-theme} + +## 解析主题 {#theme-resolving} + +可以通过创建一个 `.vitepress/theme/index.js` 或 `.vitepress/theme/index.ts` 文件 (即“主题入口文件”) 来启用自定义主题: + +``` +. +├─ docs # 项目根目录 +│ ├─ .vitepress +│ │ ├─ theme +│ │ │ └─ index.js # 主题入口 +│ │ └─ config.js # 配置文件 +│ └─ index.md +└─ package.json +``` + +当检测到存在主题入口文件时,VitePress 总会使用自定义主题而不是默认主题。但你可以[扩展默认主题](./extending-default-theme)来在其基础上实现更高级的自定义。 + +## 主题接口 {#theme-interface} + +VitePress 自定义主题是一个对象,该对象具有如下接口: + +```ts +interface Theme { + /** + * 每个页面的根布局组件 + * @required + */ + Layout: Component + /** + * 增强 Vue 应用实例 + * @optional + */ + enhanceApp?: (ctx: EnhanceAppContext) => Awaitable + /** + * 扩展另一个主题,在我们的主题之前调用它的 `enhanceApp` + * @optional + */ + extends?: Theme +} + +interface EnhanceAppContext { + app: App // Vue 应用实例 + router: Router // VitePress 路由实例 + siteData: Ref // 站点级元数据 +} +``` + +主题入口文件需要将主题作为默认导出来导出: + +```js [.vitepress/theme/index.js] + +// 可以直接在主题入口导入 Vue 文件 +// VitePress 已预先配置 @vitejs/plugin-vue +import Layout from './Layout.vue' + +export default { + Layout, + enhanceApp({ app, router, siteData }) { + // ... + } +} +``` + +默认导出是自定义主题的唯一方式,并且只有 `Layout` 属性是必须的。所以从技术上讲,一个 VitePress 主题可以是一个单独的 Vue 组件。 + +在组件内部,它的工作方式就像是一个普通的 Vite + Vue 3 应用。请注意,主题还需要保证 [SSR 兼容](./ssr-compat)。 + +## 构建布局 {#building-a-layout} + +最基本的布局组件需要包含一个 [``](../reference/runtime-api#content) 组件: + +```vue [.vitepress/theme/Layout.vue] + +``` + +上面的布局只是将每个页面的 markdown 渲染为 HTML。我们添加的第一个改进是处理 404 错误: + +```vue{1-4,9-12} + + + +``` + +[`useData()`](../reference/runtime-api#usedata) 为我们提供了所有的运行时数据,以便我们根据不同条件渲染不同的布局。我们可以访问的另一个数据是当前页面的 frontmatter。通过利用这个数据,可以让用户单独控制每个页面的布局。例如,用户可以指定一个页面是否使用特殊的主页布局: + +```md +--- +layout: home +--- +``` + +并且我们可以调整主题进行处理: + +```vue{3,12-14} + + + +``` + +当然你可以将布局切分为不同的组件: + +```vue{3-5,12-15} + + + +``` + +请查看[运行时 API 参考](../reference/runtime-api)获取主题组件中所有可用内容。此外,可以利用[构建时数据加载](./data-loading)来生成数据驱动布局——例如,一个列出当前项目中所有博客文章的页面。 + +## 分发自定义主题 {#distributing-a-custom-theme} + +分发自定义主题最简单的方式是通过将其作为 [GitHub 模版仓库](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-template-repository)。 + +如果你希望将主题作为 npm 包来分发,请按照下面的步骤操作: + +1. 在包入口将主题对象使用默认导出。 + +2. 如果合适的话,将主题配置类型定义作为 `ThemeConfig` 导出。 + +3. 如果主题需要调整 VitePress 配置,请在包的子路径下 (例如 `my-theme/config`) 下导出该配置,以便用户扩展。 + +4. 记录主题配置选项 (通过配置文件和 frontmatter)。 + +5. 提供清晰的说明,告诉用户如何使用主题 (见下文)。 + +## 使用自定义主题 {#consuming-a-custom-theme} + +要使用外部主题,请导入它并重新导出: + +```js [.vitepress/theme/index.js] +import Theme from 'awesome-vitepress-theme' + +export default Theme +``` + +如果主题需要扩展: + +```js [.vitepress/theme/index.js] +import Theme from 'awesome-vitepress-theme' + +export default { + extends: Theme, + enhanceApp(ctx) { + // ... + } +} +``` + +如果主题需要特殊的 VitePress 配置,也需要在配置中扩展: + +```ts [.vitepress/config.ts] +import baseConfig from 'awesome-vitepress-theme/config' + +export default { + // 扩展主题的基本配置(如需要) + extends: baseConfig +} +``` + +最后,如果主题为其主题配置提供了类型: + +```ts [.vitepress/config.ts] +import baseConfig from 'awesome-vitepress-theme/config' +import { defineConfigWithTheme } from 'vitepress' +import type { ThemeConfig } from 'awesome-vitepress-theme' + +export default defineConfigWithTheme({ + extends: baseConfig, + themeConfig: { + // 类型为 `ThemeConfig` + } +}) +``` diff --git a/docs/zh/guide/data-loading.md b/docs/zh/guide/data-loading.md new file mode 100644 index 00000000..417f696e --- /dev/null +++ b/docs/zh/guide/data-loading.md @@ -0,0 +1,243 @@ +# 构建时数据加载 {#build-time-data-loading} + +VitePress 提供了**数据加载**的功能,它允许加载任意数据并从页面或组件中导入它。数据加载**只在构建时**执行:最终的数据将被序列化为 JavaScript 包中的 JSON。 + +数据加载可以被用于获取远程数据,也可以基于本地文件生成元数据。例如,可以使用数据加载来解析所有本地 API 页面并自动生成所有 API 入口的索引。 + +## 基本用法 {#basic-usage} + +一个用于数据加载的文件必须以 `.data.js` 或 `.data.ts` 结尾。该文件应该提供一个默认导出的对象,该对象具有 `load()` 方法: + +```js [example.data.js] +export default { + load() { + return { + hello: 'world' + } + } +} +``` + +数据加载模块只在 Node.js 中执行,因此可以按需导入 Node API 和 npm 依赖。 + +然后,可以在 `.md` 页面和 `.vue` 组件中使用 `data` 具名导出从该文件中导入数据: + +```vue + + +
{{ data }}
+``` + +输出: + +```json +{ + "hello": "world" +} +``` + +你会注意到 data loader 本身并没有导出 `data`。这是因为 VitePress 在后台调用了 `load()` 方法,并通过名为 `data` 的具名导出隐式地暴露了结果。 + +即使它是异步的,这也是有效的: + +```js +export default { + async load() { + // 获取远程数据 + return (await fetch('...')).json() + } +} +``` + +## 使用本地文件生成数据 {#data-from-local-files} + +当需要基于本地文件生成数据时,需要在 data loader 中使用 `watch` 选项,以便这些文件改动时可以触发热更新。 + +`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 解析器发送到客户端。 + +```js +import fs from 'node:fs' +import { parse } from 'csv-parse/sync' + +export default { + watch: ['./data/*.csv'], + load(watchedFiles) { + // watchFiles 是一个所匹配文件的绝对路径的数组。 + // 生成一个博客文章元数据数组 + // 可用于在主题布局中呈现列表。 + return watchedFiles.map((file) => { + return parse(fs.readFileSync(file, 'utf-8'), { + columns: true, + skip_empty_lines: true + }) + }) + } +} +``` + +## `createContentLoader` + +当构建一个内容为主的站点时,我们经常需要创建一个“归档”或“索引”页面:一个我们可以列出内容中的所有可用条目的页面,例如博客文章或 API 页面。我们**可以**直接使用数据加载 API 实现这一点,但由于这会经常使用,VitePress 还提供了一个 `createContentLoader` 辅助函数来简化这个过程: + +```js [posts.data.js] +import { createContentLoader } from 'vitepress' + +export default createContentLoader('posts/*.md', /* options */) +``` + +该辅助函数接受一个相对于[源目录](./routing#source-directory)的 glob 模式,并返回一个 `{ watch, load }` 数据加载对象,该对象可以用作数据加载文件中的默认导出。它还基于文件修改时间戳实现了缓存以提高开发性能。 + +请注意,数据加载仅适用于 Markdown 文件——匹配的非 Markdown 文件将被跳过。 + +加载的数据将是一个类型为 `ContentData[]` 的数组: + +```ts +interface ContentData { + // 页面的映射 URL,如 /posts/hello.html(不包括 base) + // 手动迭代或使用自定义 `transform` 来标准化路径 + url: string + // 页面的 frontmatter 数据 + frontmatter: Record + + // 只有启用了相关选项,才会出现以下内容 + // 我们将在下面讨论它们 + src: string | undefined + html: string | undefined + excerpt: string | undefined +} +``` + +默认情况下只提供 `url` 和 `frontmatter`。这是因为加载的数据将作为 JSON 内联在客户端 bundle 中,我们需要谨慎考虑其大小。下面的例子展示了如何使用数据构建最小的博客索引页面: + +```vue + + + +``` + +### 选项 {#options} + +默认数据可能不适合所有需求——可以选择使用选项转换数据: + +```js [posts.data.js] +import { createContentLoader } from 'vitepress' + +export default createContentLoader('posts/*.md', { + includeSrc: true, // 包含原始 markdown 源? + render: true, // 包含渲染的整页 HTML? + excerpt: true, // 包含摘录? + transform(rawData) { + // 根据需要对原始数据进行 map、sort 或 filter + // 最终的结果是将发送给客户端的内容 + return rawData.sort((a, b) => { + return +new Date(b.frontmatter.date) - +new Date(a.frontmatter.date) + }).map((page) => { + page.src // 原始 markdown 源 + page.html // 渲染的整页 HTML + page.excerpt // 渲染的摘录 HTML(第一个 `---` 上面的内容) + return {/* ... */} + }) + } +}) +``` + +查看它在 [Vue.js 博客](https://github.com/vuejs/blog/blob/main/.vitepress/theme/posts.data.ts)中是如何使用的。 + +`createContentLoader` API 也可以在[构建钩子](../reference/site-config#build-hooks)中使用: + +```js [.vitepress/config.js] +export default { + async buildEnd() { + const posts = await createContentLoader('posts/*.md').load() + // 根据 posts 元数据生成文件,如 RSS 订阅源 + } +} +``` + +**类型** + +```ts +interface ContentOptions { + /** + * 包含 src? + * @default false + */ + includeSrc?: boolean + + /** + * 将 src 渲染为 HTML 并包含在数据中? + * @default false + */ + render?: boolean + + /** + * 如果为 `boolean`,是否解析并包含摘录? (呈现为 HTML) + * + * 如果为 `function`,则控制如何从内容中提取摘录 + * + * 如果为 `string`,则定义用于提取摘录的自定义分隔符 + * 如果 `excerpt` 为 `true`,则默认分隔符为 `---` + * + * @see https://github.com/jonschlinkert/gray-matter#optionsexcerpt + * @see https://github.com/jonschlinkert/gray-matter#optionsexcerpt_separator + * + * @default false + */ + excerpt?: + | boolean + | ((file: { data: { [key: string]: any }; content: string; excerpt?: string }, options?: any) => void) + | string + + /** + * 转换数据。请注意,如果从组件或 Markdown 文件导入,数据将以 JSON 形式内联到客户端包中 + */ + transform?: (data: ContentData[]) => T | Promise +} +``` + +## 为 data loader 导出类型 {#typed-data-loaders} + +当使用 TypeScript 时,可以像这样为 loader 和 `data` 导出类型: + +```ts +import { defineLoader } from 'vitepress' + +export interface Data { + // data 类型 +} + +declare const data: Data +export { data } + +export default defineLoader({ + // 类型检查加载器选项 + watch: ['...'], + async load(): Promise { + // ... + } +}) +``` + +## 配置 {#configuration} + +要获取 data loader 中的配置信息,可以使用如下代码: + +```ts +import type { SiteConfig } from 'vitepress' + +const config: SiteConfig = (globalThis as any).VITEPRESS_CONFIG +``` diff --git a/docs/zh/guide/deploy.md b/docs/zh/guide/deploy.md new file mode 100644 index 00000000..54ed13d4 --- /dev/null +++ b/docs/zh/guide/deploy.md @@ -0,0 +1,339 @@ +--- +outline: deep +--- + +# 部署 VitePress 站点 {#deploy-your-vitepress-site} + +以下指南基于一些前提: + +- VitePress 站点位于项目的 `docs` 目录中。 +- 你使用的是默认的生成输出目录 (`.vitepress/dist`)。 +- VitePress 作为本地依赖项安装在项目中,并且你已在 `package.json` 中设置以下脚本: + + ```json [package.json] + { + "scripts": { + "docs:build": "vitepress build docs", + "docs:preview": "vitepress preview docs" + } + } + ``` + +## 本地构建与测试 {#build-and-test-locally} + +1. 可以运行以下命令来构建文档: + + ```sh + $ npm run docs:build + ``` + +2. 构建文档后,通过运行以下命令可以在本地预览它: + + ```sh + $ npm run docs:preview + ``` + + `preview` 命令将启动一个本地静态 Web 服务 `http://localhost:4173`,该服务以 `.vitepress/dist` 作为源文件。这是检查生产版本在本地环境中是否正常的一种简单方法。 + +3. 可以通过传递 `--port` 作为参数来配置服务器的端口。 + + ```json + { + "scripts": { + "docs:preview": "vitepress preview docs --port 8080" + } + } + ``` + + 现在 `docs:preview` 方法将会在 `http://localhost:8080` 启动服务。 + +## 设定 public 根目录 {#setting-a-public-base-path} + +默认情况下,我们假设站点将部署在域名 (`/`) 的根路径上。如果站点在子路径中提供服务,例如 `https://mywebsite.com/blog/`,则需要在 VitePress 配置中将 [`base`](../reference/site-config#base) 选项设置为 `'/blog/'`。 + +**例**:如果你使用的是 Github(或 GitLab)页面并部署到 `user.github.io/repo/`,请将 `base` 设置为 `/repo/`。 + +## HTTP 缓存标头 {#http-cache-headers} + +如果可以控制生产服务器上的 HTTP 标头,则可以配置 `cache-control` 标头以在重复访问时获得更好的性能。 + +生产版本对静态资源 (JavaScript、CSS 和其他非 `public` 目录中的导入资源) 使用哈希文件名。如果你使用浏览器开发工具的网络选项卡查看生产预览,你将看到类似 `app.4f283b18.js` 的文件。 + +此哈希 `4f283b18` 是从此文件的内容生成的。相同的哈希 URL 保证提供相同的文件内容——如果内容更改,URL 也会更改。这意味着你可以安全地为这些文件使用最强的缓存标头。所有此类文件都将放置在输出目录的 `assets/` 中,因此你可以为它们配置以下标头: + +``` +Cache-Control: max-age=31536000,immutable +``` + +::: details Netlify 示例 `_headers` 文件 + +``` +/assets/* + cache-control: max-age=31536000 + cache-control: immutable +``` + +注意:该 `_headers` 文件应放置在 [public 目录](./asset-handling#the-public-directory)中 (在我们的例子中是 `docs/public/_headers`),以便将其逐字复制到输出目录。 + +[Netlify 自定义标头文档](https://docs.netlify.com/routing/headers/) + +::: + +::: details Vercel 配置示例 `vercel.json` + +```json +{ + "headers": [ + { + "source": "/assets/(.*)", + "headers": [ + { + "key": "Cache-Control", + "value": "max-age=31536000, immutable" + } + ] + } + ] +} +``` + +注意:`vercel.json` 文件应放在存储库的根目录中。 + +[Vercel 关于标头配置的文档](https://vercel.com/docs/concepts/projects/project-configuration#headers) + +::: + +## 各平台部署指南 {#platform-guides} + +### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render + +使用仪表板创建新项目并更改这些设置: + +- **构建命令:** `npm run docs:build` +- **输出目录:** `docs/.vitepress/dist` +- **node 版本:** `20` (或更高版本) + +::: warning +不要为 HTML 代码启用 _Auto Minify_ 等选项。它将从输出中删除对 Vue 有意义的注释。如果被删除,你可能会看到激活不匹配错误。 +::: + +### GitHub Pages + +1. 在项目的 `.github/workflows` 目录中创建一个名为 `deploy.yml` 的文件,其中包含这样的内容: + + ```yaml [.github/workflows/deploy.yml] + # 构建 VitePress 站点并将其部署到 GitHub Pages 的示例工作流程 + # + name: Deploy VitePress site to Pages + + on: + # 在针对 `main` 分支的推送上运行。如果你 + # 使用 `master` 分支作为默认分支,请将其更改为 `master` + push: + branches: [main] + + # 允许你从 Actions 选项卡手动运行此工作流程 + workflow_dispatch: + + # 设置 GITHUB_TOKEN 的权限,以允许部署到 GitHub Pages + permissions: + contents: read + pages: write + id-token: write + + # 只允许同时进行一次部署,跳过正在运行和最新队列之间的运行队列 + # 但是,不要取消正在进行的运行,因为我们希望允许这些生产部署完成 + concurrency: + group: pages + cancel-in-progress: false + + jobs: + # 构建工作 + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 # 如果未启用 lastUpdated,则不需要 + # - uses: pnpm/action-setup@v3 # 如果使用 pnpm,请取消此区域注释 + # with: + # version: 9 + # - uses: oven-sh/setup-bun@v1 # 如果使用 Bun,请取消注释 + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm # 或 pnpm / yarn + - name: Setup Pages + uses: actions/configure-pages@v4 + - name: Install dependencies + run: npm ci # 或 pnpm install / yarn install / bun install + - name: Build with VitePress + run: npm run docs:build # 或 pnpm docs:build / yarn docs:build / bun run docs:build + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: docs/.vitepress/dist + + # 部署工作 + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + needs: build + runs-on: ubuntu-latest + name: Deploy + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 + ``` + + ::: warning + 确保 VitePress 中的 `base` 选项配置正确。有关更多详细信息,请参阅[设置根路径](#setting-a-public-base-path)。 + ::: + +2. 在存储库设置中的“Pages”菜单项下,选择“Build and deployment > Source > GitHub Actions”。 + +3. 将更改推送到 `main` 分支并等待 GitHub Action 工作流完成。你应该看到站点部署到 `https://.github.io/[repository]/` 或 `https:///`,这取决于你的设置。你的站点将在每次推送到 `main` 分支时自动部署。 + +### GitLab Pages + +1. 如果你想部署到 `https:// .gitlab.io/ /`,将 VitePress 配置中的 `outDir` 设置为 `../public`。将 `base` 选项配置为 `'//'`。 + +2. 在项目的根目录中创建一个名为 `.gitlab-ci.yml` 的文件,其中包含以下内容。每当你更改内容时,这都会构建和部署你的站点: + + ```yaml [.gitlab-ci.yml] + image: node:18 + pages: + cache: + paths: + - node_modules/ + script: + # - apk add git # 如果你使用的是像 alpine 这样的小型 docker 镜像,并且启用了 lastUpdated,请取消注释 + - npm install + - npm run docs:build + artifacts: + paths: + - public + only: + - main + ``` + +### Azure 静态 web 应用 {#azure-static-web-apps} + +1. 参考[官方文档](https://docs.microsoft.com/en-us/azure/static-web-apps/build-configuration)。 + +2. 在配置文件中设置这些值 (并删除不需要的值,如 `api_location`): + + - **`app_location`**: `/` + - **`output_location`**: `docs/.vitepress/dist` + - **`app_build_command`**: `npm run docs:build` + +### Firebase {#firebase} + +1. 在项目的根目录下创建 `firebase.json` 和 `.firebaserc`: + + `firebase.json`: + + ```json [firebase.json] + { + "hosting": { + "public": "docs/.vitepress/dist", + "ignore": [] + } + } + ``` + + `.firebaserc`: + + ```json [.firebaserc] + { + "projects": { + "default": "" + } + } + ``` + +2. 运行 `npm run docs:build` 后,运行此命令进行部署: + + ```sh + firebase deploy + ``` + +### Surge + +1. 运行 `npm run docs:build` 后,运行此命令进行部署: + + ```sh + npx surge docs/.vitepress/dist + ``` + +### Heroku + +1. 参考 [`heroku-buildpack-static`](https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-static) 中给出的文档和指南。 + +2. 使用以下内容在项目的根目录中创建一个名为 `static.json` 的文件: + + ```json [static.json] + { + "root": "docs/.vitepress/dist" + } + ``` + +### Edgio + +请参阅[创建并部署 VitePress 应用程序到 Edgio](https://docs.edg.io/guides/vitepress)。 + +### Kinsta 静态站点托管 {#kinsta-static-site-hosting} + +你可以按照这些[说明](https://kinsta.com/docs/vitepress-static-site-example/) 在 [Kinsta](https://kinsta.com/static-site-hosting/) 上部署 VitePress 站点。 + +### Stormkit + +你可以按照这些[说明](https://stormkit.io/blog/how-to-deploy-vitepress)将你的 VitePress 项目部署到 [Stormkit](https://www.stormkit.io)。 + +### Nginx + +下面是一个 Nginx 服务器块配置示例。此配置包括对基于文本的常见资源的 gzip 压缩、使用适当缓存头为 VitePress 站点静态文件提供服务的规则以及处理 `cleanUrls: true` 的方法。 + +```nginx +server { + gzip on; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + + listen 80; + server_name _; + index index.html; + + location / { + # content location + root /app; + + # exact matches -> reverse clean urls -> folders -> not found + try_files $uri $uri.html $uri/ =404; + + # non existent pages + error_page 404 /404.html; + + # a folder without index.html raises 403 in this setup + error_page 403 /404.html; + + # adjust caching headers + # files in the assets folder have hashes filenames + location ~* ^/assets/ { + expires 1y; + add_header Cache-Control "public, immutable"; + } + } +} +``` + +本配置默认已构建的 VitePress 站点位于服务器上的 `/app` 目录中。如果站点文件位于其他位置,请相应调整 `root` 指令。 + +::: warning 不要默认为 index.html +try_files 解析不能像其他 Vue 应用那样默认为 index.html。这会导致页面状态处于无效。 +::: + +更多信息请参见 [nginx 官方文档](https://nginx.org/en/docs/)、这些 GitHub Issue [#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)。 diff --git a/docs/zh/guide/extending-default-theme.md b/docs/zh/guide/extending-default-theme.md new file mode 100644 index 00000000..4d19eea2 --- /dev/null +++ b/docs/zh/guide/extending-default-theme.md @@ -0,0 +1,330 @@ +--- +outline: deep +--- + +# 扩展默认主题 {#extending-the-default-theme} + +VitePress 默认的主题已经针对文档进行了优化,并且可以进行自定义。请参考[默认主题配置概览](../reference/default-theme-config)获取完整的选项列表。 + +但是有一些情况仅靠配置是不够的。例如: + +1. 需要调整 CSS 样式; +2. 需要修改 Vue 应用实例,例如注册全局组件; +3. 需要通过 layout 插槽将自定义内容注入到主题中; + +这些高级自定义配置将需要使用自定义主题来“拓展”默认主题。 + +:::tip +在继续之前,请确保首先阅读[自定义主题](./custom-theme)以了解其工作原理。 +::: + +## 自定义 CSS {#customizing-css} + +可以通过覆盖根级别的 CSS 变量来自定义默认主题的 CSS: + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme' +import './custom.css' + +export default DefaultTheme +``` + +```css +/* .vitepress/theme/custom.css */ +:root { + --vp-c-brand-1: #646cff; + --vp-c-brand-2: #747bff; +} +``` + +查看[默认主题 CSS 变量](https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css)来获取可以被覆盖的变量。 + +## 使用自定义字体 {#using-different-fonts} + +VitePress 使用 [Inter](https://rsms.me/inter/) 作为默认字体,并且将其包含在生成的输出中。该字体在生产环境中也会自动预加载。但是如果要使用不同的字体,这可能不是很好。 + +为了避免在生成后的输出中包含 Inter 字体,请从 `vitepress/theme-without-fonts` 中导入主题: + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme-without-fonts' +import './my-fonts.css' + +export default DefaultTheme +``` + +```css +/* .vitepress/theme/my-fonts.css */ +:root { + --vp-font-family-base: /* normal text font */ + --vp-font-family-mono: /* code font */ +} +``` + +::: warning +如果你在使用像是[团队页](../reference/default-theme-team-page)这样的组件,请确保也从 `vitepress/theme-without-fonts` 中导入它们! +::: + +如果字体是通过 `@font-face` 引用的本地文件,它将会被作为资源被包含在 `.vitepress/dist/asset` 目录下,并且使用哈希后的文件名。为了预加载这个文件,请使用 [transformHead](../reference/site-config#transformhead) 构建钩子: + +```js [.vitepress/config.js] +export default { + transformHead({ assets }) { + // 相应地调整正则表达式以匹配字体 + const myFontFile = assets.find(file => /font-name\.[\w-]+\.woff2/.test(file)) + if (myFontFile) { + return [ + [ + 'link', + { + rel: 'preload', + href: myFontFile, + as: 'font', + type: 'font/woff2', + crossorigin: '' + } + ] + ] + } + } +} +``` + +## 注册全局组件 {#registering-global-components} + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme' + +/** @type {import('vitepress').Theme} */ +export default { + extends: DefaultTheme, + enhanceApp({ app }) { + // 注册自定义全局组件 + app.component('MyGlobalComponent' /* ... */) + } +} +``` + +如果使用 TypeScript: +```ts [.vitepress/theme/index.ts] +import type { Theme } from 'vitepress' +import DefaultTheme from 'vitepress/theme' + +export default { + extends: DefaultTheme, + enhanceApp({ app }) { + // 注册自定义全局组件 + app.component('MyGlobalComponent' /* ... */) + } +} satisfies Theme +``` + +因为我们使用 Vite,还可以利用 Vite 的 [glob 导入功能](https://cn.vitejs.dev/guide/features.html#glob-import)来自动注册一个组件目录。 + +## 布局插槽 {#layout-slots} + +默认主题的 `` 组件有一些插槽,能够被用来在页面的特定位置注入内容。下面这个例子展示了将一个组件注入到 outline 之前: + +```js [.vitepress/theme/index.js] +import DefaultTheme from 'vitepress/theme' +import MyLayout from './MyLayout.vue' + +export default { + extends: DefaultTheme, + // 使用注入插槽的包装组件覆盖 Layout + Layout: MyLayout +} +``` + +```vue [.vitepress/theme/MyLayout.vue] + + + +``` + +也可以使用渲染函数。 + +```js [.vitepress/theme/index.js] +import { h } from 'vue' +import DefaultTheme from 'vitepress/theme' +import MyComponent from './MyComponent.vue' + +export default { + extends: DefaultTheme, + Layout() { + return h(DefaultTheme.Layout, null, { + 'aside-outline-before': () => h(MyComponent) + }) + } +} +``` + +默认主题布局的全部可用插槽如下: + +- 当 `layout: 'doc'` (默认) 在 frontmatter 中被启用时: + - `doc-top` + - `doc-bottom` + - `doc-footer-before` + - `doc-before` + - `doc-after` + - `sidebar-nav-before` + - `sidebar-nav-after` + - `aside-top` + - `aside-bottom` + - `aside-outline-before` + - `aside-outline-after` + - `aside-ads-before` + - `aside-ads-after` +- 当 `layout: 'home'` 在 frontmatter 中被启用时: + - `home-hero-before` + - `home-hero-info-before` + - `home-hero-info` + - `home-hero-info-after` + - `home-hero-actions-after` + - `home-hero-image` + - `home-hero-after` + - `home-features-before` + - `home-features-after` +- 当 `layout: 'page'` 在 frontmatter 中被启用时: + - `page-top` + - `page-bottom` +- 当未找到页面 (404) 时: + - `not-found` +- 总是启用: + - `layout-top` + - `layout-bottom` + - `nav-bar-title-before` + - `nav-bar-title-after` + - `nav-bar-content-before` + - `nav-bar-content-after` + - `nav-screen-content-before` + - `nav-screen-content-after` + +## 使用视图过渡 API + +### 关于外观切换 {#on-appearance-toggle} + +可以扩展默认主题以在切换颜色模式时提供自定义过渡动画。例如: + +```vue [.vitepress/theme/Layout.vue] + + + + + +``` + +Result (**warning!**: flashing colors, sudden movements, bright lights): + +
+Demo + +![Appearance Toggle Transition Demo](/appearance-toggle-transition.webp) + +
+ +有关视图过渡动画的更多详细信息,请参阅 [Chrome 文档](https://developer.chrome.com/docs/web-platform/view-transitions/)。 + +### 路由切换时 {#on-route-change} + +即将到来。 + +## 重写内部组件 {#overriding-internal-components} + +可以使用 Vite 的 [aliases](https://vitejs.dev/config/shared-options.html#resolve-alias) 来用自定义组件替换默认主题的组件: + +```ts +import { fileURLToPath, URL } from 'node:url' +import { defineConfig } from 'vitepress' + +export default defineConfig({ + vite: { + resolve: { + alias: [ + { + find: /^.*\/VPNavBar\.vue$/, + replacement: fileURLToPath( + new URL('./components/CustomNavBar.vue', import.meta.url) + ) + } + ] + } + } +}) +``` + +想要了解组件的确切名称请参考我们的[源代码](https://github.com/vuejs/vitepress/tree/main/src/client/theme-default/components)。因为组件是内部的,因此在小版本更迭中,它们名字改动的可能性很小。 diff --git a/docs/zh/guide/frontmatter.md b/docs/zh/guide/frontmatter.md new file mode 100644 index 00000000..4bcec7ea --- /dev/null +++ b/docs/zh/guide/frontmatter.md @@ -0,0 +1,48 @@ +# frontmatter + +## 用法 {#usage} + +VitePress 支持在所有 Markdown 文件中使用 YAML frontmatter,并使用 [gray-matter](https://github.com/jonschlinkert/gray-matter) 解析。frontmatter 必须位于 Markdown 文件的顶部 (在任何元素之前,包括 ` + + +``` + +## RTL 支持 (实验性功能) {#rtl-support-experimental} + +支持 RTL 需要在配置中指定 `dir: 'rtl'` 并且使用一些 RTLCSS PostCSS 插件,例如 , 或者 。需要配置 PostCSS 插件,使用 `:where([dir="ltr"])` 和 `:where([dir="rtl"])` 作为前缀,以防止 CSS 特异性问题。 diff --git a/docs/zh/guide/markdown.md b/docs/zh/guide/markdown.md new file mode 100644 index 00000000..308c49df --- /dev/null +++ b/docs/zh/guide/markdown.md @@ -0,0 +1,927 @@ +# Markdown 扩展 {#markdown-extensions} + +VitePress 带有内置的 Markdown 扩展。 + +## 标题锚点 {#header-anchors} + +标题会自动应用锚点。可以使用 `markdown.anchor` 选项配置锚点的渲染。 + +### 自定义锚点 {#custom-anchors} + +要为标题指定自定义锚点而不是使用自动生成的锚点,请向标题添加后缀: + +``` +# 使用自定义锚点 {#my-anchor} +``` + +这允许将标题链接为 `#my-anchor`,而不是默认的 `#使用自定义锚点`。 + +## 链接 {#links} + +内部和外部链接都会被特殊处理。 + +### 内部链接 {#internal-links} + +内部链接将转换为单页导航的路由链接。此外,子目录中包含的每个 `index.md` 都会自动转换为 `index.html`,并带有相应的 URL `/`。 + +例如,给定以下目录结构: + +``` +. +├─ index.md +├─ foo +│ ├─ index.md +│ ├─ one.md +│ └─ two.md +└─ bar + ├─ index.md + ├─ three.md + └─ four.md +``` + +假设现在处于 `foo/one.md` 文件中: + +```md +[Home](/) +[foo](/foo/) +[foo heading](./#heading) +[bar - three](../bar/three) +[bar - three](../bar/three.md) +[bar - four](../bar/four.html) +``` + +### 页面后缀 {#page-suffix} + +默认情况下,生成的页面和内部链接带有 `.html` 后缀。 + +### 外部链接 {#external-links} + +外部链接带有 `target="_blank" rel="noreferrer"`: + +- [vuejs.org](https://cn.vuejs.org) +- [VitePress on GitHub](https://github.com/vuejs/vitepress) + +## frontmatter {#frontmatter} + +[YAML 格式的 frontmatter](https://jekyllrb.com/docs/front-matter/) 开箱即用: + +```yaml +--- +title: Blogging Like a Hacker +lang: en-US +--- +``` + +此数据将可用于页面的其余部分,以及所有自定义和主题组件。 + +更多信息,参见 [frontmatter](../reference/frontmatter-config)。 + +## GitHub 风格的表格 {#github-style-tables} + +**输入** + +``` +| Tables | Are | Cool | +| ------------- | :-----------: | ----: | +| col 3 is | right-aligned | $1600 | +| col 2 is | centered | $12 | +| zebra stripes | are neat | $1 | +``` + +**输出** + +| Tables | Are | Cool | +| ------------- | :-----------: | -----: | +| col 3 is | right-aligned | \$1600 | +| col 2 is | centered | \$12 | +| zebra stripes | are neat | \$1 | + +## Emoji :tada: + +**输入** + +``` +:tada: :100: +``` + +**输出** + +:tada: :100: + +这里可以找到[所有支持的 emoji 列表](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.mjs)。 + +## 目录表 (TOC) {#table-of-contents} + +**输入** + +``` +[[toc]] +``` + +**输出** + +[[toc]] + +可以使用 `markdown.toc` 选项配置 TOC 的呈现效果。 + +## 自定义容器 {#custom-containers} + +自定义容器可以通过它们的类型、标题和内容来定义。 + +### 默认标题 {#default-title} + +**输入** + +```md +::: info +This is an info box. +::: + +::: tip +This is a tip. +::: + +::: warning +This is a warning. +::: + +::: danger +This is a dangerous warning. +::: + +::: details +This is a details block. +::: +``` + +**输出** + +::: info +This is an info box. +::: + +::: tip +This is a tip. +::: + +::: warning +This is a warning. +::: + +::: danger +This is a dangerous warning. +::: + +::: details +This is a details block. +::: + +### 自定义标题 {#custom-title} + +可以通过在容器的 "type" 之后附加文本来设置自定义标题。 + +**输入** + +````md +::: danger STOP +危险区域,请勿继续 +::: + +::: details 点我查看代码 +```js +console.log('Hello, VitePress!') +``` +::: +```` + +**输出** + +::: danger STOP +危险区域,请勿继续 +::: + +::: details 点我查看代码 +```js +console.log('Hello, VitePress!') +``` +::: + +此外,可以通过在站点配置中添加以下内容来全局设置自定义标题,如果不是用英语书写,这会很有帮助: + +```ts +// config.ts +export default defineConfig({ + // ... + markdown: { + container: { + tipLabel: '提示', + warningLabel: '警告', + dangerLabel: '危险', + infoLabel: '信息', + detailsLabel: '详细信息' + } + } + // ... +}) +``` + +### `raw` + +这是一个特殊的容器,可以用来防止与 VitePress 的样式和路由冲突。这在记录组件库时特别有用。可能还想查看 [whyframe](https://whyframe.dev/docs/integrations/vitepress) 以获得更好的隔离。 + +**语法** + +```md +::: raw +Wraps in a `
` +::: +``` + +`vp-raw` class 也可以直接用于元素。样式隔离目前是可选的: + +- 使用喜欢的包管理器来安装需要的依赖项: + + ```sh + $ npm add -D postcss + ``` + +- 创建 `docs/postcss.config.mjs` 文件并将以下内容添加到其中: + + ```js + import { postcssIsolateStyles } from 'vitepress' + + export default { + plugins: [postcssIsolateStyles()] + } + ``` + + 它在底层使用 [`postcss-prefix-selector`](https://github.com/postcss/postcss-load-config)。你可以像这样传递它的选项: + + ```js + postcssIsolateStyles({ + includeFiles: [/vp-doc\.css/] // 默认为 /base\.css/ + }) + ``` + +## 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)的渲染方式相同。 + +```md +> [!NOTE] +> 强调用户在快速浏览文档时也不应忽略的重要信息。 + +> [!TIP] +> 有助于用户更顺利达成目标的建议性信息。 + +> [!IMPORTANT] +> 对用户达成目标至关重要的信息。 + +> [!WARNING] +> 因为可能存在风险,所以需要用户立即关注的关键内容。 + +> [!CAUTION] +> 行为可能带来的负面影响。 +``` + +> [!NOTE] +> 强调用户在快速浏览文档时也不应忽略的重要信息。 + +> [!TIP] +> 有助于用户更顺利达成目标的建议性信息。 + +> [!IMPORTANT] +> 对用户达成目标至关重要的信息。 + +> [!WARNING] +> 因为可能存在风险,所以需要用户立即关注的关键内容。 + +> [!CAUTION] +> 行为可能带来的负面影响。 + +## 代码块中的语法高亮 {#syntax-highlighting-in-code-blocks} + +VitePress 使用 [Shiki](https://github.com/shikijs/shiki) 在 Markdown 代码块中使用彩色文本实现语法高亮。Shiki 支持多种编程语言。需要做的就是将有效的语言别名附加到代码块的开头: + +**输入** + +```` +```js +export default { + name: 'MyComponent', + // ... +} +``` +```` + +```` +```html +
    +
  • + {{ todo.text }} +
  • +
+``` +```` + +**输出** + +```js +export default { + name: 'MyComponent' + // ... +} +``` + +```html +
    +
  • + {{ todo.text }} +
  • +
+``` + +在 Shiki 的代码仓库中,可以找到[合法的编程语言列表](https://shiki.style/languages)。 + +还可以全局配置中自定义语法高亮主题。有关详细信息,参见 [`markdown` 选项](../reference/site-config#markdown)得到更多信息。 + +## 在代码块中实现行高亮 {#line-highlighting-in-code-blocks} + +**输入** + +```` +```js{4} +export default { + data () { + return { + msg: 'Highlighted!' + } + } +} +``` +```` + +**输出** + +```js{4} +export default { + data () { + return { + msg: 'Highlighted!' + } + } +} +``` + +除了单行之外,还可以指定多个单行、多行,或两者均指定: + +- 多行:例如 `{5-8}`、`{3-10}`、`{10-17}` +- 多个单行:例如 `{4,7,9}` +- 多行与单行:例如 `{4,7-13,16,23-27,40}` + +**输入** + +```` +```js{1,4,6-8} +export default { // Highlighted + data () { + return { + msg: `Highlighted! + This line isn't highlighted, + but this and the next 2 are.`, + motd: 'VitePress is awesome', + lorem: 'ipsum' + } + } +} +``` +```` + +**输出** + +```js{1,4,6-8} +export default { // Highlighted + data () { + return { + msg: `Highlighted! + This line isn't highlighted, + but this and the next 2 are.`, + motd: 'VitePress is awesome', + lorem: 'ipsum', + } + } +} +``` + +也可以使用 `// [!code highlight]` 注释实现行高亮。 + +**输入** + +```` +```js +export default { + data () { + return { + msg: 'Highlighted!' // [!!code highlight] + } + } +} +``` +```` + +**输出** + +```js +export default { + data() { + return { + msg: 'Highlighted!' // [!code highlight] + } + } +} +``` + +## 代码块中聚焦 {#focus-in-code-blocks} + +在某一行上添加 `// [!code focus]` 注释将聚焦它并模糊代码的其他部分。 + +此外,可以使用 `// [!code focus:]` 定义要聚焦的行数。 + +**输入** + +```` +```js +export default { + data () { + return { + msg: 'Focused!' // [!!code focus] + } + } +} +``` +```` + +**输出** + +```js +export default { + data() { + return { + msg: 'Focused!' // [!code focus] + } + } +} +``` + +## 代码块中的颜色差异 {#colored-diffs-in-code-blocks} + +在某一行添加 `// [!code --]` 或 `// [!code ++]` 注释将会为该行创建 diff,同时保留代码块的颜色。 + +**输入** + +```` +```js +export default { + data () { + return { + msg: 'Removed' // [!!code --] + msg: 'Added' // [!!code ++] + } + } +} +``` +```` + +**输出** + +```js +export default { + data () { + return { + msg: 'Removed' // [!code --] + msg: 'Added' // [!code ++] + } + } +} +``` + +## 高亮“错误”和“警告” {#errors-and-warnings-in-code-blocks} + +在某一行添加 `// [!code warning]` 或 `// [!code error]` 注释将会为该行相应的着色。 + +**输入** + +```` +```js +export default { + data () { + return { + msg: 'Error', // [!!code error] + msg: 'Warning' // [!!code warning] + } + } +} +``` +```` + +**输出** + +```js +export default { + data() { + return { + msg: 'Error', // [!code error] + msg: 'Warning' // [!code warning] + } + } +} +``` + +## 行号 {#line-numbers} + +可以通过以下配置为每个代码块启用行号: + +```js +export default { + markdown: { + lineNumbers: true + } +} +``` + +查看 [`markdown` 选项](../reference/site-config#markdown) 获取更多信息。 + +可以在代码块中添加 `:line-numbers` / `:no-line-numbers` 标记来覆盖在配置中的设置。 + +还可以通过在 `:line-numbers` 之后添加 `=` 来自定义起始行号,例如 `:line-numbers=2` 表示代码块中的行号从 2 开始。 + +**输入** + +````md +```ts {1} +// 默认禁用行号 +const line2 = 'This is line 2' +const line3 = 'This is line 3' +``` + +```ts:line-numbers {1} +// 启用行号 +const line2 = 'This is line 2' +const line3 = 'This is line 3' +``` + +```ts:line-numbers=2 {1} +// 行号已启用,并从 2 开始 +const line3 = 'This is line 3' +const line4 = 'This is line 4' +``` +```` + +**输出** + +```ts {1} +// 默认禁用行号 +const line2 = 'This is line 2' +const line3 = 'This is line 3' +``` + +```ts:line-numbers {1} +// 启用行号 +const line2 = 'This is line 2' +const line3 = 'This is line 3' +``` + +```ts:line-numbers=2 {1} +// 行号已启用,并从 2 开始 +const line3 = 'This is line 3' +const line4 = 'This is line 4' +``` + +## 导入代码片段 {#import-code-snippets} + +可以通过下面的语法来从现有文件中导入代码片段: + +```md +<<< @/filepath +``` + +此语法同时支持[行高亮](#line-highlighting-in-code-blocks): + +```md +<<< @/filepath{highlightLines} +``` + +**输入** + +```md +<<< @/snippets/snippet.js{2} +``` + +**Code file** + +<<< @/snippets/snippet.js + +**输出** + +<<< @/snippets/snippet.js{2} + +::: tip +`@` 的值对应于源代码根目录,默认情况下是 VitePress 项目根目录,除非配置了 `srcDir`。或者也可以从相对路径导入: + +```md +<<< ../snippets/snippet.js +``` + +::: + +也可以使用 [VS Code region](https://code.visualstudio.com/docs/editor/codebasics#_folding) 来只包含代码文件的相应部分。可以在文件目录后面的 `#` 符号后提供一个自定义的区域名: + +**输入** + +```md +<<< @/snippets/snippet-with-region.js#snippet{1} +``` + +**Code file** + +<<< @/snippets/snippet-with-region.js + +**输出** + +<<< @/snippets/snippet-with-region.js#snippet{1} + +也可以像这样在大括号内(`{}`)指定语言: + +```md +<<< @/snippets/snippet.cs{c#} + + + +<<< @/snippets/snippet.cs{1,2,4-6 c#} + + + +<<< @/snippets/snippet.cs{1,2,4-6 c#:line-numbers} +``` + +如果无法从文件扩展名推测出源语言,这将会很有帮助 + +## 代码组 {#code-groups} + +可以像这样对多个代码块进行分组: + +**输入** + +````md +::: code-group + +```js [config.js] +/** + * @type {import('vitepress').UserConfig} + */ +const config = { + // ... +} + +export default config +``` + +```ts [config.ts] +import type { UserConfig } from 'vitepress' + +const config: UserConfig = { + // ... +} + +export default config +``` + +::: +```` + +**输出** + +::: code-group + +```js [config.js] +/** + * @type {import('vitepress').UserConfig} + */ +const config = { + // ... +} + +export default config +``` + +```ts [config.ts] +import type { UserConfig } from 'vitepress' + +const config: UserConfig = { + // ... +} + +export default config +``` + +::: + +也可以在代码组中[导入代码片段](#import-code-snippets): + +**输入** + +```md +::: code-group + + + +<<< @/snippets/snippet.js + + + +<<< @/snippets/snippet-with-region.js#snippet{1,2 ts:line-numbers} [snippet with region] + +::: +``` + +**输出** + +::: code-group + +<<< @/snippets/snippet.js + +<<< @/snippets/snippet-with-region.js#snippet{1,2 ts:line-numbers} [snippet with region] + +::: + +## 包含 markdown 文件 {#markdown-file-inclusion} + +可以像这样在一个 markdown 文件中包含另一个 markdown 文件,甚至是内嵌的。 + +::: tip +也可以使用 `@`,它的值对应于源代码根目录,默认情况下是 VitePress 项目根目录,除非配置了 `srcDir`。 +::: + +例如,可以这样用相对路径包含 Markdown 文件: + +**输入** + +```md +# Docs + +## Basics + + +``` + +**Part file** (`parts/basics.md`) + +```md +Some getting started stuff. + +### Configuration + +Can be created using `.foorc.json`. +``` + +**等价代码** + +```md +# Docs + +## Basics + +Some getting started stuff. + +### Configuration + +Can be created using `.foorc.json`. +``` + +它还支持选择行范围: + +**输入** + +```md +# Docs + +## Basics + + +``` + +**Part file** (`parts/basics.md`) + +```md +Some getting started stuff. + +### Configuration + +Can be created using `.foorc.json`. +``` + +**等价代码** + +```md +# Docs + +## Basics + +### Configuration + +Can be created using `.foorc.json`. +``` + +所选行范围的格式可以是: `{3,}`、 `{,10}`、`{1,10}` + +::: warning +如果指定的文件不存在,这将不会产生错误。因此,在使用这个功能的时候请保证内容按预期呈现。 +::: + +## 数学方程 {#math-equations} + +现在这是可选的。要启用它,需要安装 `markdown-it-mathjax3`,在配置文件中设置`markdown.math` 为 `true`: + +```sh +npm add -D markdown-it-mathjax3 +``` + +```ts [.vitepress/config.ts] +export default { + markdown: { + math: true + } +} +``` + +**输入** + +```md +When $a \ne 0$, there are two solutions to $(ax^2 + bx + c = 0)$ and they are +$$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ + +**Maxwell's equations:** + +| equation | description | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | +| $\nabla \cdot \vec{\mathbf{B}} = 0$ | divergence of $\vec{\mathbf{B}}$ is zero | +| $\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | curl of $\vec{\mathbf{E}}$ is proportional to the rate of change of $\vec{\mathbf{B}}$ | +| $\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | _wha?_ | +``` + +**输出** + +When $a \ne 0$, there are two solutions to $(ax^2 + bx + c = 0)$ and they are +$$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ + +**Maxwell's equations:** + +| equation | description | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | +| $\nabla \cdot \vec{\mathbf{B}} = 0$ | divergence of $\vec{\mathbf{B}}$ is zero | +| $\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | curl of $\vec{\mathbf{E}}$ is proportional to the rate of change of $\vec{\mathbf{B}}$ | +| $\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | _wha?_ | + +## 图片懒加载 {#image-lazy-loading} + +通过在配置文件中将 `lazyLoading` 设置为 `true`,可以为通过 markdown 添加的每张图片启用懒加载。 + +```js +export default { + markdown: { + image: { + // 默认禁用;设置为 true 可为所有图片启用懒加载。 + lazyLoading: true + } + } +} +``` + +## 高级配置 {#advanced-configuration} + +VitePress 使用 [markdown-it](https://github.com/markdown-it/markdown-it) 作为 Markdown 渲染器。上面提到的很多扩展功能都是通过自定义插件实现的。可以使用 `.vitepress/config.js` 中的 `markdown` 选项来进一步自定义 `markdown-it` 实例。 + +```js +import { defineConfig } from 'vitepress' +import markdownItAnchor from 'markdown-it-anchor' +import markdownItFoo from 'markdown-it-foo' + +export default defineConfig({ + markdown: { + // markdown-it-anchor 的选项 + // https://github.com/valeriangalliat/markdown-it-anchor#usage + anchor: { + permalink: markdownItAnchor.permalink.headerLink() + }, + // @mdit-vue/plugin-toc 的选项 + // https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-toc#options + toc: { level: [1, 2] }, + config: (md) => { + // 使用更多的 Markdown-it 插件! + md.use(markdownItFoo) + } + } +}) +``` + +请查看[配置参考:站点配置](../reference/site-config#markdown)来获取完整的可配置属性列表。 diff --git a/docs/zh/guide/migration-from-vitepress-0.md b/docs/zh/guide/migration-from-vitepress-0.md new file mode 100644 index 00000000..fc2bf97a --- /dev/null +++ b/docs/zh/guide/migration-from-vitepress-0.md @@ -0,0 +1,23 @@ +n# 从 VitePress 0.x 迁移 {#migration-from-vitepress-0-x} + +如果你来自 VitePress 0.x 版本,VitePress 有了一些重大更改。请按照本指南了解如何将应用程序迁移到最新的 VitePress。 + +## 应用配置 {#app-config} + +- 国际化功能尚未实现。 + +## 主题配置 {#theme-config} + +- `sidebar` 选项改变了它的结构。 + - `children` 现在命名为 `items`。 + - 顶级侧边栏不包含 `link`。我们打算把它改回来。 +- 删除了 `repo`、`repoLabel`、`docsDir`、`docsBranch`、`editLinks`、`editLinkText`,以支持更灵活的api。 + - 要将带有图标的 GitHub 链接添加到导航,请使用 [社交链接](../reference/default-theme-config#nav) 功能。 + - 要添加“编辑此页面”功能,请使用 [编辑链接](../reference/default-theme-edit-link) 功能。 +- `lastUpdated` 选项现在分为` config.lastUpdated` 和 `themeConfig.lastUpdatedText`。 +- `carbonAds.carbon` 更改为 `carbonAds.code`. + +## frontmatter 配置 {#frontmatter-config} + +- `home: true` 选项已更改为 `layout: home`。此外,还修改了许多与主页相关的设置以提供附加功能。详情请参阅 [主页指南](../reference/default-theme-home-page)。 +- `footer` 选项移至 [`themeConfig.footer`](../reference/default-theme-footer). diff --git a/docs/zh/guide/migration-from-vuepress.md b/docs/zh/guide/migration-from-vuepress.md new file mode 100644 index 00000000..c21000cc --- /dev/null +++ b/docs/zh/guide/migration-from-vuepress.md @@ -0,0 +1,30 @@ +# 从 VuePress 迁移 {#migration-from-vuepress} + +## 配置 {#config} + +### 侧边栏 {#sidebar} + +侧边栏不再从 frontmatter 中自动获取。你可以自行阅读 [`frontmatter`](https://github.com/vuejs/vitepress/issues/572#issuecomment-1170116225) 来动态填充侧边栏。[迁移工具](https://github.com/vuejs/vitepress/issues/96)将来可能会提供。 + +## Markdown {#markdown} + +### 图片 {#images} + +与 VuePress 不同,在使用静态图片时,VitePress 会根据配置自动处理这些 [`base`](./asset-handling#base-url)。 + +因此,现在可以在没有 `img` 标签的情况下渲染图像。 + +```diff +- foo ++ ![foo](/foo.png) +``` + +::: warning +对于动态图像,仍然需要 `withBase`,如 [Base URL](./asset-handling#base-url) 中所示。 +::: + +使用 `` 正则表达式查找并替换为 `![$2]($1)` 用 `![](...)` 语法替换所有图像。 + +--- + +更多请继续关注... diff --git a/docs/zh/guide/mpa-mode.md b/docs/zh/guide/mpa-mode.md new file mode 100644 index 00000000..aec4fbaa --- /dev/null +++ b/docs/zh/guide/mpa-mode.md @@ -0,0 +1,23 @@ +# MPA 模式 {#mpa-mode} + +可以通过命令行输入 `vitepress build --mpa` 或在配置文件中指定 `mpa: true` 配置选项来启用 MPA (Multi-Page Application) 模式。 + +在 MPA 模式下,所有页面都默认不会包含任何 JavaScript。因此,站点也许可以在评估工具中获得更好的初始访问性能分数。 + +但是,由于缺少 SPA 路由,在 MPA 模式下切换页面时会重新加载整个页面,而不会像 SPA 模式那样立即响应。 + +同时请注意,默认情况下不使用 JavaScript 意味着你实际上只是将 Vue 作为服务器端模板语言。浏览器不会附加任何事件处理程序,因此将不会有任何交互性。要加载客户端 JavaScript,需要使用特殊的 ` + +# Hello +``` + +` +``` + +### 渲染原始内容 {#rendering-raw-content} + +传递给页面的参数将在客户端 JavaScript payload 中序列化,因此应该避免在参数中传递大量数据,例如从远程 CMS 获取的原始 Markdown 或 HTML 内容。 + +相反,可以使用每个路径对象上的 `content` 属性将此类内容传递到每个页面: + +```js +export default { + async paths() { + const posts = await (await fetch('https://my-cms.com/blog-posts')).json() + + return posts.map((post) => { + return { + params: { id: post.id }, + content: post.content // 原始 Markdown 或 HTML + } + }) + } +} +``` + +然后,使用以下特殊语法将内容呈现为 Markdown 文件本身的一部分: + +```md + +``` diff --git a/docs/zh/guide/sitemap-generation.md b/docs/zh/guide/sitemap-generation.md new file mode 100644 index 00000000..1431282e --- /dev/null +++ b/docs/zh/guide/sitemap-generation.md @@ -0,0 +1,58 @@ +# 生成 sitemap {#sitemap-generation} + +VitePress 提供开箱即用的配置,为站点生成 `sitemap.xml` 文件。要启用它,请将以下内容添加到 `.vitepress/config.js` 中: + +```ts +export default { + sitemap: { + hostname: 'https://example.com' + } +} +``` + +要在 `sitemap.xml` 中包含 `` 标签,可以启用 [`lastUpdated`](../reference/default-theme-last-updated) 选项。 + +## 选项 {#options} + +VitePress 的 sitemap 由 [`sitemap`](https://www.npmjs.com/package/sitemap) 模块提供支持。可以将该模块支持的选项传递给配置文件中的 `sitemap` 选项。这些选项将直接传递给 `SitemapStream` 构造函数。有关更多详细信息,请参阅 [`sitemap` 文档](https://www.npmjs.com/package/sitemap#options-you-can-pass)。例如: + +```ts +export default { + sitemap: { + hostname: 'https://example.com', + lastmodDateOnly: false + } +} +``` + +如果在配置中使用 `base`,则应将其追加到 `hostname` 选项中: + +```ts +export default { + base: '/my-site/', + sitemap: { + hostname: 'https://example.com/my-site/' + } +} +``` + +## `transformItems` Hook + +在将 sitemap 写入 `sitemap.xml` 文件之前,可以使用 `sitemap.transformItems` 钩子来修改 sitemap。使用 sitemap 调用该钩子,应返回 sitemap 数组。例如: + +```ts +export default { + sitemap: { + hostname: 'https://example.com', + transformItems: (items) => { + // 添加新项目或修改/筛选现有选项 + items.push({ + url: '/extra-page', + changefreq: 'monthly', + priority: 0.8 + }) + return items + } + } +} +``` diff --git a/docs/zh/guide/ssr-compat.md b/docs/zh/guide/ssr-compat.md new file mode 100644 index 00000000..1d638926 --- /dev/null +++ b/docs/zh/guide/ssr-compat.md @@ -0,0 +1,134 @@ +--- +outline: deep +--- + +# SSR 兼容性 {#ssr-compatibility} + +通过使用 Vue 的服务器端渲染 (SSR) 功能,VitePress 能够在生产构建期间在 Node.js 中预渲染应用程序。这意味着主题组件中的所有自定义代码都需要考虑 SSR 兼容性。 + +[Vue 官方文档的 SSR 部分](https://cn.vuejs.org/guide/scaling-up/ssr.html)提供了更多有关 SSR 是什么,SSR / SSG 之间的关系以及编写 SSR 友好的代码的常见注意事项等信息。原则上只在 Vue 组件的 `beforeMount` 或 `mounted` 钩子中访问浏览器或 DOM API。 + +## `` + +如果正在使用或演示不支持 SSR 的组件 (例如,包含自定义指令),则可以将它们包装在内置的 `` 组件中: + +```md + + + +``` + +## 在导入时访问浏览器 API 的库 {#libraries-that-access-browser-api-on-import} + +一些组件或库在**导入时**访问浏览器 API。要使用假定在导入时处于浏览器环境的代码,需要动态导入它们。 + +### 在 mounted 钩子中导入 {#importing-in-mounted-hook} + +```vue + +``` + +### 条件导入 {#conditional-import} + +也可以使用 `import.meta.env.SSR` 标志 ([Vite 环境变量](https://cn.vitejs.dev/guide/env-and-mode.html#env-variables)的一部分) 来有条件地导入依赖项: + +```js +if (!import.meta.env.SSR) { + import('./lib-that-access-window-on-import').then((module) => { + // use code + }) +} +``` + +因为 [`Theme.enhanceApp`](./custom-theme#theme-interface) 可以是异步的,所以可以有条件地导入并注册访问浏览器 API 的 Vue 插件: + +```js [.vitepress/theme/index.js] +/** @type {import('vitepress').Theme} */ +export default { + // ... + async enhanceApp({ app }) { + if (!import.meta.env.SSR) { + const plugin = await import('plugin-that-access-window-on-import') + app.use(plugin.default) + } + } +} +``` + +如果使用 TypeScript: +```ts [.vitepress/theme/index.ts] +import type { Theme } from 'vitepress' + +export default { + // ... + async enhanceApp({ app }) { + if (!import.meta.env.SSR) { + const plugin = await import('plugin-that-access-window-on-import') + app.use(plugin.default) + } + } +} satisfies Theme +``` + +### `defineClientComponent` + +VitePress 为导入 Vue 组件提供了一个方便的辅助函数,该组件可以在导入时访问浏览器 API。 + +```vue + + + +``` + +还可以将 props/children/slots 传递给目标组件: + +```vue + + + +``` + +目标组件将仅在 wrapper 组件的 mounted 钩子中导入。 diff --git a/docs/zh/guide/using-vue.md b/docs/zh/guide/using-vue.md new file mode 100644 index 00000000..be181fee --- /dev/null +++ b/docs/zh/guide/using-vue.md @@ -0,0 +1,256 @@ +# 在 Markdown 使用 Vue {#using-vue-in-markdown} + +在 VitePress 中,每个 Markdown 文件都被编译成 HTML,而且将其作为 [Vue 单文件组件](https://cn.vuejs.org/guide/scaling-up/sfc.html)处理。这意味着可以在 Markdown 中使用任何 Vue 功能,包括动态模板、使用 Vue 组件或通过添加 ` + +## Markdown Content + +The count is: {{ count }} + + + + +``` + +:::warning 避免在 Markdown 中使用 ` +``` + +## 使用 teleport 传递组件内容 {#using-teleports} + +VitePress 目前只有使用 teleport 传送到 body 的 SSG 支持。对于其他地方,可以将它们包裹在内置的 `` 组件中,或者通过 [postRender 钩子](../reference/site-config#postrender)将 teleport 标签注入到最终页面 HTML 中的正确位置。 + + + +::: details +<<< @/components/ModalDemo.vue +::: + +```md + + +
+ // ... +
+
+
+``` + + + + diff --git a/docs/zh/guide/what-is-vitepress.md b/docs/zh/guide/what-is-vitepress.md new file mode 100644 index 00000000..cee35162 --- /dev/null +++ b/docs/zh/guide/what-is-vitepress.md @@ -0,0 +1,57 @@ +# VitePress 是什么? {#what-is-vitepress} + +VitePress 是一个[静态站点生成器](https://en.wikipedia.org/wiki/Static_site_generator) (SSG),专为构建快速、以内容为中心的站点而设计。简而言之,VitePress 获取用 Markdown 编写的内容,对其应用主题,并生成可以轻松部署到任何地方的静态 HTML 页面。 + +
+ +只是想尝试一下?跳到[快速开始](./getting-started)。 + +
+ +## 使用场景 {#use-cases} + +- **文档** + + 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://cn.vuejs.org/)也是基于 VitePress 的。但是为了可以在不同的翻译文档之间切换,它自定义了自己的主题。 + +- **博客、档案和营销网站** + + VitePress 支持[完全的自定义主题](./custom-theme),具有标准 Vite + Vue 应用程序的开发体验。基于 Vite 构建还意味着可以直接利用其生态系统中丰富的 Vite 插件。此外,VitePress 提供了灵活的 API 来[加载数据](./data-loading) (本地或远程),也可以[动态生成路由](./routing#dynamic-routes)。只要可以在构建时确定数据,就可以使用它来构建几乎任何东西。 + + [Vue.js 官方博客](https://blog.vuejs.org/)是一个简单的博客页面,它根据本地内容生成其索引页面。 + +## 开发体验 {#developer-experience} + +VitePress 旨在使用 Markdown 生成内容时提供出色的开发体验。 + +- **[Vite 驱动](https://cn.vitejs.dev/)**:即时服务器启动,始终立即反映 (<100ms) 编辑变化,无需重新加载页面。 + +- **[内置 Markdown 扩展](./markdown)**:frontmatter、表格、语法高亮……应有尽有。具体来说,VitePress 提供了许多用于处理代码块的高级功能,使其真正成为技术文档的理想选择。 + +- **[Vue 增强的 Markdown](./using-vue)**:每个 Markdown 页面都是 Vue [单文件组件](https://cn.vuejs.org/guide/scaling-up/sfc.html),这要归功于 Vue 模板与 HTML 的 100% 语法兼容性。可以使用 Vue 模板语法或导入的 Vue 组件在静态内容中嵌入交互性。 + +## 性能 {#performance} + +与许多传统的 SSG 不同,每次导航都会导致页面完全重新加载,VitePress 生成的网站在初次访问时提供静态 HTML,但它变成了[单页应用程序](https://en.wikipedia.org/wiki/Single-page_application)(SPA)进行站点内的后续导航。我们认为,这种模式为性能提供了最佳平衡: + +- **快速的初始加载** + + 对任何页面的初次访问都将会是静态的、预呈现的 HTML,以实现极快的加载速度和最佳的 SEO。然后页面加载一个 JavaScript bundle,将页面变成 Vue SPA (这被称为“激活”)。与 SPA 激活缓慢的常见假设不同,由于 Vue 3 良好的原始性能和编译优化,这个过程实际上非常快。在 [PageSpeed Insights](https://pagespeed.web.dev/report?url=https%3A%2F%2Fvitepress.dev%2F) 上,典型的 VitePress 站点即使在网络速度较慢的低端移动设备上也能获得近乎完美的性能分数。 + +- **加载完成后可以快速切换** + + 更重要的是,SPA 模型在首次加载后能够提升用户体验。用户在站点内导航时,不会再触发整个页面的刷新。而是通过获取并动态更新页面的内容来实现切换。VitePress 还会自动预加载视口范围内链接对应的页面片段。这样一来,大部分情况下,用户在加载完成后就能立即浏览新页面。 + +- **高效的交互** + + 为了能够嵌入静态 Markdown 中的动态 Vue 部分,每个 Markdown 页面都被处理为 Vue 组件并编译成 JavaScript。这听起来可能效率低下,但 Vue 编译器足够聪明,可以将静态和动态部分分开,从而最大限度地减少激活成本和有效负载大小。对于初始的页面加载,静态部分会自动从 JavaScript 有效负载中删除,并在激活期间跳过。 + +## VuePress 又是什么? {#what-about-vuepress} + +VitePress 灵感来源于 VuePress。最初的 VuePress 基于 Vue 2 和 webpack。借助 Vue 3 和 Vite,VitePress 提供了更好的开发体验、更好的生产性能、更精美的默认主题和更灵活的自定义 API。 + +VitePress 和 VuePress 之间的 API 区别主要在于主题和自定义。如果使用的是带有默认主题的 VuePress 1,迁移到 VitePress 应该相对简单。 + +VuePress 2 我们也投入了精力,它也支持 Vue 3 和 Vite,与 VuePress 1 的兼容性更好。但是,并行维护两个 SSG 是难以持续的,因此 Vue 团队决定将重点放在 VitePress,作为长期的主要 SSG 选择推荐。 diff --git a/docs/zh/index.md b/docs/zh/index.md new file mode 100644 index 00000000..7beeb998 --- /dev/null +++ b/docs/zh/index.md @@ -0,0 +1,35 @@ +--- +layout: home + +hero: + name: VitePress + text: 由 Vite 和 Vue 驱动的静态站点生成器 + tagline: 将 Markdown 变成优雅的文档,只需几分钟 + actions: + - theme: brand + text: 什么是 VitePress? + link: /zh/guide/what-is-vitepress + - theme: alt + text: 快速开始 + link: /zh/guide/getting-started + - theme: alt + text: GitHub + link: https://github.com/vuejs/vitepress + image: + src: /vitepress-logo-large.svg + alt: VitePress + +features: + - icon: 📝 + title: 专注内容 + details: 只需 Markdown 即可轻松创建美观的文档站点。 + - icon: + title: 享受 Vite 无可比拟的体验 + details: 服务器即时启动,闪电般的热更新,还可以使用基于 Vite 生态的插件。 + - icon: + title: 使用 Vue 自定义 + details: 直接在 Markdown 中使用 Vue 语法和组件,或者使用 Vue 组件构建自定义主题。 + - icon: 🚀 + title: 速度真的很快! + details: 采用静态 HTML 实现快速的页面初次加载,使用客户端路由实现快速的页面切换导航。 +--- diff --git a/docs/zh/reference/cli.md b/docs/zh/reference/cli.md new file mode 100644 index 00000000..71d892c6 --- /dev/null +++ b/docs/zh/reference/cli.md @@ -0,0 +1,74 @@ +# 命令行接口 {#command-line-interface} + +## `vitepress dev` + +使用指定目录作为根目录来启动 VitePress 开发服务器。默认为当前目录。在当前目录下运行时也可以省略 `dev` 命令。 + +### 用法 + +```sh +# 从当前目录启动,省略 `dev` +vitepress + +# 从子目录启动 +vitepress dev [root] +``` + +### 选项 {#options} + +| 选项 | 说明 | +| --------------- | ------------------------------------------ | +| `--open [path]` | 启动时打开浏览器 (`boolean \| string`) | +| `--port ` | 指定端口 (`number`) | +| `--base ` | public base URL (默认值: `/`) (`string`) | +| `--cors` | 启用 CORS | +| `--strictPort` | 如果指定的端口已被占用则退出 (`boolean`) | +| `--force` | 强制优化程序忽略缓存并重新绑定 (`boolean`) | + +## `vitepress build` + +构建用于生产环境的 VitePress 站点。 + +### 用法 + +```sh +vitepress build [root] +``` + +### 选项\ + +| 选项 | 说明 | +| ------------------------------ | ------------------------------------------------------------------------------------------------- | +| `--mpa` (experimental) | [MPA 模式](../guide/mpa-mode) 下构建,无需客户端激活 (`boolean`) | +| `--base ` | public base URL (默认值: `/`) (`string`) | +| `--target ` | 转译目标 (默认值:`"modules"`) (`string`) | +| `--outDir ` | 输出目录 (默认值:`.vitepress/dist`) (`string`) | +| `--minify [minifier]` | 启用/禁用压缩,或指定要使用的压缩程序 (默认值:`"esbuild"`) (`boolean \| "terser" \| "esbuild"`) | +| `--assetsInlineLimit ` | 静态资源 base64 内联阈值(以字节为单位)(默认值:`4096`) (`number`) | + +## `vitepress preview` + +在本地预览生产版本。 + +### 用法 + +```sh +vitepress preview [root] +``` + +### 选项 + +| 选项 | 说明 | +| --------------- | -------------------------------------- | +| `--base ` | public base URL (默认值: `/`) (`string`) | +| `--port ` | 指定端口 (`number`) | + +## `vitepress init` + +在当前目录中启动[安装向导](../guide/getting-started#setup-wizard)。 + +### 用法 + +```sh +vitepress init +``` diff --git a/docs/zh/reference/default-theme-badge.md b/docs/zh/reference/default-theme-badge.md new file mode 100644 index 00000000..c19cb129 --- /dev/null +++ b/docs/zh/reference/default-theme-badge.md @@ -0,0 +1,69 @@ +# 徽标 {#badge} + +徽标可让你为标题添加状态。例如,指定部分的类型或支持的版本可能很有用。 + +## 用法 {#usage} + +可以使用全局组件 `Badge` 。 + +```html +### Title +### Title +### Title +### Title +``` + +上面的代码渲染如下: + +### Title +### Title +### Title +### Title + +## 自定义子节点 {#custom-children} + +`` 接受 `children`,这将显示在徽标中。 + +```html +### Title custom element +``` + +### Title custom element + +## 自定义不同类型徽标的背景色 {#customize-type-color} + +可以通过覆盖 css 来自定义不同类型 `` 的样式。以下是默认值。 + +```css +:root { + --vp-badge-info-border: transparent; + --vp-badge-info-text: var(--vp-c-text-2); + --vp-badge-info-bg: var(--vp-c-default-soft); + + --vp-badge-tip-border: transparent; + --vp-badge-tip-text: var(--vp-c-brand-1); + --vp-badge-tip-bg: var(--vp-c-brand-soft); + + --vp-badge-warning-border: transparent; + --vp-badge-warning-text: var(--vp-c-warning-1); + --vp-badge-warning-bg: var(--vp-c-warning-soft); + + --vp-badge-danger-border: transparent; + --vp-badge-danger-text: var(--vp-c-danger-1); + --vp-badge-danger-bg: var(--vp-c-danger-soft); +} +``` + +## `` + +`` 组件接受以下属性: + +```ts +interface Props { + // 当传递 `` 时,该值将被忽略 + text?: string + + // 默认为 `tip`. + type?: 'info' | 'tip' | 'warning' | 'danger' +} +``` diff --git a/docs/zh/reference/default-theme-carbon-ads.md b/docs/zh/reference/default-theme-carbon-ads.md new file mode 100644 index 00000000..1633b281 --- /dev/null +++ b/docs/zh/reference/default-theme-carbon-ads.md @@ -0,0 +1,22 @@ +# Carbon Ads {#carbon-ads} + +VitePress 内置了对 [Carbon Ads](https://www.carbonads.net/) 的原生支持。通过在配置中定义 Carbon Ads 凭据,VitePress 将在页面上显示广告。 + +```js +export default { + themeConfig: { + carbonAds: { + code: 'your-carbon-code', + placement: 'your-carbon-placement' + } + } +} +``` + +这些值用于调用 carbon CDN 脚本,如下所示。 + +```js +`//cdn.carbonads.com/carbon.js?serve=${code}&placement=${placement}` +``` + +要了解有关 Carbon Ads 配置的更多信息,请访问 [Carbon Ads 站点](https://www.carbonads.net/)。 diff --git a/docs/zh/reference/default-theme-config.md b/docs/zh/reference/default-theme-config.md new file mode 100644 index 00000000..dd7e86b3 --- /dev/null +++ b/docs/zh/reference/default-theme-config.md @@ -0,0 +1,438 @@ +# 默认主题配置 {#default-theme-config} + +主题配置可以让你能够自定义主题。可以通过将 `themeConfig` 添加到配置文件来进行主题配置: + +```ts +export default { + lang: 'en-US', + title: 'VitePress', + description: 'Vite & Vue powered static site generator.', + + // 主题相关配置 + themeConfig: { + logo: '/logo.svg', + nav: [...], + sidebar: { ... } + } +} +``` + +**此页面上记录的选项仅适用于默认主题**。不同的主题需要不同的主题配置。使用自定义主题时,主题配置对象将传递给主题,以便主题可以基于它作出不同表现。 + +## i18nRouting + +- 类型:`boolean` + +将本地语言更改为 `zh` 会将 URL 从 `/foo`(或 `/en/foo/`)更改为 `/zh/foo`。可以通过将 `themeConfig.i18nRouting` 设置为 `false` 来禁用此行为。 + +## logo + +- 类型:`ThemeableImage` + +导航栏上显示的 Logo,位于站点标题前。可以接受一个路径字符串,或者一个对象来设置在浅色/深色模式下不同的 Logo。 + +```ts +export default { + themeConfig: { + logo: '/logo.svg' + } +} +``` + +```ts +type ThemeableImage = + | string + | { src: string; alt?: string } + | { light: string; dark: string; alt?: string } +``` + +## siteTitle + +- 类型:`string | false` + +可以自定义此项以替换导航中的默认站点标题 (应用配置中的 `title`)。当设置为 `false` 时,导航中的标题将被禁用。这在当 `logo` 已经包含站点标题文本时很有用。 + +```ts +export default { + themeConfig: { + siteTitle: 'Hello World' + } +} +``` + +## nav + +- 类型:`NavItem` + +导航菜单项的配置。可以在[默认主题: 导航栏](./default-theme-nav#navigation-links) 了解更多详情。 + +```ts +export default { + themeConfig: { + nav: [ + { text: 'Guide', link: '/guide' }, + { + text: 'Dropdown Menu', + items: [ + { text: 'Item A', link: '/item-1' }, + { text: 'Item B', link: '/item-2' }, + { text: 'Item C', link: '/item-3' } + ] + } + ] + } +} +``` + +```ts +type NavItem = NavItemWithLink | NavItemWithChildren + +interface NavItemWithLink { + text: string + link: string + activeMatch?: string + target?: string + rel?: string + noIcon?: boolean +} + +interface NavItemChildren { + text?: string + items: NavItemWithLink[] +} + +interface NavItemWithChildren { + text?: string + items: (NavItemChildren | NavItemWithLink)[] + activeMatch?: string +} +``` + +## sidebar + +- 类型:`Sidebar` + +侧边栏菜单项的配置。可以在[默认主题: 侧边栏](./default-theme-sidebar)了解更多详情。 + +```ts +export default { + themeConfig: { + sidebar: [ + { + text: 'Guide', + items: [ + { text: 'Introduction', link: '/introduction' }, + { text: 'Getting Started', link: '/getting-started' }, + ... + ] + } + ] + } +} +``` + +```ts +export type Sidebar = SidebarItem[] | SidebarMulti + +export interface SidebarMulti { + [path: string]: SidebarItem[] +} + +export type SidebarItem = { + /** + * 侧边栏项的文本标签 + */ + text?: string + + /** + * 侧边栏项的链接 + */ + link?: string + + /** + * 侧边栏项的子项 + */ + items?: SidebarItem[] + + /** + * 如果未指定,侧边栏组不可折叠 + * + * 如果为 `true`,则侧边栏组可折叠并且默认折叠 + * + * 如果为 `false`,则侧边栏组可折叠但默认展开 + */ + collapsed?: boolean +} +``` + +## aside + +- 类型:`boolean | 'left'` +- 默认值:`true` +- 每个页面可以通过 [frontmatter](./frontmatter-config#aside) 覆盖 + +将此值设置为 `false` 可禁用 aside 容器。\ +将此值设置为 `true` 将在页面右侧渲染。\ +将此值设置为 `left` 将在页面左侧渲染。 + +如果想对所有页面禁用它,应该使用 `outline: false`。 + +## outline + +- 类型:`Outline | Outline['level'] | false` +- 每个页面可以通过 [frontmatter](./frontmatter-config#outline) 覆盖层级 + +将此值设置为 `false` 可禁止渲染大纲容器。更多详情请参考该接口: + +```ts +interface Outline { + /** + * outline 中要显示的标题级别。 + * 单个数字表示只显示该级别的标题。 + * 如果传递的是一个元组,第一个数字是最小级别,第二个数字是最大级别。 + * `'deep'` 与 `[2, 6]` 相同,将显示从 `

` 到 `

` 的所有标题。 + * + * @default 2 + */ + level?: number | [number, number] | 'deep' + + /** + * 显示在 outline 上的标题。 + * + * @default 'On this page' + */ + label?: string +} +``` + +## socialLinks + +- 类型:`SocialLink[]` + +可以定义此选项以在导航栏中展示带有图标的社交帐户链接。 + +```ts +export default { + themeConfig: { + socialLinks: [ + { icon: 'github', link: 'https://github.com/vuejs/vitepress' }, + { icon: 'twitter', link: '...' }, + // 可以通过将 SVG 作为字符串传递来添加自定义图标: + { + icon: { + svg: 'Dribbble' + }, + link: '...', + // 也可以为无障碍添加一个自定义标签 (可选但推荐): + ariaLabel: 'cool link' + } + ] + } +} +``` + +```ts +interface SocialLink { + icon: string | { svg: string } + link: string + ariaLabel?: string +} +``` + +## footer + +- 类型:`Footer` +- 可以通过 [frontmatter](./frontmatter-config#footer) 进行覆盖。 + +页脚配置。可以添加 message 和 copyright。由于设计原因,仅当页面不包含侧边栏时才会显示页脚。 + +```ts +export default { + themeConfig: { + footer: { + message: 'Released under the MIT License.', + copyright: 'Copyright © 2019-present Evan You' + } + } +} +``` + +```ts +export interface Footer { + message?: string + copyright?: string +} +``` + +## editLink + +- 类型:`EditLink` +- 每个页面可以通过 [frontmatter](./frontmatter-config#editlink) 覆盖 + +编辑链接可让显示链接以编辑 Git 管理服务 (例如 GitHub 或 GitLab) 上的页面。有关详细信息,请参阅[默认主题:编辑链接](./default-theme-edit-link)。 + +```ts +export default { + themeConfig: { + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + text: 'Edit this page on GitHub' + } + } +} +``` + +```ts +export interface EditLink { + pattern: string + text?: string +} +``` + +## lastUpdated + +- 类型:`LastUpdatedOptions` + +允许自定义上次更新的文本和日期格式。 + +```ts +export default { + themeConfig: { + lastUpdated: { + text: 'Updated at', + formatOptions: { + dateStyle: 'full', + timeStyle: 'medium' + } + } + } +} +``` + +```ts +export interface LastUpdatedOptions { + /** + * @default 'Last updated' + */ + text?: string + + /** + * @default + * { dateStyle: 'short', timeStyle: 'short' } + */ + formatOptions?: Intl.DateTimeFormatOptions & { forceLocale?: boolean } +} +``` + +## algolia + +- 类型:`AlgoliaSearch` + +支持使用 [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch) 搜索站点文档。在[默认主题:搜索](./default-theme-search) 中了解更多信息。 + +```ts +export interface AlgoliaSearchOptions extends DocSearchProps { + locales?: Record> +} +``` + +在[这里](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts)查看完整配置。 + +## carbonAds {#carbon-ads} + +- 类型:`CarbonAdsOptions` + +一个配置即可展示 [Carbon Ads](https://www.carbonads.net/)。 + +```ts +export default { + themeConfig: { + carbonAds: { + code: 'your-carbon-code', + placement: 'your-carbon-placement' + } + } +} +``` + +```ts +export interface CarbonAdsOptions { + code: string + placement: string +} +``` + +在 [Default Theme: Carbon Ads](./default-theme-carbon-ads) 中了解更多信息。 + +## docFooter + +- 类型:`DocFooter` + +可用于自定义出现在上一页和下一页链接上方的文本。如果不是用英语编写文档,这很有帮助。也可用于全局禁用上一页/下一页链接。如果想有选择地启用/禁用上一个/下一个链接,可以使用 [frontmatter](./default-theme-prev-next-links)。 + +```ts +export default { + themeConfig: { + docFooter: { + prev: 'Pagina prior', + next: 'Proxima pagina' + } + } +} +``` + +```ts +export interface DocFooter { + prev?: string | false + next?: string | false +} +``` + +## darkModeSwitchLabel + +- 类型:`string` +- 默认值:`Appearance` + +用于自定义深色模式开关标签,该标签仅在移动端视图中显示。 + +## lightModeSwitchTitle + +- 类型:`string` +- 默认值:`Switch to light theme` + +用于自定义悬停时显示的浅色模式开关标题。 + +## darkModeSwitchTitle + +- 类型:`string` +- 默认值:`Switch to dark theme` + +用于自定义悬停时显示的深色模式开关标题。 + +## sidebarMenuLabel + +- 类型:`string` +- 默认值:`Menu` + +用于自定义侧边栏菜单标签,该标签仅在移动端视图中显示。 + +## returnToTopLabel + +- 类型:`string` +- 默认值:`Return to top` + +用于自定义返回顶部按钮的标签,该标签仅在移动端视图中显示。 + +## langMenuLabel + +- 类型:`string` +- 默认值:`Change language` + +用于自定义导航栏中语言切换按钮的 aria-label,仅当使用 [i18n](../guide/i18n) 时才使用此选项。 + +## externalLinkIcon + +- 类型:`boolean` +- 默认值:`false` + +是否在 markdown 中的外部链接旁显示外部链接图标。 diff --git a/docs/zh/reference/default-theme-edit-link.md b/docs/zh/reference/default-theme-edit-link.md new file mode 100644 index 00000000..92f3cd25 --- /dev/null +++ b/docs/zh/reference/default-theme-edit-link.md @@ -0,0 +1,60 @@ +# 编辑链接 {#edit-link} + +## 站点级配置 {#site-level-config} + +编辑链接让你可以显示一个链接,以在 GitHub 或 GitLab 等 Git 管理服务上编辑页面。要启用它,请将 `themeConfig.editLink` 选项添加到配置中。 + +```js +export default { + themeConfig: { + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path' + } + } +} +``` + +`pattern` 选项定义链接的 URL 结构,并且 `:path` 将被替换为页面路径。 + +你还可以放置一个接受 [`PageData`](./runtime-api#usedata) 作为参数并返回 URL 字符串的纯函数。 + +```js +export default { + themeConfig: { + editLink: { + pattern: ({ filePath }) => { + if (filePath.startsWith('packages/')) { + return `https://github.com/acme/monorepo/edit/main/${filePath}` + } else { + return `https://github.com/acme/monorepo/edit/main/docs/${filePath}` + } + } + } + } +} +``` + +它不应该有副作用,也不应该访问其范围之外的任何东西,因为它将在浏览器中被序列化和执行。 + +默认情况下,这将在文档页面底部添加链接文本“Edit this page”。可以通过定义 `text` 选项来自定义此文本。 + +```js +export default { + themeConfig: { + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + text: 'Edit this page on GitHub' + } + } +} +``` + +## frontmatter 配置 {#frontmatter-config} + +可以使用 frontmatter 上的 `editLink` 选项单独禁用某个页面的编辑链接: + +```yaml +--- +editLink: false +--- +``` diff --git a/docs/zh/reference/default-theme-footer.md b/docs/zh/reference/default-theme-footer.md new file mode 100644 index 00000000..7499089f --- /dev/null +++ b/docs/zh/reference/default-theme-footer.md @@ -0,0 +1,53 @@ +# 页脚 {#footer} + +配置好 `themeConfig.footer`,VitePress 将在全局页面底部显示页脚。 + +```ts +export default { + themeConfig: { + footer: { + message: 'Released under the MIT License.', + copyright: 'Copyright © 2019-present Evan You' + } + } +} +``` + +```ts +export interface Footer { + // 版权前显示的信息 + message?: string + + // 实际的版权文本 + copyright?: string +} +``` + +上面的配置也支持 HTML 字符串。所以,例如,如果想配置页脚文本有一些链接,可以调整配置如下: + +```ts +export default { + themeConfig: { + footer: { + message: 'Released under the MIT License.', + copyright: 'Copyright © 2019-present Evan You' + } + } +} +``` + +::: warning +只有内联元素可以在 `message` 和 `copyright` 中使用,因为它们渲染在 `

` 元素中。如果想添加块元素,请考虑使用 [`layout-bottom`](../guide/extending-default-theme#layout-slots) 插槽。 +::: + +请注意,当[侧边栏](./default-theme-sidebar)可见时,不会显示页脚。 + +## frontmatter 配置 {#frontmatter-config} + +可以使用 frontmatter 上的 `footer` 选项在单独页面上禁用此功能: + +```yaml +--- +footer: false +--- +``` diff --git a/docs/zh/reference/default-theme-home-page.md b/docs/zh/reference/default-theme-home-page.md new file mode 100644 index 00000000..f5257024 --- /dev/null +++ b/docs/zh/reference/default-theme-home-page.md @@ -0,0 +1,195 @@ +# 主页 {#home-page} + +VitePress 默认主题提供了一个首页布局,也可以在[此站点首页](../)看到。可以通过 [frontmatter](./frontmatter-config) 指定 `layout: home` 在任何页面上使用它 + +```yaml +--- +layout: home +--- +``` + +但是,仅做这个配置不会有太大作用。可以通过设置其他选项 (例如 `hero` 和 `features`) 向主页添加几个不同的预设。 + +## Hero 部分 {#hero-section} + +Hero 部分位于主页顶部。以下是配置 Hero 的方法。 + +```yaml +--- +layout: home + +hero: + name: VitePress + text: Vite & Vue powered static site generator. + tagline: Lorem ipsum... + image: + src: /logo.png + alt: VitePress + actions: + - theme: brand + text: Get Started + link: /guide/what-is-vitepress + - theme: alt + text: View on GitHub + link: https://github.com/vuejs/vitepress +--- +``` + +```ts +interface Hero { + // `text` 上方的字符,带有品牌颜色 + // 预计简短,例如产品名称 + name?: string + + // hero 部分的主要文字, + // 被定义为 `h1` 标签 + text: string + + // `text` 下方的标语 + tagline?: string + + // text 和 tagline 区域旁的图片 + image?: ThemeableImage + + // 主页 hero 部分的操作按钮 + actions?: HeroAction[] +} + +type ThemeableImage = + | string + | { src: string; alt?: string } + | { light: string; dark: string; alt?: string } + +interface HeroAction { + // 按钮的颜色主题,默认为 `brand` + theme?: 'brand' | 'alt' + + // 按钮的标签 + text: string + + // 按钮的目标链接 + link: string + + // 链接的 target 属性 + target?: string + + // 链接的 rel 属性 + rel?: string +} +``` + +### 自定义 name 的颜色 {#customizing-the-name-color} + +VitePress 通过 (`--vp-c-brand-1`) 设置 `name` 的颜色。但是,可以通过覆盖 `--vp-home-hero-name-color` 变量来自定义此颜色。 + +```css +:root { + --vp-home-hero-name-color: blue; +} +``` + +也可以通过组合 `--vp-home-hero-name-background` 来进一步自定义 `name` 为渐变色。 + +```css +:root { + --vp-home-hero-name-color: transparent; + --vp-home-hero-name-background: -webkit-linear-gradient(120deg, #bd34fe, #41d1ff); +} +``` + +## Features 部分 {#features-section} + +在 Features 部分,可以在 Hero 部分之后列出任意数量的 Feature。可以在 frontmatter 中配置 `features`。 + +可以为每个 feature 提供一个图标,可以是表情符号或任何类型的图像。当配置的图标是图片(svg, png, jpeg...)时,必须提供合适的宽度和高度的图标;还可以在需要时配置其描述、固有大小以及深色和浅色主题下的不同表现。 + +```yaml +--- +layout: home + +features: + - icon: 🛠️ + title: Simple and minimal, always + details: Lorem ipsum... + - icon: + src: /cool-feature-icon.svg + title: Another cool feature + details: Lorem ipsum... + - icon: + dark: /dark-feature-icon.svg + light: /light-feature-icon.svg + title: Another cool feature + details: Lorem ipsum... +--- +``` + +```ts +interface Feature { + // 在每个 feature 框中显示图标 + icon?: FeatureIcon + + // feature 的标题 + title: string + + // feature 的详情 + details: string + + // 点击 feature 组件时的链接,可以是内部链接,也可以是外部链接。 + // + // + // 例如 `guide/reference/default-theme-home-page` 或 `https://example.com` + link?: string + + // feature 组件内显示的链接文本,最好与 `link` 选项一起使用 + // + // + // 例如 `Learn more`, `Visit page` 等 + linkText?: string + + // `link` 选项的链接 rel 属性 + // + // 例如 `external` + rel?: string + + // `link` 选项的链接 target 属性 + target?: string +} + +type FeatureIcon = + | string + | { src: string; alt?: string; width?: string; height: string } + | { + light: string + dark: string + alt?: string + width?: string + height: string + } +``` + +## Markdown 内容 {#markdown-content} + +可以在 frontmatter 的分隔符 `---` 下方为站点主页添加额外的 Markdown 内容。 + +````md +--- +layout: home + +hero: + name: VitePress + text: Vite & Vue powered static site generator. +--- + +## Getting Started + +You can get started using VitePress right away using `npx`! + +```sh +npm init +npx vitepress init +``` +```` + +::: info +VitePress 并不总是为 `layout: home` 页面里额外的内容自动添加样式。要回到以前的行为,可以在 frontmatter 中添加 `markdownStyles: false`。 +::: diff --git a/docs/zh/reference/default-theme-last-updated.md b/docs/zh/reference/default-theme-last-updated.md new file mode 100644 index 00000000..6c04a2c6 --- /dev/null +++ b/docs/zh/reference/default-theme-last-updated.md @@ -0,0 +1,27 @@ +# 最后更新于 {#last-updated} + +最近一条内容的更新时间会显示在页面右下角。要启用它,请将 `lastUpdated` 选项添加到配置中。 + +::: tip +你必须提交 markdown 文件才能看到最后更新时间。 +::: + +## 全局配置 {#site-level-config} + +```js +export default { + lastUpdated: true +} +``` + +## frontmatter 配置 {#frontmatter-config} + +可以使用 frontmatter 上的 `lastUpdated` 选项单独禁用某个页面的最后更新展示: + +```yaml +--- +lastUpdated: false +--- +``` + +另请参阅[默认主题:最后更新时间](./default-theme-config#lastupdated) 了解更多详细信息。主题级别的任何 [truthy](https://developer.mozilla.org/zh-CN/docs/Glossary/Truthy) 值也将启用该功能,除非在站点或页面级别明确禁用。 diff --git a/docs/zh/reference/default-theme-layout.md b/docs/zh/reference/default-theme-layout.md new file mode 100644 index 00000000..87015218 --- /dev/null +++ b/docs/zh/reference/default-theme-layout.md @@ -0,0 +1,62 @@ +# 布局 {#layout} + +可以通过设置页面 [frontmatter](./frontmatter-config) 选项来选择页面布局。有 3 种布局选项 `doc`、`page` 和 `home`。如果未指定任何内容,则该页面将被视为 `doc` 页面。 + +```yaml +--- +layout: doc +--- +``` + +## doc 布局 {#doc-layout} + +`doc` 是默认布局,它将整个 Markdown 内容设置为“documentation”外观。它的工作原理是将整个内容包装在 css `vp-doc` 类中,并将样式应用于它下面的元素。 + +几乎所有通用元素,例如 `p`, 或 `h2` 都有特殊的样式。因此,请记住,如果在 Markdown 内容中添加任何自定义 HTML,这些内容也会受到这些样式的影响。 + +它还提供下面列出的文档特定功能。这些功能仅在此布局中启用。 + +- [编辑链接](./default-theme-edit-link) +- [上下页链接](./default-theme-prev-next-links) +- [大纲](./default-theme-config#outline) +- [Carbon Ads](./default-theme-carbon-ads) + +## page 布局 {#page-layout} + +`page` 被视为“空白页”。Markdown 仍然会被解析,所有的 [Markdown 扩展](../guide/markdown) 都和 `doc` 布局一样运行,但它没有任何默认样式。 + +`page` 布局将使可以自行设计所有内容,而不会受 VitePress 主题影响。当想要创建自己的自定义页面时,这很有用。 + +请注意,即使在此布局中,如果页面具有匹配的侧边栏配置,侧边栏仍会显示。 + +## home 布局 {#home-layout} + +`home` 将生成模板化的“主页”。在此布局中,可以设置额外的选项,例如 `hero` 和 `features` 以进一步自定义内容。请访问[默认主题: 主页](./default-theme-home-page)了解更多详情。 + +## 无布局 {#no-layout} + +如果不想要任何布局,可以通过 frontmatter 传递 `layout: false`。如果想要一个完全可自定义的登录页面(默认情况下没有任何侧边栏、导航栏或页脚),此选项很有用。 + +## 自定义布局 {#custom-layout} + +也可以使用自定义布局: + +```md +--- +layout: foo +--- +``` + +这将在上下文中查找注册名为 `foo` 的组件。例如,可以在 `.vitepress/theme/index.ts`中全局注册组件: + +```ts +import DefaultTheme from 'vitepress/theme' +import Foo from './Foo.vue' + +export default { + extends: DefaultTheme, + enhanceApp({ app }) { + app.component('foo', Foo) + } +} +``` diff --git a/docs/zh/reference/default-theme-nav.md b/docs/zh/reference/default-theme-nav.md new file mode 100644 index 00000000..194d18ee --- /dev/null +++ b/docs/zh/reference/default-theme-nav.md @@ -0,0 +1,213 @@ +# 导航栏 {#nav} + +Nav 是显示在页面顶部的导航栏。它包含站点标题、全局菜单链接等。 + +## 站点标题和图标 {#site-title-and-logo} + +默认情况下,nav 显示 [`config.title`](./site-config#title) 作为站点的标题。如果想更改导航栏上显示的内容,可以在 `themeConfig.siteTitle` 选项中定义自定义文本。 + +```js +export default { + themeConfig: { + siteTitle: 'My Custom Title' + } +} +``` + +如果站点有图标,则可以通过传递图片路径来显示它。应该将图标直接放在 `public` 中,并赋值该绝对路径。 + +```js +export default { + themeConfig: { + logo: '/my-logo.svg' + } +} +``` + +添加图标时,它会与站点标题一起显示。如果只需要图标并且想要隐藏站点标题文本,请将 `siteTitle` 选项设置为 `false`。 + +```js +export default { + themeConfig: { + logo: '/my-logo.svg', + siteTitle: false + } +} +``` + +如果想添加 `alt` 属性或根据深色/浅色模式自定义,还可以将图标作为对象传递。有关详细信息,请参阅 [`themeConfig.logo`](./default-theme-config#logo)。 + +## 导航链接 {#navigation-links} + +可以定义 `themeConfig.nav` 选项以将链接添加到导航栏。 + +```js +export default { + themeConfig: { + nav: [ + { text: 'Guide', link: '/guide' }, + { text: 'Config', link: '/config' }, + { text: 'Changelog', link: 'https://github.com/...' } + ] + } +} +``` + +`text` 是 nav 中显示的实际文本,而 `link` 是单击文本时将导航到的链接。对于链接,将路径设置为不带 `.md` 后缀的实际文件,并且始终以 `/` 开头。 + +导航链接也可以是下拉菜单。为此,请替换 `link` 选项,设置 `items` 数组。 + +```js +export default { + themeConfig: { + nav: [ + { text: 'Guide', link: '/guide' }, + { + text: 'Dropdown Menu', + items: [ + { text: 'Item A', link: '/item-1' }, + { text: 'Item B', link: '/item-2' }, + { text: 'Item C', link: '/item-3' } + ] + } + ] + } +} +``` + +请注意,下拉菜单标题 (上例中的 `Dropdown Menu`) 不能具有 `link` 属性,因为它是打开下拉对话框的按钮。 + +还可以通过传入更多嵌套项来进一步向下拉菜单项添加“sections”。 + +```js +export default { + themeConfig: { + nav: [ + { text: 'Guide', link: '/guide' }, + { + text: 'Dropdown Menu', + items: [ + { + // 该部分的标题 + text: 'Section A Title', + items: [ + { text: 'Section A Item A', link: '...' }, + { text: 'Section B Item B', link: '...' } + ] + } + ] + }, + { + text: 'Dropdown Menu', + items: [ + { + // 也可以省略标题 + items: [ + { text: 'Section A Item A', link: '...' }, + { text: 'Section B Item B', link: '...' } + ] + } + ] + } + ] + } +} +``` + +### 自定义链接的路由匹配状态 {#customize-link-s-active-state} + +当前页面位于匹配路径下时,导航菜单项将突出显示。如果想自定义要匹配的路径,请将 `activeMatch` 属性和正则表达式定义为字符串值。 + +```js +export default { + themeConfig: { + nav: [ + // 当用户位于 `/config/` 路径时,该链接处于激活状态 + { + text: 'Guide', + link: '/guide', + activeMatch: '/config/' + } + ] + } +} +``` + +::: warning +`activeMatch` 应为正则表达式字符串,但必须将其定义为字符串。我们不能在这里使用实际的 RegExp 对象,因为它在构建期间不可序列化。 +::: + +### 自定义链接的“target”和“rel”属性 {#customize-link-s-target-and-rel-attributes} + +默认情况下,VitePress 会根据链接是否为外部链接自动判断 `target` 和 `rel` 属性。但如果愿意,也可以自定义它们。 + +```js +export default { + themeConfig: { + nav: [ + { + text: 'Merchandise', + link: 'https://www.thegithubshop.com/', + target: '_self', + rel: 'sponsored' + } + ] + } +} +``` + +## 社交链接 {#social-links} + +参考 [`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)。 diff --git a/docs/zh/reference/default-theme-prev-next-links.md b/docs/zh/reference/default-theme-prev-next-links.md new file mode 100644 index 00000000..cdbe8434 --- /dev/null +++ b/docs/zh/reference/default-theme-prev-next-links.md @@ -0,0 +1,43 @@ +# 上下页链接 {#prev-next-links} + +可以自定义上一页和下一页的文本和链接 (显示在文档页脚处)。如果要使其与侧边栏上的文本不同,这会很有帮助。此外,你可能会发现,要禁用未包含在侧边栏中的页面的页脚或链接时,这很有用。 + +## prev + +- 类型:`string | false | { text?: string; link?: string }` + +- 说明: + + 指定要在指向上一页的链接上显示的文本/链接。如果没有在 frontmatter 中设置它,文本/链接将从侧边栏配置中推断出来。 + +- 示例: + + - 仅自定义文本: + + ```yaml + --- + prev: 'Get Started | Markdown' + --- + ``` + + - 自定义文本和链接: + + ```yaml + --- + prev: + text: 'Markdown' + link: '/guide/markdown' + --- + ``` + + - 隐藏上一页: + + ```yaml + --- + prev: false + --- + ``` + +## next + +与 `prev` 相同,但用于下一页。 diff --git a/docs/zh/reference/default-theme-search.md b/docs/zh/reference/default-theme-search.md new file mode 100644 index 00000000..31af2c9d --- /dev/null +++ b/docs/zh/reference/default-theme-search.md @@ -0,0 +1,372 @@ +--- +outline: deep +--- + +# 搜索 {#search} + +## 本地搜索 {#local-search} + +得益于 [minisearch](https://github.com/lucaong/minisearch/),VitePress 支持使用浏览器内索引进行模糊全文搜索。要启用此功能,只需在 `.vitepress/config.ts` 文件中将 `themeConfig.search.provider` 选项设置为 `'local'` 即可: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local' + } + } +}) +``` + +示例结果: + +![搜索弹窗截图](/search.png) + +或者,你可以使用 [Algolia DocSearch](#algolia-search) 或一些社区插件,例如: 或者 。 + +### i18n {#local-search-i18n} + +你可以使用这样的配置来使用多语言搜索: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + locales: { + zh: { + translations: { + button: { + buttonText: '搜索文档', + buttonAriaLabel: '搜索文档' + }, + modal: { + noResultsText: '无法找到相关结果', + resetButtonTitle: '清除查询条件', + footer: { + selectText: '选择', + navigateText: '切换' + } + } + } + } + } + } + } + } +}) +``` + +### MiniSearch 配置项 {#mini-search-options} + +你可以像这样配置 MiniSearch : + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + miniSearch: { + /** + * @type {Pick} + */ + options: { + /* ... */ + }, + /** + * @type {import('minisearch').SearchOptions} + * @default + * { fuzzy: 0.2, prefix: true, boost: { title: 4, text: 2, titles: 1 } } + */ + searchOptions: { + /* ... */ + } + } + } + } + } +}) +``` + +参阅 [MiniSearch 文档](https://lucaong.github.io/minisearch/classes/MiniSearch.MiniSearch.html)了解更多信息。 + +### 自定义渲染内容 {#custom-content-renderer} + +可以在索引之前自定义用于渲染 Markdown 内容的函数: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + /** + * @param {string} src + * @param {import('vitepress').MarkdownEnv} env + * @param {import('markdown-it-async')} md + */ + async _render(src, env, md) { + // 返回 html 字符串 + } + } + } + } +}) +``` + +该函数将从客户端站点数据中剥离,因此你可以在其中使用 Node.js API。 + +#### 示例:从搜索中排除页面 {#example-excluding-pages-from-search} + +你可以通过将 `search: false` 添加到页面的 `frontmatter` 来从搜索中排除页面。或者: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + async _render(src, env, md) { + const html = await md.renderAsync(src, env) + if (env.frontmatter?.search === false) return '' + if (env.relativePath.startsWith('some/path')) return '' + return html + } + } + } + } +}) +``` + +::: warning 注意 +如果提供了自定义的 `_render` 函数,你需要自己处理 `search: false` 的 frontmatter。此外,在调用 `md.renderAsync` 之前,`env` 对象不会完全填充,因此对可选 `env` 属性 (如 `frontmatter`) 的任何检查都应该在此之后完成。 +::: + +#### 示例:转换内容——添加锚点 {#example-transforming-content-adding-anchors} + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + async _render(src, env, md) { + const html = await md.renderAsync(src, env) + if (env.frontmatter?.title) + return await md.renderAsync(`# ${env.frontmatter.title}`) + html + return html + } + } + } + } +}) +``` + +## Algolia Search {#algolia-search} + +VitePress 支持使用 [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch) 搜索文档站点。请参阅他们的入门指南。在你的 `.vitepress/config.ts` 中,你至少需要提供以下内容才能使其正常工作: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'algolia', + options: { + appId: '...', + apiKey: '...', + indexName: '...' + } + } + } +}) +``` + +### i18n {#algolia-search-i18n} + +你可以使用这样的配置来使用多语言搜索: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'algolia', + options: { + appId: '...', + apiKey: '...', + indexName: '...', + locales: { + zh: { + placeholder: '搜索文档', + translations: { + button: { + buttonText: '搜索文档', + buttonAriaLabel: '搜索文档' + }, + modal: { + searchBox: { + resetButtonTitle: '清除查询条件', + resetButtonAriaLabel: '清除查询条件', + cancelButtonText: '取消', + cancelButtonAriaLabel: '取消' + }, + startScreen: { + recentSearchesTitle: '搜索历史', + noRecentSearchesText: '没有搜索历史', + saveRecentSearchButtonTitle: '保存至搜索历史', + removeRecentSearchButtonTitle: '从搜索历史中移除', + favoriteSearchesTitle: '收藏', + removeFavoriteSearchButtonTitle: '从收藏中移除' + }, + errorScreen: { + titleText: '无法获取结果', + helpText: '你可能需要检查你的网络连接' + }, + footer: { + selectText: '选择', + navigateText: '切换', + closeText: '关闭', + searchByText: '搜索提供者' + }, + noResultsScreen: { + noResultsText: '无法找到相关结果', + suggestedQueryText: '你可以尝试查询', + reportMissingResultsText: '你认为该查询应该有结果?', + reportMissingResultsLinkText: '点击反馈' + } + } + } + } + } + } + } + } +}) +``` + +[这些选项](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts)可以被覆盖。请参阅 Algolia 官方文档以了解更多信息。 + +### 爬虫配置 {#crawler-config} + +以下是基于此站点使用的示例配置: + +```ts +new Crawler({ + appId: '...', + apiKey: '...', + rateLimit: 8, + startUrls: ['https://vitepress.dev/'], + renderJavaScript: false, + sitemaps: [], + exclusionPatterns: [], + ignoreCanonicalTo: false, + discoveryPatterns: ['https://vitepress.dev/**'], + schedule: 'at 05:10 on Saturday', + actions: [ + { + indexName: 'vitepress', + pathsToMatch: ['https://vitepress.dev/**'], + recordExtractor: ({ $, helpers }) => { + return helpers.docsearch({ + recordProps: { + lvl1: '.content h1', + content: '.content p, .content li', + lvl0: { + selectors: 'section.has-active div h2', + defaultValue: 'Documentation' + }, + lvl2: '.content h2', + lvl3: '.content h3', + lvl4: '.content h4', + lvl5: '.content h5' + }, + indexHeadings: true + }) + } + } + ], + initialIndexSettings: { + vitepress: { + attributesForFaceting: ['type', 'lang'], + attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'], + attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'], + attributesToSnippet: ['content:10'], + camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'], + searchableAttributes: [ + 'unordered(hierarchy_radio_camel.lvl0)', + 'unordered(hierarchy_radio.lvl0)', + 'unordered(hierarchy_radio_camel.lvl1)', + 'unordered(hierarchy_radio.lvl1)', + 'unordered(hierarchy_radio_camel.lvl2)', + 'unordered(hierarchy_radio.lvl2)', + 'unordered(hierarchy_radio_camel.lvl3)', + 'unordered(hierarchy_radio.lvl3)', + 'unordered(hierarchy_radio_camel.lvl4)', + 'unordered(hierarchy_radio.lvl4)', + 'unordered(hierarchy_radio_camel.lvl5)', + 'unordered(hierarchy_radio.lvl5)', + 'unordered(hierarchy_radio_camel.lvl6)', + 'unordered(hierarchy_radio.lvl6)', + 'unordered(hierarchy_camel.lvl0)', + 'unordered(hierarchy.lvl0)', + 'unordered(hierarchy_camel.lvl1)', + 'unordered(hierarchy.lvl1)', + 'unordered(hierarchy_camel.lvl2)', + 'unordered(hierarchy.lvl2)', + 'unordered(hierarchy_camel.lvl3)', + 'unordered(hierarchy.lvl3)', + 'unordered(hierarchy_camel.lvl4)', + 'unordered(hierarchy.lvl4)', + 'unordered(hierarchy_camel.lvl5)', + 'unordered(hierarchy.lvl5)', + 'unordered(hierarchy_camel.lvl6)', + 'unordered(hierarchy.lvl6)', + 'content' + ], + distinct: true, + attributeForDistinct: 'url', + customRanking: [ + 'desc(weight.pageRank)', + 'desc(weight.level)', + 'asc(weight.position)' + ], + ranking: [ + 'words', + 'filters', + 'typo', + 'attribute', + 'proximity', + 'exact', + 'custom' + ], + highlightPreTag: '', + highlightPostTag: '', + minWordSizefor1Typo: 3, + minWordSizefor2Typos: 7, + allowTyposOnNumericTokens: false, + minProximity: 1, + ignorePlurals: true, + advancedSyntax: true, + attributeCriteriaComputedByMinProximity: true, + removeWordsIfNoResults: 'allOptional' + } + } +}) +``` diff --git a/docs/zh/reference/default-theme-sidebar.md b/docs/zh/reference/default-theme-sidebar.md new file mode 100644 index 00000000..e353ef78 --- /dev/null +++ b/docs/zh/reference/default-theme-sidebar.md @@ -0,0 +1,180 @@ +# 侧边栏 {#sidebar} + +侧边栏是文档的主要导航块。可以在 [`themeConfig.sidebar`](./default-theme-config#sidebar) 中配置侧边栏菜单。 + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Guide', + items: [ + { text: 'Introduction', link: '/introduction' }, + { text: 'Getting Started', link: '/getting-started' }, + ... + ] + } + ] + } +} +``` + +## 基本用法 {#the-basics} + +侧边栏菜单的最简单形式是传入一个链接数组。第一级项目定义侧边栏的“部分”。它应该包含作为小标题的 `text` 和作为实际导航链接的 `items`。 + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Section Title A', + items: [ + { text: 'Item A', link: '/item-a' }, + { text: 'Item B', link: '/item-b' }, + ... + ] + }, + { + text: 'Section Title B', + items: [ + { text: 'Item C', link: '/item-c' }, + { text: 'Item D', link: '/item-d' }, + ... + ] + } + ] + } +} +``` + +每个 `link` 都应指定以 `/` 开头的实际文件的路径。如果在链接末尾添加斜杠,它将显示相应目录的 `index.md`。 + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Guide', + items: [ + // 显示的是 `/guide/index.md` 页面 + { text: 'Introduction', link: '/guide/' } + ] + } + ] + } +} +``` + +可以进一步将侧边栏项目嵌入到 6 级深度,从根级别上计数。请注意,深度超过 6 级将被忽略,并且不会在侧边栏上显示。 + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Level 1', + items: [ + { + text: 'Level 2', + items: [ + { + text: 'Level 3', + items: [ + ... + ] + } + ] + } + ] + } + ] + } +} +``` + +## 多侧边栏 {#multiple-sidebars} + +可能会根据页面路径显示不同的侧边栏。例如,如本站点所示,可能希望在文档中创建单独的侧边栏,例如“指南”页面和“配置参考”页面。 + +为此,首先将你的页面组织到每个所需部分的目录中: + +``` +. +├─ guide/ +│ ├─ index.md +│ ├─ one.md +│ └─ two.md +└─ config/ + ├─ index.md + ├─ three.md + └─ four.md +``` + +然后,更新配置以定义每个部分的侧边栏。这一次,应该传递一个对象而不是数组。 + +```js +export default { + themeConfig: { + sidebar: { + // 当用户位于 `guide` 目录时,会显示此侧边栏 + '/guide/': [ + { + text: 'Guide', + items: [ + { text: 'Index', link: '/guide/' }, + { text: 'One', link: '/guide/one' }, + { text: 'Two', link: '/guide/two' } + ] + } + ], + + // 当用户位于 `config` 目录时,会显示此侧边栏 + '/config/': [ + { + text: 'Config', + items: [ + { text: 'Index', link: '/config/' }, + { text: 'Three', link: '/config/three' }, + { text: 'Four', link: '/config/four' } + ] + } + ] + } + } +} +``` + +## 可折叠的侧边栏组 {#collapsible-sidebar-groups} + +通过向侧边栏组添加 `collapsed` 选项,它会显示一个切换按钮来隐藏/显示每个部分。 + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Section Title A', + collapsed: false, + items: [...] + } + ] + } +} +``` + +默认情况下,所有部分都是“打开”的。如果希望它们在初始页面加载时“关闭”,请将 `collapsed` 选项设置为 `true`。 + +```js +export default { + themeConfig: { + sidebar: [ + { + text: 'Section Title A', + collapsed: true, + items: [...] + } + ] + } +} +``` diff --git a/docs/zh/reference/default-theme-team-page.md b/docs/zh/reference/default-theme-team-page.md new file mode 100644 index 00000000..9f155cf2 --- /dev/null +++ b/docs/zh/reference/default-theme-team-page.md @@ -0,0 +1,255 @@ + + +# 团队页 {#team-page} + +如果你想介绍你的团队,你可以使用 Team components 来构建团队页面。有两种使用这些组件的方法。一种是将其嵌入文档页面,另一种是创建完整的团队页面。 + +## 在页面中显示团队成员 {#show-team-members-in-a-page} + +你可以在任何页面上使用从 `vitepress/theme` 暴露出的公共组件 `` 显示团队成员。 + +```html + + +# Our Team + +Say hello to our awesome team. + + +``` + +以上将在卡片外观元素中显示团队成员。它应该显示类似于下面的内容。 + + + +`` 组件有 2 种不同的尺寸,`small` 和 `medium`。虽然它取决于你的偏好,但通常尺寸在文档页面中使用时 `small` 应该更适合。此外,你可以为每个成员添加更多属性,例如添加“描述”或“赞助”按钮。在 [``](#vpteammembers) 中了解更多信息。 + +在文档页面中嵌入团队成员对于小型团队来说非常有用,某种情况下,完整的贡献团队可能太大了,可以引入部分成员作为文档上下文的参考。 + +如果你有大量成员,或者只是想有更多空间来展示团队成员,请考虑[创建一个完整的团队页面](#create-a-full-team-page)。 + +## 创建一个完整的团队页面 {#create-a-full-team-page} + +除了将团队成员添加到 doc 页面,你还可以创建一个完整的团队页面,类似于创建自定义[默认主题:主页](./default-theme-home-page)的方式。 + +要创建团队页面,首先,创建一个新的 md 文件。文件名无所谓,这里我们就叫它 `team.md` 吧。在这个文件中,在 frontmatter 设置 `layout: page`,然后你可以使用 `TeamPage` 组件来组成页面结构。 + +```html +--- +layout: page +--- + + + + + + + + + +``` + +创建完整的团队页面时,请记住用 `` 组件包装所有团队相关组件,以获得正确的布局结构,如间距。 + +`` 组件添加页面标题部分。标题是 `

` 标题。使用 `#title` 和 `#lead` 插槽来介绍你的团队。 + +`` 和在 doc 页面中使用时一样。它将显示成员列表。 + +### 添加 section 以划分团队成员 {#add-sections-to-divide-team-members} + +你可以将“section”添加到团队页面。例如,你可能有不同类型的团队成员,例如核心团队成员和社区合作伙伴。你可以将这些成员分成几个部分,以更好地解释每组的角色。 + +为此,将 `` 组件添加到我们之前创建的 `team.md` 文件中。 + +```html +--- +layout: page +--- + + + + + + + + + + + + + + +``` + +`` 组件可以有类似于 `VPTeamPageTitle` 组件的 `#title` 和 `#lead` 插槽,还有用于显示团队成员的 `#members` 插槽。 + +请记住将 `` 组件放入 `#members` 插槽中。 + +## `` + +`` 组件显示给定的成员列表。 + +```html + +``` + +```ts +interface Props { + // 每个成员的大小,默认为 `medium` + size?: 'small' | 'medium' + + // 显示的成员列表 + members: TeamMember[] +} + +interface TeamMember { + // 成员的头像图像 + avatar: string + + // 成员的名称 + name: string + + // 成员姓名下方的标题 + // 例如:Developer, Software Engineer, etc. + title?: string + + // 成员所属的组织 + org?: string + + // 组织的 URL + orgLink?: string + + // 成员的描述 + desc?: string + + // 社交媒体链接,例如 GitHub、Twitter 等,可以在此处传入 Social Links 对象 + // 参见: https://vitepress.dev/reference/default-theme-config.html#sociallinks + links?: SocialLink[] + + // 成员 sponsor 页面的 URL + sponsor?: string + + // sponsor 链接的文本,默认为 'Sponsor' + actionText?: string +} +``` + +## `` + +创建完整团队页面时的根组件。它只接受一个插槽。它将设置所有传入的团队相关组件的样式。 + +## `` + +添加页面的标题。最好在一开始就在 `` 下使用。它接受 `#title` 和 `#lead` 插槽。 + +```html + + + + + + +``` + +## `` + +在团队页面中创建一个“section”。它接受 `#title`、`#lead` 和 `#members` 插槽。你可以在 `` 中添加任意数量的section。 + +```html + + ... + + + + + + +``` diff --git a/docs/zh/reference/frontmatter-config.md b/docs/zh/reference/frontmatter-config.md new file mode 100644 index 00000000..4ee5d961 --- /dev/null +++ b/docs/zh/reference/frontmatter-config.md @@ -0,0 +1,221 @@ +--- +outline: deep +--- + +# frontmatter 配置 {#frontmatter-config} + +frontmatter 支持基于页面的配置。在每个 markdown 文件中,可以使用 frontmatter 配置来覆盖站点级别或主题级别的配置选项。此外,还有一些配置选项只能在 frontmatter 中定义。 + +示例用法: + +```md +--- +title: Docs with VitePress +editLink: true +--- +``` + +可以通过 Vue 表达式中的 `$frontmatter` 全局变量访问 frontmatter 数据: + +```md +{{ $frontmatter.title }} +``` + +## title + +- 类型:`string` + +页面的标题。它与 [config.title](./site-config#title) 相同,并且覆盖站点级配置。 + +```yaml +--- +title: VitePress +--- +``` + +## titleTemplate + +- 类型:`string | boolean` + +标题的后缀。它与 [config.titleTemplate](./site-config#titletemplate) 相同,它会覆盖站点级别的配置。 + +```yaml +--- +title: VitePress +titleTemplate: Vite & Vue powered static site generator +--- +``` + +## description + +- 类型:`string` + +页面的描述。它与 [config.description](./site-config#description) 相同,它会覆盖站点级别的配置。 + +```yaml +--- +description: VitePress +--- +``` + +## head + +- 类型:`HeadConfig[]` + +指定要为当前页面注入的额外 head 标签。将附加在站点级配置注入的头部标签之后。 + +```yaml +--- +head: + - - meta + - name: description + content: hello + - - meta + - name: keywords + content: super duper SEO +--- +``` + +```ts +type HeadConfig = + | [string, Record] + | [string, Record, string] +``` + +## 仅默认主题 {#default-theme-only} + +以下 frontmatter 选项仅在使用默认主题时适用。 + +### layout + +- 类型:`doc | home | page` +- 默认值:`doc` + +指定页面的布局。 + +- `doc`——它将默认文档样式应用于 markdown 内容。 +- `home`——“主页”的特殊布局。可以添加额外的选项,例如 `hero` 和 `features`,以快速创建漂亮的落地页。 +- `page`——表现类似于 `doc`,但它不对内容应用任何样式。当想创建一个完全自定义的页面时很有用。 + +```yaml +--- +layout: doc +--- +``` + +### hero + +当 `layout` 设置为 `home` 时,定义主页 hero 部分的内容。更多详细信息:[默认主题:主页](./default-theme-home-page)。 + +### features + +定义当`layout` 设置为 `home` 时要在 features 部分中显示的项目。更多详细信息:[默认主题:主页](./default-theme-home-page)。 + +### navbar + +- 类型:`boolean` +- 默认值:`true` + +是否显示[导航栏](./default-theme-nav)。 + +```yaml +--- +navbar: false +--- +``` + +### sidebar + +- 类型:`boolean` +- 默认值:`true` + +是否显示 [侧边栏](./default-theme-sidebar). + +```yaml +--- +sidebar: false +--- +``` + +### aside + +- 类型:`boolean | 'left'` +- 默认值:`true` + +定义侧边栏组件在 `doc` 布局中的位置。 + +将此值设置为 `false` 可禁用侧边栏容器。\ +将此值设置为 `true` 会将侧边栏渲染到右侧。\ +将此值设置为 `left` 会将侧边栏渲染到左侧。 + +```yaml +--- +aside: false +--- +``` + +### outline + +- 类型:`number | [number, number] | 'deep' | false` +- 默认值:`2` + +大纲中显示的标题级别。它与 [config.themeConfig.outline.level](./default-theme-config#outline) 相同,它会覆盖站点级的配置。 + +### lastUpdated + +- 类型:`boolean | Date` +- 默认值:`true` + +是否在当前页面的页脚中显示[最后更新时间](./default-theme-last-updated)的文本。如果指定了日期时间,则会显示该日期时间而不是上次 git 修改的时间戳。 + +```yaml +--- +lastUpdated: false +--- +``` + +### editLink + +- 类型:`boolean` +- 默认值:`true` + +是否在当前页的页脚显示[编辑链接](./default-theme-edit-link)。 + +```yaml +--- +editLink: false +--- +``` + +### footer + +- 类型:`boolean` +- 默认值:`true` + +是否显示[页脚](./default-theme-footer)。 + +```yaml +--- +footer: false +--- +``` + +### pageClass + +- 类型:`string` + +将额外的类名称添加到特定页面。 + +```yaml +--- +pageClass: custom-page-class +--- +``` + +然后可以在 `.vitepress/theme/custom.css` 文件中自定义该特定页面的样式: + +```css +.custom-page-class { + /* 特定页面的样式 */ +} +``` diff --git a/docs/zh/reference/runtime-api.md b/docs/zh/reference/runtime-api.md new file mode 100644 index 00000000..35a57872 --- /dev/null +++ b/docs/zh/reference/runtime-api.md @@ -0,0 +1,168 @@ +# 运行时 API {#runtime-api} + +VitePress 提供了几个内置的 API 来让你访问应用程序数据。VitePress 还附带了一些可以在全局范围内使用的内置组件。 + +辅助函数可从 `vitepress` 全局导入,通常用于自定义主题 Vue 组件。但是,它们也可以在 `.md` 页面内使用,因为 markdown 文件被编译成 Vue [单文件组件](https://cn.vuejs.org/guide/scaling-up/sfc.html)。 + +以 `use*` 开头的方法表示它是一个 [Vue 3 组合式 API](https://cn.vuejs.org/guide/introduction.html#composition-api) 函数,只能在 `setup()` 或 ` + + +``` + +## `useRoute` + +返回具有以下类型的当前路由对象: + +```ts +interface Route { + path: string + data: PageData + component: Component | null +} +``` + +## `useRouter` + +返回 VitePress 路由实例,以便可以以编程方式导航到另一个页面。 + +```ts +interface Router { + /** + * 当前路由 + */ + route: Route + /** + * 导航到新的 URL + */ + go: (to?: string) => Promise + /** + * 在路由更改前调用。返回 `false` 表示取消导航 + */ + onBeforeRouteChange?: (to: string) => Awaitable + /** + * 在页面组件加载前(history 状态更新后)调用。返回 `false` 表示取消导航 + */ + onBeforePageLoad?: (to: string) => Awaitable + /** + * 在页面组件加载后(页面组件实际更新前)调用 + */ + onAfterPageLoad?: (to: string) => Awaitable + /** + * 在路由更改后调用 + */ + onAfterRouteChange?: (to: string) => Awaitable +} +``` + +## `withBase` + +- **Type**: `(path: string) => string` + +将配置的 [`base`](./site-config#base) 追加到给定的 URL 路径。另请参阅 [Base URL](../guide/asset-handling#base-url)。 + +## `` + +`` 组件显示渲染的 markdown 内容。在[创建自己的主题时](../guide/custom-theme)很有用。 + +```vue + +``` + +## `` + +`` 组件仅在客户端渲染其插槽。 + +由于 VitePress 应用程序在生成静态构建时是在 Node.js 中服务器渲染的,因此任何 Vue 使用都必须符合通用代码要求。简而言之,确保仅在 beforeMount 或 mounted 钩子中访问 Browser/DOM API。 + +如果正在使用或演示对 SSR 不友好的组件 (例如,包含自定义指令),可以将它们包装在 `ClientOnly` 组件中。 + +```vue-html + + + +``` + +- 相关文档:[SSR 兼容性](../guide/ssr-compat) + +## `$frontmatter` + +在 Vue 表达式中直接访问当前页面的 [frontmatter](../guide/frontmatter) 数据。 + +```md +--- +title: Hello +--- + +# {{ $frontmatter.title }} +``` + +## `$params` + +在 Vue 表达式中直接访问当前页面的[动态路由参数](../guide/routing#dynamic-routes)。 + +```md +- package name: {{ $params.pkg }} +- version: {{ $params.version }} +``` diff --git a/docs/zh/reference/site-config.md b/docs/zh/reference/site-config.md new file mode 100644 index 00000000..72426c61 --- /dev/null +++ b/docs/zh/reference/site-config.md @@ -0,0 +1,720 @@ +--- +outline: deep +--- + +# 站点配置 {#site-config} + +站点配置可以定义站点的全局设置。应用配置选项适用于每个 VitePress 站点,无论它使用什么主题。例如根目录或站点的标题。 + +## 概览 {#overview} + +### 配置解析 {#config-resolution} + +配置文件总是从 `/.vitepress/config.[ext]` 解析,其中 `` 是 VitePress [项目根目录](../guide/routing#root-and-source-directory),`[ext]` 是支持的文件扩展名之一。开箱即用地支持 TypeScript。支持的扩展名包括 `.js`、`.ts`、`.mjs` 和 `.mts`。 + +建议在配置文件中使用 ES 模块语法。配置文件应该默认导出一个对象: + +```ts +export default { + // 应用级配置选项 + lang: 'en-US', + title: 'VitePress', + description: 'Vite & Vue powered static site generator.', + ... +} +``` + +:::details 异步的动态配置 + +如果需要动态生成配置,也可以默认导出一个函数,例如: + +```ts +import { defineConfig } from 'vitepress' + +export default async () => { + const posts = await (await fetch('https://my-cms.com/blog-posts')).json() + + return defineConfig({ + // 应用级配置选项 + lang: 'en-US', + title: 'VitePress', + description: 'Vite & Vue powered static site generator.', + + // 主题级配置选项 + themeConfig: { + sidebar: [ + ...posts.map((post) => ({ + text: post.name, + link: `/posts/${post.name}` + })) + ] + } + }) +} +``` + +也可以在最外层使用 `await`。例如: + +```ts +import { defineConfig } from 'vitepress' + +const posts = await (await fetch('https://my-cms.com/blog-posts')).json() + +export default defineConfig({ + // 应用级配置选项 + lang: 'en-US', + title: 'VitePress', + description: 'Vite & Vue powered static site generator.', + + // 主题级别配置选项 + themeConfig: { + sidebar: [ + ...posts.map((post) => ({ + text: post.name, + link: `/posts/${post.name}` + })) + ] + } +}) +``` + +::: + +### 配置智能提示 {#config-intellisense} + +使用 `defineConfig` 辅助函数将为配置选项提供 TypeScript 支持的智能提示。假设 IDE 支持它,那么在 JavaScript 和 TypeScript 中都将触发智能提示。 + +```js +import { defineConfig } from 'vitepress' + +export default defineConfig({ + // ... +}) +``` + +### 主题类型提示 {#typed-theme-config} + +默认情况下,`defineConfig` 辅助函数期望默认主题的主题配置数据类型为: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + // 类型为 `DefaultTheme.Config` + } +}) +``` + +如果使用自定义主题并希望对主题配置进行类型检查,则需要改用 `defineConfigWithTheme`,并通过通用参数传递自定义主题的配置类型: + +```ts +import { defineConfigWithTheme } from 'vitepress' +import type { ThemeConfig } from 'your-theme' + +export default defineConfigWithTheme({ + themeConfig: { + // 类型为 `ThemeConfig` + } +}) +``` + +### Vite、Vue 和 Markdown 配置 + +- **Vite** + + 可以使用 VitePress 配置中的 [vite](#vite) 选项配置底层 Vite 实例。无需创建单独的 Vite 配置文件。 + +- **Vue** + + VitePress 已经包含 Vite 的官方 Vue 插件 ([@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue)),所以我们可以配置 VitePress 中的 [vue](#vue) 选项。 + +- **Markdown** + + 可以使用 VitePress 配置中的 [markdown](#markdown) 选项配置底层的 [Markdown-It](https://github.com/markdown-it/markdown-it) 实例。 + +## 站点元数据 {#site-metadata} + +### title + +- 类型:`string` +- 默认值: `VitePress` +- 每个页面可以通过 [frontmatter](./frontmatter-config#title) 覆盖 + +站点的标题。使用默认主题时,这将显示在导航栏中。 + +它还将用作所有单独页面标题的默认后缀,除非定义了 [`titleTemplate`](#titletemplate)。单个页面的最终标题将是其第一个 `

` 标题的文本内容加上的全局 `title`。例如使用以下配置和页面内容: + +```ts +export default { + title: 'My Awesome Site' +} +``` + +```md +# Hello +``` + +页面标题就是 `Hello | My Awesome Site`. + +### titleTemplate + +- 类型:`string | boolean` +- 每个页面可以通过 [frontmatter](./frontmatter-config#titletemplate) 覆盖 + +允许自定义每个页面的标题后缀或整个标题。例如: + +```ts +export default { + title: 'My Awesome Site', + titleTemplate: 'Custom Suffix' +} +``` + +```md +# Hello +``` + +页面标题就是 `Hello | Custom Suffix`. + +要完全自定义标题的呈现方式,可以在 `titleTemplate` 中使用 `:title` 标识符: + +```ts +export default { + titleTemplate: ':title - Custom Suffix' +} +``` + +这里的 `:title` 将替换为从页面的第一个 `

` 标题推断出的文本。上一个示例页面的标题将是 `Hello - Custom Suffix`。 + +该选项可以设置为 `false` 以禁用标题后缀。 + +### description + +- 类型:`string` +- 默认值: `A VitePress site` +- 每个页面可以通过 [frontmatter](./frontmatter-config#description) 覆盖 + +站点的描述。这将呈现为页面 HTML 中的 `` 标签。 + +```ts +export default { + description: 'A VitePress site' +} +``` + +### head + +- 类型:`HeadConfig[]` +- 默认值: `[]` +- 可以通过 [frontmatter](./frontmatter-config#head) 为每个页面追加 + +要在页面 HTML 的 `` 标签中呈现的其他元素。用户添加的标签在结束 `head` 标签之前呈现,在 VitePress 标签之后。 + +```ts +type HeadConfig = + | [string, Record] + | [string, Record, string] +``` + +#### 示例:添加一个图标 {#example-adding-a-favicon} + +```ts +export default { + head: [['link', { rel: 'icon', href: '/favicon.ico' }]] +} // 将 favicon.ico 放在公共目录中,如果设置了 base,则使用 /base/favicon.ico + +/* 渲染成: + +*/ +``` + +#### 示例:添加谷歌字体 {#example-adding-google-fonts} + +```ts +export default { + head: [ + [ + 'link', + { rel: 'preconnect', href: 'https://fonts.googleapis.com' } + ], + [ + 'link', + { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: '' } + ], + [ + 'link', + { href: 'https://fonts.googleapis.com/css2?family=Roboto&display=swap', rel: 'stylesheet' } + ] + ] +} + +/* 渲染成: + + + +*/ +``` + +#### 示例:添加一个 serviceWorker {#example-registering-a-service-worker} + +```ts +export default { + head: [ + [ + 'script', + { id: 'register-sw' }, + `;(() => { + if ('serviceWorker' in navigator) { + navigator.serviceWorker.register('/sw.js') + } + })()` + ] + ] +} + +/* 渲染成: + +*/ +``` + +#### 示例:使用谷歌分析 {#example-using-google-analytics} + +```ts +export default { + head: [ + [ + 'script', + { async: '', src: 'https://www.googletagmanager.com/gtag/js?id=TAG_ID' } + ], + [ + 'script', + {}, + `window.dataLayer = window.dataLayer || []; + function gtag(){dataLayer.push(arguments);} + gtag('js', new Date()); + gtag('config', 'TAG_ID');` + ] + ] +} + +/* 渲染成: + + +*/ +``` + +### lang + +- 类型:`string` +- 默认值: `en-US` + +站点的 lang 属性。这将呈现为页面 HTML 中的 `` 标签。 + +```ts +export default { + lang: 'en-US' +} +``` + +### base + +- 类型:`string` +- 默认值: `/` + +站点将部署到的 base URL。如果计划在子路径例如 GitHub 页面下部署站点,则需要设置此项。如果计划将站点部署到 `https://foo.github.io/bar/`,那么应该将 `base` 设置为 `'/bar/'`。它应该始终以 `/` 开头和结尾。 + +base 会自动添加到其他选项中以 `/` 开头的所有 URL 前面,因此只需指定一次。 + +```ts +export default { + base: '/base/' +} +``` + +## 路由 {#routing} + +### cleanUrls + +- 类型:`boolean` +- 默认值: `false` + +当设置为 `true` 时,VitePress 将从 URL 中删除 `.html` 后缀。另请参阅[生成简洁的 URL](../guide/routing#generating-clean-url)。 + +::: warning 需要服务器支持 +要启用此功能,可能需要在托管平台上进行额外配置。要使其正常工作,服务器必须能够在**不重定向的情况下**访问 `/foo` 时提供 `/foo.html`。 +::: + +### rewrites + +- 类型:`Record` + +自定义目录 <-> URL 映射。详细信息请参阅[路由:路由重写](../guide/routing#route-rewrites)。 + +```ts +export default { + rewrites: { + 'source/:page': 'destination/:page' + } +} +``` + +## 构建 {#build} + +### srcDir + +- 类型:`string` +- 默认值: `.` + +相对于项目根目录的 markdown 文件所在的文件夹。另请参阅[根目录和源目录](../guide/routing#root-and-source-directory)。 + +```ts +export default { + srcDir: './src' +} +``` + +### srcExclude + +- 类型:`string` +- 默认值: `undefined` + +用于匹配应排除作为源内容输出的 markdown 文件,语法详见 [glob pattern](https://github.com/mrmlnc/fast-glob#pattern-syntax)。 + +```ts +export default { + srcExclude: ['**/README.md', '**/TODO.md'] +} +``` + +### outDir + +- 类型:`string` +- 默认值: `./.vitepress/dist` + +项目的构建输出位置,相对于[项目根目录](../guide/routing#root-and-source-directory)。 + +```ts +export default { + outDir: '../public' +} +``` + +### assetsDir + +- 类型:`string` +- 默认值: `assets` + +指定放置生成的静态资源的目录。该路径应位于 [`outDir`](#outdir) 内,并相对于它进行解析。 + +```ts +export default { + assetsDir: 'static' +} +``` + +### cacheDir + +- 类型:`string` +- 默认值: `./.vitepress/cache` + +缓存文件的目录,相对于[项目根目录](../guide/routing#root-and-source-directory)。另请参阅:[cacheDir](https://vitejs.dev/config/shared-options.html#cachedir)。 + +```ts +export default { + cacheDir: './.vitepress/.vite' +} +``` + +### ignoreDeadLinks + +- 类型:`boolean | 'localhostLinks' | (string | RegExp | ((link: string) => boolean))[]` +- 默认值: `false` + +当设置为 `true` 时,VitePress 不会因为死链而导致构建失败。 + +当设置为 `'localhostLinks'` ,出现死链时构建将失败,但不会检查 `localhost` 链接。 + +```ts +export default { + ignoreDeadLinks: true +} +``` + +它也可以是一组精确的 url 字符串、正则表达式模式或自定义过滤函数。 + +```ts +export default { + ignoreDeadLinks: [ + // 忽略精确网址 "/playground" + '/playground', + // 忽略所有 localhost 链接 + /^https?:\/\/localhost/, + // 忽略所有包含 "/repl/" 的链接 + /\/repl\//, + // 自定义函数,忽略所有包含 "ignore "的链接 + (url) => { + return url.toLowerCase().includes('ignore') + } + ] +} +``` + +### metaChunk + +- 类型:`boolean` +- 默认值:`false` + +当设置为 `true` 时,将页面元数据提取到单独的 JavaScript 块中,而不是内联在初始 HTML 中。这使每个页面的 HTML 负载更小,并使页面元数据可缓存,从而当站点中有很多页面时可以减少服务器带宽。 + +### mpa + +- 类型:`boolean` +- 默认值: `false` + +设置为 `true` 时,生产应用程序将在 [MPA 模式](../guide/mpa-mode)下构建。MPA 模式默认提供 零 JavaScript 支持,代价是禁用客户端导航,并且需要明确选择加入才能进行交互。 + +## 主题 {#theming} + +### appearance + +- 类型:`boolean | 'dark' | 'force-dark' | import('@vueuse/core').UseDarkOptions` +- 默认值: `true` + +是否启用深色模式 (通过将 `.dark` 类添加到 `` 元素)。 + +- 如果该选项设置为 `true`,则默认主题将由用户的首选配色方案决定。 +- 如果该选项设置为 `dark`,则默认情况下主题将是深色的,除非用户手动切换它。 +- 如果该选项设置为 `false`,用户将无法切换主题。 + +此选项注入一个内联脚本,使用 `vitepress-theme-appearance` key 从本地存储恢复用户设置。这确保在呈现页面之前应用 `.dark` 类以避免闪烁。 + +`appearance.initialValue` 只能是 `'dark' | undefined`。 不支持 Refs 或 getters。 + +### lastUpdated + +- 类型:`boolean` +- 默认值: `false` + +是否使用 Git 获取每个页面的最后更新时间戳。时间戳将包含在每个页面的页面数据中,可通过 [`useData`](./runtime-api#usedata) 访问。 + +使用默认主题时,启用此选项将显示每个页面的最后更新时间。可以通过 [`themeConfig.lastUpdatedText`](./default-theme-config#lastupdatedtext) 选项自定义文本。 + +## 自定义 {#customization} + +### markdown + +- 类型:`MarkdownOption` + +配置 Markdown 解析器选项。VitePress 使用 [Markdown-it](https://github.com/markdown-it/markdown-it) 作为解析器,使用 [Shiki](https://github.com/shikijs/shiki) 来高亮不同语言语法。在此选项中,可以传递各种 Markdown 相关选项以满足你的需要。 + +```js +export default { + markdown: {...} +} +``` + +查看[类型声明和 jsdocs](https://github.com/vuejs/vitepress/blob/main/src/node/markdown/markdown.ts) 以获得所有可配置的选项。 + +### vite + +- 类型:`import('vite').UserConfig` + +将原始 [Vite 配置](https://vitejs.dev/config/)传递给内部 Vite 开发服务器 / bundler。 + +```js +export default { + vite: { + // Vite 配置选项 + } +} +``` + +### vue + +- 类型:`import('@vitejs/plugin-vue').Options` + +将原始的 [@vitejs/plugin-vue 选项](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue#options)传递给内部插件实例。 + +```js +export default { + vue: { + // @vitejs/plugin-vue 选项 + } +} +``` + +## 构建钩子 {#build-hooks} + +VitePress 构建钩子允许向站点添加新功能和行为: + +- Sitemap +- Search Indexing +- PWA +- Teleport + +### buildEnd + +- 类型:`(siteConfig: SiteConfig) => Awaitable` + +`buildEnd` 是一个构建 CLI 钩子,它将在构建 SSG 完成后但在 VitePress CLI 进程退出之前运行。 + +```ts +export default { + async buildEnd(siteConfig) { + // ... + } +} +``` + +### postRender + +- 类型:`(context: SSGContext) => Awaitable` + + `postRender` 是一个构建钩子,在 SSG 渲染完成时调用。它将允许在 SSG 期间处理传递的内容。 + +```ts +export default { + async postRender(context) { + // ... + } +} +``` + +```ts +interface SSGContext { + content: string + teleports?: Record + [key: string]: any +} +``` + +### transformHead + +- 类型:`(context: TransformContext) => Awaitable` + +`transformHead` 是一个构建钩子,用于在生成每个页面之前转换 head。它将允许添加无法静态添加到 VitePress 配置中的 head entries。只需要返回额外的 entries,它们将自动与现有 entries 合并。 + +::: warning +不要改变 `context` 中的任何东西。 +::: + +```ts +export default { + async transformHead(context) { + // ... + } +} +``` + +```ts +interface TransformContext { + page: string // 例如 index.md (相对于 srcDir) + assets: string[] // 所有非 js/css 资源均作为完全解析的公共 URL + siteConfig: SiteConfig + siteData: SiteData + pageData: PageData + title: string + description: string + head: HeadConfig[] + content: string +} +``` + +请注意,仅在静态生成站点时才会调用此钩子。在开发期间不会调用它。如果需要在开发期间添加动态 head 条目,可以使用 [`transformPageData`](#transformpagedata) 钩子来替代: + +```ts +export default { + transformPageData(pageData) { + pageData.frontmatter.head ??= [] + pageData.frontmatter.head.push([ + 'meta', + { + name: 'og:title', + content: + pageData.frontmatter.layout === 'home' + ? `VitePress` + : `${pageData.title} | VitePress` + } + ]) + } +} +``` + +#### 示例:添加 canonical URL `` {#example-adding-a-canonical-url-link} + +```ts +export default { + transformPageData(pageData) { + const canonicalUrl = `https://example.com/${pageData.relativePath}` + .replace(/index\.md$/, '') + .replace(/\.md$/, '.html') + + pageData.frontmatter.head ??= [] + pageData.frontmatter.head.push([ + 'link', + { rel: 'canonical', href: canonicalUrl } + ]) + } +} +``` + +### transformHtml + +- 类型:`(code: string, id: string, context: TransformContext) => Awaitable` + +`transformHtml` 是一个构建钩子,用于在保存到磁盘之前转换每个页面的内容。 + +::: warning +不要改变 `context` 中的任何东西。另外,修改 html 内容可能会导致运行时出现激活问题。 +::: + +```ts +export default { + async transformHtml(code, id, context) { + // ... + } +} +``` + +### transformPageData + +- 类型:`(pageData: PageData, context: TransformPageContext) => Awaitable | { [key: string]: any } | void>` + +`transformPageData` 是一个钩子,用于转换每个页面的 `pageData`。可以直接改变 `pageData` 或返回将合并到 `PageData` 中的更改值。 + +::: warning +不要改变 `context` 中的任何东西。请注意,这可能会影响开发服务器的性能,特别是当在钩子中有一些网络请求或大量计算 (例如生成图像) 时。可以通过判断 `process.env.NODE_ENV === 'production'` 匹配符合条件的情况。 +::: + +```ts +export default { + async transformPageData(pageData, { siteConfig }) { + pageData.contributors = await getPageContributors(pageData.relativePath) + } + + // 或返回要合并的数据 + async transformPageData(pageData, { siteConfig }) { + return { + contributors: await getPageContributors(pageData.relativePath) + } + } +} +``` + +```ts +interface TransformPageContext { + siteConfig: SiteConfig +} +``` diff --git a/netlify.toml b/netlify.toml index 8ebbb56e..b74ba994 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,6 +1,38 @@ [build.environment] - NODE_VERSION = "16" + NODE_VERSION = "22" + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD = "1" [build] publish = "docs/.vitepress/dist" - command = "pnpm docs-build" + command = "pnpm docs:build && pnpm docs:lunaria:build" + +[[headers]] + for = "/assets/*" + [headers.values] + cache-control = ''' + max-age=31536000, + immutable''' + +[[headers]] + for = "/_translations/*" + [headers.values] + x-robots-tag = "noindex" + +[[redirects]] + from = "https://vitepress.vuejs.org/*" + to = "https://vitepress.dev/:splat" + force = true + +[[redirects]] + from = "/guide/" + to = "/guide/getting-started" + +[[redirects]] + from = "/llms.md" + status = 301 + to = "/llms.txt" + +[[redirects]] + from = "/llms-full.md" + status = 301 + to = "/llms-full.txt" diff --git a/package.json b/package.json index b5b501c9..c6c664f4 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,24 @@ { "name": "vitepress", - "version": "1.0.0-beta.1", + "version": "2.0.0-alpha.5", "description": "Vite & Vue powered static site generator", + "keywords": [ + "vite", + "vue", + "vitepress" + ], + "homepage": "https://vitepress.dev/", + "bugs": { + "url": "https://github.com/vuejs/vitepress/issues" + }, + "repository": "github:vuejs/vitepress", + "license": "MIT", + "author": "Evan You", "type": "module", - "packageManager": "pnpm@8.6.1", - "main": "dist/node/index.js", - "types": "types/index.d.ts", "exports": { ".": { "types": "./types/index.d.ts", - "import": "./dist/node/index.js", - "require": "./dist/node-cjs/index.cjs" + "default": "./dist/node/index.js" }, "./dist/*": "./dist/*", "./package.json": "./package.json", @@ -27,6 +35,8 @@ "default": "./dist/client/theme-default/without-fonts.js" } }, + "main": "dist/node/index.js", + "types": "types/index.d.ts", "bin": { "vitepress": "bin/vitepress.js" }, @@ -37,160 +47,182 @@ "template", "client.d.ts", "theme.d.ts", - "theme-without-fonts.d.ts" + "theme-without-fonts.d.ts", + "lib" ], - "repository": { - "type": "git", - "url": "git+https://github.com/vuejs/vitepress.git" - }, - "keywords": [ - "vite", - "vue", - "vitepress" - ], - "author": "Evan You", - "license": "MIT", - "homepage": "https://github.com/vuejs/vitepress/tree/main/#readme", - "bugs": { - "url": "https://github.com/vuejs/vitepress/issues" - }, "scripts": { - "dev": "rimraf dist && run-s dev-shared dev-start", - "dev-start": "run-p dev-client dev-node dev-watch", - "dev-client": "tsc --sourcemap -w -p src/client", - "dev-node": "DEV=true pnpm build-node -w", - "dev-shared": "node scripts/copyShared", - "dev-watch": "node scripts/watchAndCopy", - "build": "run-s build-prepare build-client build-node", - "build-prepare": "rimraf dist && node scripts/copyShared", - "build-client": "vue-tsc --noEmit -p src/client && tsc -p src/client && node scripts/copyClient", - "build-node": "tsc -p src/node --noEmit && rollup --config rollup.config.ts --configPlugin esbuild", + "dev": "rimraf dist && pnpm dev:shared && pnpm dev:start", + "dev:start": "pnpm --stream '/^dev:(client|node|watch)$/'", + "dev:client": "tsc --sourcemap -w --preserveWatchOutput -p src/client", + "dev:node": "DEV=true pnpm build:node -w", + "dev:shared": "node scripts/copyShared", + "dev:watch": "node scripts/watchAndCopy", + "build": "pnpm build:prepare && pnpm build:client && pnpm build:node", + "build:prepare": "rimraf dist && node scripts/copyShared", + "build:client": "vue-tsc --noEmit -p src/client && tsc -p src/client && node scripts/copyClient", + "build:node": "tsc -p src/node --noEmit && rollup --config rollup.config.ts --configPlugin esbuild", + "test": "pnpm --aggregate-output --reporter=append-only '/^test:(unit|e2e|init)$/'", + "test:unit": "vitest run -r __tests__/unit", + "test:unit:watch": "vitest -r __tests__/unit", + "test:e2e": "pnpm test:e2e-dev && pnpm test:e2e-build", + "test:e2e:site:dev": "pnpm -F=tests-e2e site:dev", + "test:e2e:site:build": "pnpm -F=tests-e2e site:build", + "test:e2e:site:preview": "pnpm -F=tests-e2e site:preview", + "test:e2e-dev": "pnpm -F=tests-e2e test", + "test:e2e-dev:watch": "pnpm -F=tests-e2e watch", + "test:e2e-build": "VITE_TEST_BUILD=1 pnpm test:e2e-dev", + "test:e2e-build:watch": "VITE_TEST_BUILD=1 pnpm test:e2e-dev:watch", + "test:init": "pnpm -F=tests-init test", + "test:init:watch": "pnpm -F=tests-init watch", + "docs": "pnpm --stream '/^(docs:)?dev$/'", + "docs:dev": "wait-on -d 100 dist/node/cli.js && pnpm -F=docs dev", + "docs:debug": "NODE_OPTIONS='--inspect-brk' pnpm docs:dev", + "docs:build": "pnpm build && pnpm docs:build:only", + "docs:build:only": "pnpm -F=docs build", + "docs:preview": "pnpm -F=docs preview", + "docs:lunaria:build": "pnpm -F=docs lunaria:build", + "docs:lunaria:open": "pnpm -F=docs lunaria:open", "format": "prettier --check --write .", - "format-fail": "prettier --check .", - "check": "run-s format-fail build test", - "test": "run-s test-unit test-e2e test-e2e-build", - "test-unit": "vitest run -r __tests__/unit", - "test-e2e": "vitest run -r __tests__/e2e", - "test-e2e-build": "VITE_TEST_BUILD=1 pnpm test-e2e", - "test-init": "vitest run -r __tests__/init", - "test-init-build": "VITE_TEST_BUILD=1 pnpm test-init", - "debug-e2e": "DEBUG=1 vitest -r __tests__/e2e", - "debug-e2e-build": "VITE_TEST_BUILD=1 pnpm debug-e2e", - "unit-dev": "vitest -r __tests__/unit", - "e2e-dev": "wait-on -d 100 dist/node/cli.js && node ./bin/vitepress dev __tests__/e2e", + "format:fail": "prettier --check .", + "check": "pnpm format:fail && pnpm build && pnpm test", "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s", - "release": "node scripts/release.js", - "docs": "run-p dev docs-dev", - "docs-dev": "wait-on -d 100 dist/node/cli.js && node ./bin/vitepress dev docs", - "docs-debug": "node --inspect-brk ./bin/vitepress dev docs", - "docs-build": "run-s build docs-build-only", - "docs-build-only": "node ./bin/vitepress build docs", - "docs-preview": "node ./bin/vitepress preview docs" + "release": "node scripts/release.js" + }, + "simple-git-hooks": { + "pre-commit": "pnpm lint-staged" + }, + "lint-staged": { + "*": "prettier --write --ignore-unknown" }, "dependencies": { - "@docsearch/css": "^3.4.0", - "@docsearch/js": "^3.4.0", - "@vitejs/plugin-vue": "^4.2.3", - "@vue/devtools-api": "^6.5.0", - "@vueuse/core": "^10.1.2", - "@vueuse/integrations": "^10.1.2", - "body-scroll-lock": "4.0.0-beta.0", - "focus-trap": "^7.4.3", + "@docsearch/css": "^3.9.0", + "@docsearch/js": "^3.9.0", + "@iconify-json/simple-icons": "^1.2.33", + "@shikijs/core": "^3.4.0", + "@shikijs/transformers": "^3.4.0", + "@shikijs/types": "^3.4.0", + "@vitejs/plugin-vue": "^5.2.4", + "@vue/devtools-api": "^7.7.6", + "@vue/shared": "^3.5.13", + "@vueuse/core": "^13.1.0", + "@vueuse/integrations": "^13.1.0", + "focus-trap": "^7.6.4", "mark.js": "8.11.1", - "minisearch": "^6.1.0", - "shiki": "^0.14.2", - "vite": "^4.3.9", - "vue": "^3.3.4" + "minisearch": "^7.1.2", + "shiki": "^3.4.0", + "vite": "^6.3.5", + "vue": "^3.5.13" }, "devDependencies": { - "@clack/prompts": "^0.6.3", - "@mdit-vue/plugin-component": "^0.12.0", - "@mdit-vue/plugin-frontmatter": "^0.12.0", - "@mdit-vue/plugin-headers": "^0.12.0", - "@mdit-vue/plugin-sfc": "^0.12.0", - "@mdit-vue/plugin-title": "^0.12.0", - "@mdit-vue/plugin-toc": "^0.12.0", - "@mdit-vue/shared": "^0.12.0", - "@rollup/plugin-alias": "^5.0.0", - "@rollup/plugin-commonjs": "^25.0.0", - "@rollup/plugin-json": "^6.0.0", - "@rollup/plugin-node-resolve": "^15.1.0", - "@rollup/plugin-replace": "^5.0.2", - "@types/body-scroll-lock": "^3.1.0", - "@types/compression": "^1.7.2", - "@types/cross-spawn": "^6.0.2", - "@types/debug": "^4.1.8", - "@types/escape-html": "^1.0.2", - "@types/fs-extra": "^11.0.1", - "@types/mark.js": "^8.11.8", - "@types/markdown-it": "^12.2.3", - "@types/markdown-it-attrs": "^4.1.0", - "@types/markdown-it-container": "^2.0.5", - "@types/markdown-it-emoji": "^2.0.2", - "@types/micromatch": "^4.0.2", - "@types/minimist": "^1.2.2", - "@types/node": "^20.2.5", - "@types/prompts": "^2.4.4", - "chokidar": "^3.5.3", - "compression": "^1.7.4", - "conventional-changelog-cli": "^3.0.0", - "cross-spawn": "^7.0.3", - "debug": "^4.3.4", - "esbuild": "^0.17.19", - "escape-html": "^1.0.3", - "execa": "^7.1.1", - "fast-glob": "^3.2.12", - "fs-extra": "^11.1.1", - "get-port": "^7.0.0", + "@clack/prompts": "^1.0.0-alpha.0", + "@iconify/utils": "^2.3.0", + "@mdit-vue/plugin-component": "^2.1.4", + "@mdit-vue/plugin-frontmatter": "^2.1.4", + "@mdit-vue/plugin-headers": "^2.1.4", + "@mdit-vue/plugin-sfc": "^2.1.4", + "@mdit-vue/plugin-title": "^2.1.4", + "@mdit-vue/plugin-toc": "^2.1.4", + "@mdit-vue/shared": "^2.1.4", + "@polka/compression": "^1.0.0-next.28", + "@rollup/plugin-alias": "^5.1.1", + "@rollup/plugin-commonjs": "^28.0.3", + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "^16.0.1", + "@rollup/plugin-replace": "^6.0.2", + "@types/cross-spawn": "^6.0.6", + "@types/debug": "^4.1.12", + "@types/fs-extra": "^11.0.4", + "@types/lodash.template": "^4.5.3", + "@types/mark.js": "^8.11.12", + "@types/markdown-it": "^14.1.2", + "@types/markdown-it-attrs": "^4.1.3", + "@types/markdown-it-container": "^2.0.10", + "@types/markdown-it-emoji": "^3.0.1", + "@types/minimist": "^1.2.5", + "@types/node": "^22.15.17", + "@types/picomatch": "^4.0.0", + "@types/postcss-prefix-selector": "^1.16.3", + "@types/prompts": "^2.4.9", + "chokidar": "^4.0.3", + "conventional-changelog-cli": "^5.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.4.0", + "esbuild": "^0.25.4", + "execa": "^9.5.3", + "fs-extra": "^11.3.0", + "get-port": "^7.1.0", "gray-matter": "^4.0.3", - "lint-staged": "^13.2.2", + "lint-staged": "^15.5.2", "lodash.template": "^4.5.0", - "lru-cache": "^9.1.2", - "markdown-it": "^13.0.1", - "markdown-it-anchor": "^8.6.7", - "markdown-it-attrs": "^4.1.6", - "markdown-it-container": "^3.0.0", - "markdown-it-emoji": "^2.0.2", - "micromatch": "^4.0.5", + "lru-cache": "^11.1.0", + "markdown-it": "^14.1.0", + "markdown-it-anchor": "^9.2.0", + "markdown-it-async": "^2.2.0", + "markdown-it-attrs": "^4.3.1", + "markdown-it-container": "^4.0.0", + "markdown-it-emoji": "^3.0.0", + "markdown-it-mathjax3": "^4.3.2", "minimist": "^1.2.8", - "nanoid": "^4.0.2", - "npm-run-all": "^4.1.5", - "ora": "^6.3.1", - "path-to-regexp": "^6.2.1", - "picocolors": "^1.0.0", - "pkg-dir": "^7.0.0", - "playwright-chromium": "^1.34.3", - "polka": "1.0.0-next.22", - "prettier": "^2.8.8", + "nanoid": "^5.1.5", + "ora": "^8.2.0", + "oxc-minify": "^0.69.0", + "p-map": "^7.0.3", + "path-to-regexp": "^6.3.0", + "picocolors": "^1.1.1", + "picomatch": "^4.0.2", + "pkg-dir": "^8.0.0", + "playwright-chromium": "^1.52.0", + "polka": "^1.0.0-next.28", + "postcss-prefix-selector": "^2.1.1", + "prettier": "^3.5.3", "prompts": "^2.4.2", - "punycode": "^2.3.0", - "rimraf": "^5.0.1", - "rollup": "^3.24.0", - "rollup-plugin-dts": "^5.3.0", - "rollup-plugin-esbuild": "^5.0.0", - "semver": "^7.5.1", - "shiki-processor": "^0.1.3", - "simple-git-hooks": "^2.8.1", - "sirv": "^2.0.3", - "supports-color": "^9.3.1", - "typescript": "^5.1.3", - "vitest": "^0.32.0", - "vue-tsc": "^1.6.5", - "wait-on": "^7.0.1" + "punycode": "^2.3.1", + "rimraf": "^6.0.1", + "rollup": "^4.40.2", + "rollup-plugin-dts": "6.1.1", + "rollup-plugin-esbuild": "^6.2.1", + "semver": "^7.7.1", + "simple-git-hooks": "^2.13.0", + "sirv": "^3.0.1", + "sitemap": "^8.0.0", + "tinyglobby": "^0.2.13", + "typescript": "^5.8.3", + "vitest": "^3.1.3", + "vue-tsc": "^3.0.0-alpha.6", + "wait-on": "^8.0.3" + }, + "peerDependencies": { + "markdown-it-mathjax3": "^4", + "oxc-minify": "^0.69.0", + "postcss": "^8" + }, + "peerDependenciesMeta": { + "markdown-it-mathjax3": { + "optional": true + }, + "postcss": { + "optional": true + }, + "oxc-minify": { + "optional": true + } }, + "packageManager": "pnpm@10.10.0", "pnpm": { "peerDependencyRules": { "ignoreMissing": [ - "@algolia/client-search" + "@algolia/client-search", + "search-insights", + "postcss" ] - } - }, - "simple-git-hooks": { - "pre-commit": "pnpm lint-staged" - }, - "lint-staged": { - "*": [ - "prettier --write --ignore-unknown" - ] + }, + "overrides": { + "ora>string-width": "^5" + }, + "patchedDependencies": { + "@types/mdurl@2.0.0": "patches/@types__mdurl@2.0.0.patch", + "markdown-it-anchor@9.2.0": "patches/markdown-it-anchor@9.2.0.patch" + }, + "neverBuiltDependencies": [] } } diff --git a/patches/@types__mdurl@2.0.0.patch b/patches/@types__mdurl@2.0.0.patch new file mode 100644 index 00000000..d128d01c --- /dev/null +++ b/patches/@types__mdurl@2.0.0.patch @@ -0,0 +1,19 @@ +diff --git a/lib/parse.d.mts b/lib/parse.d.mts +index 2e0d8f2ea00a06c0971a68d34946e797b7f8152d..f61d4dd05c1b181bc6d2d8683153abcd10fe9ab9 100644 +--- a/lib/parse.d.mts ++++ b/lib/parse.d.mts +@@ -1,4 +1,4 @@ +-declare class Url { ++declare class _Url { + protocol: string; + slashes: string; + auth: string; +@@ -14,5 +14,7 @@ declare class Url { + parseHost(host: string): void; + } + ++type Url = _Url; ++ + export default function parse(url: string | Url, slashesDenoteHost?: boolean): Url; +-export type { Url }; ++export { Url }; diff --git a/patches/markdown-it-anchor@9.2.0.patch b/patches/markdown-it-anchor@9.2.0.patch new file mode 100644 index 00000000..ac4498e4 --- /dev/null +++ b/patches/markdown-it-anchor@9.2.0.patch @@ -0,0 +1,17 @@ +diff --git a/types/index.d.ts b/types/index.d.ts +index 40c25c0be1add8b0fc2c51489c25a423dbc49d2c..807bc1b0e434d660c6a298b1dee1c87935bfac86 100644 +--- a/types/index.d.ts ++++ b/types/index.d.ts +@@ -1,10 +1,8 @@ + import MarkdownIt from 'markdown-it'; +-import { default as MarkdownItToken } from 'markdown-it/lib/token.mjs'; +-import { default as MarkdownItState} from 'markdown-it/lib/rules_core/state_core.mjs'; ++import { default as Token } from 'markdown-it/lib/token.mjs'; ++import { default as State } from 'markdown-it/lib/rules_core/state_core.mjs'; + + declare namespace anchor { +- export type Token = MarkdownItToken +- export type State = MarkdownItState + export type RenderHref = (slug: string, state: State) => string; + export type RenderAttrs = (slug: string, state: State) => Record; + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index acf50081..96432174 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,275 +1,304 @@ -lockfileVersion: '6.1' +lockfileVersion: '9.0' settings: - autoInstallPeers: true + autoInstallPeers: false excludeLinksFromLockfile: false +overrides: + ora>string-width: ^5 + +patchedDependencies: + '@types/mdurl@2.0.0': + hash: 3460e7d18ce390685cf4b8d8237fb20df9ad952c1336f479995a508a6395bfa4 + path: patches/@types__mdurl@2.0.0.patch + markdown-it-anchor@9.2.0: + hash: cdc28e7c329be30688ad192126ba505446611fbe526ad51483e4b1287aa35cf9 + path: patches/markdown-it-anchor@9.2.0.patch + importers: .: dependencies: '@docsearch/css': + specifier: ^3.9.0 + version: 3.9.0 + '@docsearch/js': + specifier: ^3.9.0 + version: 3.9.0(@algolia/client-search@5.24.0) + '@iconify-json/simple-icons': + specifier: ^1.2.33 + version: 1.2.33 + '@shikijs/core': specifier: ^3.4.0 version: 3.4.0 - '@docsearch/js': + '@shikijs/transformers': + specifier: ^3.4.0 + version: 3.4.0 + '@shikijs/types': specifier: ^3.4.0 version: 3.4.0 '@vitejs/plugin-vue': - specifier: ^4.2.3 - version: 4.2.3(vite@4.3.9)(vue@3.3.4) + specifier: ^5.2.4 + version: 5.2.4(vite@6.3.5(@types/node@22.15.17)(jiti@1.21.7)(lightningcss@1.30.0)(yaml@2.7.1))(vue@3.5.13(typescript@5.8.3)) '@vue/devtools-api': - specifier: ^6.5.0 - version: 6.5.0 + specifier: ^7.7.6 + version: 7.7.6 + '@vue/shared': + specifier: ^3.5.13 + version: 3.5.13 '@vueuse/core': - specifier: ^10.1.2 - version: 10.1.2(vue@3.3.4) + specifier: ^13.1.0 + version: 13.1.0(vue@3.5.13(typescript@5.8.3)) '@vueuse/integrations': - specifier: ^10.1.2 - version: 10.1.2(focus-trap@7.4.3)(vue@3.3.4) - body-scroll-lock: - specifier: 4.0.0-beta.0 - version: 4.0.0-beta.0 + specifier: ^13.1.0 + version: 13.1.0(axios@1.9.0(debug@4.4.0))(focus-trap@7.6.4)(vue@3.5.13(typescript@5.8.3)) focus-trap: - specifier: ^7.4.3 - version: 7.4.3 + specifier: ^7.6.4 + version: 7.6.4 mark.js: specifier: 8.11.1 version: 8.11.1 minisearch: - specifier: ^6.1.0 - version: 6.1.0 + specifier: ^7.1.2 + version: 7.1.2 shiki: - specifier: ^0.14.2 - version: 0.14.2 + specifier: ^3.4.0 + version: 3.4.0 vite: - specifier: ^4.3.9 - version: 4.3.9(@types/node@20.2.5) + specifier: ^6.3.5 + version: 6.3.5(@types/node@22.15.17)(jiti@1.21.7)(lightningcss@1.30.0)(yaml@2.7.1) vue: - specifier: ^3.3.4 - version: 3.3.4 + specifier: ^3.5.13 + version: 3.5.13(typescript@5.8.3) devDependencies: '@clack/prompts': - specifier: ^0.6.3 - version: 0.6.3 + specifier: ^1.0.0-alpha.0 + version: 1.0.0-alpha.0 + '@iconify/utils': + specifier: ^2.3.0 + version: 2.3.0 '@mdit-vue/plugin-component': - specifier: ^0.12.0 - version: 0.12.0 + specifier: ^2.1.4 + version: 2.1.4 '@mdit-vue/plugin-frontmatter': - specifier: ^0.12.0 - version: 0.12.0 + specifier: ^2.1.4 + version: 2.1.4 '@mdit-vue/plugin-headers': - specifier: ^0.12.0 - version: 0.12.0 + specifier: ^2.1.4 + version: 2.1.4 '@mdit-vue/plugin-sfc': - specifier: ^0.12.0 - version: 0.12.0 + specifier: ^2.1.4 + version: 2.1.4 '@mdit-vue/plugin-title': - specifier: ^0.12.0 - version: 0.12.0 + specifier: ^2.1.4 + version: 2.1.4 '@mdit-vue/plugin-toc': - specifier: ^0.12.0 - version: 0.12.0 + specifier: ^2.1.4 + version: 2.1.4 '@mdit-vue/shared': - specifier: ^0.12.0 - version: 0.12.0 + specifier: ^2.1.4 + version: 2.1.4 + '@polka/compression': + specifier: ^1.0.0-next.28 + version: 1.0.0-next.28 '@rollup/plugin-alias': - specifier: ^5.0.0 - version: 5.0.0(rollup@3.24.0) + specifier: ^5.1.1 + version: 5.1.1(rollup@4.40.2) '@rollup/plugin-commonjs': - specifier: ^25.0.0 - version: 25.0.0(rollup@3.24.0) + specifier: ^28.0.3 + version: 28.0.3(rollup@4.40.2) '@rollup/plugin-json': - specifier: ^6.0.0 - version: 6.0.0(rollup@3.24.0) + specifier: ^6.1.0 + version: 6.1.0(rollup@4.40.2) '@rollup/plugin-node-resolve': - specifier: ^15.1.0 - version: 15.1.0(rollup@3.24.0) + specifier: ^16.0.1 + version: 16.0.1(rollup@4.40.2) '@rollup/plugin-replace': - specifier: ^5.0.2 - version: 5.0.2(rollup@3.24.0) - '@types/body-scroll-lock': - specifier: ^3.1.0 - version: 3.1.0 - '@types/compression': - specifier: ^1.7.2 - version: 1.7.2 - '@types/cross-spawn': specifier: ^6.0.2 - version: 6.0.2 + version: 6.0.2(rollup@4.40.2) + '@types/cross-spawn': + specifier: ^6.0.6 + version: 6.0.6 '@types/debug': - specifier: ^4.1.8 - version: 4.1.8 - '@types/escape-html': - specifier: ^1.0.2 - version: 1.0.2 + specifier: ^4.1.12 + version: 4.1.12 '@types/fs-extra': - specifier: ^11.0.1 - version: 11.0.1 + specifier: ^11.0.4 + version: 11.0.4 + '@types/lodash.template': + specifier: ^4.5.3 + version: 4.5.3 '@types/mark.js': - specifier: ^8.11.8 - version: 8.11.8 + specifier: ^8.11.12 + version: 8.11.12 '@types/markdown-it': - specifier: ^12.2.3 - version: 12.2.3 + specifier: ^14.1.2 + version: 14.1.2 '@types/markdown-it-attrs': - specifier: ^4.1.0 - version: 4.1.0 + specifier: ^4.1.3 + version: 4.1.3 '@types/markdown-it-container': - specifier: ^2.0.5 - version: 2.0.5 + specifier: ^2.0.10 + version: 2.0.10 '@types/markdown-it-emoji': - specifier: ^2.0.2 - version: 2.0.2 - '@types/micromatch': - specifier: ^4.0.2 - version: 4.0.2 + specifier: ^3.0.1 + version: 3.0.1 '@types/minimist': - specifier: ^1.2.2 - version: 1.2.2 + specifier: ^1.2.5 + version: 1.2.5 '@types/node': - specifier: ^20.2.5 - version: 20.2.5 + specifier: ^22.15.17 + version: 22.15.17 + '@types/picomatch': + specifier: ^4.0.0 + version: 4.0.0 + '@types/postcss-prefix-selector': + specifier: ^1.16.3 + version: 1.16.3 '@types/prompts': - specifier: ^2.4.4 - version: 2.4.4 + specifier: ^2.4.9 + version: 2.4.9 chokidar: - specifier: ^3.5.3 - version: 3.5.3 - compression: - specifier: ^1.7.4 - version: 1.7.4(supports-color@9.3.1) + specifier: ^4.0.3 + version: 4.0.3 conventional-changelog-cli: - specifier: ^3.0.0 - version: 3.0.0 + specifier: ^5.0.0 + version: 5.0.0(conventional-commits-filter@5.0.0) cross-spawn: - specifier: ^7.0.3 - version: 7.0.3 + specifier: ^7.0.6 + version: 7.0.6 debug: - specifier: ^4.3.4 - version: 4.3.4(supports-color@9.3.1) + specifier: ^4.4.0 + version: 4.4.0 esbuild: - specifier: ^0.17.19 - version: 0.17.19 - escape-html: - specifier: ^1.0.3 - version: 1.0.3 + specifier: ^0.25.4 + version: 0.25.4 execa: - specifier: ^7.1.1 - version: 7.1.1 - fast-glob: - specifier: ^3.2.12 - version: 3.2.12 + specifier: ^9.5.3 + version: 9.5.3 fs-extra: - specifier: ^11.1.1 - version: 11.1.1 + specifier: ^11.3.0 + version: 11.3.0 get-port: - specifier: ^7.0.0 - version: 7.0.0 + specifier: ^7.1.0 + version: 7.1.0 gray-matter: specifier: ^4.0.3 version: 4.0.3 lint-staged: - specifier: ^13.2.2 - version: 13.2.2(supports-color@9.3.1) + specifier: ^15.5.2 + version: 15.5.2 lodash.template: specifier: ^4.5.0 version: 4.5.0 lru-cache: - specifier: ^9.1.2 - version: 9.1.2 + specifier: ^11.1.0 + version: 11.1.0 markdown-it: - specifier: ^13.0.1 - version: 13.0.1 + specifier: ^14.1.0 + version: 14.1.0 markdown-it-anchor: - specifier: ^8.6.7 - version: 8.6.7(@types/markdown-it@12.2.3)(markdown-it@13.0.1) + specifier: ^9.2.0 + version: 9.2.0(patch_hash=cdc28e7c329be30688ad192126ba505446611fbe526ad51483e4b1287aa35cf9)(@types/markdown-it@14.1.2)(markdown-it@14.1.0) + markdown-it-async: + specifier: ^2.2.0 + version: 2.2.0 markdown-it-attrs: - specifier: ^4.1.6 - version: 4.1.6(markdown-it@13.0.1) + specifier: ^4.3.1 + version: 4.3.1(markdown-it@14.1.0) markdown-it-container: + specifier: ^4.0.0 + version: 4.0.0 + markdown-it-emoji: specifier: ^3.0.0 version: 3.0.0 - markdown-it-emoji: - specifier: ^2.0.2 - version: 2.0.2 - micromatch: - specifier: ^4.0.5 - version: 4.0.5 + markdown-it-mathjax3: + specifier: ^4.3.2 + version: 4.3.2 minimist: specifier: ^1.2.8 version: 1.2.8 nanoid: - specifier: ^4.0.2 - version: 4.0.2 - npm-run-all: - specifier: ^4.1.5 - version: 4.1.5 + specifier: ^5.1.5 + version: 5.1.5 ora: - specifier: ^6.3.1 - version: 6.3.1 + specifier: ^8.2.0 + version: 8.2.0 + oxc-minify: + specifier: ^0.69.0 + version: 0.69.0 + p-map: + specifier: ^7.0.3 + version: 7.0.3 path-to-regexp: - specifier: ^6.2.1 - version: 6.2.1 + specifier: ^6.3.0 + version: 6.3.0 picocolors: - specifier: ^1.0.0 - version: 1.0.0 + specifier: ^1.1.1 + version: 1.1.1 + picomatch: + specifier: ^4.0.2 + version: 4.0.2 pkg-dir: - specifier: ^7.0.0 - version: 7.0.0 + specifier: ^8.0.0 + version: 8.0.0 playwright-chromium: - specifier: ^1.34.3 - version: 1.34.3 + specifier: ^1.52.0 + version: 1.52.0 polka: - specifier: 1.0.0-next.22 - version: 1.0.0-next.22 + specifier: ^1.0.0-next.28 + version: 1.0.0-next.28 + postcss-prefix-selector: + specifier: ^2.1.1 + version: 2.1.1(postcss@8.5.3) prettier: - specifier: ^2.8.8 - version: 2.8.8 + specifier: ^3.5.3 + version: 3.5.3 prompts: specifier: ^2.4.2 version: 2.4.2 punycode: - specifier: ^2.3.0 - version: 2.3.0 + specifier: ^2.3.1 + version: 2.3.1 rimraf: - specifier: ^5.0.1 - version: 5.0.1 + specifier: ^6.0.1 + version: 6.0.1 rollup: - specifier: ^3.24.0 - version: 3.24.0 + specifier: ^4.40.2 + version: 4.40.2 rollup-plugin-dts: - specifier: ^5.3.0 - version: 5.3.0(rollup@3.24.0)(typescript@5.1.3) + specifier: 6.1.1 + version: 6.1.1(rollup@4.40.2)(typescript@5.8.3) rollup-plugin-esbuild: - specifier: ^5.0.0 - version: 5.0.0(esbuild@0.17.19)(rollup@3.24.0)(supports-color@9.3.1) + specifier: ^6.2.1 + version: 6.2.1(esbuild@0.25.4)(rollup@4.40.2) semver: - specifier: ^7.5.1 - version: 7.5.1 - shiki-processor: - specifier: ^0.1.3 - version: 0.1.3(shiki@0.14.2) + specifier: ^7.7.1 + version: 7.7.1 simple-git-hooks: - specifier: ^2.8.1 - version: 2.8.1 + specifier: ^2.13.0 + version: 2.13.0 sirv: - specifier: ^2.0.3 - version: 2.0.3 - supports-color: - specifier: ^9.3.1 - version: 9.3.1 + specifier: ^3.0.1 + version: 3.0.1 + sitemap: + specifier: ^8.0.0 + version: 8.0.0 + tinyglobby: + specifier: ^0.2.13 + version: 0.2.13 typescript: - specifier: ^5.1.3 - version: 5.1.3 + specifier: ^5.8.3 + version: 5.8.3 vitest: - specifier: ^0.32.0 - version: 0.32.0(supports-color@9.3.1) + specifier: ^3.1.3 + version: 3.1.3(@types/debug@4.1.12)(@types/node@22.15.17)(esbuild@0.25.4)(jiti@1.21.7)(yaml@2.7.1) vue-tsc: - specifier: ^1.6.5 - version: 1.6.5(typescript@5.1.3) + specifier: ^3.0.0-alpha.6 + version: 3.0.0-alpha.6(typescript@5.8.3) wait-on: - specifier: ^7.0.1 - version: 7.0.1(debug@4.3.4) + specifier: ^8.0.3 + version: 8.0.3(debug@4.4.0) __tests__/e2e: devDependencies: @@ -285,203 +314,163 @@ importers: docs: devDependencies: + '@lunariajs/core': + specifier: ^0.1.1 + version: 0.1.1 + markdown-it-mathjax3: + specifier: ^4.3.2 + version: 4.3.2 + open-cli: + specifier: ^8.0.0 + version: 8.0.0 + postcss-rtlcss: + specifier: ^5.7.0 + version: 5.7.0(postcss@8.5.3) vitepress: specifier: workspace:* version: link:.. + vitepress-plugin-group-icons: + specifier: ^1.5.2 + version: 1.5.2 + vitepress-plugin-llms: + specifier: ^1.1.3 + version: 1.1.3 packages: - /@algolia/autocomplete-core@1.8.2: - resolution: {integrity: sha512-mTeshsyFhAqw/ebqNsQpMtbnjr+qVOSKXArEj4K0d7sqc8It1XD0gkASwecm9mF/jlOQ4Z9RNg1HbdA8JPdRwQ==} - dependencies: - '@algolia/autocomplete-shared': 1.8.2 - dev: false + '@algolia/autocomplete-core@1.17.9': + resolution: {integrity: sha512-O7BxrpLDPJWWHv/DLA9DRFWs+iY1uOJZkqUwjS5HSZAGcl0hIVCQ97LTLewiZmZ402JYUrun+8NqFP+hCknlbQ==} + + '@algolia/autocomplete-plugin-algolia-insights@1.17.9': + resolution: {integrity: sha512-u1fEHkCbWF92DBeB/KHeMacsjsoI0wFhjZtlCq2ddZbAehshbZST6Hs0Avkc0s+4UyBGbMDnSuXHLuvRWK5iDQ==} + peerDependencies: + search-insights: '>= 1 < 3' - /@algolia/autocomplete-preset-algolia@1.8.2(algoliasearch@4.17.1): - resolution: {integrity: sha512-J0oTx4me6ZM9kIKPuL3lyU3aB8DEvpVvR6xWmHVROx5rOYJGQcZsdG4ozxwcOyiiu3qxMkIbzntnV1S1VWD8yA==} + '@algolia/autocomplete-preset-algolia@1.17.9': + resolution: {integrity: sha512-Na1OuceSJeg8j7ZWn5ssMu/Ax3amtOwk76u4h5J4eK2Nx2KB5qt0Z4cOapCsxot9VcEN11ADV5aUSlQF4RhGjQ==} peerDependencies: '@algolia/client-search': '>= 4.9.1 < 6' algoliasearch: '>= 4.9.1 < 6' - peerDependenciesMeta: - '@algolia/client-search': - optional: true - dependencies: - '@algolia/autocomplete-shared': 1.8.2 - algoliasearch: 4.17.1 - dev: false - /@algolia/autocomplete-shared@1.8.2: - resolution: {integrity: sha512-b6Z/X4MczChMcfhk6kfRmBzPgjoPzuS9KGR4AFsiLulLNRAAqhP+xZTKtMnZGhLuc61I20d5WqlId02AZvcO6g==} - dev: false + '@algolia/autocomplete-shared@1.17.9': + resolution: {integrity: sha512-iDf05JDQ7I0b7JEA/9IektxN/80a2MZ1ToohfmNS3rfeuQnIKI3IJlIafD0xu4StbtQTghx9T3Maa97ytkXenQ==} + peerDependencies: + '@algolia/client-search': '>= 4.9.1 < 6' + algoliasearch: '>= 4.9.1 < 6' - /@algolia/cache-browser-local-storage@4.17.1: - resolution: {integrity: sha512-e91Jpu93X3t3mVdQwF3ZDjSFMFIfzSc+I76G4EX8nl9RYXgqcjframoL05VTjcD2YCsI18RIHAWVCBoCXVZnrw==} - dependencies: - '@algolia/cache-common': 4.17.1 - dev: false + '@algolia/client-abtesting@5.24.0': + resolution: {integrity: sha512-pNTIB5YqVVwu6UogvdX8TqsRZENaflqMMjdY7/XIPMNGrBoNH9tewINLI7+qc9tIaOLcAp3ZldqoEwAihZZ3ig==} + engines: {node: '>= 14.0.0'} - /@algolia/cache-common@4.17.1: - resolution: {integrity: sha512-fvi1WT8aSiGAKrcTw8Qg3RYgcwW8GZMHcqEm4AyDBEy72JZlFBSY80cTQ75MslINjCHXLDT+9EN8AGI9WVY7uA==} - dev: false + '@algolia/client-analytics@5.24.0': + resolution: {integrity: sha512-IF+r9RRQsIf0ylIBNFxo7c6hDxxuhIfIbffhBXEF1HD13rjhP5AVfiaea9RzbsAZoySkm318plDpH/nlGIjbRA==} + engines: {node: '>= 14.0.0'} - /@algolia/cache-in-memory@4.17.1: - resolution: {integrity: sha512-NbBt6eBWlsXc5geSpfPRC5dkIB/0Ptthw8r0yM5Z7D3sPlYdnTZSO9y9XWXIptRMwmZe4cM8iBMN8y0tzbcBkA==} - dependencies: - '@algolia/cache-common': 4.17.1 - dev: false + '@algolia/client-common@5.24.0': + resolution: {integrity: sha512-p8K6tiXQTebRBxbrzWIfGCvfkT+Umml+2lzI92acZjHsvl6KYH6igOfVstKqXJRei9pvRzEEvVDNDLXDVleGTA==} + engines: {node: '>= 14.0.0'} - /@algolia/client-account@4.17.1: - resolution: {integrity: sha512-3rL/6ofJvyL+q8TiWM3qoM9tig+SY4gB1Vbsj+UeJPnJm8Khm+7OS+r+mFraqR6pTehYqN8yGYoE7x4diEn4aA==} - dependencies: - '@algolia/client-common': 4.17.1 - '@algolia/client-search': 4.17.1 - '@algolia/transporter': 4.17.1 - dev: false + '@algolia/client-insights@5.24.0': + resolution: {integrity: sha512-jOHF0+tixR3IZJMhZPquFNdCVPzwzzXoiqVsbTvfKojeaY6ZXybgUiTSB8JNX+YpsUT8Ebhu3UvRy4mw2PbEzw==} + engines: {node: '>= 14.0.0'} - /@algolia/client-analytics@4.17.1: - resolution: {integrity: sha512-Bepr2w249vODqeBtM7i++tPmUsQ9B81aupUGbDWmjA/FX+jzQqOdhW8w1CFO5kWViNKTbz2WBIJ9U3x8hOa4bA==} - dependencies: - '@algolia/client-common': 4.17.1 - '@algolia/client-search': 4.17.1 - '@algolia/requester-common': 4.17.1 - '@algolia/transporter': 4.17.1 - dev: false + '@algolia/client-personalization@5.24.0': + resolution: {integrity: sha512-Fx/Fp6d8UmDBHecTt0XYF8C9TAaA3qeCQortfGSZzWp4gVmtrUCFNZ1SUwb8ULREnO9DanVrM5hGE8R8C4zZTQ==} + engines: {node: '>= 14.0.0'} - /@algolia/client-common@4.17.1: - resolution: {integrity: sha512-+r7kg4EgbFnGsDnoGSVNtXZO8xvZ0vzf1WAOV7sqV9PMf1bp6cpJP/3IuPrSk4t5w2KVl+pC8jfTM7HcFlfBEQ==} - dependencies: - '@algolia/requester-common': 4.17.1 - '@algolia/transporter': 4.17.1 - dev: false + '@algolia/client-query-suggestions@5.24.0': + resolution: {integrity: sha512-F8ypOedSMhz6W7zuT5O1SXXsdXSOVhY2U6GkRbYk/mzrhs3jWFR3uQIfeQVWmsJjUwIGZmPoAr9E+T/Zm2M4wA==} + engines: {node: '>= 14.0.0'} - /@algolia/client-personalization@4.17.1: - resolution: {integrity: sha512-gJku9DG/THJpfsSlG/az0a3QIn+VVff9kKh8PG8+7ZfxOHS+C+Y5YSeZVsC+c2cfoKLPo3CuHIiJ/p86erR3bA==} - dependencies: - '@algolia/client-common': 4.17.1 - '@algolia/requester-common': 4.17.1 - '@algolia/transporter': 4.17.1 - dev: false + '@algolia/client-search@5.24.0': + resolution: {integrity: sha512-k+nuciQuq7WERNNE+hsx3DX636zIy+9R4xdtvW3PANT2a2BDGOv3fv2mta8+QUMcVTVcGe/Mo3QCb4pc1HNoxA==} + engines: {node: '>= 14.0.0'} - /@algolia/client-search@4.17.1: - resolution: {integrity: sha512-Q5YfT5gVkx60PZDQBqp/zH9aUbBdC7HVvxupiHUgnCKqRQsRZjOhLest7AI6FahepuZLBZS62COrO7v+JvKY7w==} - dependencies: - '@algolia/client-common': 4.17.1 - '@algolia/requester-common': 4.17.1 - '@algolia/transporter': 4.17.1 - dev: false + '@algolia/ingestion@1.24.0': + resolution: {integrity: sha512-/lqVxmrvwoA+OyVK4XLMdz/PJaCTW4qYchX1AZ+98fdnH3K6XM/kMydQLfP0bUNGBQbmVrF88MqhqZRnZEn/MA==} + engines: {node: '>= 14.0.0'} - /@algolia/logger-common@4.17.1: - resolution: {integrity: sha512-Us28Ot+fLEmX9M96sa65VZ8EyEEzhYPxfhV9aQyKDjfXbUdJlJxKt6wZpoEg9RAPSdO8IjK9nmuW2P8au3rRsg==} - dev: false + '@algolia/monitoring@1.24.0': + resolution: {integrity: sha512-cRisDXQJhvfZCXL4hD22qca2CmW52TniOx6L7pvkaBDx0oQk1k9o+3w11fgfcCG+47OndMeNx5CMpu+K+COMzg==} + engines: {node: '>= 14.0.0'} - /@algolia/logger-console@4.17.1: - resolution: {integrity: sha512-iKGQTpOjHiE64W3JIOu6dmDvn+AfYIElI9jf/Nt6umRPmP/JI9rK+OHUoW4pKrBtdG0DPd62ppeNXzSnLxY6/g==} - dependencies: - '@algolia/logger-common': 4.17.1 - dev: false + '@algolia/recommend@5.24.0': + resolution: {integrity: sha512-JTMz0JqN2gidvKa2QCF/rMe8LNtdHaght03px2cluZaZfBRYy8TgHgkCeBspKKvV/abWJwl7J0FzWThCshqT3w==} + engines: {node: '>= 14.0.0'} - /@algolia/requester-browser-xhr@4.17.1: - resolution: {integrity: sha512-W5mGfGDsyfVR+r4pUFrYLGBEM18gs38+GNt5PE5uPULy4uVTSnnVSkJkWeRkmLBk9zEZ/Nld8m4zavK6dtEuYg==} - dependencies: - '@algolia/requester-common': 4.17.1 - dev: false + '@algolia/requester-browser-xhr@5.24.0': + resolution: {integrity: sha512-B2Gc+iSxct1WSza5CF6AgfNgmLvVb61d5bqmIWUZixtJIhyAC6lSQZuF+nvt+lmKhQwuY2gYjGGClil8onQvKQ==} + engines: {node: '>= 14.0.0'} - /@algolia/requester-common@4.17.1: - resolution: {integrity: sha512-HggXdjvVFQR0I5l7hM5WdHgQ1tqcRWeyXZz8apQ7zPWZhirmY2E9D6LVhDh/UnWQNEm7nBtM+eMFONJ3bZccIQ==} - dev: false + '@algolia/requester-fetch@5.24.0': + resolution: {integrity: sha512-6E5+hliqGc5w8ZbyTAQ+C3IGLZ/GiX623Jl2bgHA974RPyFWzVSj4rKqkboUAxQmrFY7Z02ybJWVZS5OhPQocA==} + engines: {node: '>= 14.0.0'} - /@algolia/requester-node-http@4.17.1: - resolution: {integrity: sha512-NzFWecXT6d0PPsQY9L+/qoK2deF74OLcpvqCH+Vh3mh+QzPsFafcBExdguAjZsAWDn1R6JEeFW7/fo/p0SE57w==} - dependencies: - '@algolia/requester-common': 4.17.1 - dev: false + '@algolia/requester-node-http@5.24.0': + resolution: {integrity: sha512-zM+nnqZpiQj20PyAh6uvgdSz+hD7Rj7UfAZwizqNP+bLvcbGXZwABERobuilkCQqyDBBH4uv0yqIcPRl8dSBEg==} + engines: {node: '>= 14.0.0'} - /@algolia/transporter@4.17.1: - resolution: {integrity: sha512-ZM+qhX47Vh46mWH8/U9ihvy98HdTYpYQDSlqBD7IbiUbbyoCMke+qmdSX2MGhR2FCcXBSxejsJKKVAfbpaLVgg==} - dependencies: - '@algolia/cache-common': 4.17.1 - '@algolia/logger-common': 4.17.1 - '@algolia/requester-common': 4.17.1 - dev: false + '@antfu/install-pkg@1.1.0': + resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==} - /@babel/code-frame@7.21.4: - resolution: {integrity: sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.18.6 - dev: true + '@antfu/utils@8.1.1': + resolution: {integrity: sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==} - /@babel/helper-string-parser@7.21.5: - resolution: {integrity: sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==} + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} - /@babel/helper-validator-identifier@7.19.1: - resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} - /@babel/highlight@7.18.6: - resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} + '@babel/helper-validator-identifier@7.27.1': + resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.19.1 - chalk: 2.4.2 - js-tokens: 4.0.0 - dev: true - /@babel/parser@7.22.4: - resolution: {integrity: sha512-VLLsx06XkEYqBtE5YGPwfSGwfrjnyPP5oiGty3S8pQLFDFLaS8VwWSIxkTXpcvr5zeYLE6+MBNl2npl/YnfofA==} + '@babel/parser@7.27.2': + resolution: {integrity: sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==} engines: {node: '>=6.0.0'} hasBin: true - dependencies: - '@babel/types': 7.22.4 - /@babel/types@7.22.4: - resolution: {integrity: sha512-Tx9x3UBHTTsMSW85WB2kphxYQVvrZ/t1FxD88IpSgIjiUJlCm9z+xWIDwyo1vffTwSqteqyznB8ZE9vYYk16zA==} + '@babel/types@7.27.1': + resolution: {integrity: sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.21.5 - '@babel/helper-validator-identifier': 7.19.1 - to-fast-properties: 2.0.0 - /@clack/core@0.3.2: - resolution: {integrity: sha512-FZnsNynwGDIDktx6PEZK1EuCkFpY4ldEX6VYvfl0dqeoLPb9Jpw1xoUXaVcGR8ExmYNm1w2vdGdJkEUYD/2pqg==} - dependencies: - picocolors: 1.0.0 - sisteransi: 1.0.5 - dev: true + '@clack/core@0.3.5': + resolution: {integrity: sha512-5cfhQNH+1VQ2xLQlmzXMqUoiaH0lRBq9/CLW9lTyMbuKLC3+xEK01tHVvyut++mLOn5urSHmkm6I0Lg9MaJSTQ==} - /@clack/prompts@0.6.3: - resolution: {integrity: sha512-AM+kFmAHawpUQv2q9+mcB6jLKxXGjgu/r2EQjEwujgpCdzrST6BJqYw00GRn56/L/Izw5U7ImoLmy00X/r80Pw==} - dependencies: - '@clack/core': 0.3.2 - picocolors: 1.0.0 - sisteransi: 1.0.5 - dev: true - bundledDependencies: - - is-unicode-supported + '@clack/core@1.0.0-alpha.0': + resolution: {integrity: sha512-Cp/bPW/pMUCkJ7Lr8VFixvFrlnJ4tQPDHqfTNQ51z50qwX1fSIAstQLfel2NquVHqbfjyrUkBsal8OJRBPJVjw==} - /@docsearch/css@3.4.0: - resolution: {integrity: sha512-Hg8Xfma+rFwRi6Y/pfei4FJoQ1hdVURmmNs/XPoMTCPAImU+d5yxj+M+qdLtNjWRpfWziU4dQcqY94xgFBn2dg==} - dev: false + '@clack/prompts@1.0.0-alpha.0': + resolution: {integrity: sha512-Aem7r4U2A4jdOh0PIv51Ugi+4vDgzJjGVMnuPUNVVHDGhFHEO//u6F/JY6NsZQFtXrd7ZmfePSiipikr/e5wWg==} - /@docsearch/js@3.4.0: - resolution: {integrity: sha512-uOtOHZJv+5PQmL68+srVzlGhLejnEBJgZl1bR87Zh/uK5RUI7p6el1R8hGTl2F8K2tCloNRxTMtXyYUNbMV+qw==} - dependencies: - '@docsearch/react': 3.4.0 - preact: 10.15.1 - transitivePeerDependencies: - - '@algolia/client-search' - - '@types/react' - - react - - react-dom - dev: false + '@conventional-changelog/git-client@1.0.1': + resolution: {integrity: sha512-PJEqBwAleffCMETaVm/fUgHldzBE35JFk3/9LL6NUA5EXa3qednu+UT6M7E5iBu3zIQZCULYIiZ90fBYHt6xUw==} + engines: {node: '>=18'} + peerDependencies: + conventional-commits-filter: ^5.0.0 + conventional-commits-parser: ^6.0.0 + peerDependenciesMeta: + conventional-commits-filter: + optional: true + conventional-commits-parser: + optional: true + + '@docsearch/css@3.9.0': + resolution: {integrity: sha512-cQbnVbq0rrBwNAKegIac/t6a8nWoUAn8frnkLFW6YARaRmAQr5/Eoe6Ln2fqkUCZ40KpdrKbpSAmgrkviOxuWA==} + + '@docsearch/js@3.9.0': + resolution: {integrity: sha512-4bKHcye6EkLgRE8ze0vcdshmEqxeiJM77M0JXjef7lrYZfSlMunrDOCqyLjiZyo1+c0BhUqA2QpFartIjuHIjw==} - /@docsearch/react@3.4.0: - resolution: {integrity: sha512-ufrp5879XYGojgS30ZAp8H4qIMbahRHB9M85VDBP36Xgz5QjYM54i1URKj5e219F7gqTtOivfztFTij6itc0MQ==} + '@docsearch/react@3.9.0': + resolution: {integrity: sha512-mb5FOZYZIkRQ6s/NWnM98k879vu5pscWqTLubLFBO87igYYT4VzVazh4h5o/zCvTIZgEt3PvsCOMOswOUo9yHQ==} peerDependencies: - '@types/react': '>= 16.8.0 < 19.0.0' - react: '>= 16.8.0 < 19.0.0' - react-dom: '>= 16.8.0 < 19.0.0' + '@types/react': '>= 16.8.0 < 20.0.0' + react: '>= 16.8.0 < 20.0.0' + react-dom: '>= 16.8.0 < 20.0.0' + search-insights: '>= 1 < 3' peerDependenciesMeta: '@types/react': optional: true @@ -489,4173 +478,5915 @@ packages: optional: true react-dom: optional: true - dependencies: - '@algolia/autocomplete-core': 1.8.2 - '@algolia/autocomplete-preset-algolia': 1.8.2(algoliasearch@4.17.1) - '@docsearch/css': 3.4.0 - algoliasearch: 4.17.1 - transitivePeerDependencies: - - '@algolia/client-search' - dev: false + search-insights: + optional: true - /@esbuild/android-arm64@0.17.19: - resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} - engines: {node: '>=12'} + '@emnapi/core@1.4.3': + resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==} + + '@emnapi/runtime@1.4.3': + resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==} + + '@emnapi/wasi-threads@1.0.2': + resolution: {integrity: sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==} + + '@esbuild/aix-ppc64@0.25.4': + resolution: {integrity: sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.4': + resolution: {integrity: sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==} + engines: {node: '>=18'} cpu: [arm64] os: [android] - requiresBuild: true - optional: true - /@esbuild/android-arm@0.17.19: - resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} - engines: {node: '>=12'} + '@esbuild/android-arm@0.25.4': + resolution: {integrity: sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==} + engines: {node: '>=18'} cpu: [arm] os: [android] - requiresBuild: true - optional: true - /@esbuild/android-x64@0.17.19: - resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} - engines: {node: '>=12'} + '@esbuild/android-x64@0.25.4': + resolution: {integrity: sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==} + engines: {node: '>=18'} cpu: [x64] os: [android] - requiresBuild: true - optional: true - /@esbuild/darwin-arm64@0.17.19: - resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} - engines: {node: '>=12'} + '@esbuild/darwin-arm64@0.25.4': + resolution: {integrity: sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==} + engines: {node: '>=18'} cpu: [arm64] os: [darwin] - requiresBuild: true - optional: true - /@esbuild/darwin-x64@0.17.19: - resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} - engines: {node: '>=12'} + '@esbuild/darwin-x64@0.25.4': + resolution: {integrity: sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==} + engines: {node: '>=18'} cpu: [x64] os: [darwin] - requiresBuild: true - optional: true - /@esbuild/freebsd-arm64@0.17.19: - resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} - engines: {node: '>=12'} + '@esbuild/freebsd-arm64@0.25.4': + resolution: {integrity: sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==} + engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - requiresBuild: true - optional: true - /@esbuild/freebsd-x64@0.17.19: - resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} - engines: {node: '>=12'} + '@esbuild/freebsd-x64@0.25.4': + resolution: {integrity: sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==} + engines: {node: '>=18'} cpu: [x64] os: [freebsd] - requiresBuild: true - optional: true - /@esbuild/linux-arm64@0.17.19: - resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} - engines: {node: '>=12'} + '@esbuild/linux-arm64@0.25.4': + resolution: {integrity: sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==} + engines: {node: '>=18'} cpu: [arm64] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-arm@0.17.19: - resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} - engines: {node: '>=12'} + '@esbuild/linux-arm@0.25.4': + resolution: {integrity: sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==} + engines: {node: '>=18'} cpu: [arm] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-ia32@0.17.19: - resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} - engines: {node: '>=12'} + '@esbuild/linux-ia32@0.25.4': + resolution: {integrity: sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==} + engines: {node: '>=18'} cpu: [ia32] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-loong64@0.17.19: - resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} - engines: {node: '>=12'} + '@esbuild/linux-loong64@0.25.4': + resolution: {integrity: sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==} + engines: {node: '>=18'} cpu: [loong64] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-mips64el@0.17.19: - resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} - engines: {node: '>=12'} + '@esbuild/linux-mips64el@0.25.4': + resolution: {integrity: sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==} + engines: {node: '>=18'} cpu: [mips64el] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-ppc64@0.17.19: - resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} - engines: {node: '>=12'} + '@esbuild/linux-ppc64@0.25.4': + resolution: {integrity: sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==} + engines: {node: '>=18'} cpu: [ppc64] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-riscv64@0.17.19: - resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} - engines: {node: '>=12'} + '@esbuild/linux-riscv64@0.25.4': + resolution: {integrity: sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==} + engines: {node: '>=18'} cpu: [riscv64] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-s390x@0.17.19: - resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} - engines: {node: '>=12'} + '@esbuild/linux-s390x@0.25.4': + resolution: {integrity: sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==} + engines: {node: '>=18'} cpu: [s390x] os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-x64@0.17.19: - resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} - engines: {node: '>=12'} + '@esbuild/linux-x64@0.25.4': + resolution: {integrity: sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==} + engines: {node: '>=18'} cpu: [x64] os: [linux] - requiresBuild: true - optional: true - /@esbuild/netbsd-x64@0.17.19: - resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} - engines: {node: '>=12'} + '@esbuild/netbsd-arm64@0.25.4': + resolution: {integrity: sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.4': + resolution: {integrity: sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==} + engines: {node: '>=18'} cpu: [x64] os: [netbsd] - requiresBuild: true - optional: true - /@esbuild/openbsd-x64@0.17.19: - resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} - engines: {node: '>=12'} + '@esbuild/openbsd-arm64@0.25.4': + resolution: {integrity: sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.4': + resolution: {integrity: sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==} + engines: {node: '>=18'} cpu: [x64] os: [openbsd] - requiresBuild: true - optional: true - /@esbuild/sunos-x64@0.17.19: - resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} - engines: {node: '>=12'} + '@esbuild/sunos-x64@0.25.4': + resolution: {integrity: sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==} + engines: {node: '>=18'} cpu: [x64] os: [sunos] - requiresBuild: true - optional: true - /@esbuild/win32-arm64@0.17.19: - resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} - engines: {node: '>=12'} + '@esbuild/win32-arm64@0.25.4': + resolution: {integrity: sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==} + engines: {node: '>=18'} cpu: [arm64] os: [win32] - requiresBuild: true - optional: true - /@esbuild/win32-ia32@0.17.19: - resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} - engines: {node: '>=12'} + '@esbuild/win32-ia32@0.25.4': + resolution: {integrity: sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==} + engines: {node: '>=18'} cpu: [ia32] os: [win32] - requiresBuild: true - optional: true - /@esbuild/win32-x64@0.17.19: - resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} - engines: {node: '>=12'} + '@esbuild/win32-x64@0.25.4': + resolution: {integrity: sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==} + engines: {node: '>=18'} cpu: [x64] os: [win32] - requiresBuild: true - optional: true - /@hapi/hoek@9.3.0: + '@hapi/hoek@9.3.0': resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} - dev: true - /@hapi/topo@5.1.0: + '@hapi/topo@5.1.0': resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} - dependencies: - '@hapi/hoek': 9.3.0 - dev: true - /@hutson/parse-repository-url@3.0.2: - resolution: {integrity: sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==} - engines: {node: '>=6.9.0'} - dev: true + '@hutson/parse-repository-url@5.0.0': + resolution: {integrity: sha512-e5+YUKENATs1JgYHMzTr2MW/NDcXGfYFAuOQU8gJgF/kEh4EqKgfGrfLI67bMD4tbhZVlkigz/9YYwWcbOFthg==} + engines: {node: '>=10.13.0'} + + '@iconify-json/logos@1.2.4': + resolution: {integrity: sha512-XC4If5D/hbaZvUkTV8iaZuGlQCyG6CNOlaAaJaGa13V5QMYwYjgtKk3vPP8wz3wtTVNVEVk3LRx1fOJz+YnSMw==} + + '@iconify-json/simple-icons@1.2.33': + resolution: {integrity: sha512-nL5/UmI9x5PQ/AHv6bOaL2pH6twEdEz4pI89efB/K7HFn5etQnxMtGx9DFlOg/sRA2/yFpX8KXvc95CSDv5bJA==} + + '@iconify-json/vscode-icons@1.2.20': + resolution: {integrity: sha512-xuWqr/SrckUoFi6kpSH/NrNGK+CuZ8LNnBY8qkRdkQvHmhirXvwsLfTKHoFndTsOlxfsHahlOLVCCb523kdqMA==} + + '@iconify/types@2.0.0': + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} + + '@iconify/utils@2.3.0': + resolution: {integrity: sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==} - /@isaacs/cliui@8.0.2: + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} - dependencies: - string-width: 5.1.2 - string-width-cjs: /string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: /strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: /wrap-ansi@7.0.0 - dev: true - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - /@mdit-vue/plugin-component@0.12.0: - resolution: {integrity: sha512-LrwV3f0Y6H7b7m/w1Y3bkGuR3HOiBK4QiHHW3HuRMza6MZodDQbj8Baik5/V5GiSg1/ltijS1CymVcycd1EfTw==} - dependencies: - '@types/markdown-it': 12.2.3 - markdown-it: 13.0.1 - dev: true + '@kwsites/file-exists@1.1.1': + resolution: {integrity: sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==} - /@mdit-vue/plugin-frontmatter@0.12.0: - resolution: {integrity: sha512-26Y3JktjGgNoCVH7NLqi5RcdAauAqxepTt2qXueRcRHtGpiRQV2/M1FveIhCOTCtHSuG5bBOHUxGaV6vRK3Vbw==} - dependencies: - '@mdit-vue/types': 0.12.0 - '@types/markdown-it': 12.2.3 - gray-matter: 4.0.3 - markdown-it: 13.0.1 - dev: true + '@kwsites/promise-deferred@1.1.1': + resolution: {integrity: sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==} - /@mdit-vue/plugin-headers@0.12.0: - resolution: {integrity: sha512-7qR63J2uc/rXbjHT77WoYBm9imwzx1tVESmRK+Uth6kqFvSWAXAFPcm4PBatGEE8TgzhklPs5BTcQtQhmmsyaw==} - dependencies: - '@mdit-vue/shared': 0.12.0 - '@mdit-vue/types': 0.12.0 - '@types/markdown-it': 12.2.3 - markdown-it: 13.0.1 - dev: true + '@lunariajs/core@0.1.1': + resolution: {integrity: sha512-sAqM9+DVsLe3xHM9wu2pEnKGYMs/bWS9qpR+CGHol3RihOELnOQTzHddXbdB1MtgesbI8dnQuG64Ocd8KkWsng==} + engines: {node: '>=18.17.0'} + hasBin: true - /@mdit-vue/plugin-sfc@0.12.0: - resolution: {integrity: sha512-mH+rHsERzDxGucAQJILspRiD723AIWMmtMhp7lDKdkCIbIhYfupFv/CkSeX+LAx5UY5greWvUTPGYVKn4gw/5Q==} - dependencies: - '@mdit-vue/types': 0.12.0 - '@types/markdown-it': 12.2.3 - markdown-it: 13.0.1 - dev: true + '@mdit-vue/plugin-component@2.1.4': + resolution: {integrity: sha512-fiLbwcaE6gZE4c8Mkdkc4X38ltXh/EdnuPE1hepFT2dLiW6I4X8ho2Wq7nhYuT8RmV4OKlCFENwCuXlKcpV/sw==} - /@mdit-vue/plugin-title@0.12.0: - resolution: {integrity: sha512-XrQcior1EmPgsDG88KsoF4LUSQw/RS1Nyfn5xNWGiurO70a2hml4kCe0XzT4sLKUAPG0HNbIY6b92ezNezqWTg==} - dependencies: - '@mdit-vue/shared': 0.12.0 - '@mdit-vue/types': 0.12.0 - '@types/markdown-it': 12.2.3 - markdown-it: 13.0.1 - dev: true + '@mdit-vue/plugin-frontmatter@2.1.4': + resolution: {integrity: sha512-mOlavV176njnozIf0UZGFYymmQ2LK5S1rjrbJ1uGz4Df59tu0DQntdE7YZXqmJJA9MiSx7ViCTUQCNPKg7R8Ow==} - /@mdit-vue/plugin-toc@0.12.0: - resolution: {integrity: sha512-tT985CqvLp17DFWHrSvmmJbh7qcy0Rl0dBbYN//Fn952a04dbr1mb2LqW0B1oStSAQj2q24HpK4ZPgYOt7Z1Jg==} - dependencies: - '@mdit-vue/shared': 0.12.0 - '@mdit-vue/types': 0.12.0 - '@types/markdown-it': 12.2.3 - markdown-it: 13.0.1 - dev: true + '@mdit-vue/plugin-headers@2.1.4': + resolution: {integrity: sha512-tyZwGZu2mYkNSqigFP1CK3aZYxuYwrqcrIh8ljd8tfD1UDPJkAbQeayq62U572po2IuWVB1BqIG8JIXp5POOTA==} - /@mdit-vue/shared@0.12.0: - resolution: {integrity: sha512-E+sGSubhvnp+Gmb2hJXFDxdLwwQD1H52EVbA4yrxxI5q/cwtnPIN2eJU3zlZB9KcvzXYDFFwt/x2mfhK8RZKBg==} - dependencies: - '@mdit-vue/types': 0.12.0 - '@types/markdown-it': 12.2.3 - markdown-it: 13.0.1 - dev: true + '@mdit-vue/plugin-sfc@2.1.4': + resolution: {integrity: sha512-oqAlMulkz280xUJIkormzp6Ps0x5WULZrwRivylWJWDEyVAFCj5VgR3Dx6CP2jdgyuPXwW3+gh2Kzw+Xe+kEIQ==} + + '@mdit-vue/plugin-title@2.1.4': + resolution: {integrity: sha512-uuF24gJvvLVIWG/VBtCDRqMndfd5JzOXoBoHPdKKLk3PA4P84dsB0u0NnnBUEl/YBOumdCotasn7OfFMmco9uQ==} + + '@mdit-vue/plugin-toc@2.1.4': + resolution: {integrity: sha512-vvOU7u6aNmvPwKXzmoHion1sv4zChBp20LDpSHlRlXc3btLwdYIA0DR+UiO5YeyLUAO0XSHQKBpsIWi57K9/3w==} + + '@mdit-vue/shared@2.1.4': + resolution: {integrity: sha512-Axd8g2iKQTMuHcPXZH5JY3hbSMeLyoeu0ftdgMrjuPzHpJnWiPSAnA0dAx5NQFQqZkXHhyIrAssLSrOWjFmPKg==} - /@mdit-vue/types@0.12.0: - resolution: {integrity: sha512-mrC4y8n88BYvgcgzq9bvTlDgFyi2zuvzmPilRvRc3Uz1iIvq8mDhxJ0rHKFUNzPEScpDvJdIujqiDrulMqiudA==} - dev: true + '@mdit-vue/types@2.1.4': + resolution: {integrity: sha512-QiGNZslz+zXUs2X8D11UQhB4KAMZ0DZghvYxa7+1B+VMLcDtz//XHpWbcuexjzE3kBXSxIUTPH3eSQCa0puZHA==} - /@nodelib/fs.scandir@2.1.5: + '@napi-rs/wasm-runtime@0.2.9': + resolution: {integrity: sha512-OKRBiajrrxB9ATokgEQoG87Z25c67pCpYcCwmXYX8PBftC9pBfN18gnm/fh1wurSLEKIAt+QRFLFCQISrb66Jg==} + + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - dev: true - /@nodelib/fs.stat@2.0.5: + '@nodelib/fs.stat@2.0.5': resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} engines: {node: '>= 8'} - dev: true - /@nodelib/fs.walk@1.2.8: + '@nodelib/fs.walk@1.2.8': resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.15.0 - dev: true - - /@pkgjs/parseargs@0.11.0: - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - requiresBuild: true - dev: true - optional: true - /@polka/url@1.0.0-next.21: - resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} - dev: true + '@oxc-minify/binding-darwin-arm64@0.69.0': + resolution: {integrity: sha512-GkA53C8uPPR9S080ZxFs72f8fegVlb7IcFJiYd9qWB4sjkut2LtjlQPlMmefK3RolGjpwKgHCDhENwb6Nj+BHA==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [darwin] - /@rollup/plugin-alias@5.0.0(rollup@3.24.0): - resolution: {integrity: sha512-l9hY5chSCjuFRPsnRm16twWBiSApl2uYFLsepQYwtBuAxNMQ/1dJqADld40P0Jkqm65GRTLy/AC6hnpVebtLsA==} + '@oxc-minify/binding-darwin-x64@0.69.0': + resolution: {integrity: sha512-vlbu/tfqg1kEIGtEITxzScOYNXLojroeg2XCG5S6GOZKM7dkerDU/Freds5QEFyW4Eykc3NXMlor4aQCq0L1uA==} engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - rollup: 3.24.0 - slash: 4.0.0 - dev: true + cpu: [x64] + os: [darwin] - /@rollup/plugin-commonjs@25.0.0(rollup@3.24.0): - resolution: {integrity: sha512-hoho2Kay9TZrLu0bnDsTTCaj4Npa+THk9snajP/XDNb9a9mmjTjh52EQM9sKl3HD1LsnihX7js+eA2sd2uKAhw==} + '@oxc-minify/binding-freebsd-x64@0.69.0': + resolution: {integrity: sha512-t5Ae+3hrfAxcl0Xmkxc3hjWRVBaX04pBLa1xgBAJuKP8KkCmzlRgmxe9YX6rQE8EOALyUDePv0NnhaAVuJfVRA==} engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.68.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.0.2(rollup@3.24.0) - commondir: 1.0.1 - estree-walker: 2.0.2 - glob: 8.1.0 - is-reference: 1.2.1 - magic-string: 0.27.0 - rollup: 3.24.0 - dev: true + cpu: [x64] + os: [freebsd] - /@rollup/plugin-json@6.0.0(rollup@3.24.0): - resolution: {integrity: sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==} + '@oxc-minify/binding-linux-arm-gnueabihf@0.69.0': + resolution: {integrity: sha512-w1BR/Xk5qUzrFofwTfi+dclUBTfTaHm+O7uHraX981DH3+qbOYWKhPR1RamS52AlQgJqzmckV2w6OitSOsRW9Q==} engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.0.2(rollup@3.24.0) - rollup: 3.24.0 - dev: true + cpu: [arm] + os: [linux] - /@rollup/plugin-node-resolve@15.1.0(rollup@3.24.0): - resolution: {integrity: sha512-xeZHCgsiZ9pzYVgAo9580eCGqwh/XCEUM9q6iQfGNocjgkufHAqC3exA+45URvhiYV8sBF9RlBai650eNs7AsA==} + '@oxc-minify/binding-linux-arm64-gnu@0.69.0': + resolution: {integrity: sha512-OdJo1Uhfdr5u1ZbNfupE0rYffVumvP27UxEGtptOeAbAYVIaLhwuLIo7y/7xBMFBEDyulPMbMWE7HGObA/aATg==} engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.78.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.0.2(rollup@3.24.0) - '@types/resolve': 1.20.2 - deepmerge: 4.3.1 - is-builtin-module: 3.2.1 - is-module: 1.0.0 - resolve: 1.22.2 - rollup: 3.24.0 - dev: true + cpu: [arm64] + os: [linux] - /@rollup/plugin-replace@5.0.2(rollup@3.24.0): - resolution: {integrity: sha512-M9YXNekv/C/iHHK+cvORzfRYfPbq0RDD8r0G+bMiTXjNGKulPnCT9O3Ss46WfhI6ZOCgApOP7xAdmCQJ+U2LAA==} + '@oxc-minify/binding-linux-arm64-musl@0.69.0': + resolution: {integrity: sha512-JNl65iqV+ca4Yq5R6zW7XE3cKFhyXvMtfPCKbMIoRM3XjYaxynQc7djm9w8mwbVA/jrPN8MEh2dFuR8H5DNqyA==} engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.0.2(rollup@3.24.0) - magic-string: 0.27.0 - rollup: 3.24.0 - dev: true + cpu: [arm64] + os: [linux] - /@rollup/pluginutils@5.0.2(rollup@3.24.0): - resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} + '@oxc-minify/binding-linux-riscv64-gnu@0.69.0': + resolution: {integrity: sha512-emOPhLyt5BXb0twWt2+zqSYbE8mPHExmazszCmC7o+MEbxBOoPRw12o2ucua8u3mMsXSWkToxgVBI9FKIMp1Dw==} engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@types/estree': 1.0.1 - estree-walker: 2.0.2 - picomatch: 2.3.1 - rollup: 3.24.0 - dev: true + cpu: [riscv64] + os: [linux] - /@sideway/address@4.1.4: - resolution: {integrity: sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==} - dependencies: - '@hapi/hoek': 9.3.0 - dev: true + '@oxc-minify/binding-linux-s390x-gnu@0.69.0': + resolution: {integrity: sha512-YDFZQkQvbqJdAomA8Z9Hf26Gg55ieBzPCdzHRpNLUxcih/eRiBxCNm19dfExMz49MK1cTAJaqt7SGvvyHtNFJQ==} + engines: {node: '>=14.0.0'} + cpu: [s390x] + os: [linux] - /@sideway/formula@3.0.1: - resolution: {integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==} - dev: true + '@oxc-minify/binding-linux-x64-gnu@0.69.0': + resolution: {integrity: sha512-uD+2JCWHAq20C5d45C9aaxM/70RHwLU9PW/4altiklM98nFFTftcYi7UbJy4tNGTf5/5STsmBB/KeKAlWB+jAw==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [linux] - /@sideway/pinpoint@2.0.0: - resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==} - dev: true + '@oxc-minify/binding-linux-x64-musl@0.69.0': + resolution: {integrity: sha512-SAQdffOinw2yMGygSipkvEHd5/fBCC5ZuNdO9Ag7ZR39PS+2dKbKfQXQ6qL2kUvwOAglHDg49qDdRSUkanRMrg==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [linux] - /@types/body-parser@1.19.2: - resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==} - dependencies: - '@types/connect': 3.4.35 - '@types/node': 20.2.5 - dev: true + '@oxc-minify/binding-wasm32-wasi@0.69.0': + resolution: {integrity: sha512-s+SDrjW6IUB5oLqIKeUprTtWCJ3NuucaBZPdTTO+tzgUEKx+FNr1fw3Y5f7ALoqIV2UiQmOtV3AGP/hAvnYcHg==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] - /@types/body-scroll-lock@3.1.0: - resolution: {integrity: sha512-3owAC4iJub5WPqRhxd8INarF2bWeQq1yQHBgYhN0XLBJMpd5ED10RrJ3aKiAwlTyL5wK7RkBD4SZUQz2AAAMdA==} - dev: true + '@oxc-minify/binding-win32-arm64-msvc@0.69.0': + resolution: {integrity: sha512-gA8HSO97hi2T6M344gmxIkwwG82TIB6EjHvVO/7KBDmzwQH5ZTzaIEzS7SVk5yeDOo39dkY19YDK+HJ66+knjw==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [win32] - /@types/braces@3.0.1: - resolution: {integrity: sha512-+euflG6ygo4bn0JHtn4pYqcXwRtLvElQ7/nnjDu7iYG56H0+OhCd7d6Ug0IE3WcFpZozBKW2+80FUbv5QGk5AQ==} - dev: true + '@oxc-minify/binding-win32-x64-msvc@0.69.0': + resolution: {integrity: sha512-UleNZqdw72QxvgrqdAkorWzQABg1Gx286R8QE2WLdOx1YnlQsbKLzSeP4ItPqAeVIl116hw/ScUXpCgUDUgTiA==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [win32] - /@types/chai-subset@1.3.3: - resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==} - dependencies: - '@types/chai': 4.3.5 - dev: true + '@oxc-project/runtime@0.69.0': + resolution: {integrity: sha512-v4WCEJEktTuWY+DEaR1XNITKZD9S0BCyoBeCTyHUH3ppgrb4IlMeDTkwNyfvaIXBFfhlCX4DI445TJ4cqiK0FA==} + engines: {node: '>=6.9.0'} - /@types/chai@4.3.5: - resolution: {integrity: sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==} - dev: true + '@oxc-project/types@0.69.0': + resolution: {integrity: sha512-bu3gzdAlLgncoaqyqWVpMAKx4axo+j3ewvvdAt5iCLtvHB/n3Qeif67NU+2TM/ami1nV5/KVO9lxCH8paPATBA==} - /@types/compression@1.7.2: - resolution: {integrity: sha512-lwEL4M/uAGWngWFLSG87ZDr2kLrbuR8p7X+QZB1OQlT+qkHsCPDVFnHPyXf4Vyl4yDDorNY+mAhosxkCvppatg==} - dependencies: - '@types/express': 4.17.17 - dev: true + '@polka/compression@1.0.0-next.28': + resolution: {integrity: sha512-aDmrBhgHJtxE+jy145WfhW9WmTAFmES/dNnn1LAs8UnnkFgBUj4T8I4ScQ9+rOkpDZStvnVP5iqhN3tvt7O1NA==} + engines: {node: '>=6'} - /@types/connect@3.4.35: - resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==} - dependencies: - '@types/node': 20.2.5 - dev: true + '@polka/url@1.0.0-next.29': + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} - /@types/cross-spawn@6.0.2: - resolution: {integrity: sha512-KuwNhp3eza+Rhu8IFI5HUXRP0LIhqH5cAjubUvGXXthh4YYBuP2ntwEX+Cz8GJoZUHlKo247wPWOfA9LYEq4cw==} + '@rolldown/binding-darwin-arm64@1.0.0-beta.8-commit.8951737': + resolution: {integrity: sha512-ccQdWbP9dUv5XfvY+jKQPJL1bTT3vg4XI2gO60sL8iG5A77Kn5l8NQDlgqezL+tX9ayfgHZn83l/xLfg/w+MMg==} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.0-beta.8-commit.8951737': + resolution: {integrity: sha512-PLbKS1relWlkK4HBfr2OMUg7zUSyA/8bJfc2t5quQNHTuDCrZf9vHLIvuYWwzLmasgJBpMCipKFJ0quxz8SOCg==} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.0-beta.8-commit.8951737': + resolution: {integrity: sha512-AltIXTVrSl7Axp0YFV2O3vBzwdK4vfkwfiHM42YzEkbOmHiL+9su+QkzNzlJoOxmM5/W9JhxQcj6VmtHsNvx+w==} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.8-commit.8951737': + resolution: {integrity: sha512-7Qn3XE+8r03yeO+eWVw1xtMkjLsFx0TOAE9+INABF3qABvKpAJgX8edhZpR9jPPkQ8iN0d4UNF/2pMeOuOGMmw==} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.8-commit.8951737': + resolution: {integrity: sha512-Y35shEzqlvso2JZNCn969U5mftD+hY5Xpp3mkV8mVILFYmupZCAjzrzATh+SUHbjUBAdk0YyPzVF42TNSqaZbA==} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.8-commit.8951737': + resolution: {integrity: sha512-DUiIyXJUvVmy1s5EFNAOC4qADOTxfME5y1Z9JoFYCPvTiazeMqEfYQUUF0n46CpR2LBrMYSe64PYUFAkLt/AcA==} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.8-commit.8951737': + resolution: {integrity: sha512-lVhPuDuPhXfvFkNK8A6DHsZmd15WTmFQGSo36LuELbdN+Cc2ETouiY/UF92ALw0O9suP0T0rbqQnce3y6SSPuw==} + cpu: [x64] + os: [linux] + + '@rolldown/binding-linux-x64-musl@1.0.0-beta.8-commit.8951737': + resolution: {integrity: sha512-PbyEo7AElXiwbSsp4hEwzIK/mjNEg+pc4TKXTmxA1N/ZHZY4xtZFXQ+Fk2aWxkGKZI0PFT1lywC4yJ68pKczcg==} + cpu: [x64] + os: [linux] + + '@rolldown/binding-wasm32-wasi@1.0.0-beta.8-commit.8951737': + resolution: {integrity: sha512-iAhw6VWj973h2DOVJowvstA4otMfjk7xkQACk6eQR80TQ7CDbEi3NNhE/q1XNNv3U+sbzNfHvpAbMWCphTKkAg==} + engines: {node: '>=14.21.3'} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.8-commit.8951737': + resolution: {integrity: sha512-jp5guKSx6296lDCFwyYCFHkS0uReqXeLrHyqD5MaqBThgGhTizp1jdKYqkvoEhtcN0VigKAVrlDfil5+TyaOsQ==} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.8-commit.8951737': + resolution: {integrity: sha512-9yPFf9kXFCVR+bvzU883X9RTkWM5sEGyxelW736jbGymyW8trXVm4wCoG+N5c+Jq/+mRTkGnxwd6llCkWzr1hg==} + cpu: [ia32] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.8-commit.8951737': + resolution: {integrity: sha512-zGvEYtt6xose5gMWQvW/4TU6l+bbRTu4gy+rqdS6BEjP60v84wo+pteVCuuCWqXbJiex/+L2WEPgN69QJFOnUQ==} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.0-beta.8-commit.8951737': + resolution: {integrity: sha512-dx9SoAb0lLSZp3Jhy5jRCdJg5OJXv7S7bdF+qpLjPMoRPfvFcwIRi9QPdtprqjdkOR72+peteBYTdlx1LWmQSA==} + + '@rollup/plugin-alias@5.1.1': + resolution: {integrity: sha512-PR9zDb+rOzkRb2VD+EuKB7UC41vU5DIwZ5qqCpk0KJudcWAyi8rvYOhS7+L5aZCspw1stTViLgN5v6FF1p5cgQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-commonjs@28.0.3': + resolution: {integrity: sha512-pyltgilam1QPdn+Zd9gaCfOLcnjMEJ9gV+bTw6/r73INdvzf1ah9zLIJBm+kW7R6IUFIQ1YO+VqZtYxZNWFPEQ==} + engines: {node: '>=16.0.0 || 14 >= 14.17'} + peerDependencies: + rollup: ^2.68.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-json@6.1.0': + resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-node-resolve@16.0.1': + resolution: {integrity: sha512-tk5YCxJWIG81umIvNkSod2qK5KyQW19qcBF/B78n1bjtOON6gzKoVeSzAE8yHCZEDmqkHKkxplExA8KzdJLJpA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-replace@6.0.2': + resolution: {integrity: sha512-7QaYCf8bqF04dOy7w/eHmJeNExxTYwvKAmlSAH/EaWWUzbT0h5sbF6bktFoX/0F/0qwng5/dWFMyf3gzaM8DsQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/pluginutils@5.1.4': + resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.40.2': + resolution: {integrity: sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.40.2': + resolution: {integrity: sha512-13unNoZ8NzUmnndhPTkWPWbX3vtHodYmy+I9kuLxN+F+l+x3LdVF7UCu8TWVMt1POHLh6oDHhnOA04n8oJZhBw==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.40.2': + resolution: {integrity: sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.40.2': + resolution: {integrity: sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.40.2': + resolution: {integrity: sha512-8t6aL4MD+rXSHHZUR1z19+9OFJ2rl1wGKvckN47XFRVO+QL/dUSpKA2SLRo4vMg7ELA8pzGpC+W9OEd1Z/ZqoQ==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.40.2': + resolution: {integrity: sha512-C+AyHBzfpsOEYRFjztcYUFsH4S7UsE9cDtHCtma5BK8+ydOZYgMmWg1d/4KBytQspJCld8ZIujFMAdKG1xyr4Q==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.40.2': + resolution: {integrity: sha512-de6TFZYIvJwRNjmW3+gaXiZ2DaWL5D5yGmSYzkdzjBDS3W+B9JQ48oZEsmMvemqjtAFzE16DIBLqd6IQQRuG9Q==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.40.2': + resolution: {integrity: sha512-urjaEZubdIkacKc930hUDOfQPysezKla/O9qV+O89enqsqUmQm8Xj8O/vh0gHg4LYfv7Y7UsE3QjzLQzDYN1qg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.40.2': + resolution: {integrity: sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.40.2': + resolution: {integrity: sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loongarch64-gnu@4.40.2': + resolution: {integrity: sha512-Ybc/1qUampKuRF4tQXc7G7QY9YRyeVSykfK36Y5Qc5dmrIxwFhrOzqaVTNoZygqZ1ZieSWTibfFhQ5qK8jpWxw==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.40.2': + resolution: {integrity: sha512-3FCIrnrt03CCsZqSYAOW/k9n625pjpuMzVfeI+ZBUSDT3MVIFDSPfSUgIl9FqUftxcUXInvFah79hE1c9abD+Q==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.40.2': + resolution: {integrity: sha512-QNU7BFHEvHMp2ESSY3SozIkBPaPBDTsfVNGx3Xhv+TdvWXFGOSH2NJvhD1zKAT6AyuuErJgbdvaJhYVhVqrWTg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.40.2': + resolution: {integrity: sha512-5W6vNYkhgfh7URiXTO1E9a0cy4fSgfE4+Hl5agb/U1sa0kjOLMLC1wObxwKxecE17j0URxuTrYZZME4/VH57Hg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.40.2': + resolution: {integrity: sha512-B7LKIz+0+p348JoAL4X/YxGx9zOx3sR+o6Hj15Y3aaApNfAshK8+mWZEf759DXfRLeL2vg5LYJBB7DdcleYCoQ==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.40.2': + resolution: {integrity: sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.40.2': + resolution: {integrity: sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.40.2': + resolution: {integrity: sha512-Bjv/HG8RRWLNkXwQQemdsWw4Mg+IJ29LK+bJPW2SCzPKOUaMmPEppQlu/Fqk1d7+DX3V7JbFdbkh/NMmurT6Pg==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.40.2': + resolution: {integrity: sha512-dt1llVSGEsGKvzeIO76HToiYPNPYPkmjhMHhP00T9S4rDern8P2ZWvWAQUEJ+R1UdMWJ/42i/QqJ2WV765GZcA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.40.2': + resolution: {integrity: sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA==} + cpu: [x64] + os: [win32] + + '@sec-ant/readable-stream@0.4.1': + resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} + + '@shikijs/core@3.4.0': + resolution: {integrity: sha512-0YOzTSRDn/IAfQWtK791gs1u8v87HNGToU6IwcA3K7nPoVOrS2Dh6X6A6YfXgPTSkTwR5y6myk0MnI0htjnwrA==} + + '@shikijs/engine-javascript@3.4.0': + resolution: {integrity: sha512-1ywDoe+z/TPQKj9Jw0eU61B003J9DqUFRfH+DVSzdwPUFhR7yOmfyLzUrFz0yw8JxFg/NgzXoQyyykXgO21n5Q==} + + '@shikijs/engine-oniguruma@3.4.0': + resolution: {integrity: sha512-zwcWlZ4OQuJ/+1t32ClTtyTU1AiDkK1lhtviRWoq/hFqPjCNyLj22bIg9rB7BfoZKOEOfrsGz7No33BPCf+WlQ==} + + '@shikijs/langs@3.4.0': + resolution: {integrity: sha512-bQkR+8LllaM2duU9BBRQU0GqFTx7TuF5kKlw/7uiGKoK140n1xlLAwCgXwSxAjJ7Htk9tXTFwnnsJTCU5nDPXQ==} + + '@shikijs/themes@3.4.0': + resolution: {integrity: sha512-YPP4PKNFcFGLxItpbU0ZW1Osyuk8AyZ24YEFaq04CFsuCbcqydMvMUTi40V2dkc0qs1U2uZFrnU6s5zI6IH+uA==} + + '@shikijs/transformers@3.4.0': + resolution: {integrity: sha512-GrGaOj1/I6h75IU0VvjdWDpqGCynx0bqHzd1rErBTGxrcmusYIBhrV7aEySWyJ6HHb9figeXfcNxUFS1HKUfBw==} + + '@shikijs/types@3.4.0': + resolution: {integrity: sha512-EUT/0lGiE//7j5N/yTMNMT3eCWNcHJLrRKxT0NDXWIfdfSmFJKfPX7nMmRBrQnWboAzIsUziCThrYMMhjbMS1A==} + + '@shikijs/vscode-textmate@10.0.2': + resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + + '@sideway/address@4.1.5': + resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} + + '@sideway/formula@3.0.1': + resolution: {integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==} + + '@sideway/pinpoint@2.0.0': + resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==} + + '@sindresorhus/merge-streams@4.0.0': + resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} + engines: {node: '>=18'} + + '@tokenizer/token@0.3.0': + resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + + '@tybys/wasm-util@0.9.0': + resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} + + '@types/cross-spawn@6.0.6': + resolution: {integrity: sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==} + + '@types/debug@4.1.12': + resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + + '@types/estree@1.0.7': + resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} + + '@types/fs-extra@11.0.4': + resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} + + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + + '@types/jquery@3.5.32': + resolution: {integrity: sha512-b9Xbf4CkMqS02YH8zACqN1xzdxc3cO735Qe5AbSUFmyOiaWAbcpqh9Wna+Uk0vgACvoQHpWDg2rGdHkYPLmCiQ==} + + '@types/jsonfile@6.1.4': + resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} + + '@types/linkify-it@5.0.0': + resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} + + '@types/lodash.template@4.5.3': + resolution: {integrity: sha512-Mo0UYKLu1oXgkV9TVoXZLlXXjyIXlW7ZQRxi/4gQJmzJr63dmicE8gG0OkPjYTKBrBic852q0JzqrtNUWLBIyA==} + + '@types/lodash@4.17.16': + resolution: {integrity: sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==} + + '@types/mark.js@8.11.12': + resolution: {integrity: sha512-244ZnaIBpz4c6xutliAnYVZp6xJlmC569jZqnR3ElO1Y01ooYASSVQEqpd2x0A2UfrgVMs5V9/9tUAdZaDMytQ==} + + '@types/markdown-it-attrs@4.1.3': + resolution: {integrity: sha512-1JsseFdHD6rQHsPcy4W3xx/whxvZ09Z+CqPpnOtrGtpmkFW07N11q7oM383//LtoKv54yn+HGnk6r4ZHUTHJVg==} + + '@types/markdown-it-container@2.0.10': + resolution: {integrity: sha512-zv+YxrlSYRq51e9kzm3orv4OvF4U79Ll1OyplNXr00o4ZC/8PukJk/jEWH7CnsMtrSWZlyv0czhz42jm9J4uLw==} + + '@types/markdown-it-emoji@3.0.1': + resolution: {integrity: sha512-cz1j8R35XivBqq9mwnsrP2fsz2yicLhB8+PDtuVkKOExwEdsVBNI+ROL3sbhtR5occRZ66vT0QnwFZCqdjf3pA==} + + '@types/markdown-it@14.1.2': + resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} + + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + + '@types/mdurl@2.0.0': + resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} + + '@types/minimist@1.2.5': + resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} + + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + + '@types/node@17.0.45': + resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} + + '@types/node@22.15.17': + resolution: {integrity: sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==} + + '@types/normalize-package-data@2.4.4': + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + + '@types/picomatch@4.0.0': + resolution: {integrity: sha512-J1Bng+wlyEERWSgJQU1Pi0HObCLVcr994xT/M+1wcl/yNRTGBupsCxthgkdYG+GCOMaQH7iSVUY3LJVBBqG7MQ==} + + '@types/postcss-prefix-selector@1.16.3': + resolution: {integrity: sha512-YZLPWRkJIrYjwaqojVDXzaRCAEYslRAm8Shznwwn+ZFA4iKQR4LZlS3d+ZMVteFz4iyQnngZZG7k/GIzV1f3mQ==} + + '@types/prompts@2.4.9': + resolution: {integrity: sha512-qTxFi6Buiu8+50/+3DGIWLHM6QuWsEKugJnnP6iv2Mc4ncxE4A/OJkjuVOA+5X0X1S/nq5VJRa8Lu+nwcvbrKA==} + + '@types/resolve@1.20.2': + resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + + '@types/sax@1.2.7': + resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==} + + '@types/semver@7.7.0': + resolution: {integrity: sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==} + + '@types/sizzle@2.3.9': + resolution: {integrity: sha512-xzLEyKB50yqCUPUJkIsrVvoWNfFUbIZI+RspLWt8u+tIW/BetMBZtgV2LY/2o+tYH8dRvQ+eoPf3NdhQCcLE2w==} + + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + + '@types/web-bluetooth@0.0.21': + resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==} + + '@ungap/structured-clone@1.3.0': + resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + + '@vitejs/plugin-vue@5.2.4': + resolution: {integrity: sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 + vue: ^3.2.25 + + '@vitest/expect@3.1.3': + resolution: {integrity: sha512-7FTQQuuLKmN1Ig/h+h/GO+44Q1IlglPlR2es4ab7Yvfx+Uk5xsv+Ykk+MEt/M2Yn/xGmzaLKxGw2lgy2bwuYqg==} + + '@vitest/mocker@3.1.3': + resolution: {integrity: sha512-PJbLjonJK82uCWHjzgBJZuR7zmAOrSvKk1QBxrennDIgtH4uK0TB1PvYmc0XBCigxxtiAVPfWtAdy4lpz8SQGQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@3.1.3': + resolution: {integrity: sha512-i6FDiBeJUGLDKADw2Gb01UtUNb12yyXAqC/mmRWuYl+m/U9GS7s8us5ONmGkGpUUo7/iAYzI2ePVfOZTYvUifA==} + + '@vitest/runner@3.1.3': + resolution: {integrity: sha512-Tae+ogtlNfFei5DggOsSUvkIaSuVywujMj6HzR97AHK6XK8i3BuVyIifWAm/sE3a15lF5RH9yQIrbXYuo0IFyA==} + + '@vitest/snapshot@3.1.3': + resolution: {integrity: sha512-XVa5OPNTYUsyqG9skuUkFzAeFnEzDp8hQu7kZ0N25B1+6KjGm4hWLtURyBbsIAOekfWQ7Wuz/N/XXzgYO3deWQ==} + + '@vitest/spy@3.1.3': + resolution: {integrity: sha512-x6w+ctOEmEXdWaa6TO4ilb7l9DxPR5bwEb6hILKuxfU1NqWT2mpJD9NJN7t3OTfxmVlOMrvtoFJGdgyzZ605lQ==} + + '@vitest/utils@3.1.3': + resolution: {integrity: sha512-2Ltrpht4OmHO9+c/nmHtF09HWiyWdworqnHIwjfvDyWjuwKbdkcS9AnhsDn+8E2RM4x++foD1/tNuLPVvWG1Rg==} + + '@volar/language-core@2.4.13': + resolution: {integrity: sha512-MnQJ7eKchJx5Oz+YdbqyFUk8BN6jasdJv31n/7r6/WwlOOv7qzvot6B66887l2ST3bUW4Mewml54euzpJWA6bg==} + + '@volar/source-map@2.4.13': + resolution: {integrity: sha512-l/EBcc2FkvHgz2ZxV+OZK3kMSroMr7nN3sZLF2/f6kWW66q8+tEL4giiYyFjt0BcubqJhBt6soYIrAPhg/Yr+Q==} + + '@volar/typescript@2.4.13': + resolution: {integrity: sha512-Ukz4xv84swJPupZeoFsQoeJEOm7U9pqsEnaGGgt5ni3SCTa22m8oJP5Nng3Wed7Uw5RBELdLxxORX8YhJPyOgQ==} + + '@vue/compiler-core@3.5.13': + resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==} + + '@vue/compiler-dom@3.5.13': + resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==} + + '@vue/compiler-sfc@3.5.13': + resolution: {integrity: sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==} + + '@vue/compiler-ssr@3.5.13': + resolution: {integrity: sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==} + + '@vue/compiler-vue2@2.7.16': + resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==} + + '@vue/devtools-api@7.7.6': + resolution: {integrity: sha512-b2Xx0KvXZObePpXPYHvBRRJLDQn5nhKjXh7vUhMEtWxz1AYNFOVIsh5+HLP8xDGL7sy+Q7hXeUxPHB/KgbtsPw==} + + '@vue/devtools-kit@7.7.6': + resolution: {integrity: sha512-geu7ds7tem2Y7Wz+WgbnbZ6T5eadOvozHZ23Atk/8tksHMFOFylKi1xgGlQlVn0wlkEf4hu+vd5ctj1G4kFtwA==} + + '@vue/devtools-shared@7.7.6': + resolution: {integrity: sha512-yFEgJZ/WblEsojQQceuyK6FzpFDx4kqrz2ohInxNj5/DnhoX023upTv4OD6lNPLAA5LLkbwPVb10o/7b+Y4FVA==} + + '@vue/language-core@3.0.0-alpha.6': + resolution: {integrity: sha512-aZoL7H7+5SGkx4uqp5tC1/50tROsFgVyk5XbfM+HGfTZMwvvoHMq4uTzRyyH5sH8eXs/zmjlZCg2Vs8khxUqjQ==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@vue/reactivity@3.5.13': + resolution: {integrity: sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==} + + '@vue/runtime-core@3.5.13': + resolution: {integrity: sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==} + + '@vue/runtime-dom@3.5.13': + resolution: {integrity: sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==} + + '@vue/server-renderer@3.5.13': + resolution: {integrity: sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==} + peerDependencies: + vue: 3.5.13 + + '@vue/shared@3.5.13': + resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==} + + '@vueuse/core@13.1.0': + resolution: {integrity: sha512-PAauvdRXZvTWXtGLg8cPUFjiZEddTqmogdwYpnn60t08AA5a8Q4hZokBnpTOnVNqySlFlTcRYIC8OqreV4hv3Q==} + peerDependencies: + vue: ^3.5.0 + + '@vueuse/integrations@13.1.0': + resolution: {integrity: sha512-wJ6aANdUs4SOpVabChQK+uLIwxRTUAEmn1DJnflGG7Wq6yaipiRmp6as/Md201FjJnquQt8MecIPbFv8HSBeDA==} + peerDependencies: + async-validator: ^4 + axios: ^1 + change-case: ^5 + drauu: ^0.4 + focus-trap: ^7 + fuse.js: ^7 + idb-keyval: ^6 + jwt-decode: ^4 + nprogress: ^0.2 + qrcode: ^1.5 + sortablejs: ^1 + universal-cookie: ^7 + vue: ^3.5.0 + peerDependenciesMeta: + async-validator: + optional: true + axios: + optional: true + change-case: + optional: true + drauu: + optional: true + focus-trap: + optional: true + fuse.js: + optional: true + idb-keyval: + optional: true + jwt-decode: + optional: true + nprogress: + optional: true + qrcode: + optional: true + sortablejs: + optional: true + universal-cookie: + optional: true + + '@vueuse/metadata@13.1.0': + resolution: {integrity: sha512-+TDd7/a78jale5YbHX9KHW3cEDav1lz1JptwDvep2zSG8XjCsVE+9mHIzjTOaPbHUAk5XiE4jXLz51/tS+aKQw==} + + '@vueuse/shared@13.1.0': + resolution: {integrity: sha512-IVS/qRRjhPTZ6C2/AM3jieqXACGwFZwWTdw5sNTSKk2m/ZpkuuN+ri+WCVUP8TqaKwJYt/KuMwmXspMAw8E6ew==} + peerDependencies: + vue: ^3.5.0 + + '@xmldom/xmldom@0.9.8': + resolution: {integrity: sha512-p96FSY54r+WJ50FIOsCOjyj/wavs8921hG5+kVMmZgKcvIKxMXHTrjNJvRgWa/zuX3B6t2lijLNFaOyuxUH+2A==} + engines: {node: '>=14.6'} + + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + + acorn@8.14.1: + resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} + engines: {node: '>=0.4.0'} + hasBin: true + + add-stream@1.0.0: + resolution: {integrity: sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==} + + algoliasearch@5.24.0: + resolution: {integrity: sha512-CkaUygzZ91Xbw11s0CsHMawrK3tl+Ue57725HGRgRzKgt2Z4wvXVXRCtQfvzh8K7Tp4Zp7f1pyHAtMROtTJHxg==} + engines: {node: '>= 14.0.0'} + + alien-signals@1.0.13: + resolution: {integrity: sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==} + + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + + ansi-escapes@7.0.0: + resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} + engines: {node: '>=18'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + ansis@4.0.0: + resolution: {integrity: sha512-P8nrHI1EyW9OfBt1X7hMSwGN2vwRuqHSKJAT1gbLWZRzDa24oHjYwGHvEgHeBepupzk878yS/HBZ0NMPYtbolw==} + engines: {node: '>=14'} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-ify@1.0.0: + resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + axios@1.9.0: + resolution: {integrity: sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==} + + bail@2.0.2: + resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + birpc@2.3.0: + resolution: {integrity: sha512-ijbtkn/F3Pvzb6jHypHRyve2QApOCZDR25D/VnkY2G/lBNcXCTsnsCxgY4k4PkVB7zfwzYbY3O9Lcqe3xufS5g==} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + + bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + + byte-size@9.0.1: + resolution: {integrity: sha512-YLe9x3rabBrcI0cueCdLS2l5ONUKywcRpTs02B8KP9/Cimhj7o3ZccGrPnRvcbyHMbb7W79/3MUJl7iGgTXKEw==} + engines: {node: '>=12.17'} + peerDependencies: + '@75lb/nature': latest + peerDependenciesMeta: + '@75lb/nature': + optional: true + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + + chai@5.2.0: + resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} + engines: {node: '>=12'} + + chalk@5.4.1: + resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + + character-entities@2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} + + cheerio-select@1.6.0: + resolution: {integrity: sha512-eq0GdBvxVFbqWgmCm7M3XGs1I8oLy/nExUnh6oLqmBditPO9AqQJrkslDpMun/hZ0yyTs8L0m85OHp4ho6Qm9g==} + + cheerio@1.0.0-rc.10: + resolution: {integrity: sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==} + engines: {node: '>= 6'} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + + commander@13.1.0: + resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} + engines: {node: '>=18'} + + commander@6.2.1: + resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} + engines: {node: '>= 6'} + + commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + + compare-func@2.0.0: + resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} + + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + confbox@0.2.2: + resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==} + + conventional-changelog-angular@8.0.0: + resolution: {integrity: sha512-CLf+zr6St0wIxos4bmaKHRXWAcsCXrJU6F4VdNDrGRK3B8LDLKoX3zuMV5GhtbGkVR/LohZ6MT6im43vZLSjmA==} + engines: {node: '>=18'} + + conventional-changelog-atom@5.0.0: + resolution: {integrity: sha512-WfzCaAvSCFPkznnLgLnfacRAzjgqjLUjvf3MftfsJzQdDICqkOOpcMtdJF3wTerxSpv2IAAjX8doM3Vozqle3g==} + engines: {node: '>=18'} + + conventional-changelog-cli@5.0.0: + resolution: {integrity: sha512-9Y8fucJe18/6ef6ZlyIlT2YQUbczvoQZZuYmDLaGvcSBP+M6h+LAvf7ON7waRxKJemcCII8Yqu5/8HEfskTxJQ==} + engines: {node: '>=18'} + hasBin: true + + conventional-changelog-codemirror@5.0.0: + resolution: {integrity: sha512-8gsBDI5Y3vrKUCxN6Ue8xr6occZ5nsDEc4C7jO/EovFGozx8uttCAyfhRrvoUAWi2WMm3OmYs+0mPJU7kQdYWQ==} + engines: {node: '>=18'} + + conventional-changelog-conventionalcommits@8.0.0: + resolution: {integrity: sha512-eOvlTO6OcySPyyyk8pKz2dP4jjElYunj9hn9/s0OB+gapTO8zwS9UQWrZ1pmF2hFs3vw1xhonOLGcGjy/zgsuA==} + engines: {node: '>=18'} + + conventional-changelog-core@8.0.0: + resolution: {integrity: sha512-EATUx5y9xewpEe10UEGNpbSHRC6cVZgO+hXQjofMqpy+gFIrcGvH3Fl6yk2VFKh7m+ffenup2N7SZJYpyD9evw==} + engines: {node: '>=18'} + + conventional-changelog-ember@5.0.0: + resolution: {integrity: sha512-RPflVfm5s4cSO33GH/Ey26oxhiC67akcxSKL8CLRT3kQX2W3dbE19sSOM56iFqUJYEwv9mD9r6k79weWe1urfg==} + engines: {node: '>=18'} + + conventional-changelog-eslint@6.0.0: + resolution: {integrity: sha512-eiUyULWjzq+ybPjXwU6NNRflApDWlPEQEHvI8UAItYW/h22RKkMnOAtfCZxMmrcMO1OKUWtcf2MxKYMWe9zJuw==} + engines: {node: '>=18'} + + conventional-changelog-express@5.0.0: + resolution: {integrity: sha512-D8Q6WctPkQpvr2HNCCmwU5GkX22BVHM0r4EW8vN0230TSyS/d6VQJDAxGb84lbg0dFjpO22MwmsikKL++Oo/oQ==} + engines: {node: '>=18'} + + conventional-changelog-jquery@6.0.0: + resolution: {integrity: sha512-2kxmVakyehgyrho2ZHBi90v4AHswkGzHuTaoH40bmeNqUt20yEkDOSpw8HlPBfvEQBwGtbE+5HpRwzj6ac2UfA==} + engines: {node: '>=18'} + + conventional-changelog-jshint@5.0.0: + resolution: {integrity: sha512-gGNphSb/opc76n2eWaO6ma4/Wqu3tpa2w7i9WYqI6Cs2fncDSI2/ihOfMvXveeTTeld0oFvwMVNV+IYQIk3F3g==} + engines: {node: '>=18'} + + conventional-changelog-preset-loader@5.0.0: + resolution: {integrity: sha512-SetDSntXLk8Jh1NOAl1Gu5uLiCNSYenB5tm0YVeZKePRIgDW9lQImromTwLa3c/Gae298tsgOM+/CYT9XAl0NA==} + engines: {node: '>=18'} + + conventional-changelog-writer@8.0.1: + resolution: {integrity: sha512-hlqcy3xHred2gyYg/zXSMXraY2mjAYYo0msUCpK+BGyaVJMFCKWVXPIHiaacGO2GGp13kvHWXFhYmxT4QQqW3Q==} + engines: {node: '>=18'} + hasBin: true + + conventional-changelog@6.0.0: + resolution: {integrity: sha512-tuUH8H/19VjtD9Ig7l6TQRh+Z0Yt0NZ6w/cCkkyzUbGQTnUEmKfGtkC9gGfVgCfOL1Rzno5NgNF4KY8vR+Jo3w==} + engines: {node: '>=18'} + + conventional-commits-filter@5.0.0: + resolution: {integrity: sha512-tQMagCOC59EVgNZcC5zl7XqO30Wki9i9J3acbUvkaosCT6JX3EeFwJD7Qqp4MCikRnzS18WXV3BLIQ66ytu6+Q==} + engines: {node: '>=18'} + + conventional-commits-parser@6.1.0: + resolution: {integrity: sha512-5nxDo7TwKB5InYBl4ZC//1g9GRwB/F3TXOGR9hgUjMGfvSP4Vu5NkpNro2+1+TIEy1vwxApl5ircECr2ri5JIw==} + engines: {node: '>=18'} + hasBin: true + + copy-anything@3.0.5: + resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} + engines: {node: '>=12.13'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + crypto-random-string@4.0.0: + resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} + engines: {node: '>=12'} + + css-select@4.3.0: + resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} + + css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + de-indent@1.0.2: + resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decode-named-character-reference@1.1.0: + resolution: {integrity: sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==} + + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + default-browser-id@5.0.0: + resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} + engines: {node: '>=18'} + + default-browser@5.2.1: + resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} + engines: {node: '>=18'} + + define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + detect-libc@2.0.4: + resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} + engines: {node: '>=8'} + + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + + dom-serializer@1.4.1: + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@3.3.0: + resolution: {integrity: sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==} + engines: {node: '>= 4'} + + domhandler@4.3.1: + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} + engines: {node: '>= 4'} + + domutils@2.8.0: + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + + dot-prop@5.3.0: + resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} + engines: {node: '>=8'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + emoji-regex@10.4.0: + resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + entities@2.2.0: + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + esbuild@0.25.4: + resolution: {integrity: sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-goat@3.0.0: + resolution: {integrity: sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==} + engines: {node: '>=10'} + + escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + + esm@3.2.25: + resolution: {integrity: sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==} + engines: {node: '>=6'} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + + execa@9.5.3: + resolution: {integrity: sha512-QFNnTvU3UjgWFy8Ef9iDHvIdcgZ344ebkwYx4/KLbR+CKQA4xBaHzv+iRpp86QfMHP8faFQLh8iOc57215y4Rg==} + engines: {node: ^18.19.0 || >=20.5.0} + + expect-type@1.2.1: + resolution: {integrity: sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==} + engines: {node: '>=12.0.0'} + + exsolve@1.0.5: + resolution: {integrity: sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==} + + extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + + fault@2.0.1: + resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==} + + fdir@6.4.4: + resolution: {integrity: sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + figures@6.1.0: + resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} + engines: {node: '>=18'} + + file-type@18.7.0: + resolution: {integrity: sha512-ihHtXRzXEziMrQ56VSgU7wkxh55iNchFkosu7Y9/S+tXHdKyrGjVK0ujbqNnsxzea+78MaLhN6PGmfYSAv1ACw==} + engines: {node: '>=14.16'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up-simple@1.0.1: + resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==} + engines: {node: '>=18'} + + focus-trap@7.6.4: + resolution: {integrity: sha512-xx560wGBk7seZ6y933idtjJQc1l+ck+pI3sKvhKozdBV1dRZoKhkW5xoCaFv9tQiX5RH1xfSxjuNu6g+lmN/gw==} + + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + form-data@4.0.2: + resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} + engines: {node: '>= 6'} + + format@0.2.2: + resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} + engines: {node: '>=0.4.x'} + + fs-extra@11.3.0: + resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==} + engines: {node: '>=14.14'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.3.0: + resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} + engines: {node: '>=18'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-port@7.1.0: + resolution: {integrity: sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==} + engines: {node: '>=16'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-stdin@9.0.0: + resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==} + engines: {node: '>=12'} + + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + + get-stream@9.0.1: + resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} + engines: {node: '>=18'} + + get-tsconfig@4.10.0: + resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==} + + git-raw-commits@5.0.0: + resolution: {integrity: sha512-I2ZXrXeOc0KrCvC7swqtIFXFN+rbjnC7b2T943tvemIOVNl+XP8YnA9UVwqFhzzLClnSA60KR/qEjLpXzs73Qg==} + engines: {node: '>=18'} + hasBin: true + + git-semver-tags@8.0.0: + resolution: {integrity: sha512-N7YRIklvPH3wYWAR2vysaqGLPRcpwQ0GKdlqTiVN5w1UmCdaeY3K8s6DMKRCh54DDdzyt/OAB6C8jgVtb7Y2Fg==} + engines: {node: '>=18'} + hasBin: true + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob@11.0.2: + resolution: {integrity: sha512-YT7U7Vye+t5fZ/QMkBFrTJ7ZQxInIUjwyAjVj84CYXqgBdv30MFUPGnBR6sQaVq6Is15wYJUsnzTuWaGRBhBAQ==} + engines: {node: 20 || >=22} + hasBin: true + + globals@15.15.0: + resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} + engines: {node: '>=18'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + gray-matter@4.0.3: + resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} + engines: {node: '>=6.0'} + + handlebars@4.7.8: + resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} + engines: {node: '>=0.4.7'} + hasBin: true + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hast-util-to-html@9.0.5: + resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} + + hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + hookable@5.5.3: + resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + + hosted-git-info@7.0.2: + resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} + engines: {node: ^16.14.0 || >=18.0.0} + + html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + + htmlparser2@5.0.1: + resolution: {integrity: sha512-vKZZra6CSe9qsJzh0BjBGXo8dvzNsq/oGvsjfRdOrrryfeD9UOBEEQdeoqCRmKZchF5h2zOBMQ6YuQ0uRUmdbQ==} + + htmlparser2@6.1.0: + resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==} + + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + + human-signals@8.0.1: + resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==} + engines: {node: '>=18.18.0'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + index-to-position@1.1.0: + resolution: {integrity: sha512-XPdx9Dq4t9Qk1mTMbWONJqU7boCoumEH7fRET37HX5+khDUl3J2W6PdALxhILYlIYx2amlwYcRPp28p0tSiojg==} + engines: {node: '>=18'} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + + is-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + + is-fullwidth-code-point@5.0.0: + resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + engines: {node: '>=18'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + + is-interactive@2.0.0: + resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} + engines: {node: '>=12'} + + is-module@1.0.0: + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-obj@2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + is-reference@1.2.1: + resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} + + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-stream@4.0.1: + resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} + engines: {node: '>=18'} + + is-unicode-supported@1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} + + is-what@4.1.16: + resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} + engines: {node: '>=12.13'} + + is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@4.1.0: + resolution: {integrity: sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==} + engines: {node: 20 || >=22} + + jiti@1.21.7: + resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} + hasBin: true + + joi@17.13.3: + resolution: {integrity: sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + + juice@8.1.0: + resolution: {integrity: sha512-FLzurJrx5Iv1e7CfBSZH68dC04EEvXvvVvPYB7Vx1WAuhCp1ZPIMtqxc+WTWxVkpTIC2Ach/GAv0rQbtGf6YMA==} + engines: {node: '>=10.0.0'} + hasBin: true + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + + lightningcss-darwin-arm64@1.30.0: + resolution: {integrity: sha512-L9lhvW4rTHL6vaG1WU3Itj0ivtdBuwu7ufrKEbijRCPhS1pt1haXEXI8h9g73qCQsOaYs1GCc9chvSgxPmhpRA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.30.0: + resolution: {integrity: sha512-+qNst+L3GGwG5LypEFTmDUOtNarQVh717Enk4AfmKfwlTrKCSe9kAiPyK7ces269a+f0jNSa8Uww8WwGFXzt8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.30.0: + resolution: {integrity: sha512-/sfAWALScgggjjk5ZlmGdpFELwGPIwzAdfcBJcT6UTgQoDHzQ4aP41XTq3N4LL01U9dsJp6uAvCvmHX7snqTdg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.30.0: + resolution: {integrity: sha512-3B5val/f61unLgfZHEfkZGzunlyyL76l8xRoxFx+G0uwxK7rvaFcnkyf6k4Zto2STVj05FsLs+aTZoTqslPaug==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.30.0: + resolution: {integrity: sha512-Q45+fvm7eAAmorsEzc1ZBwajGnXDocB/nRaSldpHQa36QbP93GrzmBqfSdi2pEks2yXMxST4yznio24Q6en7Sg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.30.0: + resolution: {integrity: sha512-RNZNW/AyKax8wWR4xMKoyAb40dqhzOtnAw4knjbyxJUUEL0wzBEXO3k44AS3UFRjxTyd/s46adVQXxE/vOaSgg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.30.0: + resolution: {integrity: sha512-ExVnSepsAyQb547i7SvPhS0SrgIDUjA1dYTT0DNFt/YsqfKhkxg405VDtMoV2MQGAyoEQIub+YK5NQo9Lw7IzQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.30.0: + resolution: {integrity: sha512-e/nHeX5SAEcfAzyLob5H1Jhm8uHLKwpOIHzcURKnXTMFdBqIDOsETMhmcB5AGDqsr6Q5D9u0QVswDdRo+btSgg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.30.0: + resolution: {integrity: sha512-Fd9XejM6GPHx5rv7I8aqsc8mBHs+TpHEVDalP5PVP986tF6rmiVfwQzM2Ic4Cn0rXbS3z95Ru8x50hnzfR2GDA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.30.0: + resolution: {integrity: sha512-2BhpVDbNa+HpXPu63EYfcsL2TCBKLeuMckx4d6UZCzaj1KVuSRXi6r7H3rUeaADuX5NB/BT2smP4HI3s6I1/Ag==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.30.0: + resolution: {integrity: sha512-uuurN2onfoNwQtaWnX9UYLz6DlZHnUd88SceOXDAQzQ5+FJ+ELPgcC/EVtRJoFOveXe44zRE+foh2KMD/vQxqQ==} + engines: {node: '>= 12.0.0'} + + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} + + linkify-it@5.0.0: + resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} + + lint-staged@15.5.2: + resolution: {integrity: sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==} + engines: {node: '>=18.12.0'} + hasBin: true + + listr2@8.3.3: + resolution: {integrity: sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==} + engines: {node: '>=18.0.0'} + + local-pkg@1.1.1: + resolution: {integrity: sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==} + engines: {node: '>=14'} + + lodash._reinterpolate@3.0.0: + resolution: {integrity: sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==} + + lodash.template@4.5.0: + resolution: {integrity: sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==} + deprecated: This package is deprecated. Use https://socket.dev/npm/package/eta instead. + + lodash.templatesettings@4.2.0: + resolution: {integrity: sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + log-symbols@6.0.0: + resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} + engines: {node: '>=18'} + + log-update@6.1.0: + resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} + engines: {node: '>=18'} + + longest-streak@3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + + loupe@3.1.3: + resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@11.1.0: + resolution: {integrity: sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==} + engines: {node: 20 || >=22} + + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + + mark.js@8.11.1: + resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==} + + markdown-it-anchor@9.2.0: + resolution: {integrity: sha512-sa2ErMQ6kKOA4l31gLGYliFQrMKkqSO0ZJgGhDHKijPf0pNFM9vghjAh3gn26pS4JDRs7Iwa9S36gxm3vgZTzg==} + peerDependencies: + '@types/markdown-it': '*' + markdown-it: '*' + + markdown-it-async@2.2.0: + resolution: {integrity: sha512-sITME+kf799vMeO/ww/CjH6q+c05f6TLpn6VOmmWCGNqPJzSh+uFgZoMB9s0plNtW6afy63qglNAC3MhrhP/gg==} + + markdown-it-attrs@4.3.1: + resolution: {integrity: sha512-/ko6cba+H6gdZ0DOw7BbNMZtfuJTRp9g/IrGIuz8lYc/EfnmWRpaR3CFPnNbVz0LDvF8Gf1hFGPqrQqq7De0rg==} + engines: {node: '>=6'} + peerDependencies: + markdown-it: '>= 9.0.0' + + markdown-it-container@4.0.0: + resolution: {integrity: sha512-HaNccxUH0l7BNGYbFbjmGpf5aLHAMTinqRZQAEQbMr2cdD3z91Q6kIo1oUn1CQndkT03jat6ckrdRYuwwqLlQw==} + + markdown-it-emoji@3.0.0: + resolution: {integrity: sha512-+rUD93bXHubA4arpEZO3q80so0qgoFJEKRkRbjKX8RTdca89v2kfyF+xR3i2sQTwql9tpPZPOQN5B+PunspXRg==} + + markdown-it-mathjax3@4.3.2: + resolution: {integrity: sha512-TX3GW5NjmupgFtMJGRauioMbbkGsOXAAt1DZ/rzzYmTHqzkO1rNAdiMD4NiruurToPApn2kYy76x02QN26qr2w==} + + markdown-it@14.1.0: + resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} + hasBin: true + + markdown-title@1.0.2: + resolution: {integrity: sha512-MqIQVVkz+uGEHi3TsHx/czcxxCbRIL7sv5K5DnYw/tI+apY54IbPefV/cmgxp6LoJSEx/TqcHdLs/298afG5QQ==} + engines: {node: '>=6'} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mathjax-full@3.2.2: + resolution: {integrity: sha512-+LfG9Fik+OuI8SLwsiR02IVdjcnRCy5MufYLi0C3TdMT56L/pjB0alMVGgoWJF8pN9Rc7FESycZB9BMNWIid5w==} + + mdast-util-from-markdown@2.0.2: + resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==} + + mdast-util-frontmatter@2.0.1: + resolution: {integrity: sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==} + + mdast-util-phrasing@4.1.0: + resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} + + mdast-util-to-hast@13.2.0: + resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==} + + mdast-util-to-markdown@2.1.2: + resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==} + + mdast-util-to-string@4.0.0: + resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + + mdurl@2.0.0: + resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + + mensch@0.3.4: + resolution: {integrity: sha512-IAeFvcOnV9V0Yk+bFhYR07O3yNina9ANIN5MoXBKYJ/RLYPurd2d0yw14MDhpr9/momp0WofT1bPUh3hkzdi/g==} + + meow@12.1.1: + resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} + engines: {node: '>=16.10'} + + meow@13.2.0: + resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} + engines: {node: '>=18'} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + mhchemparser@4.2.1: + resolution: {integrity: sha512-kYmyrCirqJf3zZ9t/0wGgRZ4/ZJw//VwaRVGA75C4nhE60vtnIzhl9J9ndkX/h6hxSN7pjg/cE0VxbnNM+bnDQ==} + + micromark-core-commonmark@2.0.3: + resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} + + micromark-extension-frontmatter@2.0.0: + resolution: {integrity: sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==} + + micromark-factory-destination@2.0.1: + resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==} + + micromark-factory-label@2.0.1: + resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==} + + micromark-factory-space@2.0.1: + resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==} + + micromark-factory-title@2.0.1: + resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==} + + micromark-factory-whitespace@2.0.1: + resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==} + + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} + + micromark-util-chunked@2.0.1: + resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==} + + micromark-util-classify-character@2.0.1: + resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==} + + micromark-util-combine-extensions@2.0.1: + resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==} + + micromark-util-decode-numeric-character-reference@2.0.2: + resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==} + + micromark-util-decode-string@2.0.1: + resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==} + + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} + + micromark-util-html-tag-name@2.0.1: + resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==} + + micromark-util-normalize-identifier@2.0.1: + resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==} + + micromark-util-resolve-all@2.0.1: + resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==} + + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} + + micromark-util-subtokenize@2.1.0: + resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==} + + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} + + micromark-util-types@2.0.2: + resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} + + micromark@4.0.2: + resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + millify@6.1.0: + resolution: {integrity: sha512-H/E3J6t+DQs/F2YgfDhxUVZz/dF8JXPPKTLHL/yHCcLZLtCXJDUaqvhJXQwqOVBvbyNn4T0WjLpIHd7PAw7fBA==} + hasBin: true + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@2.6.0: + resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} + engines: {node: '>=4.0.0'} + hasBin: true + + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + + minimatch@10.0.1: + resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} + engines: {node: 20 || >=22} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + minisearch@7.1.2: + resolution: {integrity: sha512-R1Pd9eF+MD5JYDDSPAp/q1ougKglm14uEkPMvQ/05RGmx6G9wvmLTrTI/Q5iPNJLYqNdsDQ7qTGIcNWR+FrHmA==} + + mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + + mj-context-menu@0.6.1: + resolution: {integrity: sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA==} + + mlly@1.7.4: + resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} + + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + muggle-string@0.4.1: + resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nanoid@5.1.5: + resolution: {integrity: sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==} + engines: {node: ^18 || >=20} + hasBin: true + + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + normalize-package-data@6.0.2: + resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==} + engines: {node: ^16.14.0 || >=18.0.0} + + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + npm-run-path@6.0.0: + resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==} + engines: {node: '>=18'} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + + oniguruma-parser@0.12.1: + resolution: {integrity: sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==} + + oniguruma-to-es@4.3.3: + resolution: {integrity: sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg==} + + open-cli@8.0.0: + resolution: {integrity: sha512-3muD3BbfLyzl+aMVSEfn2FfOqGdPYR0O4KNnxXsLEPE2q9OSjBfJAaB6XKbrUzLgymoSMejvb5jpXJfru/Ko2A==} + engines: {node: '>=18'} + hasBin: true + + open@10.1.2: + resolution: {integrity: sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==} + engines: {node: '>=18'} + + ora@8.2.0: + resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==} + engines: {node: '>=18'} + + oxc-minify@0.69.0: + resolution: {integrity: sha512-QaPB3syyTEE7PSgSIL+CrFr5MfL43tEJi5KjpD4Ko29I6ZBbevQKMZ0wnBXz82bkzzyru08g0dMTaLbjPmOsXw==} + engines: {node: '>=14.0.0'} + + p-map@7.0.3: + resolution: {integrity: sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==} + engines: {node: '>=18'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + package-manager-detector@1.3.0: + resolution: {integrity: sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==} + + parse-json@8.3.0: + resolution: {integrity: sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==} + engines: {node: '>=18'} + + parse-ms@4.0.0: + resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} + engines: {node: '>=18'} + + parse5-htmlparser2-tree-adapter@6.0.1: + resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} + + parse5@6.0.1: + resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@2.0.0: + resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} + engines: {node: 20 || >=22} + + path-to-regexp@6.3.0: + resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + pathval@2.0.0: + resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + engines: {node: '>= 14.16'} + + peek-readable@5.4.2: + resolution: {integrity: sha512-peBp3qZyuS6cNIJ2akRNG1uo1WJ1d0wTxg/fxMdZ0BqCVhx242bSFHM9eNqflfJVS9SsgkzgT/1UgnsurBOTMg==} + engines: {node: '>=14.16'} + + perfect-debounce@1.0.0: + resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + + pidtree@0.6.0: + resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} + engines: {node: '>=0.10'} + hasBin: true + + pkg-dir@8.0.0: + resolution: {integrity: sha512-4peoBq4Wks0riS0z8741NVv+/8IiTvqnZAr8QGgtdifrtpdXbNw/FxRS1l6NFqm4EMzuS0EDqNNx4XGaz8cuyQ==} + engines: {node: '>=18'} + + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + + pkg-types@2.1.0: + resolution: {integrity: sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==} + + playwright-chromium@1.52.0: + resolution: {integrity: sha512-ZTpzBzRFFRglyqRnAqdK5mFaw1P41qe8V2zSR+fA0eKPgGEEaH7r91ejXKijs3WhReatRcatHQe3ndMBMN1PLA==} + engines: {node: '>=18'} + hasBin: true + + playwright-core@1.52.0: + resolution: {integrity: sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==} + engines: {node: '>=18'} + hasBin: true + + polka@1.0.0-next.28: + resolution: {integrity: sha512-ryc8D/B5E/YnlWHkNMnRvNntPc4GwU1/+iDBjiXVz1SUjDRqlxYX5Ic0IaDLA/cQ+g7/x+jUzEjv2K16u1J+wA==} + engines: {node: '>=8'} + + postcss-prefix-selector@2.1.1: + resolution: {integrity: sha512-ZBgf427Et6+XnrnJ9VXtJEKCjJwTvn2wn/qMg+wvvlRhIeFIAxdbrlZZ0CSsWYMJfcyPLBh8ogj5O1kb/Mcx3g==} + peerDependencies: + postcss: ^8.0.0 + + postcss-rtlcss@5.7.0: + resolution: {integrity: sha512-qx0KQ9iX17Qsi6AGZL3D6Ty7UjDebApE92FLP1Z8tQg4cGck/V/w0UrIo1rFQSh3rYsxDnSf1r30X8GNyxy6VQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + postcss: ^8.4.21 + + postcss@8.5.3: + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + engines: {node: ^10 || ^12 || >=14} + + preact@10.26.6: + resolution: {integrity: sha512-5SRRBinwpwkaD+OqlBDeITlRgvd8I8QlxHJw9AxSdMNV6O+LodN9nUyYGpSF7sadHjs6RzeFShMexC6DbtWr9g==} + + prettier@3.5.3: + resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} + engines: {node: '>=14'} + hasBin: true + + pretty-ms@9.2.0: + resolution: {integrity: sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==} + engines: {node: '>=18'} + + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + + property-information@7.1.0: + resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + punycode.js@2.3.1: + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} + engines: {node: '>=6'} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + quansync@0.2.10: + resolution: {integrity: sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + read-package-up@11.0.0: + resolution: {integrity: sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==} + engines: {node: '>=18'} + + read-pkg@9.0.1: + resolution: {integrity: sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==} + engines: {node: '>=18'} + + readable-stream@4.7.0: + resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + readable-web-to-node-stream@3.0.4: + resolution: {integrity: sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==} + engines: {node: '>=8'} + + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + + regex-recursion@6.0.2: + resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==} + + regex-utilities@2.3.0: + resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} + + regex@6.0.1: + resolution: {integrity: sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==} + + regexparam@3.0.0: + resolution: {integrity: sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q==} + engines: {node: '>=8'} + + remark-frontmatter@5.0.0: + resolution: {integrity: sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ==} + + remark-parse@11.0.0: + resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} + + remark-stringify@11.0.0: + resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} + + remark@15.0.1: + resolution: {integrity: sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} + hasBin: true + + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + + rimraf@6.0.1: + resolution: {integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==} + engines: {node: 20 || >=22} + hasBin: true + + rolldown-vite@6.3.9: + resolution: {integrity: sha512-A4MasNEixPEcBOWrgO2pAsmLW9YbtaXpyRz6irfptllOcZu2yL4U+qKxxjmVs0v9Ch05yGqoQN26hI12kyviWA==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + esbuild: ^0.25.0 + jiti: '>=1.21.0' + less: '*' + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + rolldown@1.0.0-beta.8-commit.8951737: + resolution: {integrity: sha512-wivu32OtHnJ1C0L3hPhEx/zniMoaE1jn+pjB3T+UOy1NGm323unnLlcOv2A6xSrNMiM6cBp2JlRRInQ9i/zJHA==} + hasBin: true + peerDependencies: + '@oxc-project/runtime': 0.69.0 + peerDependenciesMeta: + '@oxc-project/runtime': + optional: true + + rollup-plugin-dts@6.1.1: + resolution: {integrity: sha512-aSHRcJ6KG2IHIioYlvAOcEq6U99sVtqDDKVhnwt70rW6tsz3tv5OSjEiWcgzfsHdLyGXZ/3b/7b/+Za3Y6r1XA==} + engines: {node: '>=16'} + peerDependencies: + rollup: ^3.29.4 || ^4 + typescript: ^4.5 || ^5.0 + + rollup-plugin-esbuild@6.2.1: + resolution: {integrity: sha512-jTNOMGoMRhs0JuueJrJqbW8tOwxumaWYq+V5i+PD+8ecSCVkuX27tGW7BXqDgoULQ55rO7IdNxPcnsWtshz3AA==} + engines: {node: '>=14.18.0'} + peerDependencies: + esbuild: '>=0.18.0' + rollup: ^1.20.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 + + rollup@4.40.2: + resolution: {integrity: sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + rtlcss@4.3.0: + resolution: {integrity: sha512-FI+pHEn7Wc4NqKXMXFM+VAYKEj/mRIcW4h24YVwVtyjI+EqGrLc2Hx/Ny0lrZ21cBWU2goLy36eqMcNj3AQJig==} + engines: {node: '>=12.0.0'} + hasBin: true + + run-applescript@7.0.0: + resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} + engines: {node: '>=18'} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + rxjs@7.8.2: + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + sax@1.4.1: + resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} + + section-matter@1.0.0: + resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} + engines: {node: '>=4'} + + semver@7.7.1: + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} + engines: {node: '>=10'} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shiki@3.4.0: + resolution: {integrity: sha512-Ni80XHcqhOEXv5mmDAvf5p6PAJqbUc/RzFeaOqk+zP5DLvTPS3j0ckvA+MI87qoxTQ5RGJDVTbdl/ENLSyyAnQ==} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + simple-git-hooks@2.13.0: + resolution: {integrity: sha512-N+goiLxlkHJlyaYEglFypzVNMaNplPAk5syu0+OPp/Bk6dwVoXF6FfOw2vO0Dp+JHsBaI+w6cm8TnFl2Hw6tDA==} + hasBin: true + + simple-git@3.27.0: + resolution: {integrity: sha512-ivHoFS9Yi9GY49ogc6/YAi3Fl9ROnF4VyubNylgCkA+RVqLaKWnDSzXOVzya8csELIaWaYNutsEuAhZrtOjozA==} + + sirv@3.0.1: + resolution: {integrity: sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==} + engines: {node: '>=18'} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + sitemap@8.0.0: + resolution: {integrity: sha512-+AbdxhM9kJsHtruUF39bwS/B0Fytw6Fr1o4ZAIAEqA6cke2xcoO2GleBw9Zw7nRzILVEgz7zBM5GiTJjie1G9A==} + engines: {node: '>=14.0.0', npm: '>=6.0.0'} + hasBin: true + + slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + + slice-ansi@7.1.0: + resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} + engines: {node: '>=18'} + + slick@1.12.2: + resolution: {integrity: sha512-4qdtOGcBjral6YIBCWJ0ljFSKNLz9KkhbWtuGvUyRowl1kxfuE1x/Z/aJcaiilpb3do9bl5K7/1h9XC5wWpY/A==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + + spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + + spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + + spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + + spdx-license-ids@3.0.21: + resolution: {integrity: sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==} + + speakingurl@14.0.1: + resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==} + engines: {node: '>=0.10.0'} + + speech-rule-engine@4.1.2: + resolution: {integrity: sha512-S6ji+flMEga+1QU79NDbwZ8Ivf0S/MpupQQiIC0rTpU/ZTKgcajijJJb1OcByBQDjrXCN1/DJtGz4ZJeBMPGJw==} + hasBin: true + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@3.9.0: + resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} + + stdin-discarder@0.2.2: + resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} + engines: {node: '>=18'} + + string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-bom-string@1.0.0: + resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} + engines: {node: '>=0.10.0'} + + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + + strip-final-newline@4.0.0: + resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==} + engines: {node: '>=18'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + strtok3@7.1.1: + resolution: {integrity: sha512-mKX8HA/cdBqMKUr0MMZAFssCkIGoZeSCMXgnt79yKxNFguMLVFgRe6wB+fsL0NmoHDbeyZXczy7vEPSoo3rkzg==} + engines: {node: '>=16'} + + superjson@2.2.2: + resolution: {integrity: sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==} + engines: {node: '>=16'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + tabbable@6.2.0: + resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + + temp-dir@3.0.0: + resolution: {integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==} + engines: {node: '>=14.16'} + + tempfile@5.0.0: + resolution: {integrity: sha512-bX655WZI/F7EoTDw9JvQURqAXiPHi8o8+yFxPF2lWYyz1aHnmMRuXWqL6YB6GmeO0o4DIYWHLgGNi/X64T+X4Q==} + engines: {node: '>=14.18'} + + tempy@3.1.0: + resolution: {integrity: sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==} + engines: {node: '>=14.16'} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinyexec@1.0.1: + resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==} + + tinyglobby@0.2.13: + resolution: {integrity: sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==} + engines: {node: '>=12.0.0'} + + tinypool@1.0.2: + resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} + + tinyspy@3.0.2: + resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + engines: {node: '>=14.0.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + token-types@5.0.1: + resolution: {integrity: sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==} + engines: {node: '>=14.16'} + + tokenx@0.4.1: + resolution: {integrity: sha512-LCMniis0WsHel07xh3K9OIt5c9Xla1awtOoWBmUHZBQR7pvTvgGFuYpLiCZWohXPC1YuZORnN0+fCVYI/ie8Jg==} + + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + + trough@2.2.0: + resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} + + trouter@4.0.0: + resolution: {integrity: sha512-bwwr76BThfiVwAFZqks5cJ+VoKNM3/2Yg1ZwJslkdmAUQ6S0UNoCoGYFDxdw+u1skfexggdmD2p35kW5Td4Cug==} + engines: {node: '>=6'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-fest@1.4.0: + resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} + engines: {node: '>=10'} + + type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} + + typescript@5.8.3: + resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} + engines: {node: '>=14.17'} + hasBin: true + + uc.micro@2.1.0: + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + + ufo@1.6.1: + resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} + + uglify-js@3.19.3: + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} + engines: {node: '>=0.8.0'} + hasBin: true + + ultramatter@0.0.4: + resolution: {integrity: sha512-1f/hO3mR+/Hgue4eInOF/Qm/wzDqwhYha4DxM0hre9YIUyso3fE2XtrAU6B4njLqTC8CM49EZaYgsVSa+dXHGw==} + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} + + unicorn-magic@0.3.0: + resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} + engines: {node: '>=18'} + + unified@11.0.5: + resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} + + unique-string@3.0.0: + resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==} + engines: {node: '>=12'} + + unist-util-is@6.0.0: + resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} + + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-remove@4.0.0: + resolution: {integrity: sha512-b4gokeGId57UVRX/eVKej5gXqGlc9+trkORhFJpu9raqZkZhU0zm8Doi05+HaiBsMEIJowL+2WtQ5ItjsngPXg==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-parents@6.0.1: + resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} + + unist-util-visit@5.0.0: + resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unplugin-utils@0.2.4: + resolution: {integrity: sha512-8U/MtpkPkkk3Atewj1+RcKIjb5WBimZ/WSLhhR3w6SsIj8XJuKTacSP8g+2JhfSGw0Cb125Y+2zA/IzJZDVbhA==} + engines: {node: '>=18.12.0'} + + valid-data-url@3.0.1: + resolution: {integrity: sha512-jOWVmzVceKlVVdwjNSenT4PbGghU0SBIizAev8ofZVgivk/TVHXSbNL8LP6M3spZvkR9/QolkyJavGSX5Cs0UA==} + engines: {node: '>=10'} + + validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + + vfile-message@4.0.2: + resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} + + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + + vite-node@3.1.3: + resolution: {integrity: sha512-uHV4plJ2IxCl4u1up1FQRrqclylKAogbtBfOTwcuJ28xFi+89PZ57BRh+naIRvH70HPwxy5QHYzg1OrEaC7AbA==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + + vite@6.3.5: + resolution: {integrity: sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitepress-plugin-group-icons@1.5.2: + resolution: {integrity: sha512-zen07KxZ83y3eecou4EraaEgwIriwHaB5Q0cHAmS4yO1UZEQvbljTylHPqiJ7LNkV39U8VehfcyquAJXg/26LA==} + + vitepress-plugin-llms@1.1.3: + resolution: {integrity: sha512-7pJbG92hI70KerMc0SViIsKzwQHNz6ftrwfmwaT/z1TyfIH3p0X2sZ+fHmSIYYtrYhGPEpqiUhGfAVLhLX54hQ==} + + vitest@3.1.3: + resolution: {integrity: sha512-188iM4hAHQ0km23TN/adso1q5hhwKqUpv+Sd6p5sOuh6FhQnRNW3IsiIpvxqahtBabsJ2SLZgmGSpcYK4wQYJw==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.1.3 + '@vitest/ui': 3.1.3 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + vscode-uri@3.1.0: + resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} + + vue-tsc@3.0.0-alpha.6: + resolution: {integrity: sha512-sx9+jk0vaUnfexDN+56VtarBPqP4JAAY2UUUMfl/splywx7wKdmhG9v1VaqvZJ30Ixr+1KfOzqbviAJXcr3jYQ==} + hasBin: true + peerDependencies: + typescript: '>=5.0.0' + + vue@3.5.13: + resolution: {integrity: sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + wait-on@8.0.3: + resolution: {integrity: sha512-nQFqAFzZDeRxsu7S3C7LbuxslHhk+gnJZHyethuGKAn2IVleIbTB9I3vJSQiSR+DifUqmdzfPMoMPJfLqMF2vw==} + engines: {node: '>=12.0.0'} + hasBin: true + + web-resource-inliner@6.0.1: + resolution: {integrity: sha512-kfqDxt5dTB1JhqsCUQVFDj0rmY+4HLwGQIsLPbyrsN9y9WV/1oFDSx3BQ4GfCv9X+jVeQ7rouTqwK53rA/7t8A==} + engines: {node: '>=10.0.0'} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + wicked-good-xpath@1.3.0: + resolution: {integrity: sha512-Gd9+TUn5nXdwj/hFsPVx5cuHHiF5Bwuc30jZ4+ronF1qHK5O7HD0sgmXWSEgwKquT3ClLoKPVbO6qGwVwLzvAw==} + + wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yaml@2.7.1: + resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==} + engines: {node: '>= 14'} + hasBin: true + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yoctocolors@2.1.1: + resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==} + engines: {node: '>=18'} + + zod@3.24.4: + resolution: {integrity: sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==} + + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + +snapshots: + + '@algolia/autocomplete-core@1.17.9(@algolia/client-search@5.24.0)(algoliasearch@5.24.0)': + dependencies: + '@algolia/autocomplete-plugin-algolia-insights': 1.17.9(@algolia/client-search@5.24.0)(algoliasearch@5.24.0) + '@algolia/autocomplete-shared': 1.17.9(@algolia/client-search@5.24.0)(algoliasearch@5.24.0) + transitivePeerDependencies: + - '@algolia/client-search' + - algoliasearch + - search-insights + + '@algolia/autocomplete-plugin-algolia-insights@1.17.9(@algolia/client-search@5.24.0)(algoliasearch@5.24.0)': + dependencies: + '@algolia/autocomplete-shared': 1.17.9(@algolia/client-search@5.24.0)(algoliasearch@5.24.0) + transitivePeerDependencies: + - '@algolia/client-search' + - algoliasearch + + '@algolia/autocomplete-preset-algolia@1.17.9(@algolia/client-search@5.24.0)(algoliasearch@5.24.0)': + dependencies: + '@algolia/autocomplete-shared': 1.17.9(@algolia/client-search@5.24.0)(algoliasearch@5.24.0) + '@algolia/client-search': 5.24.0 + algoliasearch: 5.24.0 + + '@algolia/autocomplete-shared@1.17.9(@algolia/client-search@5.24.0)(algoliasearch@5.24.0)': + dependencies: + '@algolia/client-search': 5.24.0 + algoliasearch: 5.24.0 + + '@algolia/client-abtesting@5.24.0': + dependencies: + '@algolia/client-common': 5.24.0 + '@algolia/requester-browser-xhr': 5.24.0 + '@algolia/requester-fetch': 5.24.0 + '@algolia/requester-node-http': 5.24.0 + + '@algolia/client-analytics@5.24.0': + dependencies: + '@algolia/client-common': 5.24.0 + '@algolia/requester-browser-xhr': 5.24.0 + '@algolia/requester-fetch': 5.24.0 + '@algolia/requester-node-http': 5.24.0 + + '@algolia/client-common@5.24.0': {} + + '@algolia/client-insights@5.24.0': + dependencies: + '@algolia/client-common': 5.24.0 + '@algolia/requester-browser-xhr': 5.24.0 + '@algolia/requester-fetch': 5.24.0 + '@algolia/requester-node-http': 5.24.0 + + '@algolia/client-personalization@5.24.0': + dependencies: + '@algolia/client-common': 5.24.0 + '@algolia/requester-browser-xhr': 5.24.0 + '@algolia/requester-fetch': 5.24.0 + '@algolia/requester-node-http': 5.24.0 + + '@algolia/client-query-suggestions@5.24.0': + dependencies: + '@algolia/client-common': 5.24.0 + '@algolia/requester-browser-xhr': 5.24.0 + '@algolia/requester-fetch': 5.24.0 + '@algolia/requester-node-http': 5.24.0 + + '@algolia/client-search@5.24.0': + dependencies: + '@algolia/client-common': 5.24.0 + '@algolia/requester-browser-xhr': 5.24.0 + '@algolia/requester-fetch': 5.24.0 + '@algolia/requester-node-http': 5.24.0 + + '@algolia/ingestion@1.24.0': + dependencies: + '@algolia/client-common': 5.24.0 + '@algolia/requester-browser-xhr': 5.24.0 + '@algolia/requester-fetch': 5.24.0 + '@algolia/requester-node-http': 5.24.0 + + '@algolia/monitoring@1.24.0': + dependencies: + '@algolia/client-common': 5.24.0 + '@algolia/requester-browser-xhr': 5.24.0 + '@algolia/requester-fetch': 5.24.0 + '@algolia/requester-node-http': 5.24.0 + + '@algolia/recommend@5.24.0': + dependencies: + '@algolia/client-common': 5.24.0 + '@algolia/requester-browser-xhr': 5.24.0 + '@algolia/requester-fetch': 5.24.0 + '@algolia/requester-node-http': 5.24.0 + + '@algolia/requester-browser-xhr@5.24.0': + dependencies: + '@algolia/client-common': 5.24.0 + + '@algolia/requester-fetch@5.24.0': + dependencies: + '@algolia/client-common': 5.24.0 + + '@algolia/requester-node-http@5.24.0': + dependencies: + '@algolia/client-common': 5.24.0 + + '@antfu/install-pkg@1.1.0': + dependencies: + package-manager-detector: 1.3.0 + tinyexec: 1.0.1 + + '@antfu/utils@8.1.1': {} + + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.27.1 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.27.1': {} + + '@babel/parser@7.27.2': + dependencies: + '@babel/types': 7.27.1 + + '@babel/types@7.27.1': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + + '@clack/core@0.3.5': + dependencies: + picocolors: 1.1.1 + sisteransi: 1.0.5 + + '@clack/core@1.0.0-alpha.0': + dependencies: + picocolors: 1.1.1 + sisteransi: 1.0.5 + + '@clack/prompts@1.0.0-alpha.0': + dependencies: + '@clack/core': 1.0.0-alpha.0 + picocolors: 1.1.1 + sisteransi: 1.0.5 + + '@conventional-changelog/git-client@1.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.1.0)': + dependencies: + '@types/semver': 7.7.0 + semver: 7.7.1 + optionalDependencies: + conventional-commits-filter: 5.0.0 + conventional-commits-parser: 6.1.0 + + '@docsearch/css@3.9.0': {} + + '@docsearch/js@3.9.0(@algolia/client-search@5.24.0)': + dependencies: + '@docsearch/react': 3.9.0(@algolia/client-search@5.24.0) + preact: 10.26.6 + transitivePeerDependencies: + - '@algolia/client-search' + - '@types/react' + - react + - react-dom + - search-insights + + '@docsearch/react@3.9.0(@algolia/client-search@5.24.0)': + dependencies: + '@algolia/autocomplete-core': 1.17.9(@algolia/client-search@5.24.0)(algoliasearch@5.24.0) + '@algolia/autocomplete-preset-algolia': 1.17.9(@algolia/client-search@5.24.0)(algoliasearch@5.24.0) + '@docsearch/css': 3.9.0 + algoliasearch: 5.24.0 + transitivePeerDependencies: + - '@algolia/client-search' + + '@emnapi/core@1.4.3': + dependencies: + '@emnapi/wasi-threads': 1.0.2 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.4.3': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.0.2': + dependencies: + tslib: 2.8.1 + optional: true + + '@esbuild/aix-ppc64@0.25.4': + optional: true + + '@esbuild/android-arm64@0.25.4': + optional: true + + '@esbuild/android-arm@0.25.4': + optional: true + + '@esbuild/android-x64@0.25.4': + optional: true + + '@esbuild/darwin-arm64@0.25.4': + optional: true + + '@esbuild/darwin-x64@0.25.4': + optional: true + + '@esbuild/freebsd-arm64@0.25.4': + optional: true + + '@esbuild/freebsd-x64@0.25.4': + optional: true + + '@esbuild/linux-arm64@0.25.4': + optional: true + + '@esbuild/linux-arm@0.25.4': + optional: true + + '@esbuild/linux-ia32@0.25.4': + optional: true + + '@esbuild/linux-loong64@0.25.4': + optional: true + + '@esbuild/linux-mips64el@0.25.4': + optional: true + + '@esbuild/linux-ppc64@0.25.4': + optional: true + + '@esbuild/linux-riscv64@0.25.4': + optional: true + + '@esbuild/linux-s390x@0.25.4': + optional: true + + '@esbuild/linux-x64@0.25.4': + optional: true + + '@esbuild/netbsd-arm64@0.25.4': + optional: true + + '@esbuild/netbsd-x64@0.25.4': + optional: true + + '@esbuild/openbsd-arm64@0.25.4': + optional: true + + '@esbuild/openbsd-x64@0.25.4': + optional: true + + '@esbuild/sunos-x64@0.25.4': + optional: true + + '@esbuild/win32-arm64@0.25.4': + optional: true + + '@esbuild/win32-ia32@0.25.4': + optional: true + + '@esbuild/win32-x64@0.25.4': + optional: true + + '@hapi/hoek@9.3.0': {} + + '@hapi/topo@5.1.0': + dependencies: + '@hapi/hoek': 9.3.0 + + '@hutson/parse-repository-url@5.0.0': {} + + '@iconify-json/logos@1.2.4': + dependencies: + '@iconify/types': 2.0.0 + + '@iconify-json/simple-icons@1.2.33': + dependencies: + '@iconify/types': 2.0.0 + + '@iconify-json/vscode-icons@1.2.20': + dependencies: + '@iconify/types': 2.0.0 + + '@iconify/types@2.0.0': {} + + '@iconify/utils@2.3.0': + dependencies: + '@antfu/install-pkg': 1.1.0 + '@antfu/utils': 8.1.1 + '@iconify/types': 2.0.0 + debug: 4.4.0 + globals: 15.15.0 + kolorist: 1.8.0 + local-pkg: 1.1.1 + mlly: 1.7.4 + transitivePeerDependencies: + - supports-color + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@kwsites/file-exists@1.1.1': + dependencies: + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + + '@kwsites/promise-deferred@1.1.1': {} + + '@lunariajs/core@0.1.1': + dependencies: + '@clack/core': 0.3.5 + fast-glob: 3.3.3 + get-port: 7.1.0 + jiti: 1.21.7 + micromatch: 4.0.8 + path-to-regexp: 6.3.0 + picocolors: 1.1.1 + simple-git: 3.27.0 + ultramatter: 0.0.4 + zod: 3.24.4 + transitivePeerDependencies: + - supports-color + + '@mdit-vue/plugin-component@2.1.4': + dependencies: + '@types/markdown-it': 14.1.2 + markdown-it: 14.1.0 + + '@mdit-vue/plugin-frontmatter@2.1.4': + dependencies: + '@mdit-vue/types': 2.1.4 + '@types/markdown-it': 14.1.2 + gray-matter: 4.0.3 + markdown-it: 14.1.0 + + '@mdit-vue/plugin-headers@2.1.4': + dependencies: + '@mdit-vue/shared': 2.1.4 + '@mdit-vue/types': 2.1.4 + '@types/markdown-it': 14.1.2 + markdown-it: 14.1.0 + + '@mdit-vue/plugin-sfc@2.1.4': + dependencies: + '@mdit-vue/types': 2.1.4 + '@types/markdown-it': 14.1.2 + markdown-it: 14.1.0 + + '@mdit-vue/plugin-title@2.1.4': + dependencies: + '@mdit-vue/shared': 2.1.4 + '@mdit-vue/types': 2.1.4 + '@types/markdown-it': 14.1.2 + markdown-it: 14.1.0 + + '@mdit-vue/plugin-toc@2.1.4': dependencies: - '@types/node': 20.2.5 - dev: true + '@mdit-vue/shared': 2.1.4 + '@mdit-vue/types': 2.1.4 + '@types/markdown-it': 14.1.2 + markdown-it: 14.1.0 + + '@mdit-vue/shared@2.1.4': + dependencies: + '@mdit-vue/types': 2.1.4 + '@types/markdown-it': 14.1.2 + markdown-it: 14.1.0 + + '@mdit-vue/types@2.1.4': {} + + '@napi-rs/wasm-runtime@0.2.9': + dependencies: + '@emnapi/core': 1.4.3 + '@emnapi/runtime': 1.4.3 + '@tybys/wasm-util': 0.9.0 + optional: true + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 + + '@oxc-minify/binding-darwin-arm64@0.69.0': + optional: true + + '@oxc-minify/binding-darwin-x64@0.69.0': + optional: true + + '@oxc-minify/binding-freebsd-x64@0.69.0': + optional: true + + '@oxc-minify/binding-linux-arm-gnueabihf@0.69.0': + optional: true + + '@oxc-minify/binding-linux-arm64-gnu@0.69.0': + optional: true + + '@oxc-minify/binding-linux-arm64-musl@0.69.0': + optional: true + + '@oxc-minify/binding-linux-riscv64-gnu@0.69.0': + optional: true + + '@oxc-minify/binding-linux-s390x-gnu@0.69.0': + optional: true + + '@oxc-minify/binding-linux-x64-gnu@0.69.0': + optional: true + + '@oxc-minify/binding-linux-x64-musl@0.69.0': + optional: true + + '@oxc-minify/binding-wasm32-wasi@0.69.0': + dependencies: + '@napi-rs/wasm-runtime': 0.2.9 + optional: true + + '@oxc-minify/binding-win32-arm64-msvc@0.69.0': + optional: true + + '@oxc-minify/binding-win32-x64-msvc@0.69.0': + optional: true + + '@oxc-project/runtime@0.69.0': {} + + '@oxc-project/types@0.69.0': {} + + '@polka/compression@1.0.0-next.28': {} + + '@polka/url@1.0.0-next.29': {} + + '@rolldown/binding-darwin-arm64@1.0.0-beta.8-commit.8951737': + optional: true + + '@rolldown/binding-darwin-x64@1.0.0-beta.8-commit.8951737': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.0-beta.8-commit.8951737': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.8-commit.8951737': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.8-commit.8951737': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.8-commit.8951737': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.8-commit.8951737': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.0-beta.8-commit.8951737': + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.0-beta.8-commit.8951737': + dependencies: + '@napi-rs/wasm-runtime': 0.2.9 + optional: true - /@types/debug@4.1.8: - resolution: {integrity: sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==} - dependencies: - '@types/ms': 0.7.31 - dev: true + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.8-commit.8951737': + optional: true + + '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.8-commit.8951737': + optional: true - /@types/escape-html@1.0.2: - resolution: {integrity: sha512-gaBLT8pdcexFztLSPRtriHeXY/Kn4907uOCZ4Q3lncFBkheAWOuNt53ypsF8szgxbEJ513UeBzcf4utN0EzEwA==} - dev: true + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.8-commit.8951737': + optional: true + + '@rolldown/pluginutils@1.0.0-beta.8-commit.8951737': {} - /@types/estree@1.0.1: - resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==} - dev: true + '@rollup/plugin-alias@5.1.1(rollup@4.40.2)': + optionalDependencies: + rollup: 4.40.2 - /@types/express-serve-static-core@4.17.35: - resolution: {integrity: sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==} + '@rollup/plugin-commonjs@28.0.3(rollup@4.40.2)': dependencies: - '@types/node': 20.2.5 - '@types/qs': 6.9.7 - '@types/range-parser': 1.2.4 - '@types/send': 0.17.1 - dev: true + '@rollup/pluginutils': 5.1.4(rollup@4.40.2) + commondir: 1.0.1 + estree-walker: 2.0.2 + fdir: 6.4.4(picomatch@4.0.2) + is-reference: 1.2.1 + magic-string: 0.30.17 + picomatch: 4.0.2 + optionalDependencies: + rollup: 4.40.2 - /@types/express@4.17.17: - resolution: {integrity: sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==} + '@rollup/plugin-json@6.1.0(rollup@4.40.2)': dependencies: - '@types/body-parser': 1.19.2 - '@types/express-serve-static-core': 4.17.35 - '@types/qs': 6.9.7 - '@types/serve-static': 1.15.1 - dev: true + '@rollup/pluginutils': 5.1.4(rollup@4.40.2) + optionalDependencies: + rollup: 4.40.2 - /@types/fs-extra@11.0.1: - resolution: {integrity: sha512-MxObHvNl4A69ofaTRU8DFqvgzzv8s9yRtaPPm5gud9HDNvpB3GPQFvNuTWAI59B9huVGV5jXYJwbCsmBsOGYWA==} + '@rollup/plugin-node-resolve@16.0.1(rollup@4.40.2)': dependencies: - '@types/jsonfile': 6.1.1 - '@types/node': 20.2.5 - dev: true + '@rollup/pluginutils': 5.1.4(rollup@4.40.2) + '@types/resolve': 1.20.2 + deepmerge: 4.3.1 + is-module: 1.0.0 + resolve: 1.22.10 + optionalDependencies: + rollup: 4.40.2 - /@types/jquery@3.5.16: - resolution: {integrity: sha512-bsI7y4ZgeMkmpG9OM710RRzDFp+w4P1RGiIt30C1mSBT+ExCleeh4HObwgArnDFELmRrOpXgSYN9VF1hj+f1lw==} + '@rollup/plugin-replace@6.0.2(rollup@4.40.2)': dependencies: - '@types/sizzle': 2.3.3 - dev: true + '@rollup/pluginutils': 5.1.4(rollup@4.40.2) + magic-string: 0.30.17 + optionalDependencies: + rollup: 4.40.2 - /@types/jsonfile@6.1.1: - resolution: {integrity: sha512-GSgiRCVeapDN+3pqA35IkQwasaCh/0YFH5dEF6S88iDvEn901DjOeH3/QPY+XYP1DFzDZPvIvfeEgk+7br5png==} + '@rollup/pluginutils@5.1.4(rollup@4.40.2)': dependencies: - '@types/node': 20.2.5 - dev: true + '@types/estree': 1.0.7 + estree-walker: 2.0.2 + picomatch: 4.0.2 + optionalDependencies: + rollup: 4.40.2 + + '@rollup/rollup-android-arm-eabi@4.40.2': + optional: true + + '@rollup/rollup-android-arm64@4.40.2': + optional: true + + '@rollup/rollup-darwin-arm64@4.40.2': + optional: true + + '@rollup/rollup-darwin-x64@4.40.2': + optional: true + + '@rollup/rollup-freebsd-arm64@4.40.2': + optional: true + + '@rollup/rollup-freebsd-x64@4.40.2': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.40.2': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.40.2': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.40.2': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.40.2': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.40.2': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.40.2': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.40.2': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.40.2': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.40.2': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.40.2': + optional: true + + '@rollup/rollup-linux-x64-musl@4.40.2': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.40.2': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.40.2': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.40.2': + optional: true - /@types/linkify-it@3.0.2: - resolution: {integrity: sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==} - dev: true + '@sec-ant/readable-stream@0.4.1': {} - /@types/mark.js@8.11.8: - resolution: {integrity: sha512-BoWCd9ydi1hZxDfu/lF0v1hHMsNUjuxZEDJsdHlmm6GlKk4qxlLya7D3FS81QmabwFbYPpoDOh9603JESUkHbA==} + '@shikijs/core@3.4.0': dependencies: - '@types/jquery': 3.5.16 - dev: true + '@shikijs/types': 3.4.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.5 - /@types/markdown-it-attrs@4.1.0: - resolution: {integrity: sha512-ILGUUJf7gydzxY3FrN2XwFT/f6rfxtkXZal478Jf4vqFn2AkQCwGCTx3TI+IPT+5ipOf+hUplem8wfVuCyK/Pw==} + '@shikijs/engine-javascript@3.4.0': dependencies: - '@types/markdown-it': 12.2.3 - dev: true + '@shikijs/types': 3.4.0 + '@shikijs/vscode-textmate': 10.0.2 + oniguruma-to-es: 4.3.3 - /@types/markdown-it-container@2.0.5: - resolution: {integrity: sha512-8v5jIC5gcCUv+JcD0DExwNBkoKC0kLB4acensF0NoNlTIcXmQxF3RDjzAdIW82sXSoR+n772ePguxIWlq2ELvA==} + '@shikijs/engine-oniguruma@3.4.0': dependencies: - '@types/markdown-it': 12.2.3 - dev: true + '@shikijs/types': 3.4.0 + '@shikijs/vscode-textmate': 10.0.2 - /@types/markdown-it-emoji@2.0.2: - resolution: {integrity: sha512-2ln8Wjbcj/0oRi/6VnuMeWEHHuK8uapFttvcLmDIe1GKCsFBLOLBX+D+xhDa9oWOQV0IpvxwrSfKKssAqqroog==} + '@shikijs/langs@3.4.0': dependencies: - '@types/markdown-it': 12.2.3 - dev: true + '@shikijs/types': 3.4.0 - /@types/markdown-it@12.2.3: - resolution: {integrity: sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==} + '@shikijs/themes@3.4.0': dependencies: - '@types/linkify-it': 3.0.2 - '@types/mdurl': 1.0.2 - dev: true + '@shikijs/types': 3.4.0 - /@types/mdurl@1.0.2: - resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==} - dev: true + '@shikijs/transformers@3.4.0': + dependencies: + '@shikijs/core': 3.4.0 + '@shikijs/types': 3.4.0 - /@types/micromatch@4.0.2: - resolution: {integrity: sha512-oqXqVb0ci19GtH0vOA/U2TmHTcRY9kuZl4mqUxe0QmJAlIW13kzhuK5pi1i9+ngav8FjpSb9FVS/GE00GLX1VA==} + '@shikijs/types@3.4.0': dependencies: - '@types/braces': 3.0.1 - dev: true + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 - /@types/mime@1.3.2: - resolution: {integrity: sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==} - dev: true + '@shikijs/vscode-textmate@10.0.2': {} - /@types/mime@3.0.1: - resolution: {integrity: sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==} - dev: true + '@sideway/address@4.1.5': + dependencies: + '@hapi/hoek': 9.3.0 - /@types/minimist@1.2.2: - resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} - dev: true + '@sideway/formula@3.0.1': {} - /@types/ms@0.7.31: - resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} - dev: true + '@sideway/pinpoint@2.0.0': {} - /@types/node@20.2.5: - resolution: {integrity: sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==} + '@sindresorhus/merge-streams@4.0.0': {} - /@types/normalize-package-data@2.4.1: - resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} - dev: true + '@tokenizer/token@0.3.0': {} - /@types/prompts@2.4.4: - resolution: {integrity: sha512-p5N9uoTH76lLvSAaYSZtBCdEXzpOOufsRjnhjVSrZGXikVGHX9+cc9ERtHRV4hvBKHyZb1bg4K+56Bd2TqUn4A==} + '@tybys/wasm-util@0.9.0': dependencies: - '@types/node': 20.2.5 - kleur: 3.0.3 - dev: true + tslib: 2.8.1 + optional: true - /@types/qs@6.9.7: - resolution: {integrity: sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==} - dev: true + '@types/cross-spawn@6.0.6': + dependencies: + '@types/node': 22.15.17 + + '@types/debug@4.1.12': + dependencies: + '@types/ms': 2.1.0 - /@types/range-parser@1.2.4: - resolution: {integrity: sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==} - dev: true + '@types/estree@1.0.7': {} - /@types/resolve@1.20.2: - resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} - dev: true + '@types/fs-extra@11.0.4': + dependencies: + '@types/jsonfile': 6.1.4 + '@types/node': 22.15.17 - /@types/send@0.17.1: - resolution: {integrity: sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==} + '@types/hast@3.0.4': dependencies: - '@types/mime': 1.3.2 - '@types/node': 20.2.5 - dev: true + '@types/unist': 3.0.3 - /@types/serve-static@1.15.1: - resolution: {integrity: sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ==} + '@types/jquery@3.5.32': dependencies: - '@types/mime': 3.0.1 - '@types/node': 20.2.5 - dev: true + '@types/sizzle': 2.3.9 - /@types/sizzle@2.3.3: - resolution: {integrity: sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==} - dev: true + '@types/jsonfile@6.1.4': + dependencies: + '@types/node': 22.15.17 - /@types/web-bluetooth@0.0.17: - resolution: {integrity: sha512-4p9vcSmxAayx72yn70joFoL44c9MO/0+iVEBIQXe3v2h2SiAsEIo/G5v6ObFWvNKRFjbrVadNf9LqEEZeQPzdA==} - dev: false + '@types/linkify-it@5.0.0': {} - /@vitejs/plugin-vue@4.2.3(vite@4.3.9)(vue@3.3.4): - resolution: {integrity: sha512-R6JDUfiZbJA9cMiguQ7jxALsgiprjBeHL5ikpXfJCH62pPHtI+JdJ5xWj6Ev73yXSlYl86+blXn1kZHQ7uElxw==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - vite: ^4.0.0 - vue: ^3.2.25 + '@types/lodash.template@4.5.3': dependencies: - vite: 4.3.9(@types/node@20.2.5) - vue: 3.3.4 - dev: false + '@types/lodash': 4.17.16 - /@vitest/expect@0.32.0: - resolution: {integrity: sha512-VxVHhIxKw9Lux+O9bwLEEk2gzOUe93xuFHy9SzYWnnoYZFYg1NfBtnfnYWiJN7yooJ7KNElCK5YtA7DTZvtXtg==} + '@types/lodash@4.17.16': {} + + '@types/mark.js@8.11.12': dependencies: - '@vitest/spy': 0.32.0 - '@vitest/utils': 0.32.0 - chai: 4.3.7 - dev: true + '@types/jquery': 3.5.32 - /@vitest/runner@0.32.0: - resolution: {integrity: sha512-QpCmRxftHkr72xt5A08xTEs9I4iWEXIOCHWhQQguWOKE4QH7DXSKZSOFibuwEIMAD7G0ERvtUyQn7iPWIqSwmw==} + '@types/markdown-it-attrs@4.1.3': dependencies: - '@vitest/utils': 0.32.0 - concordance: 5.0.4 - p-limit: 4.0.0 - pathe: 1.1.1 - dev: true + '@types/markdown-it': 14.1.2 - /@vitest/snapshot@0.32.0: - resolution: {integrity: sha512-yCKorPWjEnzpUxQpGlxulujTcSPgkblwGzAUEL+z01FTUg/YuCDZ8dxr9sHA08oO2EwxzHXNLjQKWJ2zc2a19Q==} + '@types/markdown-it-container@2.0.10': dependencies: - magic-string: 0.30.0 - pathe: 1.1.1 - pretty-format: 27.5.1 - dev: true + '@types/markdown-it': 14.1.2 - /@vitest/spy@0.32.0: - resolution: {integrity: sha512-MruAPlM0uyiq3d53BkwTeShXY0rYEfhNGQzVO5GHBmmX3clsxcWp79mMnkOVcV244sNTeDcHbcPFWIjOI4tZvw==} + '@types/markdown-it-emoji@3.0.1': dependencies: - tinyspy: 2.1.1 - dev: true + '@types/markdown-it': 14.1.2 - /@vitest/utils@0.32.0: - resolution: {integrity: sha512-53yXunzx47MmbuvcOPpLaVljHaeSu1G2dHdmy7+9ngMnQIkBQcvwOcoclWFnxDMxFbnq8exAfh3aKSZaK71J5A==} + '@types/markdown-it@14.1.2': dependencies: - concordance: 5.0.4 - loupe: 2.3.6 - pretty-format: 27.5.1 - dev: true + '@types/linkify-it': 5.0.0 + '@types/mdurl': 2.0.0(patch_hash=3460e7d18ce390685cf4b8d8237fb20df9ad952c1336f479995a508a6395bfa4) - /@volar/language-core@1.4.1: - resolution: {integrity: sha512-EIY+Swv+TjsWpxOxujjMf1ZXqOjg9MT2VMXZ+1dKva0wD8W0L6EtptFFcCJdBbcKmGMFkr57Qzz9VNMWhs3jXQ==} + '@types/mdast@4.0.4': dependencies: - '@volar/source-map': 1.4.1 - dev: true + '@types/unist': 3.0.3 + + '@types/mdurl@2.0.0(patch_hash=3460e7d18ce390685cf4b8d8237fb20df9ad952c1336f479995a508a6395bfa4)': {} + + '@types/minimist@1.2.5': {} + + '@types/ms@2.1.0': {} - /@volar/source-map@1.4.1: - resolution: {integrity: sha512-bZ46ad72dsbzuOWPUtJjBXkzSQzzSejuR3CT81+GvTEI2E994D8JPXzM3tl98zyCNnjgs4OkRyliImL1dvJ5BA==} + '@types/node@17.0.45': {} + + '@types/node@22.15.17': dependencies: - muggle-string: 0.2.2 - dev: true + undici-types: 6.21.0 - /@volar/typescript@1.4.1-patch.2(typescript@5.1.3): - resolution: {integrity: sha512-lPFYaGt8OdMEzNGJJChF40uYqMO4Z/7Q9fHPQC/NRVtht43KotSXLrkPandVVMf9aPbiJ059eAT+fwHGX16k4w==} - peerDependencies: - typescript: '*' + '@types/normalize-package-data@2.4.4': {} + + '@types/picomatch@4.0.0': {} + + '@types/postcss-prefix-selector@1.16.3': dependencies: - '@volar/language-core': 1.4.1 - typescript: 5.1.3 - dev: true - - /@volar/vue-language-core@1.6.5: - resolution: {integrity: sha512-IF2b6hW4QAxfsLd5mePmLgtkXzNi+YnH6ltCd80gb7+cbdpFMjM1I+w+nSg2kfBTyfu+W8useCZvW89kPTBpzg==} - dependencies: - '@volar/language-core': 1.4.1 - '@volar/source-map': 1.4.1 - '@vue/compiler-dom': 3.3.4 - '@vue/compiler-sfc': 3.3.4 - '@vue/reactivity': 3.3.4 - '@vue/shared': 3.3.4 - minimatch: 9.0.1 - muggle-string: 0.2.2 - vue-template-compiler: 2.7.14 - dev: true - - /@volar/vue-typescript@1.6.5(typescript@5.1.3): - resolution: {integrity: sha512-er9rVClS4PHztMUmtPMDTl+7c7JyrxweKSAEe/o/Noeq2bQx6v3/jZHVHBe8ZNUti5ubJL/+Tg8L3bzmlalV8A==} - peerDependencies: - typescript: '*' + postcss: 8.5.3 + + '@types/prompts@2.4.9': dependencies: - '@volar/typescript': 1.4.1-patch.2(typescript@5.1.3) - '@volar/vue-language-core': 1.6.5 - typescript: 5.1.3 - dev: true + '@types/node': 22.15.17 + kleur: 3.0.3 + + '@types/resolve@1.20.2': {} - /@vue/compiler-core@3.3.4: - resolution: {integrity: sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==} + '@types/sax@1.2.7': dependencies: - '@babel/parser': 7.22.4 - '@vue/shared': 3.3.4 - estree-walker: 2.0.2 - source-map-js: 1.0.2 + '@types/node': 22.15.17 + + '@types/semver@7.7.0': {} - /@vue/compiler-dom@3.3.4: - resolution: {integrity: sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==} + '@types/sizzle@2.3.9': {} + + '@types/unist@3.0.3': {} + + '@types/web-bluetooth@0.0.21': {} + + '@ungap/structured-clone@1.3.0': {} + + '@vitejs/plugin-vue@5.2.4(vite@6.3.5(@types/node@22.15.17)(jiti@1.21.7)(lightningcss@1.30.0)(yaml@2.7.1))(vue@3.5.13(typescript@5.8.3))': dependencies: - '@vue/compiler-core': 3.3.4 - '@vue/shared': 3.3.4 + vite: 6.3.5(@types/node@22.15.17)(jiti@1.21.7)(lightningcss@1.30.0)(yaml@2.7.1) + vue: 3.5.13(typescript@5.8.3) - /@vue/compiler-sfc@3.3.4: - resolution: {integrity: sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==} + '@vitest/expect@3.1.3': dependencies: - '@babel/parser': 7.22.4 - '@vue/compiler-core': 3.3.4 - '@vue/compiler-dom': 3.3.4 - '@vue/compiler-ssr': 3.3.4 - '@vue/reactivity-transform': 3.3.4 - '@vue/shared': 3.3.4 - estree-walker: 2.0.2 - magic-string: 0.30.0 - postcss: 8.4.24 - source-map-js: 1.0.2 + '@vitest/spy': 3.1.3 + '@vitest/utils': 3.1.3 + chai: 5.2.0 + tinyrainbow: 2.0.0 - /@vue/compiler-ssr@3.3.4: - resolution: {integrity: sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==} + '@vitest/mocker@3.1.3(rolldown-vite@6.3.9(@types/node@22.15.17)(esbuild@0.25.4)(jiti@1.21.7)(yaml@2.7.1))': dependencies: - '@vue/compiler-dom': 3.3.4 - '@vue/shared': 3.3.4 + '@vitest/spy': 3.1.3 + estree-walker: 3.0.3 + magic-string: 0.30.17 + optionalDependencies: + vite: rolldown-vite@6.3.9(@types/node@22.15.17)(esbuild@0.25.4)(jiti@1.21.7)(yaml@2.7.1) - /@vue/devtools-api@6.5.0: - resolution: {integrity: sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==} - dev: false + '@vitest/pretty-format@3.1.3': + dependencies: + tinyrainbow: 2.0.0 - /@vue/reactivity-transform@3.3.4: - resolution: {integrity: sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==} + '@vitest/runner@3.1.3': dependencies: - '@babel/parser': 7.22.4 - '@vue/compiler-core': 3.3.4 - '@vue/shared': 3.3.4 - estree-walker: 2.0.2 - magic-string: 0.30.0 + '@vitest/utils': 3.1.3 + pathe: 2.0.3 - /@vue/reactivity@3.3.4: - resolution: {integrity: sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==} + '@vitest/snapshot@3.1.3': dependencies: - '@vue/shared': 3.3.4 + '@vitest/pretty-format': 3.1.3 + magic-string: 0.30.17 + pathe: 2.0.3 - /@vue/runtime-core@3.3.4: - resolution: {integrity: sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==} + '@vitest/spy@3.1.3': dependencies: - '@vue/reactivity': 3.3.4 - '@vue/shared': 3.3.4 - dev: false + tinyspy: 3.0.2 - /@vue/runtime-dom@3.3.4: - resolution: {integrity: sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==} + '@vitest/utils@3.1.3': dependencies: - '@vue/runtime-core': 3.3.4 - '@vue/shared': 3.3.4 - csstype: 3.1.2 - dev: false + '@vitest/pretty-format': 3.1.3 + loupe: 3.1.3 + tinyrainbow: 2.0.0 - /@vue/server-renderer@3.3.4(vue@3.3.4): - resolution: {integrity: sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==} - peerDependencies: - vue: 3.3.4 + '@volar/language-core@2.4.13': dependencies: - '@vue/compiler-ssr': 3.3.4 - '@vue/shared': 3.3.4 - vue: 3.3.4 - dev: false + '@volar/source-map': 2.4.13 - /@vue/shared@3.3.4: - resolution: {integrity: sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==} + '@volar/source-map@2.4.13': {} - /@vueuse/core@10.1.2(vue@3.3.4): - resolution: {integrity: sha512-roNn8WuerI56A5uiTyF/TEYX0Y+VKlhZAF94unUfdhbDUI+NfwQMn4FUnUscIRUhv3344qvAghopU4bzLPNFlA==} + '@volar/typescript@2.4.13': dependencies: - '@types/web-bluetooth': 0.0.17 - '@vueuse/metadata': 10.1.2 - '@vueuse/shared': 10.1.2(vue@3.3.4) - vue-demi: 0.14.5(vue@3.3.4) - transitivePeerDependencies: - - '@vue/composition-api' - - vue - dev: false + '@volar/language-core': 2.4.13 + path-browserify: 1.0.1 + vscode-uri: 3.1.0 - /@vueuse/integrations@10.1.2(focus-trap@7.4.3)(vue@3.3.4): - resolution: {integrity: sha512-wUpG3Wv6LiWerOwCzOAM0iGhNQ4vfFUTkhj/xQy7TLXduh2M3D8N08aS0KqlxsejY6R8NLxydDIM+68QfHZZ8Q==} - peerDependencies: - async-validator: '*' - axios: '*' - change-case: '*' - drauu: '*' - focus-trap: '*' - fuse.js: '*' - idb-keyval: '*' - jwt-decode: '*' - nprogress: '*' - qrcode: '*' - sortablejs: '*' - universal-cookie: '*' - peerDependenciesMeta: - async-validator: - optional: true - axios: - optional: true - change-case: - optional: true - drauu: - optional: true - focus-trap: - optional: true - fuse.js: - optional: true - idb-keyval: - optional: true - jwt-decode: - optional: true - nprogress: - optional: true - qrcode: - optional: true - sortablejs: - optional: true - universal-cookie: - optional: true + '@vue/compiler-core@3.5.13': dependencies: - '@vueuse/core': 10.1.2(vue@3.3.4) - '@vueuse/shared': 10.1.2(vue@3.3.4) - focus-trap: 7.4.3 - vue-demi: 0.14.5(vue@3.3.4) - transitivePeerDependencies: - - '@vue/composition-api' - - vue - dev: false + '@babel/parser': 7.27.2 + '@vue/shared': 3.5.13 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.2.1 - /@vueuse/metadata@10.1.2: - resolution: {integrity: sha512-3mc5BqN9aU2SqBeBuWE7ne4OtXHoHKggNgxZR2K+zIW4YLsy6xoZ4/9vErQs6tvoKDX6QAqm3lvsrv0mczAwIQ==} - dev: false + '@vue/compiler-dom@3.5.13': + dependencies: + '@vue/compiler-core': 3.5.13 + '@vue/shared': 3.5.13 - /@vueuse/shared@10.1.2(vue@3.3.4): - resolution: {integrity: sha512-1uoUTPBlgyscK9v6ScGeVYDDzlPSFXBlxuK7SfrDGyUTBiznb3mNceqhwvZHjtDRELZEN79V5uWPTF1VDV8svA==} + '@vue/compiler-sfc@3.5.13': dependencies: - vue-demi: 0.14.5(vue@3.3.4) - transitivePeerDependencies: - - '@vue/composition-api' - - vue - dev: false + '@babel/parser': 7.27.2 + '@vue/compiler-core': 3.5.13 + '@vue/compiler-dom': 3.5.13 + '@vue/compiler-ssr': 3.5.13 + '@vue/shared': 3.5.13 + estree-walker: 2.0.2 + magic-string: 0.30.17 + postcss: 8.5.3 + source-map-js: 1.2.1 - /JSONStream@1.3.5: - resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} - hasBin: true + '@vue/compiler-ssr@3.5.13': dependencies: - jsonparse: 1.3.1 - through: 2.3.8 - dev: true + '@vue/compiler-dom': 3.5.13 + '@vue/shared': 3.5.13 - /accepts@1.3.8: - resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} - engines: {node: '>= 0.6'} + '@vue/compiler-vue2@2.7.16': dependencies: - mime-types: 2.1.35 - negotiator: 0.6.3 - dev: true + de-indent: 1.0.2 + he: 1.2.0 - /acorn-walk@8.2.0: - resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} - engines: {node: '>=0.4.0'} - dev: true + '@vue/devtools-api@7.7.6': + dependencies: + '@vue/devtools-kit': 7.7.6 - /acorn@8.8.2: - resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true + '@vue/devtools-kit@7.7.6': + dependencies: + '@vue/devtools-shared': 7.7.6 + birpc: 2.3.0 + hookable: 5.5.3 + mitt: 3.0.1 + perfect-debounce: 1.0.0 + speakingurl: 14.0.1 + superjson: 2.2.2 - /add-stream@1.0.0: - resolution: {integrity: sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==} - dev: true + '@vue/devtools-shared@7.7.6': + dependencies: + rfdc: 1.4.1 - /aggregate-error@3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} + '@vue/language-core@3.0.0-alpha.6(typescript@5.8.3)': dependencies: - clean-stack: 2.2.0 - indent-string: 4.0.0 - dev: true - - /algoliasearch@4.17.1: - resolution: {integrity: sha512-4GDQ1RhP2qUR3x8PevFRbEdqZqIARNViZYjgTJmA1T7wRNtFA3W4Aqc/RsODqa1J8IO/QDla5x4tWuUS8NV8wA==} - dependencies: - '@algolia/cache-browser-local-storage': 4.17.1 - '@algolia/cache-common': 4.17.1 - '@algolia/cache-in-memory': 4.17.1 - '@algolia/client-account': 4.17.1 - '@algolia/client-analytics': 4.17.1 - '@algolia/client-common': 4.17.1 - '@algolia/client-personalization': 4.17.1 - '@algolia/client-search': 4.17.1 - '@algolia/logger-common': 4.17.1 - '@algolia/logger-console': 4.17.1 - '@algolia/requester-browser-xhr': 4.17.1 - '@algolia/requester-common': 4.17.1 - '@algolia/requester-node-http': 4.17.1 - '@algolia/transporter': 4.17.1 - dev: false - - /ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} + '@volar/language-core': 2.4.13 + '@vue/compiler-dom': 3.5.13 + '@vue/compiler-vue2': 2.7.16 + '@vue/shared': 3.5.13 + alien-signals: 1.0.13 + minimatch: 9.0.5 + muggle-string: 0.4.1 + path-browserify: 1.0.1 + optionalDependencies: + typescript: 5.8.3 + + '@vue/reactivity@3.5.13': dependencies: - type-fest: 0.21.3 - dev: true + '@vue/shared': 3.5.13 - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: true + '@vue/runtime-core@3.5.13': + dependencies: + '@vue/reactivity': 3.5.13 + '@vue/shared': 3.5.13 - /ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - dev: true + '@vue/runtime-dom@3.5.13': + dependencies: + '@vue/reactivity': 3.5.13 + '@vue/runtime-core': 3.5.13 + '@vue/shared': 3.5.13 + csstype: 3.1.3 - /ansi-sequence-parser@1.1.0: - resolution: {integrity: sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==} + '@vue/server-renderer@3.5.13(vue@3.5.13(typescript@5.8.3))': + dependencies: + '@vue/compiler-ssr': 3.5.13 + '@vue/shared': 3.5.13 + vue: 3.5.13(typescript@5.8.3) - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} + '@vue/shared@3.5.13': {} + + '@vueuse/core@13.1.0(vue@3.5.13(typescript@5.8.3))': dependencies: - color-convert: 1.9.3 - dev: true + '@types/web-bluetooth': 0.0.21 + '@vueuse/metadata': 13.1.0 + '@vueuse/shared': 13.1.0(vue@3.5.13(typescript@5.8.3)) + vue: 3.5.13(typescript@5.8.3) - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} + '@vueuse/integrations@13.1.0(axios@1.9.0(debug@4.4.0))(focus-trap@7.6.4)(vue@3.5.13(typescript@5.8.3))': dependencies: - color-convert: 2.0.1 - dev: true + '@vueuse/core': 13.1.0(vue@3.5.13(typescript@5.8.3)) + '@vueuse/shared': 13.1.0(vue@3.5.13(typescript@5.8.3)) + vue: 3.5.13(typescript@5.8.3) + optionalDependencies: + axios: 1.9.0(debug@4.4.0) + focus-trap: 7.6.4 - /ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - dev: true + '@vueuse/metadata@13.1.0': {} - /ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - dev: true + '@vueuse/shared@13.1.0(vue@3.5.13(typescript@5.8.3))': + dependencies: + vue: 3.5.13(typescript@5.8.3) - /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} + '@xmldom/xmldom@0.9.8': {} + + abort-controller@3.0.0: dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - dev: true + event-target-shim: 5.0.1 - /argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + acorn@8.14.1: {} + + add-stream@1.0.0: {} + + algoliasearch@5.24.0: dependencies: - sprintf-js: 1.0.3 - dev: true + '@algolia/client-abtesting': 5.24.0 + '@algolia/client-analytics': 5.24.0 + '@algolia/client-common': 5.24.0 + '@algolia/client-insights': 5.24.0 + '@algolia/client-personalization': 5.24.0 + '@algolia/client-query-suggestions': 5.24.0 + '@algolia/client-search': 5.24.0 + '@algolia/ingestion': 1.24.0 + '@algolia/monitoring': 1.24.0 + '@algolia/recommend': 5.24.0 + '@algolia/requester-browser-xhr': 5.24.0 + '@algolia/requester-fetch': 5.24.0 + '@algolia/requester-node-http': 5.24.0 - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true + alien-signals@1.0.13: {} + + ansi-colors@4.1.3: {} - /array-buffer-byte-length@1.0.0: - resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + ansi-escapes@7.0.0: dependencies: - call-bind: 1.0.2 - is-array-buffer: 3.0.2 - dev: true + environment: 1.1.0 - /array-ify@1.0.0: - resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} - dev: true + ansi-regex@5.0.1: {} - /arrify@1.0.1: - resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} - engines: {node: '>=0.10.0'} - dev: true + ansi-regex@6.1.0: {} - /assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - dev: true + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 - /astral-regex@2.0.0: - resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} - engines: {node: '>=8'} - dev: true + ansi-styles@6.2.1: {} - /asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: true + ansis@4.0.0: {} - /available-typed-arrays@1.0.5: - resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} - engines: {node: '>= 0.4'} - dev: true + arg@5.0.2: {} - /axios@0.27.2(debug@4.3.4): - resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==} + argparse@1.0.10: dependencies: - follow-redirects: 1.15.2(debug@4.3.4) - form-data: 4.0.0 - transitivePeerDependencies: - - debug - dev: true + sprintf-js: 1.0.3 - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true + argparse@2.0.1: {} - /base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - dev: true + array-ify@1.0.0: {} - /binary-extensions@2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} - engines: {node: '>=8'} - dev: true + assertion-error@2.0.1: {} + + asynckit@0.4.0: {} - /bl@5.1.0: - resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} + axios@1.9.0(debug@4.4.0): dependencies: - buffer: 6.0.3 - inherits: 2.0.4 - readable-stream: 3.6.2 - dev: true + follow-redirects: 1.15.9(debug@4.4.0) + form-data: 4.0.2 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug - /blueimp-md5@2.19.0: - resolution: {integrity: sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==} - dev: true + bail@2.0.2: {} - /body-scroll-lock@4.0.0-beta.0: - resolution: {integrity: sha512-a7tP5+0Mw3YlUJcGAKUqIBkYYGlYxk2fnCasq/FUph1hadxlTRjF+gAcZksxANnaMnALjxEddmSi/H3OR8ugcQ==} - dev: false + balanced-match@1.0.2: {} - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: true + base64-js@1.5.1: {} - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + birpc@2.3.0: {} + + boolbase@1.0.0: {} + + brace-expansion@2.0.1: dependencies: balanced-match: 1.0.2 - dev: true - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} + braces@3.0.3: dependencies: - fill-range: 7.0.1 - dev: true + fill-range: 7.1.1 - /buffer@6.0.3: - resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + buffer@6.0.3: dependencies: base64-js: 1.5.1 ieee754: 1.2.1 - dev: true - - /builtin-modules@3.3.0: - resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} - engines: {node: '>=6'} - dev: true - /bytes@3.0.0: - resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==} - engines: {node: '>= 0.8'} - dev: true + bundle-name@4.1.0: + dependencies: + run-applescript: 7.0.0 - /cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - dev: true + byte-size@9.0.1: {} - /call-bind@1.0.2: - resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} - dependencies: - function-bind: 1.1.1 - get-intrinsic: 1.2.1 - dev: true + cac@6.7.14: {} - /camelcase-keys@6.2.2: - resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} - engines: {node: '>=8'} + call-bind-apply-helpers@1.0.2: dependencies: - camelcase: 5.3.1 - map-obj: 4.3.0 - quick-lru: 4.0.1 - dev: true + es-errors: 1.3.0 + function-bind: 1.1.2 - /camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - dev: true + ccount@2.0.1: {} - /chai@4.3.7: - resolution: {integrity: sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==} - engines: {node: '>=4'} + chai@5.2.0: dependencies: - assertion-error: 1.1.0 - check-error: 1.0.2 - deep-eql: 4.1.3 - get-func-name: 2.0.0 - loupe: 2.3.6 - pathval: 1.1.1 - type-detect: 4.0.8 - dev: true - - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - dev: true + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.1.3 + pathval: 2.0.0 - /chalk@5.2.0: - resolution: {integrity: sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - dev: true + chalk@5.4.1: {} - /check-error@1.0.2: - resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==} - dev: true + character-entities-html4@2.1.0: {} - /chokidar@3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} - engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.2 - dev: true + character-entities-legacy@3.0.0: {} - /clean-stack@2.2.0: - resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} - engines: {node: '>=6'} - dev: true + character-entities@2.0.2: {} - /cli-cursor@3.1.0: - resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} - engines: {node: '>=8'} + check-error@2.1.1: {} + + cheerio-select@1.6.0: dependencies: - restore-cursor: 3.1.0 - dev: true + css-select: 4.3.0 + css-what: 6.1.0 + domelementtype: 2.3.0 + domhandler: 4.3.1 + domutils: 2.8.0 - /cli-cursor@4.0.0: - resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + cheerio@1.0.0-rc.10: dependencies: - restore-cursor: 4.0.0 - dev: true + cheerio-select: 1.6.0 + dom-serializer: 1.4.1 + domhandler: 4.3.1 + htmlparser2: 6.1.0 + parse5: 6.0.1 + parse5-htmlparser2-tree-adapter: 6.0.1 + tslib: 2.8.1 - /cli-spinners@2.9.0: - resolution: {integrity: sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==} - engines: {node: '>=6'} - dev: true + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 - /cli-truncate@2.1.0: - resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} - engines: {node: '>=8'} + cli-cursor@5.0.0: dependencies: - slice-ansi: 3.0.0 - string-width: 4.2.3 - dev: true + restore-cursor: 5.1.0 - /cli-truncate@3.1.0: - resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + cli-spinners@2.9.2: {} + + cli-truncate@4.0.0: dependencies: slice-ansi: 5.0.0 - string-width: 5.1.2 - dev: true + string-width: 7.2.0 - /cliui@7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + cliui@8.0.1: dependencies: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - dev: true - - /clone@1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - dev: true - - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - dev: true - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} + color-convert@2.0.1: dependencies: color-name: 1.1.4 - dev: true - - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: true - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true + color-name@1.1.4: {} - /colorette@2.0.20: - resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - dev: true + colorette@2.0.20: {} - /combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} + combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 - dev: true - /commander@10.0.1: - resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} - engines: {node: '>=14'} - dev: true + comma-separated-tokens@2.0.3: {} - /commondir@1.0.1: - resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - dev: true + commander@13.1.0: {} - /compare-func@2.0.0: - resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} + commander@6.2.1: {} + + commondir@1.0.1: {} + + compare-func@2.0.0: dependencies: array-ify: 1.0.0 dot-prop: 5.3.0 - dev: true - - /compressible@2.0.18: - resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - dev: true - - /compression@1.7.4(supports-color@9.3.1): - resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==} - engines: {node: '>= 0.8.0'} - dependencies: - accepts: 1.3.8 - bytes: 3.0.0 - compressible: 2.0.18 - debug: 2.6.9(supports-color@9.3.1) - on-headers: 1.0.2 - safe-buffer: 5.1.2 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - dev: true - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true + confbox@0.1.8: {} - /concordance@5.0.4: - resolution: {integrity: sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==} - engines: {node: '>=10.18.0 <11 || >=12.14.0 <13 || >=14'} - dependencies: - date-time: 3.1.0 - esutils: 2.0.3 - fast-diff: 1.3.0 - js-string-escape: 1.0.1 - lodash: 4.17.21 - md5-hex: 3.0.1 - semver: 7.5.1 - well-known-symbols: 2.0.0 - dev: true + confbox@0.2.2: {} - /conventional-changelog-angular@6.0.0: - resolution: {integrity: sha512-6qLgrBF4gueoC7AFVHu51nHL9pF9FRjXrH+ceVf7WmAfH3gs+gEYOkvxhjMPjZu57I4AGUGoNTY8V7Hrgf1uqg==} - engines: {node: '>=14'} + conventional-changelog-angular@8.0.0: dependencies: compare-func: 2.0.0 - dev: true - /conventional-changelog-atom@3.0.0: - resolution: {integrity: sha512-pnN5bWpH+iTUWU3FaYdw5lJmfWeqSyrUkG+wyHBI9tC1dLNnHkbAOg1SzTQ7zBqiFrfo55h40VsGXWMdopwc5g==} - engines: {node: '>=14'} - dev: true + conventional-changelog-atom@5.0.0: {} - /conventional-changelog-cli@3.0.0: - resolution: {integrity: sha512-3zMYi0IrfNd6AAHdPMrcgCg5DbcffiqNaEBf8cYrlntXPbBIXaELTbnRmUy5TQAe0Hkgi0J6+/VmRCkkJQflcQ==} - engines: {node: '>=14'} - hasBin: true + conventional-changelog-cli@5.0.0(conventional-commits-filter@5.0.0): dependencies: add-stream: 1.0.0 - conventional-changelog: 4.0.0 - meow: 8.1.2 - tempfile: 3.0.0 - dev: true + conventional-changelog: 6.0.0(conventional-commits-filter@5.0.0) + meow: 13.2.0 + tempfile: 5.0.0 + transitivePeerDependencies: + - conventional-commits-filter - /conventional-changelog-codemirror@3.0.0: - resolution: {integrity: sha512-wzchZt9HEaAZrenZAUUHMCFcuYzGoZ1wG/kTRMICxsnW5AXohYMRxnyecP9ob42Gvn5TilhC0q66AtTPRSNMfw==} - engines: {node: '>=14'} - dev: true + conventional-changelog-codemirror@5.0.0: {} - /conventional-changelog-conventionalcommits@6.0.0: - resolution: {integrity: sha512-pOQWvJ2se8UmGj3Vz5NzhljdgHvGow6ATZ7pM0TZqGekAfwgJkr3YQ9ZbooB4VIh35KS/cpfIgVrLoqLNvFNYg==} - engines: {node: '>=14'} + conventional-changelog-conventionalcommits@8.0.0: dependencies: compare-func: 2.0.0 - dev: true - /conventional-changelog-core@5.0.1: - resolution: {integrity: sha512-Rvi5pH+LvgsqGwZPZ3Cq/tz4ty7mjijhr3qR4m9IBXNbxGGYgTVVO+duXzz9aArmHxFtwZ+LRkrNIMDQzgoY4A==} - engines: {node: '>=14'} + conventional-changelog-core@8.0.0(conventional-commits-filter@5.0.0): dependencies: + '@hutson/parse-repository-url': 5.0.0 add-stream: 1.0.0 - conventional-changelog-writer: 6.0.0 - conventional-commits-parser: 4.0.0 - dateformat: 3.0.3 - get-pkg-repo: 4.2.1 - git-raw-commits: 3.0.0 - git-remote-origin-url: 2.0.0 - git-semver-tags: 5.0.0 - normalize-package-data: 3.0.3 - read-pkg: 3.0.0 - read-pkg-up: 3.0.0 - dev: true - - /conventional-changelog-ember@3.0.0: - resolution: {integrity: sha512-7PYthCoSxIS98vWhVcSphMYM322OxptpKAuHYdVspryI0ooLDehRXWeRWgN+zWSBXKl/pwdgAg8IpLNSM1/61A==} - engines: {node: '>=14'} - dev: true + conventional-changelog-writer: 8.0.1 + conventional-commits-parser: 6.1.0 + git-raw-commits: 5.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.1.0) + git-semver-tags: 8.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.1.0) + hosted-git-info: 7.0.2 + normalize-package-data: 6.0.2 + read-package-up: 11.0.0 + read-pkg: 9.0.1 + transitivePeerDependencies: + - conventional-commits-filter + + conventional-changelog-ember@5.0.0: {} - /conventional-changelog-eslint@4.0.0: - resolution: {integrity: sha512-nEZ9byP89hIU0dMx37JXQkE1IpMmqKtsaR24X7aM3L6Yy/uAtbb+ogqthuNYJkeO1HyvK7JsX84z8649hvp43Q==} - engines: {node: '>=14'} - dev: true + conventional-changelog-eslint@6.0.0: {} - /conventional-changelog-express@3.0.0: - resolution: {integrity: sha512-HqxihpUMfIuxvlPvC6HltA4ZktQEUan/v3XQ77+/zbu8No/fqK3rxSZaYeHYant7zRxQNIIli7S+qLS9tX9zQA==} - engines: {node: '>=14'} - dev: true + conventional-changelog-express@5.0.0: {} - /conventional-changelog-jquery@4.0.0: - resolution: {integrity: sha512-TTIN5CyzRMf8PUwyy4IOLmLV2DFmPtasKN+x7EQKzwSX8086XYwo+NeaeA3VUT8bvKaIy5z/JoWUvi7huUOgaw==} - engines: {node: '>=14'} - dev: true + conventional-changelog-jquery@6.0.0: {} - /conventional-changelog-jshint@3.0.0: - resolution: {integrity: sha512-bQof4byF4q+n+dwFRkJ/jGf9dCNUv4/kCDcjeCizBvfF81TeimPZBB6fT4HYbXgxxfxWXNl/i+J6T0nI4by6DA==} - engines: {node: '>=14'} + conventional-changelog-jshint@5.0.0: dependencies: compare-func: 2.0.0 - dev: true - /conventional-changelog-preset-loader@3.0.0: - resolution: {integrity: sha512-qy9XbdSLmVnwnvzEisjxdDiLA4OmV3o8db+Zdg4WiFw14fP3B6XNz98X0swPPpkTd/pc1K7+adKgEDM1JCUMiA==} - engines: {node: '>=14'} - dev: true + conventional-changelog-preset-loader@5.0.0: {} - /conventional-changelog-writer@6.0.0: - resolution: {integrity: sha512-8PyWTnn7zBIt9l4hj4UusFs1TyG+9Ulu1zlOAc72L7Sdv9Hsc8E86ot7htY3HXCVhXHB/NO0pVGvZpwsyJvFfw==} - engines: {node: '>=14'} - hasBin: true + conventional-changelog-writer@8.0.1: dependencies: - conventional-commits-filter: 3.0.0 - dateformat: 3.0.3 - handlebars: 4.7.7 - json-stringify-safe: 5.0.1 - meow: 8.1.2 - semver: 6.3.0 - split: 1.0.1 - dev: true - - /conventional-changelog@4.0.0: - resolution: {integrity: sha512-JbZjwE1PzxQCvm+HUTIr+pbSekS8qdOZzMakdFyPtdkEWwFvwEJYONzjgMm0txCb2yBcIcfKDmg8xtCKTdecNQ==} - engines: {node: '>=14'} + conventional-commits-filter: 5.0.0 + handlebars: 4.7.8 + meow: 13.2.0 + semver: 7.7.1 + + conventional-changelog@6.0.0(conventional-commits-filter@5.0.0): dependencies: - conventional-changelog-angular: 6.0.0 - conventional-changelog-atom: 3.0.0 - conventional-changelog-codemirror: 3.0.0 - conventional-changelog-conventionalcommits: 6.0.0 - conventional-changelog-core: 5.0.1 - conventional-changelog-ember: 3.0.0 - conventional-changelog-eslint: 4.0.0 - conventional-changelog-express: 3.0.0 - conventional-changelog-jquery: 4.0.0 - conventional-changelog-jshint: 3.0.0 - conventional-changelog-preset-loader: 3.0.0 - dev: true - - /conventional-commits-filter@3.0.0: - resolution: {integrity: sha512-1ymej8b5LouPx9Ox0Dw/qAO2dVdfpRFq28e5Y0jJEU8ZrLdy0vOSkkIInwmxErFGhg6SALro60ZrwYFVTUDo4Q==} - engines: {node: '>=14'} + conventional-changelog-angular: 8.0.0 + conventional-changelog-atom: 5.0.0 + conventional-changelog-codemirror: 5.0.0 + conventional-changelog-conventionalcommits: 8.0.0 + conventional-changelog-core: 8.0.0(conventional-commits-filter@5.0.0) + conventional-changelog-ember: 5.0.0 + conventional-changelog-eslint: 6.0.0 + conventional-changelog-express: 5.0.0 + conventional-changelog-jquery: 6.0.0 + conventional-changelog-jshint: 5.0.0 + conventional-changelog-preset-loader: 5.0.0 + transitivePeerDependencies: + - conventional-commits-filter + + conventional-commits-filter@5.0.0: {} + + conventional-commits-parser@6.1.0: dependencies: - lodash.ismatch: 4.4.0 - modify-values: 1.0.1 - dev: true + meow: 13.2.0 - /conventional-commits-parser@4.0.0: - resolution: {integrity: sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg==} - engines: {node: '>=14'} - hasBin: true + copy-anything@3.0.5: dependencies: - JSONStream: 1.3.5 - is-text-path: 1.0.1 - meow: 8.1.2 - split2: 3.2.2 - dev: true - - /core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - dev: true - - /cross-spawn@6.0.5: - resolution: {integrity: sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==} - engines: {node: '>=4.8'} - dependencies: - nice-try: 1.0.5 - path-key: 2.0.1 - semver: 5.7.1 - shebang-command: 1.2.0 - which: 1.3.1 - dev: true - - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} + is-what: 4.1.16 + + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - dev: true - - /csstype@3.1.2: - resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} - dev: false - /dargs@7.0.0: - resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==} - engines: {node: '>=8'} - dev: true + crypto-random-string@4.0.0: + dependencies: + type-fest: 1.4.0 - /date-time@3.1.0: - resolution: {integrity: sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==} - engines: {node: '>=6'} + css-select@4.3.0: dependencies: - time-zone: 1.0.0 - dev: true + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 4.3.1 + domutils: 2.8.0 + nth-check: 2.1.1 - /dateformat@3.0.3: - resolution: {integrity: sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==} - dev: true + css-what@6.1.0: {} - /de-indent@1.0.2: - resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} - dev: true + csstype@3.1.3: {} - /debug@2.6.9(supports-color@9.3.1): - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true + de-indent@1.0.2: {} + + debug@4.4.0: dependencies: - ms: 2.0.0 - supports-color: 9.3.1 - dev: true + ms: 2.1.3 - /debug@4.3.4(supports-color@9.3.1): - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true + decode-named-character-reference@1.1.0: dependencies: - ms: 2.1.2 - supports-color: 9.3.1 - dev: true + character-entities: 2.0.2 - /decamelize-keys@1.1.1: - resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} - engines: {node: '>=0.10.0'} + deep-eql@5.0.2: {} + + deepmerge@4.3.1: {} + + default-browser-id@5.0.0: {} + + default-browser@5.2.1: dependencies: - decamelize: 1.2.0 - map-obj: 1.0.1 - dev: true + bundle-name: 4.1.0 + default-browser-id: 5.0.0 - /decamelize@1.2.0: - resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} - engines: {node: '>=0.10.0'} - dev: true + define-lazy-prop@3.0.0: {} - /deep-eql@4.1.3: - resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} - engines: {node: '>=6'} + delayed-stream@1.0.0: {} + + dequal@2.0.3: {} + + detect-libc@2.0.4: {} + + devlop@1.1.0: dependencies: - type-detect: 4.0.8 - dev: true + dequal: 2.0.3 - /deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - dev: true + dom-serializer@1.4.1: + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + entities: 2.2.0 - /defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + domelementtype@2.3.0: {} + + domhandler@3.3.0: dependencies: - clone: 1.0.4 - dev: true + domelementtype: 2.3.0 - /define-properties@1.2.0: - resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} - engines: {node: '>= 0.4'} + domhandler@4.3.1: dependencies: - has-property-descriptors: 1.0.0 - object-keys: 1.1.1 - dev: true + domelementtype: 2.3.0 - /delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - dev: true + domutils@2.8.0: + dependencies: + dom-serializer: 1.4.1 + domelementtype: 2.3.0 + domhandler: 4.3.1 - /dot-prop@5.3.0: - resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} - engines: {node: '>=8'} + dot-prop@5.3.0: dependencies: is-obj: 2.0.0 - dev: true - /eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: true + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: true + eastasianwidth@0.2.0: {} - /emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: true + emoji-regex@10.4.0: {} - /entities@3.0.1: - resolution: {integrity: sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==} - engines: {node: '>=0.12'} - dev: true + emoji-regex@8.0.0: {} - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - dependencies: - is-arrayish: 0.2.1 - dev: true + emoji-regex@9.2.2: {} - /es-abstract@1.21.2: - resolution: {integrity: sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.0 - available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - es-set-tostringtag: 2.0.1 - es-to-primitive: 1.2.1 - function.prototype.name: 1.1.5 - get-intrinsic: 1.2.1 - get-symbol-description: 1.0.0 - globalthis: 1.0.3 - gopd: 1.0.1 - has: 1.0.3 - has-property-descriptors: 1.0.0 - has-proto: 1.0.1 - has-symbols: 1.0.3 - internal-slot: 1.0.5 - is-array-buffer: 3.0.2 - is-callable: 1.2.7 - is-negative-zero: 2.0.2 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.2 - is-string: 1.0.7 - is-typed-array: 1.1.10 - is-weakref: 1.0.2 - object-inspect: 1.12.3 - object-keys: 1.1.1 - object.assign: 4.1.4 - regexp.prototype.flags: 1.5.0 - safe-regex-test: 1.0.0 - string.prototype.trim: 1.2.7 - string.prototype.trimend: 1.0.6 - string.prototype.trimstart: 1.0.6 - typed-array-length: 1.0.4 - unbox-primitive: 1.0.2 - which-typed-array: 1.1.9 - dev: true - - /es-module-lexer@1.2.1: - resolution: {integrity: sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==} - dev: true - - /es-set-tostringtag@2.0.1: - resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} - engines: {node: '>= 0.4'} + entities@2.2.0: {} + + entities@4.5.0: {} + + environment@1.1.0: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-module-lexer@1.7.0: {} + + es-object-atoms@1.1.1: dependencies: - get-intrinsic: 1.2.1 - has: 1.0.3 - has-tostringtag: 1.0.0 - dev: true + es-errors: 1.3.0 - /es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} - engines: {node: '>= 0.4'} + es-set-tostringtag@2.1.0: dependencies: - is-callable: 1.2.7 - is-date-object: 1.0.5 - is-symbol: 1.0.4 - dev: true + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 - /esbuild@0.17.19: - resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true + esbuild@0.25.4: optionalDependencies: - '@esbuild/android-arm': 0.17.19 - '@esbuild/android-arm64': 0.17.19 - '@esbuild/android-x64': 0.17.19 - '@esbuild/darwin-arm64': 0.17.19 - '@esbuild/darwin-x64': 0.17.19 - '@esbuild/freebsd-arm64': 0.17.19 - '@esbuild/freebsd-x64': 0.17.19 - '@esbuild/linux-arm': 0.17.19 - '@esbuild/linux-arm64': 0.17.19 - '@esbuild/linux-ia32': 0.17.19 - '@esbuild/linux-loong64': 0.17.19 - '@esbuild/linux-mips64el': 0.17.19 - '@esbuild/linux-ppc64': 0.17.19 - '@esbuild/linux-riscv64': 0.17.19 - '@esbuild/linux-s390x': 0.17.19 - '@esbuild/linux-x64': 0.17.19 - '@esbuild/netbsd-x64': 0.17.19 - '@esbuild/openbsd-x64': 0.17.19 - '@esbuild/sunos-x64': 0.17.19 - '@esbuild/win32-arm64': 0.17.19 - '@esbuild/win32-ia32': 0.17.19 - '@esbuild/win32-x64': 0.17.19 - - /escalade@3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} - engines: {node: '>=6'} - dev: true + '@esbuild/aix-ppc64': 0.25.4 + '@esbuild/android-arm': 0.25.4 + '@esbuild/android-arm64': 0.25.4 + '@esbuild/android-x64': 0.25.4 + '@esbuild/darwin-arm64': 0.25.4 + '@esbuild/darwin-x64': 0.25.4 + '@esbuild/freebsd-arm64': 0.25.4 + '@esbuild/freebsd-x64': 0.25.4 + '@esbuild/linux-arm': 0.25.4 + '@esbuild/linux-arm64': 0.25.4 + '@esbuild/linux-ia32': 0.25.4 + '@esbuild/linux-loong64': 0.25.4 + '@esbuild/linux-mips64el': 0.25.4 + '@esbuild/linux-ppc64': 0.25.4 + '@esbuild/linux-riscv64': 0.25.4 + '@esbuild/linux-s390x': 0.25.4 + '@esbuild/linux-x64': 0.25.4 + '@esbuild/netbsd-arm64': 0.25.4 + '@esbuild/netbsd-x64': 0.25.4 + '@esbuild/openbsd-arm64': 0.25.4 + '@esbuild/openbsd-x64': 0.25.4 + '@esbuild/sunos-x64': 0.25.4 + '@esbuild/win32-arm64': 0.25.4 + '@esbuild/win32-ia32': 0.25.4 + '@esbuild/win32-x64': 0.25.4 - /escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - dev: true + escalade@3.2.0: {} - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - dev: true + escape-goat@3.0.0: {} - /esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - dev: true + escape-string-regexp@5.0.0: {} - /estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + esm@3.2.25: {} - /esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - dev: true + esprima@4.0.1: {} + + estree-walker@2.0.2: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.7 + + event-target-shim@5.0.1: {} + + eventemitter3@5.0.1: {} + + events@3.3.0: {} - /execa@7.1.1: - resolution: {integrity: sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==} - engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} + execa@8.0.1: dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 4.3.1 + cross-spawn: 7.0.6 + get-stream: 8.0.1 + human-signals: 5.0.0 is-stream: 3.0.0 merge-stream: 2.0.0 - npm-run-path: 5.1.0 + npm-run-path: 5.3.0 onetime: 6.0.0 - signal-exit: 3.0.7 + signal-exit: 4.1.0 strip-final-newline: 3.0.0 - dev: true - /extend-shallow@2.0.1: - resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} - engines: {node: '>=0.10.0'} + execa@9.5.3: + dependencies: + '@sindresorhus/merge-streams': 4.0.0 + cross-spawn: 7.0.6 + figures: 6.1.0 + get-stream: 9.0.1 + human-signals: 8.0.1 + is-plain-obj: 4.1.0 + is-stream: 4.0.1 + npm-run-path: 6.0.0 + pretty-ms: 9.2.0 + signal-exit: 4.1.0 + strip-final-newline: 4.0.0 + yoctocolors: 2.1.1 + + expect-type@1.2.1: {} + + exsolve@1.0.5: {} + + extend-shallow@2.0.1: dependencies: is-extendable: 0.1.1 - dev: true - /fast-diff@1.3.0: - resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} - dev: true + extend@3.0.2: {} - /fast-glob@3.2.12: - resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} - engines: {node: '>=8.6.0'} + fast-glob@3.3.3: dependencies: '@nodelib/fs.stat': 2.0.5 '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.5 - dev: true + micromatch: 4.0.8 - /fastq@1.15.0: - resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + fastq@1.19.1: dependencies: - reusify: 1.0.4 - dev: true + reusify: 1.1.0 - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} + fault@2.0.1: dependencies: - to-regex-range: 5.0.1 - dev: true + format: 0.2.2 - /find-up@2.1.0: - resolution: {integrity: sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==} - engines: {node: '>=4'} - dependencies: - locate-path: 2.0.0 - dev: true + fdir@6.4.4(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 - /find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} + figures@6.1.0: dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - dev: true + is-unicode-supported: 2.1.0 - /find-up@6.3.0: - resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + file-type@18.7.0: dependencies: - locate-path: 7.2.0 - path-exists: 5.0.0 - dev: true + readable-web-to-node-stream: 3.0.4 + strtok3: 7.1.1 + token-types: 5.0.1 - /focus-trap@7.4.3: - resolution: {integrity: sha512-BgSSbK4GPnS2VbtZ50VtOv1Sti6DIkj3+LkVjiWMNjLeAp1SH1UlLx3ULu/DCu4vq5R4/uvTm+zrvsMsuYmGLg==} + fill-range@7.1.1: dependencies: - tabbable: 6.1.2 - dev: false + to-regex-range: 5.0.1 - /follow-redirects@1.15.2(debug@4.3.4): - resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - dependencies: - debug: 4.3.4(supports-color@9.3.1) - dev: true + find-up-simple@1.0.1: {} - /for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + focus-trap@7.6.4: dependencies: - is-callable: 1.2.7 - dev: true + tabbable: 6.2.0 - /foreground-child@3.1.1: - resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} - engines: {node: '>=14'} + follow-redirects@1.15.9(debug@4.4.0): + optionalDependencies: + debug: 4.4.0 + + foreground-child@3.3.1: dependencies: - cross-spawn: 7.0.3 - signal-exit: 4.0.2 - dev: true + cross-spawn: 7.0.6 + signal-exit: 4.1.0 - /form-data@4.0.0: - resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} - engines: {node: '>= 6'} + form-data@4.0.2: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 mime-types: 2.1.35 - dev: true - /fs-extra@11.1.1: - resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==} - engines: {node: '>=14.14'} + format@0.2.2: {} + + fs-extra@11.3.0: dependencies: graceful-fs: 4.2.11 jsonfile: 6.1.0 - universalify: 2.0.0 - dev: true + universalify: 2.0.1 - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true - - /fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true + fsevents@2.3.3: optional: true - /function-bind@1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - dev: true - - /function.prototype.name@1.1.5: - resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - functions-have-names: 1.2.3 - dev: true + function-bind@1.1.2: {} - /functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - dev: true - - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: true + get-caller-file@2.0.5: {} - /get-func-name@2.0.0: - resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==} - dev: true + get-east-asian-width@1.3.0: {} - /get-intrinsic@1.2.1: - resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} + get-intrinsic@1.3.0: dependencies: - function-bind: 1.1.1 - has: 1.0.3 - has-proto: 1.0.1 - has-symbols: 1.0.3 - dev: true + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 - /get-pkg-repo@4.2.1: - resolution: {integrity: sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==} - engines: {node: '>=6.9.0'} - hasBin: true - dependencies: - '@hutson/parse-repository-url': 3.0.2 - hosted-git-info: 4.1.0 - through2: 2.0.5 - yargs: 16.2.0 - dev: true + get-port@7.1.0: {} - /get-port@7.0.0: - resolution: {integrity: sha512-mDHFgApoQd+azgMdwylJrv2DX47ywGq1i5VFJE7fZ0dttNq3iQMfsU4IvEgBHojA3KqEudyu7Vq+oN8kNaNkWw==} - engines: {node: '>=16'} - dev: true + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 - /get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - dev: true + get-stdin@9.0.0: {} - /get-symbol-description@1.0.0: - resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - dev: true + get-stream@8.0.1: {} - /git-raw-commits@3.0.0: - resolution: {integrity: sha512-b5OHmZ3vAgGrDn/X0kS+9qCfNKWe4K/jFnhwzVWWg0/k5eLa3060tZShrRg8Dja5kPc+YjS0Gc6y7cRr44Lpjw==} - engines: {node: '>=14'} - hasBin: true + get-stream@9.0.1: dependencies: - dargs: 7.0.0 - meow: 8.1.2 - split2: 3.2.2 - dev: true + '@sec-ant/readable-stream': 0.4.1 + is-stream: 4.0.1 - /git-remote-origin-url@2.0.0: - resolution: {integrity: sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==} - engines: {node: '>=4'} + get-tsconfig@4.10.0: dependencies: - gitconfiglocal: 1.0.0 - pify: 2.3.0 - dev: true + resolve-pkg-maps: 1.0.0 - /git-semver-tags@5.0.0: - resolution: {integrity: sha512-fZ+tmZ1O5aXW/T5nLzZLbxWAHdQTLLXalOECMNAmhoEQSfqZjtaeMjpsXH4C5qVhrICTkVQeQFujB1lKzIHljA==} - engines: {node: '>=14'} - hasBin: true + git-raw-commits@5.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.1.0): dependencies: - meow: 8.1.2 - semver: 6.3.0 - dev: true + '@conventional-changelog/git-client': 1.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.1.0) + meow: 13.2.0 + transitivePeerDependencies: + - conventional-commits-filter + - conventional-commits-parser - /gitconfiglocal@1.0.0: - resolution: {integrity: sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==} + git-semver-tags@8.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.1.0): dependencies: - ini: 1.3.8 - dev: true + '@conventional-changelog/git-client': 1.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.1.0) + meow: 13.2.0 + transitivePeerDependencies: + - conventional-commits-filter + - conventional-commits-parser - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 - dev: true - - /glob@10.2.7: - resolution: {integrity: sha512-jTKehsravOJo8IJxUGfZILnkvVJM/MOfHRs8QcXolVef2zNI9Tqyy5+SeuOAZd3upViEZQLyFpQhYiHLrMUNmA==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true - dependencies: - foreground-child: 3.1.1 - jackspeak: 2.2.1 - minimatch: 9.0.1 - minipass: 6.0.2 - path-scurry: 1.9.2 - dev: true - /glob@8.1.0: - resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} - engines: {node: '>=12'} + glob@11.0.2: dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 5.1.6 - once: 1.4.0 - dev: true + foreground-child: 3.3.1 + jackspeak: 4.1.0 + minimatch: 10.0.1 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.0 - /globalthis@1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} - engines: {node: '>= 0.4'} - dependencies: - define-properties: 1.2.0 - dev: true + globals@15.15.0: {} - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} - dependencies: - get-intrinsic: 1.2.1 - dev: true + gopd@1.2.0: {} - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - dev: true + graceful-fs@4.2.11: {} - /gray-matter@4.0.3: - resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} - engines: {node: '>=6.0'} + gray-matter@4.0.3: dependencies: js-yaml: 3.14.1 kind-of: 6.0.3 section-matter: 1.0.0 strip-bom-string: 1.0.0 - dev: true - /handlebars@4.7.7: - resolution: {integrity: sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==} - engines: {node: '>=0.4.7'} - hasBin: true + handlebars@4.7.8: dependencies: minimist: 1.2.8 neo-async: 2.6.2 source-map: 0.6.1 wordwrap: 1.0.0 optionalDependencies: - uglify-js: 3.17.4 - dev: true + uglify-js: 3.19.3 - /hard-rejection@2.1.0: - resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} - engines: {node: '>=6'} - dev: true + has-symbols@1.1.0: {} - /has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - dev: true + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - dev: true + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 - /has-property-descriptors@1.0.0: - resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} + hast-util-to-html@9.0.5: dependencies: - get-intrinsic: 1.2.1 - dev: true + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.0 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.4 + zwitch: 2.0.4 - /has-proto@1.0.1: - resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} - engines: {node: '>= 0.4'} - dev: true + hast-util-whitespace@3.0.0: + dependencies: + '@types/hast': 3.0.4 - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - dev: true + he@1.2.0: {} - /has-tostringtag@1.0.0: - resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true + hookable@5.5.3: {} - /has@1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} + hosted-git-info@7.0.2: dependencies: - function-bind: 1.1.1 - dev: true + lru-cache: 10.4.3 - /he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true - dev: true + html-void-elements@3.0.0: {} - /hosted-git-info@2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - dev: true + htmlparser2@5.0.1: + dependencies: + domelementtype: 2.3.0 + domhandler: 3.3.0 + domutils: 2.8.0 + entities: 2.2.0 - /hosted-git-info@4.1.0: - resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} - engines: {node: '>=10'} + htmlparser2@6.1.0: dependencies: - lru-cache: 6.0.0 - dev: true + domelementtype: 2.3.0 + domhandler: 4.3.1 + domutils: 2.8.0 + entities: 2.2.0 - /human-signals@4.3.1: - resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} - engines: {node: '>=14.18.0'} - dev: true + human-signals@5.0.0: {} - /ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - dev: true + human-signals@8.0.1: {} - /indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - dev: true + ieee754@1.2.1: {} + + index-to-position@1.1.0: {} - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + is-core-module@2.16.1: dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: true + hasown: 2.0.2 - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true + is-docker@3.0.0: {} - /ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - dev: true + is-extendable@0.1.1: {} - /internal-slot@1.0.5: - resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.1 - has: 1.0.3 - side-channel: 1.0.4 - dev: true + is-extglob@2.1.1: {} - /is-array-buffer@3.0.2: - resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - is-typed-array: 1.1.10 - dev: true + is-fullwidth-code-point@3.0.0: {} - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true + is-fullwidth-code-point@4.0.0: {} - /is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + is-fullwidth-code-point@5.0.0: dependencies: - has-bigints: 1.0.2 - dev: true + get-east-asian-width: 1.3.0 - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} + is-glob@4.0.3: dependencies: - binary-extensions: 2.2.0 - dev: true + is-extglob: 2.1.1 - /is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} + is-inside-container@1.0.0: dependencies: - call-bind: 1.0.2 - has-tostringtag: 1.0.0 - dev: true + is-docker: 3.0.0 - /is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} - dependencies: - builtin-modules: 3.3.0 - dev: true + is-interactive@2.0.0: {} - /is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - dev: true + is-module@1.0.0: {} - /is-core-module@2.12.1: - resolution: {integrity: sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==} - dependencies: - has: 1.0.3 - dev: true + is-number@7.0.0: {} - /is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true + is-obj@2.0.0: {} - /is-extendable@0.1.1: - resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} - engines: {node: '>=0.10.0'} - dev: true + is-plain-obj@4.1.0: {} - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: true + is-reference@1.2.1: + dependencies: + '@types/estree': 1.0.7 - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: true + is-stream@3.0.0: {} - /is-fullwidth-code-point@4.0.0: - resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} - engines: {node: '>=12'} - dev: true + is-stream@4.0.1: {} - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - dev: true + is-unicode-supported@1.3.0: {} - /is-interactive@2.0.0: - resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} - engines: {node: '>=12'} - dev: true + is-unicode-supported@2.1.0: {} - /is-module@1.0.0: - resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} - dev: true + is-what@4.1.16: {} - /is-negative-zero@2.0.2: - resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} - engines: {node: '>= 0.4'} - dev: true + is-wsl@3.1.0: + dependencies: + is-inside-container: 1.0.0 - /is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} + isexe@2.0.0: {} + + jackspeak@4.1.0: dependencies: - has-tostringtag: 1.0.0 - dev: true + '@isaacs/cliui': 8.0.2 - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true + jiti@1.21.7: {} - /is-obj@2.0.0: - resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} - engines: {node: '>=8'} - dev: true + joi@17.13.3: + dependencies: + '@hapi/hoek': 9.3.0 + '@hapi/topo': 5.1.0 + '@sideway/address': 4.1.5 + '@sideway/formula': 3.0.1 + '@sideway/pinpoint': 2.0.0 - /is-plain-obj@1.1.0: - resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} - engines: {node: '>=0.10.0'} - dev: true + js-tokens@4.0.0: {} - /is-reference@1.2.1: - resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} + js-yaml@3.14.1: dependencies: - '@types/estree': 1.0.1 - dev: true + argparse: 1.0.10 + esprima: 4.0.1 - /is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} + jsonfile@6.1.0: dependencies: - call-bind: 1.0.2 - has-tostringtag: 1.0.0 - dev: true + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 - /is-shared-array-buffer@1.0.2: - resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + juice@8.1.0: dependencies: - call-bind: 1.0.2 - dev: true + cheerio: 1.0.0-rc.10 + commander: 6.2.1 + mensch: 0.3.4 + slick: 1.12.2 + web-resource-inliner: 6.0.1 + transitivePeerDependencies: + - encoding - /is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true + kind-of@6.0.3: {} - /is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true + kleur@3.0.3: {} - /is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true + kolorist@1.8.0: {} - /is-text-path@1.0.1: - resolution: {integrity: sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==} - engines: {node: '>=0.10.0'} - dependencies: - text-extensions: 1.9.0 - dev: true + lightningcss-darwin-arm64@1.30.0: + optional: true - /is-typed-array@1.1.10: - resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.0 - dev: true + lightningcss-darwin-x64@1.30.0: + optional: true - /is-unicode-supported@1.3.0: - resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} - engines: {node: '>=12'} - dev: true + lightningcss-freebsd-x64@1.30.0: + optional: true - /is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - dependencies: - call-bind: 1.0.2 - dev: true + lightningcss-linux-arm-gnueabihf@1.30.0: + optional: true + + lightningcss-linux-arm64-gnu@1.30.0: + optional: true - /isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - dev: true + lightningcss-linux-arm64-musl@1.30.0: + optional: true - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true + lightningcss-linux-x64-gnu@1.30.0: + optional: true + + lightningcss-linux-x64-musl@1.30.0: + optional: true + + lightningcss-win32-arm64-msvc@1.30.0: + optional: true + + lightningcss-win32-x64-msvc@1.30.0: + optional: true + + lightningcss@1.30.0: + dependencies: + detect-libc: 2.0.4 + optionalDependencies: + lightningcss-darwin-arm64: 1.30.0 + lightningcss-darwin-x64: 1.30.0 + lightningcss-freebsd-x64: 1.30.0 + lightningcss-linux-arm-gnueabihf: 1.30.0 + lightningcss-linux-arm64-gnu: 1.30.0 + lightningcss-linux-arm64-musl: 1.30.0 + lightningcss-linux-x64-gnu: 1.30.0 + lightningcss-linux-x64-musl: 1.30.0 + lightningcss-win32-arm64-msvc: 1.30.0 + lightningcss-win32-x64-msvc: 1.30.0 + + lilconfig@3.1.3: {} + + linkify-it@5.0.0: + dependencies: + uc.micro: 2.1.0 + + lint-staged@15.5.2: + dependencies: + chalk: 5.4.1 + commander: 13.1.0 + debug: 4.4.0 + execa: 8.0.1 + lilconfig: 3.1.3 + listr2: 8.3.3 + micromatch: 4.0.8 + pidtree: 0.6.0 + string-argv: 0.3.2 + yaml: 2.7.1 + transitivePeerDependencies: + - supports-color + + listr2@8.3.3: + dependencies: + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.1 + log-update: 6.1.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.0 - /jackspeak@2.2.1: - resolution: {integrity: sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==} - engines: {node: '>=14'} + local-pkg@1.1.1: dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - dev: true + mlly: 1.7.4 + pkg-types: 2.1.0 + quansync: 0.2.10 + + lodash._reinterpolate@3.0.0: {} - /joi@17.9.2: - resolution: {integrity: sha512-Itk/r+V4Dx0V3c7RLFdRh12IOjySm2/WGPMubBT92cQvRfYZhPM2W0hZlctjj72iES8jsRCwp7S/cRmWBnJ4nw==} + lodash.template@4.5.0: dependencies: - '@hapi/hoek': 9.3.0 - '@hapi/topo': 5.1.0 - '@sideway/address': 4.1.4 - '@sideway/formula': 3.0.1 - '@sideway/pinpoint': 2.0.0 - dev: true + lodash._reinterpolate: 3.0.0 + lodash.templatesettings: 4.2.0 - /joycon@3.1.1: - resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} - engines: {node: '>=10'} - dev: true + lodash.templatesettings@4.2.0: + dependencies: + lodash._reinterpolate: 3.0.0 - /js-string-escape@1.0.1: - resolution: {integrity: sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==} - engines: {node: '>= 0.8'} - dev: true + lodash@4.17.21: {} - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: true + log-symbols@6.0.0: + dependencies: + chalk: 5.4.1 + is-unicode-supported: 1.3.0 - /js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true + log-update@6.1.0: dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - dev: true + ansi-escapes: 7.0.0 + cli-cursor: 5.0.0 + slice-ansi: 7.1.0 + strip-ansi: 7.1.0 + wrap-ansi: 9.0.0 - /json-parse-better-errors@1.0.2: - resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==} - dev: true + longest-streak@3.1.0: {} - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true + loupe@3.1.3: {} - /json-stringify-safe@5.0.1: - resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} - dev: true + lru-cache@10.4.3: {} - /jsonc-parser@3.2.0: - resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + lru-cache@11.1.0: {} - /jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + magic-string@0.30.17: dependencies: - universalify: 2.0.0 - optionalDependencies: - graceful-fs: 4.2.11 - dev: true + '@jridgewell/sourcemap-codec': 1.5.0 - /jsonparse@1.3.1: - resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} - engines: {'0': node >= 0.2.0} - dev: true + mark.js@8.11.1: {} - /kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - dev: true + markdown-it-anchor@9.2.0(patch_hash=cdc28e7c329be30688ad192126ba505446611fbe526ad51483e4b1287aa35cf9)(@types/markdown-it@14.1.2)(markdown-it@14.1.0): + dependencies: + '@types/markdown-it': 14.1.2 + markdown-it: 14.1.0 - /kleur@3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} - dev: true + markdown-it-async@2.2.0: + dependencies: + '@types/markdown-it': 14.1.2 + markdown-it: 14.1.0 - /lilconfig@2.1.0: - resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} - engines: {node: '>=10'} - dev: true + markdown-it-attrs@4.3.1(markdown-it@14.1.0): + dependencies: + markdown-it: 14.1.0 + + markdown-it-container@4.0.0: {} - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true + markdown-it-emoji@3.0.0: {} - /linkify-it@4.0.1: - resolution: {integrity: sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==} + markdown-it-mathjax3@4.3.2: dependencies: - uc.micro: 1.0.6 - dev: true + juice: 8.1.0 + mathjax-full: 3.2.2 + transitivePeerDependencies: + - encoding - /lint-staged@13.2.2(supports-color@9.3.1): - resolution: {integrity: sha512-71gSwXKy649VrSU09s10uAT0rWCcY3aewhMaHyl2N84oBk4Xs9HgxvUp3AYu+bNsK4NrOYYxvSgg7FyGJ+jGcA==} - engines: {node: ^14.13.1 || >=16.0.0} - hasBin: true + markdown-it@14.1.0: dependencies: - chalk: 5.2.0 - cli-truncate: 3.1.0 - commander: 10.0.1 - debug: 4.3.4(supports-color@9.3.1) - execa: 7.1.1 - lilconfig: 2.1.0 - listr2: 5.0.8 - micromatch: 4.0.5 - normalize-path: 3.0.0 - object-inspect: 1.12.3 - pidtree: 0.6.0 - string-argv: 0.3.2 - yaml: 2.3.1 + argparse: 2.0.1 + entities: 4.5.0 + linkify-it: 5.0.0 + mdurl: 2.0.0 + punycode.js: 2.3.1 + uc.micro: 2.1.0 + + markdown-title@1.0.2: {} + + math-intrinsics@1.1.0: {} + + mathjax-full@3.2.2: + dependencies: + esm: 3.2.25 + mhchemparser: 4.2.1 + mj-context-menu: 0.6.1 + speech-rule-engine: 4.1.2 + + mdast-util-from-markdown@2.0.2: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + decode-named-character-reference: 1.1.0 + devlop: 1.1.0 + mdast-util-to-string: 4.0.0 + micromark: 4.0.2 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-decode-string: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + unist-util-stringify-position: 4.0.0 transitivePeerDependencies: - - enquirer - supports-color - dev: true - /listr2@5.0.8: - resolution: {integrity: sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA==} - engines: {node: ^14.13.1 || >=16.0.0} - peerDependencies: - enquirer: '>= 2.3.0 < 3' - peerDependenciesMeta: - enquirer: - optional: true + mdast-util-frontmatter@2.0.1: dependencies: - cli-truncate: 2.1.0 - colorette: 2.0.20 - log-update: 4.0.0 - p-map: 4.0.0 - rfdc: 1.3.0 - rxjs: 7.8.1 - through: 2.3.8 - wrap-ansi: 7.0.0 - dev: true + '@types/mdast': 4.0.4 + devlop: 1.1.0 + escape-string-regexp: 5.0.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 + micromark-extension-frontmatter: 2.0.0 + transitivePeerDependencies: + - supports-color - /load-json-file@4.0.0: - resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==} - engines: {node: '>=4'} + mdast-util-phrasing@4.1.0: dependencies: - graceful-fs: 4.2.11 - parse-json: 4.0.0 - pify: 3.0.0 - strip-bom: 3.0.0 - dev: true + '@types/mdast': 4.0.4 + unist-util-is: 6.0.0 - /local-pkg@0.4.3: - resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} - engines: {node: '>=14'} - dev: true - - /locate-path@2.0.0: - resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==} - engines: {node: '>=4'} + mdast-util-to-hast@13.2.0: dependencies: - p-locate: 2.0.0 - path-exists: 3.0.0 - dev: true + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.3.0 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.1 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.3 - /locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} + mdast-util-to-markdown@2.1.2: dependencies: - p-locate: 4.1.0 - dev: true + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + longest-streak: 3.1.0 + mdast-util-phrasing: 4.1.0 + mdast-util-to-string: 4.0.0 + micromark-util-classify-character: 2.0.1 + micromark-util-decode-string: 2.0.1 + unist-util-visit: 5.0.0 + zwitch: 2.0.4 - /locate-path@7.2.0: - resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + mdast-util-to-string@4.0.0: dependencies: - p-locate: 6.0.0 - dev: true + '@types/mdast': 4.0.4 - /lodash._reinterpolate@3.0.0: - resolution: {integrity: sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==} - dev: true + mdurl@2.0.0: {} - /lodash.ismatch@4.4.0: - resolution: {integrity: sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==} - dev: true + mensch@0.3.4: {} - /lodash.template@4.5.0: - resolution: {integrity: sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==} - dependencies: - lodash._reinterpolate: 3.0.0 - lodash.templatesettings: 4.2.0 - dev: true + meow@12.1.1: {} - /lodash.templatesettings@4.2.0: - resolution: {integrity: sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==} - dependencies: - lodash._reinterpolate: 3.0.0 - dev: true + meow@13.2.0: {} - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true + merge-stream@2.0.0: {} - /log-symbols@5.1.0: - resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==} - engines: {node: '>=12'} + merge2@1.4.1: {} + + mhchemparser@4.2.1: {} + + micromark-core-commonmark@2.0.3: dependencies: - chalk: 5.2.0 - is-unicode-supported: 1.3.0 - dev: true + decode-named-character-reference: 1.1.0 + devlop: 1.1.0 + micromark-factory-destination: 2.0.1 + micromark-factory-label: 2.0.1 + micromark-factory-space: 2.0.1 + micromark-factory-title: 2.0.1 + micromark-factory-whitespace: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-html-tag-name: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - /log-update@4.0.0: - resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==} - engines: {node: '>=10'} + micromark-extension-frontmatter@2.0.0: dependencies: - ansi-escapes: 4.3.2 - cli-cursor: 3.1.0 - slice-ansi: 4.0.0 - wrap-ansi: 6.2.0 - dev: true + fault: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - /loupe@2.3.6: - resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} + micromark-factory-destination@2.0.1: dependencies: - get-func-name: 2.0.0 - dev: true + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} + micromark-factory-label@2.0.1: dependencies: - yallist: 4.0.0 - dev: true + devlop: 1.1.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - /lru-cache@9.1.2: - resolution: {integrity: sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==} - engines: {node: 14 || >=16.14} - dev: true + micromark-factory-space@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-types: 2.0.2 - /magic-string@0.27.0: - resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} - engines: {node: '>=12'} + micromark-factory-title@2.0.1: dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - /magic-string@0.30.0: - resolution: {integrity: sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==} - engines: {node: '>=12'} + micromark-factory-whitespace@2.0.1: dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - /map-obj@1.0.1: - resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} - engines: {node: '>=0.10.0'} - dev: true + micromark-util-character@2.1.1: + dependencies: + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - /map-obj@4.3.0: - resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} - engines: {node: '>=8'} - dev: true + micromark-util-chunked@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 - /mark.js@8.11.1: - resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==} - dev: false + micromark-util-classify-character@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - /markdown-it-anchor@8.6.7(@types/markdown-it@12.2.3)(markdown-it@13.0.1): - resolution: {integrity: sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==} - peerDependencies: - '@types/markdown-it': '*' - markdown-it: '*' + micromark-util-combine-extensions@2.0.1: dependencies: - '@types/markdown-it': 12.2.3 - markdown-it: 13.0.1 - dev: true + micromark-util-chunked: 2.0.1 + micromark-util-types: 2.0.2 - /markdown-it-attrs@4.1.6(markdown-it@13.0.1): - resolution: {integrity: sha512-O7PDKZlN8RFMyDX13JnctQompwrrILuz2y43pW2GagcwpIIElkAdfeek+erHfxUOlXWPsjFeWmZ8ch1xtRLWpA==} - engines: {node: '>=6'} - peerDependencies: - markdown-it: '>= 9.0.0' + micromark-util-decode-numeric-character-reference@2.0.2: dependencies: - markdown-it: 13.0.1 - dev: true + micromark-util-symbol: 2.0.1 - /markdown-it-container@3.0.0: - resolution: {integrity: sha512-y6oKTq4BB9OQuY/KLfk/O3ysFhB3IMYoIWhGJEidXt1NQFocFK2sA2t0NYZAMyMShAGL6x5OPIbrmXPIqaN9rw==} - dev: true + micromark-util-decode-string@2.0.1: + dependencies: + decode-named-character-reference: 1.1.0 + micromark-util-character: 2.1.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-symbol: 2.0.1 - /markdown-it-emoji@2.0.2: - resolution: {integrity: sha512-zLftSaNrKuYl0kR5zm4gxXjHaOI3FAOEaloKmRA5hijmJZvSjmxcokOLlzycb/HXlUFWzXqpIEoyEMCE4i9MvQ==} - dev: true + micromark-util-encode@2.0.1: {} - /markdown-it@13.0.1: - resolution: {integrity: sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==} - hasBin: true - dependencies: - argparse: 2.0.1 - entities: 3.0.1 - linkify-it: 4.0.1 - mdurl: 1.0.1 - uc.micro: 1.0.6 - dev: true - - /md5-hex@3.0.1: - resolution: {integrity: sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==} - engines: {node: '>=8'} + micromark-util-html-tag-name@2.0.1: {} + + micromark-util-normalize-identifier@2.0.1: dependencies: - blueimp-md5: 2.19.0 - dev: true + micromark-util-symbol: 2.0.1 - /mdurl@1.0.1: - resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==} - dev: true + micromark-util-resolve-all@2.0.1: + dependencies: + micromark-util-types: 2.0.2 - /memorystream@0.3.1: - resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} - engines: {node: '>= 0.10.0'} - dev: true + micromark-util-sanitize-uri@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 - /meow@8.1.2: - resolution: {integrity: sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==} - engines: {node: '>=10'} + micromark-util-subtokenize@2.1.0: dependencies: - '@types/minimist': 1.2.2 - camelcase-keys: 6.2.2 - decamelize-keys: 1.1.1 - hard-rejection: 2.1.0 - minimist-options: 4.1.0 - normalize-package-data: 3.0.3 - read-pkg-up: 7.0.1 - redent: 3.0.0 - trim-newlines: 3.0.1 - type-fest: 0.18.1 - yargs-parser: 20.2.9 - dev: true - - /merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true + devlop: 1.1.0 + micromark-util-chunked: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: true + micromark-util-symbol@2.0.1: {} - /micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} + micromark-util-types@2.0.2: {} + + micromark@4.0.2: + dependencies: + '@types/debug': 4.1.12 + debug: 4.4.0 + decode-named-character-reference: 1.1.0 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-combine-extensions: 2.0.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-encode: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + transitivePeerDependencies: + - supports-color + + micromatch@4.0.8: dependencies: - braces: 3.0.2 + braces: 3.0.3 picomatch: 2.3.1 - dev: true - /mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - dev: true + millify@6.1.0: + dependencies: + yargs: 17.7.2 - /mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} + mime-db@1.52.0: {} + + mime-types@2.1.35: dependencies: mime-db: 1.52.0 - dev: true - - /mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - dev: true - /mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - dev: true + mime@2.6.0: {} - /min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - dev: true + mimic-fn@4.0.0: {} - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - dev: true + mimic-function@5.0.1: {} - /minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} + minimatch@10.0.1: dependencies: brace-expansion: 2.0.1 - dev: true - /minimatch@9.0.1: - resolution: {integrity: sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==} - engines: {node: '>=16 || 14 >=14.17'} + minimatch@9.0.5: dependencies: brace-expansion: 2.0.1 - dev: true - - /minimist-options@4.1.0: - resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} - engines: {node: '>= 6'} - dependencies: - arrify: 1.0.1 - is-plain-obj: 1.1.0 - kind-of: 6.0.3 - dev: true - - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - dev: true - - /minipass@6.0.2: - resolution: {integrity: sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==} - engines: {node: '>=16 || 14 >=14.17'} - dev: true - /minisearch@6.1.0: - resolution: {integrity: sha512-PNxA/X8pWk+TiqPbsoIYH0GQ5Di7m6326/lwU/S4mlo4wGQddIcf/V//1f9TB0V4j59b57b+HZxt8h3iMROGvg==} - dev: false + minimist@1.2.8: {} - /mlly@1.3.0: - resolution: {integrity: sha512-HT5mcgIQKkOrZecOjOX3DJorTikWXwsBfpcr/MGBkhfWcjiqvnaL/9ppxvIUXfjT6xt4DVIAsN9fMUz1ev4bIw==} - dependencies: - acorn: 8.8.2 - pathe: 1.1.1 - pkg-types: 1.0.3 - ufo: 1.1.2 - dev: true + minipass@7.1.2: {} - /modify-values@1.0.1: - resolution: {integrity: sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==} - engines: {node: '>=0.10.0'} - dev: true + minisearch@7.1.2: {} - /mrmime@1.0.1: - resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==} - engines: {node: '>=10'} - dev: true + mitt@3.0.1: {} - /ms@2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - dev: true + mj-context-menu@0.6.1: {} - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true + mlly@1.7.4: + dependencies: + acorn: 8.14.1 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.1 - /muggle-string@0.2.2: - resolution: {integrity: sha512-YVE1mIJ4VpUMqZObFndk9CJu6DBJR/GB13p3tXuNbwD4XExaI5EOuRl6BHeIDxIqXZVxSfAC+y6U1Z/IxCfKUg==} - dev: true + mrmime@2.0.1: {} - /nanoid@3.3.6: - resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true + ms@2.1.3: {} - /nanoid@4.0.2: - resolution: {integrity: sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==} - engines: {node: ^14 || ^16 || >=18} - hasBin: true - dev: true + muggle-string@0.4.1: {} - /negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} - dev: true + nanoid@3.3.11: {} - /neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - dev: true + nanoid@5.1.5: {} - /nice-try@1.0.5: - resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} - dev: true + neo-async@2.6.2: {} - /normalize-package-data@2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + node-fetch@2.7.0: dependencies: - hosted-git-info: 2.8.9 - resolve: 1.22.2 - semver: 5.7.1 - validate-npm-package-license: 3.0.4 - dev: true + whatwg-url: 5.0.0 - /normalize-package-data@3.0.3: - resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} - engines: {node: '>=10'} + normalize-package-data@6.0.2: dependencies: - hosted-git-info: 4.1.0 - is-core-module: 2.12.1 - semver: 7.5.1 + hosted-git-info: 7.0.2 + semver: 7.7.1 validate-npm-package-license: 3.0.4 - dev: true - - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: true - /npm-run-all@4.1.5: - resolution: {integrity: sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==} - engines: {node: '>= 4'} - hasBin: true - dependencies: - ansi-styles: 3.2.1 - chalk: 2.4.2 - cross-spawn: 6.0.5 - memorystream: 0.3.1 - minimatch: 3.1.2 - pidtree: 0.3.1 - read-pkg: 3.0.0 - shell-quote: 1.8.1 - string.prototype.padend: 3.1.4 - dev: true - - /npm-run-path@5.1.0: - resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + npm-run-path@5.3.0: dependencies: path-key: 4.0.0 - dev: true - - /object-inspect@1.12.3: - resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} - dev: true - - /object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - dev: true - - /object.assign@4.1.4: - resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - has-symbols: 1.0.3 - object-keys: 1.1.1 - dev: true - - /on-headers@1.0.2: - resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} - engines: {node: '>= 0.8'} - dev: true - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + npm-run-path@6.0.0: dependencies: - wrappy: 1.0.2 - dev: true + path-key: 4.0.0 + unicorn-magic: 0.3.0 - /onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} + nth-check@2.1.1: dependencies: - mimic-fn: 2.1.0 - dev: true + boolbase: 1.0.0 - /onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} + onetime@6.0.0: dependencies: mimic-fn: 4.0.0 - dev: true - /ora@6.3.1: - resolution: {integrity: sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - chalk: 5.2.0 - cli-cursor: 4.0.0 - cli-spinners: 2.9.0 - is-interactive: 2.0.0 - is-unicode-supported: 1.3.0 - log-symbols: 5.1.0 - stdin-discarder: 0.1.0 - strip-ansi: 7.1.0 - wcwidth: 1.0.1 - dev: true - - /p-limit@1.3.0: - resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==} - engines: {node: '>=4'} + onetime@7.0.0: dependencies: - p-try: 1.0.0 - dev: true + mimic-function: 5.0.1 - /p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - dependencies: - p-try: 2.2.0 - dev: true + oniguruma-parser@0.12.1: {} - /p-limit@4.0.0: - resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + oniguruma-to-es@4.3.3: dependencies: - yocto-queue: 1.0.0 - dev: true + oniguruma-parser: 0.12.1 + regex: 6.0.1 + regex-recursion: 6.0.2 - /p-locate@2.0.0: - resolution: {integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==} - engines: {node: '>=4'} + open-cli@8.0.0: dependencies: - p-limit: 1.3.0 - dev: true + file-type: 18.7.0 + get-stdin: 9.0.0 + meow: 12.1.1 + open: 10.1.2 + tempy: 3.1.0 - /p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} + open@10.1.2: dependencies: - p-limit: 2.3.0 - dev: true + default-browser: 5.2.1 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + is-wsl: 3.1.0 - /p-locate@6.0.0: - resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + ora@8.2.0: dependencies: - p-limit: 4.0.0 - dev: true + chalk: 5.4.1 + cli-cursor: 5.0.0 + cli-spinners: 2.9.2 + is-interactive: 2.0.0 + is-unicode-supported: 2.1.0 + log-symbols: 6.0.0 + stdin-discarder: 0.2.2 + string-width: 5.1.2 + strip-ansi: 7.1.0 - /p-map@4.0.0: - resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} - engines: {node: '>=10'} - dependencies: - aggregate-error: 3.1.0 - dev: true + oxc-minify@0.69.0: + optionalDependencies: + '@oxc-minify/binding-darwin-arm64': 0.69.0 + '@oxc-minify/binding-darwin-x64': 0.69.0 + '@oxc-minify/binding-freebsd-x64': 0.69.0 + '@oxc-minify/binding-linux-arm-gnueabihf': 0.69.0 + '@oxc-minify/binding-linux-arm64-gnu': 0.69.0 + '@oxc-minify/binding-linux-arm64-musl': 0.69.0 + '@oxc-minify/binding-linux-riscv64-gnu': 0.69.0 + '@oxc-minify/binding-linux-s390x-gnu': 0.69.0 + '@oxc-minify/binding-linux-x64-gnu': 0.69.0 + '@oxc-minify/binding-linux-x64-musl': 0.69.0 + '@oxc-minify/binding-wasm32-wasi': 0.69.0 + '@oxc-minify/binding-win32-arm64-msvc': 0.69.0 + '@oxc-minify/binding-win32-x64-msvc': 0.69.0 - /p-try@1.0.0: - resolution: {integrity: sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==} - engines: {node: '>=4'} - dev: true + p-map@7.0.3: {} - /p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - dev: true + package-json-from-dist@1.0.1: {} - /parse-json@4.0.0: - resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} - engines: {node: '>=4'} - dependencies: - error-ex: 1.3.2 - json-parse-better-errors: 1.0.2 - dev: true + package-manager-detector@1.3.0: {} - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} + parse-json@8.3.0: dependencies: - '@babel/code-frame': 7.21.4 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - dev: true + '@babel/code-frame': 7.27.1 + index-to-position: 1.1.0 + type-fest: 4.41.0 - /path-exists@3.0.0: - resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} - engines: {node: '>=4'} - dev: true + parse-ms@4.0.0: {} - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: true + parse5-htmlparser2-tree-adapter@6.0.1: + dependencies: + parse5: 6.0.1 - /path-exists@5.0.0: - resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true + parse5@6.0.1: {} - /path-key@2.0.1: - resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} - engines: {node: '>=4'} - dev: true + path-browserify@1.0.1: {} - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true + path-key@3.1.1: {} - /path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - dev: true + path-key@4.0.0: {} - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true + path-parse@1.0.7: {} - /path-scurry@1.9.2: - resolution: {integrity: sha512-qSDLy2aGFPm8i4rsbHd4MNyTcrzHFsLQykrtbuGRknZZCBBVXSv2tSCDN2Cg6Rt/GFRw8GoW9y9Ecw5rIPG1sg==} - engines: {node: '>=16 || 14 >=14.17'} + path-scurry@2.0.0: dependencies: - lru-cache: 9.1.2 - minipass: 6.0.2 - dev: true + lru-cache: 11.1.0 + minipass: 7.1.2 - /path-to-regexp@6.2.1: - resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==} - dev: true + path-to-regexp@6.3.0: {} - /path-type@3.0.0: - resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==} - engines: {node: '>=4'} - dependencies: - pify: 3.0.0 - dev: true + pathe@2.0.3: {} - /pathe@1.1.1: - resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==} - dev: true + pathval@2.0.0: {} - /pathval@1.1.1: - resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - dev: true + peek-readable@5.4.2: {} - /picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + perfect-debounce@1.0.0: {} - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true + picocolors@1.1.1: {} - /pidtree@0.3.1: - resolution: {integrity: sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==} - engines: {node: '>=0.10'} - hasBin: true - dev: true + picomatch@2.3.1: {} - /pidtree@0.6.0: - resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} - engines: {node: '>=0.10'} - hasBin: true - dev: true + picomatch@4.0.2: {} - /pify@2.3.0: - resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} - engines: {node: '>=0.10.0'} - dev: true + pidtree@0.6.0: {} - /pify@3.0.0: - resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} - engines: {node: '>=4'} - dev: true + pkg-dir@8.0.0: + dependencies: + find-up-simple: 1.0.1 - /pkg-dir@7.0.0: - resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==} - engines: {node: '>=14.16'} + pkg-types@1.3.1: dependencies: - find-up: 6.3.0 - dev: true + confbox: 0.1.8 + mlly: 1.7.4 + pathe: 2.0.3 - /pkg-types@1.0.3: - resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} + pkg-types@2.1.0: dependencies: - jsonc-parser: 3.2.0 - mlly: 1.3.0 - pathe: 1.1.1 - dev: true + confbox: 0.2.2 + exsolve: 1.0.5 + pathe: 2.0.3 - /playwright-chromium@1.34.3: - resolution: {integrity: sha512-iAvJ7Ab72vRGMab+j2UEqD4xhHf6CzGGntTHeeApsHD/qVDmQUgSE2iKmVeZsNyXMyqrcx83fGsohfq1va01og==} - engines: {node: '>=14'} - hasBin: true - requiresBuild: true + playwright-chromium@1.52.0: dependencies: - playwright-core: 1.34.3 - dev: true + playwright-core: 1.52.0 - /playwright-core@1.34.3: - resolution: {integrity: sha512-2pWd6G7OHKemc5x1r1rp8aQcpvDh7goMBZlJv6Co5vCNLVcQJdhxRL09SGaY6HcyHH9aT4tiynZabMofVasBYw==} - engines: {node: '>=14'} - hasBin: true - dev: true + playwright-core@1.52.0: {} - /polka@1.0.0-next.22: - resolution: {integrity: sha512-a7tsZy5gFbJr0aUltZS97xCkbPglXuD67AMvTyZX7BTDBH384FWf0ZQF6rPvdutSxnO1vUlXM2zSLf5tCKk5RA==} - engines: {node: '>=8'} + polka@1.0.0-next.28: dependencies: - '@polka/url': 1.0.0-next.21 - trouter: 3.2.1 - dev: true + '@polka/url': 1.0.0-next.29 + trouter: 4.0.0 - /postcss@8.4.24: - resolution: {integrity: sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==} - engines: {node: ^10 || ^12 || >=14} + postcss-prefix-selector@2.1.1(postcss@8.5.3): dependencies: - nanoid: 3.3.6 - picocolors: 1.0.0 - source-map-js: 1.0.2 + postcss: 8.5.3 - /preact@10.15.1: - resolution: {integrity: sha512-qs2ansoQEwzNiV5eAcRT1p1EC/dmEzaATVDJNiB3g2sRDWdA7b7MurXdJjB2+/WQktGWZwxvDrnuRFbWuIr64g==} - dev: false + postcss-rtlcss@5.7.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + rtlcss: 4.3.0 - /prettier@2.8.8: - resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} - engines: {node: '>=10.13.0'} - hasBin: true - dev: true + postcss@8.5.3: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + preact@10.26.6: {} + + prettier@3.5.3: {} - /pretty-format@27.5.1: - resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + pretty-ms@9.2.0: dependencies: - ansi-regex: 5.0.1 - ansi-styles: 5.2.0 - react-is: 17.0.2 - dev: true + parse-ms: 4.0.0 - /process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - dev: true + process@0.11.10: {} - /prompts@2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} + prompts@2.4.2: dependencies: kleur: 3.0.3 sisteransi: 1.0.5 - dev: true - /punycode@2.3.0: - resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} - engines: {node: '>=6'} - dev: true + property-information@7.1.0: {} - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true + proxy-from-env@1.1.0: {} - /quick-lru@4.0.1: - resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} - engines: {node: '>=8'} - dev: true + punycode.js@2.3.1: {} - /react-is@17.0.2: - resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} - dev: true + punycode@2.3.1: {} - /read-pkg-up@3.0.0: - resolution: {integrity: sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==} - engines: {node: '>=4'} + quansync@0.2.10: {} + + queue-microtask@1.2.3: {} + + read-package-up@11.0.0: dependencies: - find-up: 2.1.0 - read-pkg: 3.0.0 - dev: true + find-up-simple: 1.0.1 + read-pkg: 9.0.1 + type-fest: 4.41.0 - /read-pkg-up@7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} + read-pkg@9.0.1: dependencies: - find-up: 4.1.0 - read-pkg: 5.2.0 - type-fest: 0.8.1 - dev: true + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 6.0.2 + parse-json: 8.3.0 + type-fest: 4.41.0 + unicorn-magic: 0.1.0 - /read-pkg@3.0.0: - resolution: {integrity: sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==} - engines: {node: '>=4'} + readable-stream@4.7.0: + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + + readable-web-to-node-stream@3.0.4: dependencies: - load-json-file: 4.0.0 - normalize-package-data: 2.5.0 - path-type: 3.0.0 - dev: true + readable-stream: 4.7.0 - /read-pkg@5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} + readdirp@4.1.2: {} + + regex-recursion@6.0.2: dependencies: - '@types/normalize-package-data': 2.4.1 - normalize-package-data: 2.5.0 - parse-json: 5.2.0 - type-fest: 0.6.0 - dev: true - - /readable-stream@2.3.8: - resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - dev: true - - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} + regex-utilities: 2.3.0 + + regex-utilities@2.3.0: {} + + regex@6.0.1: dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - dev: true + regex-utilities: 2.3.0 + + regexparam@3.0.0: {} - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} + remark-frontmatter@5.0.0: dependencies: - picomatch: 2.3.1 - dev: true + '@types/mdast': 4.0.4 + mdast-util-frontmatter: 2.0.1 + micromark-extension-frontmatter: 2.0.0 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color - /redent@3.0.0: - resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} - engines: {node: '>=8'} + remark-parse@11.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.2 + micromark-util-types: 2.0.2 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-stringify@11.0.0: dependencies: - indent-string: 4.0.0 - strip-indent: 3.0.0 - dev: true + '@types/mdast': 4.0.4 + mdast-util-to-markdown: 2.1.2 + unified: 11.0.5 - /regexp.prototype.flags@1.5.0: - resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==} - engines: {node: '>= 0.4'} + remark@15.0.1: dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - functions-have-names: 1.2.3 - dev: true + '@types/mdast': 4.0.4 + remark-parse: 11.0.0 + remark-stringify: 11.0.0 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color - /regexparam@1.3.0: - resolution: {integrity: sha512-6IQpFBv6e5vz1QAqI+V4k8P2e/3gRrqfCJ9FI+O1FLQTO+Uz6RXZEZOPmTJ6hlGj7gkERzY5BRCv09whKP96/g==} - engines: {node: '>=6'} - dev: true + require-directory@2.1.1: {} - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: true + resolve-pkg-maps@1.0.0: {} - /resolve@1.22.2: - resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} - hasBin: true + resolve@1.22.10: dependencies: - is-core-module: 2.12.1 + is-core-module: 2.16.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - dev: true - /restore-cursor@3.1.0: - resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} - engines: {node: '>=8'} + restore-cursor@5.1.0: dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - dev: true + onetime: 7.0.0 + signal-exit: 4.1.0 - /restore-cursor@4.0.0: - resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - dev: true + reusify@1.1.0: {} - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: true + rfdc@1.4.1: {} - /rfdc@1.3.0: - resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} - dev: true + rimraf@6.0.1: + dependencies: + glob: 11.0.2 + package-json-from-dist: 1.0.1 - /rimraf@5.0.1: - resolution: {integrity: sha512-OfFZdwtd3lZ+XZzYP/6gTACubwFcHdLRqS9UX3UwpU2dnGQYkPFISRwvM3w9IiB2w7bW5qGo/uAwE4SmXXSKvg==} - engines: {node: '>=14'} - hasBin: true + rolldown-vite@6.3.9(@types/node@22.15.17)(esbuild@0.25.4)(jiti@1.21.7)(yaml@2.7.1): dependencies: - glob: 10.2.7 - dev: true + '@oxc-project/runtime': 0.69.0 + fdir: 6.4.4(picomatch@4.0.2) + lightningcss: 1.30.0 + picomatch: 4.0.2 + postcss: 8.5.3 + rolldown: 1.0.0-beta.8-commit.8951737(@oxc-project/runtime@0.69.0) + tinyglobby: 0.2.13 + optionalDependencies: + '@types/node': 22.15.17 + esbuild: 0.25.4 + fsevents: 2.3.3 + jiti: 1.21.7 + yaml: 2.7.1 - /rollup-plugin-dts@5.3.0(rollup@3.24.0)(typescript@5.1.3): - resolution: {integrity: sha512-8FXp0ZkyZj1iU5klkIJYLjIq/YZSwBoERu33QBDxm/1yw5UU4txrEtcmMkrq+ZiKu3Q4qvPCNqc3ovX6rjqzbQ==} - engines: {node: '>=v14'} - peerDependencies: - rollup: ^3.0.0 - typescript: ^4.1 || ^5.0 + rolldown@1.0.0-beta.8-commit.8951737(@oxc-project/runtime@0.69.0): dependencies: - magic-string: 0.30.0 - rollup: 3.24.0 - typescript: 5.1.3 + '@oxc-project/types': 0.69.0 + '@rolldown/pluginutils': 1.0.0-beta.8-commit.8951737 + ansis: 4.0.0 optionalDependencies: - '@babel/code-frame': 7.21.4 - dev: true + '@oxc-project/runtime': 0.69.0 + '@rolldown/binding-darwin-arm64': 1.0.0-beta.8-commit.8951737 + '@rolldown/binding-darwin-x64': 1.0.0-beta.8-commit.8951737 + '@rolldown/binding-freebsd-x64': 1.0.0-beta.8-commit.8951737 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.8-commit.8951737 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.8-commit.8951737 + '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.8-commit.8951737 + '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.8-commit.8951737 + '@rolldown/binding-linux-x64-musl': 1.0.0-beta.8-commit.8951737 + '@rolldown/binding-wasm32-wasi': 1.0.0-beta.8-commit.8951737 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.8-commit.8951737 + '@rolldown/binding-win32-ia32-msvc': 1.0.0-beta.8-commit.8951737 + '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.8-commit.8951737 + + rollup-plugin-dts@6.1.1(rollup@4.40.2)(typescript@5.8.3): + dependencies: + magic-string: 0.30.17 + rollup: 4.40.2 + typescript: 5.8.3 + optionalDependencies: + '@babel/code-frame': 7.27.1 - /rollup-plugin-esbuild@5.0.0(esbuild@0.17.19)(rollup@3.24.0)(supports-color@9.3.1): - resolution: {integrity: sha512-1cRIOHAPh8WQgdQQyyvFdeOdxuiyk+zB5zJ5+YOwrZP4cJ0MT3Fs48pQxrZeyZHcn+klFherytILVfE4aYrneg==} - engines: {node: '>=14.18.0', npm: '>=8.0.0'} - peerDependencies: - esbuild: '>=0.10.1' - rollup: ^1.20.0 || ^2.0.0 || ^3.0.0 - dependencies: - '@rollup/pluginutils': 5.0.2(rollup@3.24.0) - debug: 4.3.4(supports-color@9.3.1) - es-module-lexer: 1.2.1 - esbuild: 0.17.19 - joycon: 3.1.1 - jsonc-parser: 3.2.0 - rollup: 3.24.0 + rollup-plugin-esbuild@6.2.1(esbuild@0.25.4)(rollup@4.40.2): + dependencies: + debug: 4.4.0 + es-module-lexer: 1.7.0 + esbuild: 0.25.4 + get-tsconfig: 4.10.0 + rollup: 4.40.2 + unplugin-utils: 0.2.4 transitivePeerDependencies: - supports-color - dev: true - /rollup@3.24.0: - resolution: {integrity: sha512-OgraHOIg2YpHQTjl0/ymWfFNBEyPucB7lmhXrQUh38qNOegxLapSPFs9sNr0qKR75awW41D93XafoR2QfhBdUQ==} - engines: {node: '>=14.18.0', npm: '>=8.0.0'} - hasBin: true + rollup@4.40.2: + dependencies: + '@types/estree': 1.0.7 optionalDependencies: - fsevents: 2.3.2 - - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + '@rollup/rollup-android-arm-eabi': 4.40.2 + '@rollup/rollup-android-arm64': 4.40.2 + '@rollup/rollup-darwin-arm64': 4.40.2 + '@rollup/rollup-darwin-x64': 4.40.2 + '@rollup/rollup-freebsd-arm64': 4.40.2 + '@rollup/rollup-freebsd-x64': 4.40.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.40.2 + '@rollup/rollup-linux-arm-musleabihf': 4.40.2 + '@rollup/rollup-linux-arm64-gnu': 4.40.2 + '@rollup/rollup-linux-arm64-musl': 4.40.2 + '@rollup/rollup-linux-loongarch64-gnu': 4.40.2 + '@rollup/rollup-linux-powerpc64le-gnu': 4.40.2 + '@rollup/rollup-linux-riscv64-gnu': 4.40.2 + '@rollup/rollup-linux-riscv64-musl': 4.40.2 + '@rollup/rollup-linux-s390x-gnu': 4.40.2 + '@rollup/rollup-linux-x64-gnu': 4.40.2 + '@rollup/rollup-linux-x64-musl': 4.40.2 + '@rollup/rollup-win32-arm64-msvc': 4.40.2 + '@rollup/rollup-win32-ia32-msvc': 4.40.2 + '@rollup/rollup-win32-x64-msvc': 4.40.2 + fsevents: 2.3.3 + + rtlcss@4.3.0: + dependencies: + escalade: 3.2.0 + picocolors: 1.1.1 + postcss: 8.5.3 + strip-json-comments: 3.1.1 + + run-applescript@7.0.0: {} + + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 - dev: true - /rxjs@7.8.1: - resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + rxjs@7.8.2: dependencies: - tslib: 2.5.3 - dev: true - - /safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - dev: true + tslib: 2.8.1 - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: true + safe-buffer@5.2.1: {} - /safe-regex-test@1.0.0: - resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - is-regex: 1.1.4 - dev: true + sax@1.4.1: {} - /section-matter@1.0.0: - resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} - engines: {node: '>=4'} + section-matter@1.0.0: dependencies: extend-shallow: 2.0.1 kind-of: 6.0.3 - dev: true - - /semver@5.7.1: - resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} - hasBin: true - dev: true - /semver@6.3.0: - resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} - hasBin: true - dev: true - - /semver@7.5.1: - resolution: {integrity: sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==} - engines: {node: '>=10'} - hasBin: true - dependencies: - lru-cache: 6.0.0 - dev: true - - /shebang-command@1.2.0: - resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} - engines: {node: '>=0.10.0'} - dependencies: - shebang-regex: 1.0.0 - dev: true + semver@7.7.1: {} - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 - dev: true - - /shebang-regex@1.0.0: - resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} - engines: {node: '>=0.10.0'} - dev: true - - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true - - /shell-quote@1.8.1: - resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} - dev: true - /shiki-processor@0.1.3(shiki@0.14.2): - resolution: {integrity: sha512-oZqVFKweklwt+fj6yUPb+ffrCpYYoJ4RYxNt7w1+aoHetHq5ZaN6oX6+4HrypOi0s/O6A2neBpn+Xf6bM4KfsQ==} - peerDependencies: - shiki: 0.x - dependencies: - shiki: 0.14.2 - dev: true - - /shiki@0.14.2: - resolution: {integrity: sha512-ltSZlSLOuSY0M0Y75KA+ieRaZ0Trf5Wl3gutE7jzLuIcWxLp5i/uEnLoQWNvgKXQ5OMpGkJnVMRLAuzjc0LJ2A==} - dependencies: - ansi-sequence-parser: 1.1.0 - jsonc-parser: 3.2.0 - vscode-oniguruma: 1.7.0 - vscode-textmate: 8.0.0 + shebang-regex@3.0.0: {} - /side-channel@1.0.4: - resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + shiki@3.4.0: dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - object-inspect: 1.12.3 - dev: true + '@shikijs/core': 3.4.0 + '@shikijs/engine-javascript': 3.4.0 + '@shikijs/engine-oniguruma': 3.4.0 + '@shikijs/langs': 3.4.0 + '@shikijs/themes': 3.4.0 + '@shikijs/types': 3.4.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 - /siginfo@2.0.0: - resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - dev: true + siginfo@2.0.0: {} - /signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true + signal-exit@4.1.0: {} - /signal-exit@4.0.2: - resolution: {integrity: sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==} - engines: {node: '>=14'} - dev: true + simple-git-hooks@2.13.0: {} - /simple-git-hooks@2.8.1: - resolution: {integrity: sha512-DYpcVR1AGtSfFUNzlBdHrQGPsOhuuEJ/FkmPOOlFysP60AHd3nsEpkGq/QEOdtUyT1Qhk7w9oLmFoMG+75BDog==} - hasBin: true - requiresBuild: true - dev: true + simple-git@3.27.0: + dependencies: + '@kwsites/file-exists': 1.1.1 + '@kwsites/promise-deferred': 1.1.1 + debug: 4.4.0 + transitivePeerDependencies: + - supports-color - /sirv@2.0.3: - resolution: {integrity: sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==} - engines: {node: '>= 10'} + sirv@3.0.1: dependencies: - '@polka/url': 1.0.0-next.21 - mrmime: 1.0.1 + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 totalist: 3.0.1 - dev: true - - /sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - dev: true - /slash@4.0.0: - resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} - engines: {node: '>=12'} - dev: true + sisteransi@1.0.5: {} - /slice-ansi@3.0.0: - resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} - engines: {node: '>=8'} + sitemap@8.0.0: dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 - dev: true + '@types/node': 17.0.45 + '@types/sax': 1.2.7 + arg: 5.0.2 + sax: 1.4.1 - /slice-ansi@4.0.0: - resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} - engines: {node: '>=10'} + slice-ansi@5.0.0: dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 - dev: true + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 - /slice-ansi@5.0.0: - resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} - engines: {node: '>=12'} + slice-ansi@7.1.0: dependencies: ansi-styles: 6.2.1 - is-fullwidth-code-point: 4.0.0 - dev: true + is-fullwidth-code-point: 5.0.0 - /source-map-js@1.0.2: - resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} - engines: {node: '>=0.10.0'} + slick@1.12.2: {} - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: true + source-map-js@1.2.1: {} - /spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + source-map@0.6.1: {} + + space-separated-tokens@2.0.2: {} + + spdx-correct@3.2.0: dependencies: spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.13 - dev: true + spdx-license-ids: 3.0.21 - /spdx-exceptions@2.3.0: - resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} - dev: true + spdx-exceptions@2.5.0: {} - /spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + spdx-expression-parse@3.0.1: dependencies: - spdx-exceptions: 2.3.0 - spdx-license-ids: 3.0.13 - dev: true + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.21 - /spdx-license-ids@3.0.13: - resolution: {integrity: sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==} - dev: true + spdx-license-ids@3.0.21: {} - /split2@3.2.2: - resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} - dependencies: - readable-stream: 3.6.2 - dev: true + speakingurl@14.0.1: {} - /split@1.0.1: - resolution: {integrity: sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==} + speech-rule-engine@4.1.2: dependencies: - through: 2.3.8 - dev: true + '@xmldom/xmldom': 0.9.8 + commander: 13.1.0 + wicked-good-xpath: 1.3.0 - /sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - dev: true + sprintf-js@1.0.3: {} - /stackback@0.0.2: - resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - dev: true + stackback@0.0.2: {} - /std-env@3.3.3: - resolution: {integrity: sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg==} - dev: true + std-env@3.9.0: {} - /stdin-discarder@0.1.0: - resolution: {integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - bl: 5.1.0 - dev: true + stdin-discarder@0.2.2: {} - /string-argv@0.3.2: - resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} - engines: {node: '>=0.6.19'} - dev: true + string-argv@0.3.2: {} - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - dev: true - /string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} + string-width@5.1.2: dependencies: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 strip-ansi: 7.1.0 - dev: true - /string.prototype.padend@3.1.4: - resolution: {integrity: sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw==} - engines: {node: '>= 0.4'} + string-width@7.2.0: dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - dev: true + emoji-regex: 10.4.0 + get-east-asian-width: 1.3.0 + strip-ansi: 7.1.0 - /string.prototype.trim@1.2.7: - resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==} - engines: {node: '>= 0.4'} + string_decoder@1.3.0: dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - dev: true + safe-buffer: 5.2.1 - /string.prototype.trimend@1.0.6: - resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} + stringify-entities@4.0.4: dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - dev: true + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 - /string.prototype.trimstart@1.0.6: - resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} + strip-ansi@6.0.1: dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - dev: true + ansi-regex: 5.0.1 - /string_decoder@1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + strip-ansi@7.1.0: dependencies: - safe-buffer: 5.1.2 - dev: true + ansi-regex: 6.1.0 - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - dependencies: - safe-buffer: 5.2.1 - dev: true + strip-bom-string@1.0.0: {} - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} + strip-final-newline@3.0.0: {} + + strip-final-newline@4.0.0: {} + + strip-json-comments@3.1.1: {} + + strtok3@7.1.1: dependencies: - ansi-regex: 5.0.1 - dev: true + '@tokenizer/token': 0.3.0 + peek-readable: 5.4.2 - /strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} + superjson@2.2.2: dependencies: - ansi-regex: 6.0.1 - dev: true + copy-anything: 3.0.5 - /strip-bom-string@1.0.0: - resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} - engines: {node: '>=0.10.0'} - dev: true + supports-preserve-symlinks-flag@1.0.0: {} - /strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - dev: true + tabbable@6.2.0: {} - /strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - dev: true + temp-dir@3.0.0: {} - /strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} + tempfile@5.0.0: dependencies: - min-indent: 1.0.1 - dev: true + temp-dir: 3.0.0 - /strip-literal@1.0.1: - resolution: {integrity: sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==} + tempy@3.1.0: dependencies: - acorn: 8.8.2 - dev: true + is-stream: 3.0.0 + temp-dir: 3.0.0 + type-fest: 2.19.0 + unique-string: 3.0.0 - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - dev: true + tinybench@2.9.0: {} - /supports-color@9.3.1: - resolution: {integrity: sha512-knBY82pjmnIzK3NifMo3RxEIRD9E0kIzV4BKcyTZ9+9kWgLMxd4PrsTSMoFQUabgRBbF8KOLRDCyKgNV+iK44Q==} - engines: {node: '>=12'} - dev: true + tinyexec@0.3.2: {} - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: true + tinyexec@1.0.1: {} - /tabbable@6.1.2: - resolution: {integrity: sha512-qCN98uP7i9z0fIS4amQ5zbGBOq+OSigYeGvPy7NDk8Y9yncqDZ9pRPgfsc2PJIVM9RrJj7GIfuRgmjoUU9zTHQ==} - dev: false + tinyglobby@0.2.13: + dependencies: + fdir: 6.4.4(picomatch@4.0.2) + picomatch: 4.0.2 - /temp-dir@2.0.0: - resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} - engines: {node: '>=8'} - dev: true + tinypool@1.0.2: {} - /tempfile@3.0.0: - resolution: {integrity: sha512-uNFCg478XovRi85iD42egu+eSFUmmka750Jy7L5tfHI5hQKKtbPnxaSaXAbBqCDYrw3wx4tXjKwci4/QmsZJxw==} - engines: {node: '>=8'} - dependencies: - temp-dir: 2.0.0 - uuid: 3.4.0 - dev: true + tinyrainbow@2.0.0: {} - /text-extensions@1.9.0: - resolution: {integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==} - engines: {node: '>=0.10'} - dev: true + tinyspy@3.0.2: {} - /through2@2.0.5: - resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} + to-regex-range@5.0.1: dependencies: - readable-stream: 2.3.8 - xtend: 4.0.2 - dev: true + is-number: 7.0.0 - /through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - dev: true + token-types@5.0.1: + dependencies: + '@tokenizer/token': 0.3.0 + ieee754: 1.2.1 - /time-zone@1.0.0: - resolution: {integrity: sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==} - engines: {node: '>=4'} - dev: true + tokenx@0.4.1: {} - /tinybench@2.5.0: - resolution: {integrity: sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==} - dev: true + totalist@3.0.1: {} - /tinypool@0.5.0: - resolution: {integrity: sha512-paHQtnrlS1QZYKF/GnLoOM/DN9fqaGOFbCbxzAhwniySnzl9Ebk8w73/dd34DAhe/obUbPAOldTyYXQZxnPBPQ==} - engines: {node: '>=14.0.0'} - dev: true + tr46@0.0.3: {} - /tinyspy@2.1.1: - resolution: {integrity: sha512-XPJL2uSzcOyBMky6OFrusqWlzfFrXtE0hPuMgW8A2HmaqrPo4ZQHRN/V0QXN3FSjKxpsbRrFc5LI7KOwBsT1/w==} - engines: {node: '>=14.0.0'} - dev: true + trim-lines@3.0.1: {} - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} + trough@2.2.0: {} - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} + trouter@4.0.0: dependencies: - is-number: 7.0.0 - dev: true + regexparam: 3.0.0 - /totalist@3.0.1: - resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} - engines: {node: '>=6'} - dev: true + tslib@2.8.1: {} - /trim-newlines@3.0.1: - resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} - engines: {node: '>=8'} - dev: true + type-fest@1.4.0: {} - /trouter@3.2.1: - resolution: {integrity: sha512-oY3CmIiEYOe1YMEzh++I67lrNOUldtCeuLL0vRPydvQLHZpSJ03B5dgDFlpFsiriMq6e//NDjjopjUzXOztHow==} - engines: {node: '>=6'} - dependencies: - regexparam: 1.3.0 - dev: true + type-fest@2.19.0: {} - /tslib@2.5.3: - resolution: {integrity: sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==} - dev: true + type-fest@4.41.0: {} - /type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - dev: true + typescript@5.8.3: {} - /type-fest@0.18.1: - resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} - engines: {node: '>=10'} - dev: true + uc.micro@2.1.0: {} - /type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - dev: true + ufo@1.6.1: {} - /type-fest@0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - dev: true + uglify-js@3.19.3: + optional: true - /type-fest@0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - dev: true + ultramatter@0.0.4: {} - /typed-array-length@1.0.4: - resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + undici-types@6.21.0: {} + + unicorn-magic@0.1.0: {} + + unicorn-magic@0.3.0: {} + + unified@11.0.5: dependencies: - call-bind: 1.0.2 - for-each: 0.3.3 - is-typed-array: 1.1.10 - dev: true + '@types/unist': 3.0.3 + bail: 2.0.2 + devlop: 1.1.0 + extend: 3.0.2 + is-plain-obj: 4.1.0 + trough: 2.2.0 + vfile: 6.0.3 - /typescript@5.1.3: - resolution: {integrity: sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==} - engines: {node: '>=14.17'} - hasBin: true - dev: true + unique-string@3.0.0: + dependencies: + crypto-random-string: 4.0.0 - /uc.micro@1.0.6: - resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} - dev: true + unist-util-is@6.0.0: + dependencies: + '@types/unist': 3.0.3 - /ufo@1.1.2: - resolution: {integrity: sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==} - dev: true + unist-util-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 - /uglify-js@3.17.4: - resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} - engines: {node: '>=0.8.0'} - hasBin: true - requiresBuild: true - dev: true - optional: true + unist-util-remove@4.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 - /unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + unist-util-stringify-position@4.0.0: dependencies: - call-bind: 1.0.2 - has-bigints: 1.0.2 - has-symbols: 1.0.3 - which-boxed-primitive: 1.0.2 - dev: true + '@types/unist': 3.0.3 - /universalify@2.0.0: - resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} - engines: {node: '>= 10.0.0'} - dev: true + unist-util-visit-parents@6.0.1: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.0 - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: true + unist-util-visit@5.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 - /uuid@3.4.0: - resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} - deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. - hasBin: true - dev: true + universalify@2.0.1: {} - /validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + unplugin-utils@0.2.4: + dependencies: + pathe: 2.0.3 + picomatch: 4.0.2 + + valid-data-url@3.0.1: {} + + validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - dev: true - /vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} - dev: true + vfile-message@4.0.2: + dependencies: + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 - /vite-node@0.32.0(@types/node@20.2.5)(supports-color@9.3.1): - resolution: {integrity: sha512-220P/y8YacYAU+daOAqiGEFXx2A8AwjadDzQqos6wSukjvvTWNqleJSwoUn0ckyNdjHIKoxn93Nh1vWBqEKr3Q==} - engines: {node: '>=v14.18.0'} - hasBin: true + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile-message: 4.0.2 + + vite-node@3.1.3(@types/node@22.15.17)(esbuild@0.25.4)(jiti@1.21.7)(yaml@2.7.1): dependencies: cac: 6.7.14 - debug: 4.3.4(supports-color@9.3.1) - mlly: 1.3.0 - pathe: 1.1.1 - picocolors: 1.0.0 - vite: 4.3.9(@types/node@20.2.5) + debug: 4.4.0 + es-module-lexer: 1.7.0 + pathe: 2.0.3 + vite: rolldown-vite@6.3.9(@types/node@22.15.17)(esbuild@0.25.4)(jiti@1.21.7)(yaml@2.7.1) transitivePeerDependencies: - '@types/node' + - esbuild + - jiti - less - sass + - sass-embedded - stylus - sugarss - supports-color - terser - dev: true + - tsx + - yaml - /vite@4.3.9(@types/node@20.2.5): - resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==} - engines: {node: ^14.18.0 || >=16.0.0} - hasBin: true - peerDependencies: - '@types/node': '>= 14' - less: '*' - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true + vite@6.3.5(@types/node@22.15.17)(jiti@1.21.7)(lightningcss@1.30.0)(yaml@2.7.1): dependencies: - '@types/node': 20.2.5 - esbuild: 0.17.19 - postcss: 8.4.24 - rollup: 3.24.0 + esbuild: 0.25.4 + fdir: 6.4.4(picomatch@4.0.2) + picomatch: 4.0.2 + postcss: 8.5.3 + rollup: 4.40.2 + tinyglobby: 0.2.13 optionalDependencies: - fsevents: 2.3.2 + '@types/node': 22.15.17 + fsevents: 2.3.3 + jiti: 1.21.7 + lightningcss: 1.30.0 + yaml: 2.7.1 - /vitest@0.32.0(supports-color@9.3.1): - resolution: {integrity: sha512-SW83o629gCqnV3BqBnTxhB10DAwzwEx3z+rqYZESehUB+eWsJxwcBQx7CKy0otuGMJTYh7qCVuUX23HkftGl/Q==} - engines: {node: '>=v14.18.0'} - hasBin: true - peerDependencies: - '@edge-runtime/vm': '*' - '@vitest/browser': '*' - '@vitest/ui': '*' - happy-dom: '*' - jsdom: '*' - playwright: '*' - safaridriver: '*' - webdriverio: '*' - peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@vitest/browser': - optional: true - '@vitest/ui': - optional: true - happy-dom: - optional: true - jsdom: - optional: true - playwright: - optional: true - safaridriver: - optional: true - webdriverio: - optional: true + vitepress-plugin-group-icons@1.5.2: dependencies: - '@types/chai': 4.3.5 - '@types/chai-subset': 1.3.3 - '@types/node': 20.2.5 - '@vitest/expect': 0.32.0 - '@vitest/runner': 0.32.0 - '@vitest/snapshot': 0.32.0 - '@vitest/spy': 0.32.0 - '@vitest/utils': 0.32.0 - acorn: 8.8.2 - acorn-walk: 8.2.0 - cac: 6.7.14 - chai: 4.3.7 - concordance: 5.0.4 - debug: 4.3.4(supports-color@9.3.1) - local-pkg: 0.4.3 - magic-string: 0.30.0 - pathe: 1.1.1 - picocolors: 1.0.0 - std-env: 3.3.3 - strip-literal: 1.0.1 - tinybench: 2.5.0 - tinypool: 0.5.0 - vite: 4.3.9(@types/node@20.2.5) - vite-node: 0.32.0(@types/node@20.2.5)(supports-color@9.3.1) - why-is-node-running: 2.2.2 + '@iconify-json/logos': 1.2.4 + '@iconify-json/vscode-icons': 1.2.20 + '@iconify/utils': 2.3.0 transitivePeerDependencies: + - supports-color + + vitepress-plugin-llms@1.1.3: + dependencies: + byte-size: 9.0.1 + gray-matter: 4.0.3 + markdown-title: 1.0.2 + millify: 6.1.0 + minimatch: 10.0.1 + picocolors: 1.1.1 + remark: 15.0.1 + remark-frontmatter: 5.0.0 + tokenx: 0.4.1 + unist-util-remove: 4.0.0 + transitivePeerDependencies: + - '@75lb/nature' + - supports-color + + vitest@3.1.3(@types/debug@4.1.12)(@types/node@22.15.17)(esbuild@0.25.4)(jiti@1.21.7)(yaml@2.7.1): + dependencies: + '@vitest/expect': 3.1.3 + '@vitest/mocker': 3.1.3(rolldown-vite@6.3.9(@types/node@22.15.17)(esbuild@0.25.4)(jiti@1.21.7)(yaml@2.7.1)) + '@vitest/pretty-format': 3.1.3 + '@vitest/runner': 3.1.3 + '@vitest/snapshot': 3.1.3 + '@vitest/spy': 3.1.3 + '@vitest/utils': 3.1.3 + chai: 5.2.0 + debug: 4.4.0 + expect-type: 1.2.1 + magic-string: 0.30.17 + pathe: 2.0.3 + std-env: 3.9.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.13 + tinypool: 1.0.2 + tinyrainbow: 2.0.0 + vite: rolldown-vite@6.3.9(@types/node@22.15.17)(esbuild@0.25.4)(jiti@1.21.7)(yaml@2.7.1) + vite-node: 3.1.3(@types/node@22.15.17)(esbuild@0.25.4)(jiti@1.21.7)(yaml@2.7.1) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/debug': 4.1.12 + '@types/node': 22.15.17 + transitivePeerDependencies: + - esbuild + - jiti - less + - msw - sass + - sass-embedded - stylus - sugarss - supports-color - terser - dev: true - - /vscode-oniguruma@1.7.0: - resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} - - /vscode-textmate@8.0.0: - resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} - - /vue-demi@0.14.5(vue@3.3.4): - resolution: {integrity: sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - peerDependencies: - '@vue/composition-api': ^1.0.0-rc.1 - vue: ^3.0.0-0 || ^2.6.0 - peerDependenciesMeta: - '@vue/composition-api': - optional: true - dependencies: - vue: 3.3.4 - dev: false + - tsx + - yaml - /vue-template-compiler@2.7.14: - resolution: {integrity: sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==} - dependencies: - de-indent: 1.0.2 - he: 1.2.0 - dev: true + vscode-uri@3.1.0: {} - /vue-tsc@1.6.5(typescript@5.1.3): - resolution: {integrity: sha512-Wtw3J7CC+JM2OR56huRd5iKlvFWpvDiU+fO1+rqyu4V2nMTotShz4zbOZpW5g9fUOcjnyZYfBo5q5q+D/q27JA==} - hasBin: true - peerDependencies: - typescript: '*' + vue-tsc@3.0.0-alpha.6(typescript@5.8.3): dependencies: - '@volar/vue-language-core': 1.6.5 - '@volar/vue-typescript': 1.6.5(typescript@5.1.3) - semver: 7.5.1 - typescript: 5.1.3 - dev: true + '@volar/typescript': 2.4.13 + '@vue/language-core': 3.0.0-alpha.6(typescript@5.8.3) + typescript: 5.8.3 - /vue@3.3.4: - resolution: {integrity: sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==} + vue@3.5.13(typescript@5.8.3): dependencies: - '@vue/compiler-dom': 3.3.4 - '@vue/compiler-sfc': 3.3.4 - '@vue/runtime-dom': 3.3.4 - '@vue/server-renderer': 3.3.4(vue@3.3.4) - '@vue/shared': 3.3.4 - dev: false + '@vue/compiler-dom': 3.5.13 + '@vue/compiler-sfc': 3.5.13 + '@vue/runtime-dom': 3.5.13 + '@vue/server-renderer': 3.5.13(vue@3.5.13(typescript@5.8.3)) + '@vue/shared': 3.5.13 + optionalDependencies: + typescript: 5.8.3 - /wait-on@7.0.1(debug@4.3.4): - resolution: {integrity: sha512-9AnJE9qTjRQOlTZIldAaf/da2eW0eSRSgcqq85mXQja/DW3MriHxkpODDSUEg+Gri/rKEcXUZHe+cevvYItaog==} - engines: {node: '>=12.0.0'} - hasBin: true + wait-on@8.0.3(debug@4.4.0): dependencies: - axios: 0.27.2(debug@4.3.4) - joi: 17.9.2 + axios: 1.9.0(debug@4.4.0) + joi: 17.13.3 lodash: 4.17.21 minimist: 1.2.8 - rxjs: 7.8.1 + rxjs: 7.8.2 transitivePeerDependencies: - debug - dev: true - - /wcwidth@1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - dependencies: - defaults: 1.0.4 - dev: true - - /well-known-symbols@2.0.0: - resolution: {integrity: sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==} - engines: {node: '>=6'} - dev: true - /which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + web-resource-inliner@6.0.1: dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 - dev: true + ansi-colors: 4.1.3 + escape-goat: 3.0.0 + htmlparser2: 5.0.1 + mime: 2.6.0 + node-fetch: 2.7.0 + valid-data-url: 3.0.1 + transitivePeerDependencies: + - encoding - /which-typed-array@1.1.9: - resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.0 - is-typed-array: 1.1.10 - dev: true + webidl-conversions@3.0.1: {} - /which@1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} - hasBin: true + whatwg-url@5.0.0: dependencies: - isexe: 2.0.0 - dev: true + tr46: 0.0.3 + webidl-conversions: 3.0.1 - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true + which@2.0.2: dependencies: isexe: 2.0.0 - dev: true - /why-is-node-running@2.2.2: - resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} - engines: {node: '>=8'} - hasBin: true + why-is-node-running@2.3.0: dependencies: siginfo: 2.0.0 stackback: 0.0.2 - dev: true - /wordwrap@1.0.0: - resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - dev: true + wicked-good-xpath@1.3.0: {} - /wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true + wordwrap@1.0.0: {} - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: true - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} + wrap-ansi@8.1.0: dependencies: ansi-styles: 6.2.1 string-width: 5.1.2 strip-ansi: 7.1.0 - dev: true - - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true - /xtend@4.0.2: - resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} - engines: {node: '>=0.4'} - dev: true - - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: true + wrap-ansi@9.0.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 7.2.0 + strip-ansi: 7.1.0 - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true + y18n@5.0.8: {} - /yaml@2.3.1: - resolution: {integrity: sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==} - engines: {node: '>= 14'} - dev: true + yaml@2.7.1: {} - /yargs-parser@20.2.9: - resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} - engines: {node: '>=10'} - dev: true + yargs-parser@21.1.1: {} - /yargs@16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} + yargs@17.7.2: dependencies: - cliui: 7.0.4 - escalade: 3.1.1 + cliui: 8.0.1 + escalade: 3.2.0 get-caller-file: 2.0.5 require-directory: 2.1.1 string-width: 4.2.3 y18n: 5.0.8 - yargs-parser: 20.2.9 - dev: true + yargs-parser: 21.1.1 - /yocto-queue@1.0.0: - resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} - engines: {node: '>=12.20'} - dev: true + yoctocolors@2.1.1: {} + + zod@3.24.4: {} + + zwitch@2.0.4: {} diff --git a/rollup.config.ts b/rollup.config.ts index 1a5ec684..77a2a610 100644 --- a/rollup.config.ts +++ b/rollup.config.ts @@ -1,15 +1,13 @@ -import { promises as fs } from 'fs' -import { builtinModules, createRequire } from 'module' -import { resolve } from 'path' -import { fileURLToPath } from 'url' -import { type RollupOptions, defineConfig } from 'rollup' -import { nodeResolve } from '@rollup/plugin-node-resolve' +import alias from '@rollup/plugin-alias' import commonjs from '@rollup/plugin-commonjs' -import esbuild from 'rollup-plugin-esbuild' import json from '@rollup/plugin-json' +import { nodeResolve } from '@rollup/plugin-node-resolve' import replace from '@rollup/plugin-replace' -import alias from '@rollup/plugin-alias' +import * as fs from 'node:fs/promises' +import { builtinModules, createRequire } from 'node:module' +import { type RollupOptions, defineConfig } from 'rollup' import dts from 'rollup-plugin-dts' +import esbuild from 'rollup-plugin-esbuild' const require = createRequire(import.meta.url) const pkg = require('./package.json') @@ -17,23 +15,16 @@ const pkg = require('./package.json') const DEV = !!process.env.DEV const PROD = !DEV -const ROOT = fileURLToPath(import.meta.url) -const r = (p: string) => resolve(ROOT, '..', p) - const external = [ ...Object.keys(pkg.dependencies), + ...Object.keys(pkg.peerDependencies), ...builtinModules.flatMap((m) => m.includes('punycode') ? [] : [m, `node:${m}`] - ), - r('types/shared.d.ts') + ) ] const plugins = [ - alias({ - entries: { - 'readable-stream': 'stream' - } - }), + alias({ entries: { 'readable-stream': 'stream' } }), replace({ // polyfill broken browser check from bundled deps 'navigator.userAgentData': 'undefined', @@ -42,17 +33,17 @@ const plugins = [ }), commonjs(), nodeResolve({ preferBuiltins: false }), - esbuild({ target: 'node14' }), + esbuild({ target: 'node18' }), json() ] const esmBuild: RollupOptions = { - input: [r('src/node/index.ts'), r('src/node/cli.ts')], + input: ['src/node/index.ts', 'src/node/cli.ts'], output: { format: 'esm', entryFileNames: `[name].js`, - chunkFileNames: 'serve-[hash].js', - dir: r('dist/node'), + chunkFileNames: 'chunk-[hash].js', + dir: 'dist/node', sourcemap: DEV }, external, @@ -62,60 +53,47 @@ const esmBuild: RollupOptions = { } } -const cjsBuild: RollupOptions = { - input: [r('src/node/index.ts'), r('src/node/cli.ts')], - output: { - format: 'cjs', - dir: r('dist/node-cjs'), - entryFileNames: `[name].cjs`, - chunkFileNames: 'serve-[hash].cjs' - }, - external, - plugins, - onwarn(warning, warn) { - if (warning.code !== 'EVAL') warn(warning) - } -} +const typesExternal = [ + ...external, + /\/vitepress\/(?!(dist|node_modules|vitepress)\/).*\.d\.ts$/, + 'source-map-js', + 'fast-glob' +] + +const dtsNode = dts({ + respectExternal: true, + tsconfig: 'src/node/tsconfig.json', + compilerOptions: { preserveSymlinks: false } +}) const nodeTypes: RollupOptions = { - input: r('src/node/index.ts'), + input: 'src/node/index.ts', output: { format: 'esm', file: 'dist/node/index.d.ts' }, - external, - plugins: [dts({ respectExternal: true })] + external: typesExternal, + plugins: [dtsNode] } const clientTypes: RollupOptions = { - input: r('dist/client-types/index.d.ts'), + input: 'dist/client-types/index.d.ts', output: { format: 'esm', file: 'dist/client/index.d.ts' }, - external, + external: typesExternal, plugins: [ dts({ respectExternal: true }), { name: 'cleanup', async closeBundle() { if (PROD) { - await fs.rm(r('dist/client-types'), { recursive: true }) + await fs.rm('dist/client-types', { recursive: true }) } } } ] } -const config = defineConfig([]) - -config.push(esmBuild) - -if (PROD) { - config.push(cjsBuild) -} - -config.push(nodeTypes) -config.push(clientTypes) - -export default config +export default defineConfig([esmBuild, nodeTypes, clientTypes]) diff --git a/scripts/copyClient.js b/scripts/copyClient.js index 44360e28..465be10c 100644 --- a/scripts/copyClient.js +++ b/scripts/copyClient.js @@ -1,11 +1,11 @@ import { copy } from 'fs-extra' -import fg from 'fast-glob' +import { globSync } from 'tinyglobby' function toDest(file) { return file.replace(/^src\//, 'dist/') } -fg.sync('src/client/**').forEach((file) => { +globSync(['src/client/**']).forEach((file) => { if (/(\.ts|tsconfig\.json)$/.test(file)) return copy(file, toDest(file)) }) diff --git a/scripts/copyShared.js b/scripts/copyShared.js index 465f2853..af73c48e 100644 --- a/scripts/copyShared.js +++ b/scripts/copyShared.js @@ -1,7 +1,7 @@ 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([ copy(file, file.replace(/^src\/shared\//, 'src/node/')), copy(file, file.replace(/^src\/shared\//, 'src/client/')) diff --git a/scripts/release.js b/scripts/release.js index 8968f4d2..5ac16c98 100644 --- a/scripts/release.js +++ b/scripts/release.js @@ -1,7 +1,7 @@ -import { readFileSync, writeFileSync } from 'fs' -import { resolve } from 'path' -import { fileURLToPath } from 'url' -import { createRequire } from 'module' +import { readFileSync, writeFileSync } from 'node:fs' +import { resolve } from 'node:path' +import { fileURLToPath } from 'node:url' +import { createRequire } from 'node:module' import c from 'picocolors' import prompts from 'prompts' import { execa } from 'execa' diff --git a/scripts/watchAndCopy.js b/scripts/watchAndCopy.js index 58c3b421..c66085f8 100644 --- a/scripts/watchAndCopy.js +++ b/scripts/watchAndCopy.js @@ -1,5 +1,5 @@ -import { copy, remove } from 'fs-extra' import { watch } from 'chokidar' +import { copy, remove } from 'fs-extra' import { normalizePath } from 'vite' function toClientAndNode(method, file) { @@ -18,14 +18,19 @@ function toDist(file) { } // copy shared files to the client and node directory whenever they change. -watch('src/shared/**/*.ts') +watch('src/shared', { + ignored: (path, stats) => stats?.isFile() && !path.endsWith('.ts') +}) .on('change', (file) => toClientAndNode('copy', file)) .on('add', (file) => toClientAndNode('copy', file)) .on('unlink', (file) => toClientAndNode('remove', file)) // copy non ts files, such as an html or css, to the dist directory whenever // they change. -watch('src/client/**/!(*.ts|tsconfig.json)') +watch('src/client', { + ignored: (path, stats) => + stats?.isFile() && (path.endsWith('.ts') || path.endsWith('tsconfig.json')) +}) .on('change', (file) => copy(file, toDist(file))) .on('add', (file) => copy(file, toDist(file))) .on('unlink', (file) => remove(toDist(file))) diff --git a/src/client/app/components/ClientOnly.ts b/src/client/app/components/ClientOnly.ts index e7b1f17e..680094ce 100644 --- a/src/client/app/components/ClientOnly.ts +++ b/src/client/app/components/ClientOnly.ts @@ -1,4 +1,4 @@ -import { defineComponent, ref, onMounted } from 'vue' +import { defineComponent, onMounted, ref } from 'vue' export const ClientOnly = defineComponent({ setup(_, { slots }) { diff --git a/src/client/app/components/Content.ts b/src/client/app/components/Content.ts index 4752554e..12456451 100644 --- a/src/client/app/components/Content.ts +++ b/src/client/app/components/Content.ts @@ -1,5 +1,5 @@ -import { defineComponent, h } from 'vue' -import { useRoute } from '../router' +import { useData, useRoute } from 'vitepress' +import { defineComponent, h, watch } from 'vue' import { contentUpdatedCallbacks } from '../utils' const runCbs = () => contentUpdatedCallbacks.forEach((fn) => fn()) @@ -11,14 +11,21 @@ export const Content = defineComponent({ }, setup(props) { const route = useRoute() + const { frontmatter, site } = useData() + watch(frontmatter, runCbs, { deep: true, flush: 'post' }) return () => - h(props.as, { style: { position: 'relative' } }, [ - route.component - ? h(route.component, { - onVnodeMounted: runCbs, - onVnodeUpdated: runCbs - }) - : '404 Page Not Found' - ]) + h( + props.as, + site.value.contentProps ?? { style: { position: 'relative' } }, + [ + route.component + ? h(route.component, { + onVnodeMounted: runCbs, + onVnodeUpdated: runCbs, + onVnodeUnmounted: runCbs + }) + : '404 Page Not Found' + ] + ) } }) diff --git a/src/client/app/composables/codeGroups.ts b/src/client/app/composables/codeGroups.ts index e4bd5c5c..d8a38ba7 100644 --- a/src/client/app/composables/codeGroups.ts +++ b/src/client/app/composables/codeGroups.ts @@ -1,6 +1,17 @@ -import { inBrowser } from 'vitepress' +import { inBrowser, onContentUpdated } from 'vitepress' export function useCodeGroups() { + if (import.meta.env.DEV) { + onContentUpdated(() => { + document.querySelectorAll('.vp-code-group > .blocks').forEach((el) => { + Array.from(el.children).forEach((child) => { + child.classList.remove('active') + }) + el.children[0].classList.add('active') + }) + }) + } + if (inBrowser) { window.addEventListener('click', (e) => { const el = e.target as HTMLInputElement @@ -8,17 +19,27 @@ export function useCodeGroups() { if (el.matches('.vp-code-group input')) { // input <- .tabs <- .vp-code-group const group = el.parentElement?.parentElement - const i = Array.from(group?.querySelectorAll('input') || []).indexOf(el) + if (!group) return + + const i = Array.from(group.querySelectorAll('input')).indexOf(el) + if (i < 0) return + + const blocks = group.querySelector('.blocks') + if (!blocks) return + + const current = Array.from(blocks.children).find((child) => + child.classList.contains('active') + ) + if (!current) return + + const next = blocks.children[i] + if (!next || current === next) return - const current = group?.querySelector('div[class*="language-"].active') - const next = group?.querySelectorAll( - 'div[class*="language-"]:not(.language-id)' - )?.[i] + current.classList.remove('active') + next.classList.add('active') - if (current && next && current !== next) { - current.classList.remove('active') - next.classList.add('active') - } + const label = group?.querySelector(`label[for="${el.id}"]`) + label?.scrollIntoView({ block: 'nearest' }) } }) } diff --git a/src/client/app/composables/copyCode.ts b/src/client/app/composables/copyCode.ts index 8d3afb52..2c458bb4 100644 --- a/src/client/app/composables/copyCode.ts +++ b/src/client/app/composables/copyCode.ts @@ -2,13 +2,12 @@ import { inBrowser } from 'vitepress' export function useCopyCode() { if (inBrowser) { - const timeoutIdMap: Map = new Map() + const timeoutIdMap: WeakMap = new WeakMap() window.addEventListener('click', (e) => { const el = e.target as HTMLElement if (el.matches('div[class*="language-"] > button.copy')) { const parent = el.parentElement - const sibling = el.nextElementSibling - ?.nextElementSibling as HTMLPreElement | null + const sibling = el.nextElementSibling?.nextElementSibling if (!parent || !sibling) { return } @@ -17,12 +16,15 @@ export function useCopyCode() { parent.className ) - let text = '' + const ignoredNodes = ['.vp-copy-ignore', '.diff.remove'] - sibling - .querySelectorAll('span.line:not(.diff.remove)') - .forEach((node) => (text += (node.textContent || '') + '\n')) - text = text.slice(0, -1) + // Clone the node and remove the ignored nodes + const clone = sibling.cloneNode(true) as HTMLElement + clone + .querySelectorAll(ignoredNodes.join(',')) + .forEach((node) => node.remove()) + + let text = clone.textContent || '' if (isShell) { text = text.replace(/^ *(\$|>) /gm, '').trim() diff --git a/src/client/app/composables/head.ts b/src/client/app/composables/head.ts index 5dc1a4fb..13fb9bb0 100644 --- a/src/client/app/composables/head.ts +++ b/src/client/app/composables/head.ts @@ -1,31 +1,52 @@ import { watchEffect, type Ref } from 'vue' import { - type HeadConfig, - type SiteData, createTitle, - mergeHead + mergeHead, + type HeadConfig, + type SiteData } from '../../shared' import type { Route } from '../router' export function useUpdateHead(route: Route, siteDataByRouteRef: Ref) { - let managedHeadTags: HTMLElement[] = [] let isFirstUpdate = true + let managedHeadElements: (HTMLElement | undefined)[] = [] const updateHeadTags = (newTags: HeadConfig[]) => { if (import.meta.env.PROD && isFirstUpdate) { // in production, the initial meta tags are already pre-rendered so we // skip the first update. isFirstUpdate = false + newTags.forEach((tag) => { + const headEl = createHeadElement(tag) + for (const el of document.head.children) { + if (el.isEqualNode(headEl)) { + managedHeadElements.push(el as HTMLElement) + return + } + } + }) return } - managedHeadTags.forEach((el) => document.head.removeChild(el)) - managedHeadTags = [] - newTags.forEach((headConfig) => { - const el = createHeadElement(headConfig) - document.head.appendChild(el) - managedHeadTags.push(el) + const newElements: (HTMLElement | undefined)[] = + newTags.map(createHeadElement) + + managedHeadElements.forEach((oldEl, oldIndex) => { + const matchedIndex = newElements.findIndex((newEl) => + newEl?.isEqualNode(oldEl ?? null) + ) + if (matchedIndex !== -1) { + delete newElements[matchedIndex] + } else { + oldEl?.remove() + delete managedHeadElements[oldIndex] + } }) + + newElements.forEach((el) => el && document.head.appendChild(el)) + managedHeadElements = [...managedHeadElements, ...newElements].filter( + Boolean + ) } watchEffect(() => { @@ -35,11 +56,22 @@ export function useUpdateHead(route: Route, siteDataByRouteRef: Ref) { const frontmatterHead = (pageData && pageData.frontmatter.head) || [] // update title and description - document.title = createTitle(siteData, pageData) + const title = createTitle(siteData, pageData) + if (title !== document.title) { + document.title = title + } - document - .querySelector(`meta[name=description]`)! - .setAttribute('content', pageDescription || siteData.description) + const description = pageDescription || siteData.description + let metaDescriptionElement = document.querySelector( + `meta[name=description]` + ) + if (metaDescriptionElement) { + if (metaDescriptionElement.getAttribute('content') !== description) { + metaDescriptionElement.setAttribute('content', description) + } + } else { + createHeadElement(['meta', { name: 'description', content: description }]) + } updateHeadTags( mergeHead(siteData.head, filterOutHeadDescription(frontmatterHead)) @@ -55,6 +87,10 @@ function createHeadElement([tag, attrs, innerHTML]: HeadConfig) { if (innerHTML) { el.innerHTML = innerHTML } + if (tag === 'script' && attrs.async == null) { + // async is true by default for dynamically created scripts + ;(el as HTMLScriptElement).async = false + } return el } diff --git a/src/client/app/composables/preFetch.ts b/src/client/app/composables/preFetch.ts index 04492144..003d54c9 100644 --- a/src/client/app/composables/preFetch.ts +++ b/src/client/app/composables/preFetch.ts @@ -1,8 +1,8 @@ // Customized pre-fetch for page chunks based on // https://github.com/GoogleChromeLabs/quicklink -import { useRoute } from '../router' import { onMounted, onUnmounted, watch } from 'vue' +import { useRoute } from '../router' import { inBrowser, pathToFile } from '../utils' const hasFetched = new Set() @@ -66,7 +66,7 @@ export function usePrefetch() { if (!hasFetched.has(pathname)) { hasFetched.add(pathname) const pageChunkPath = pathToFile(pathname) - doFetch(pageChunkPath) + if (pageChunkPath) doFetch(pageChunkPath) } } }) @@ -76,7 +76,6 @@ export function usePrefetch() { document .querySelectorAll('#app a') .forEach((link) => { - const { target } = link const { hostname, pathname } = new URL( link.href instanceof SVGAnimatedString ? link.href.animVal @@ -91,7 +90,7 @@ export function usePrefetch() { if ( // only prefetch same tab navigation, since a new tab will load // the lean js chunk instead. - target !== `_blank` && + link.target !== '_blank' && // only prefetch inbound links hostname === location.hostname ) { diff --git a/src/client/app/data.ts b/src/client/app/data.ts index d6d3efa3..16288e87 100644 --- a/src/client/app/data.ts +++ b/src/client/app/data.ts @@ -1,20 +1,24 @@ +import siteData from '@siteData' +import { useDark, usePreferredDark } from '@vueuse/core' import { - type InjectionKey, - type Ref, computed, inject, readonly, ref, - shallowRef + shallowRef, + watch, + type InjectionKey, + type Ref } from 'vue' -import type { Route } from './router' -import siteData from '@siteData' import { - type PageData, - type SiteData, + APPEARANCE_KEY, + createTitle, + inBrowser, resolveSiteDataByRoute, - createTitle + type PageData, + type SiteData } from '../shared' +import type { Route } from './router' export const dataSymbol: InjectionKey = Symbol() @@ -42,9 +46,13 @@ export interface VitePressData { title: Ref description: Ref lang: Ref - isDark: Ref dir: Ref localeIndex: Ref + isDark: Ref + /** + * Current location hash + */ + hash: Ref } // site data is a singleton @@ -54,7 +62,7 @@ export const siteDataRef: Ref = shallowRef( // hmr if (import.meta.hot) { - import.meta.hot.accept('/@siteData', (m) => { + import.meta.hot.accept('@siteData', (m) => { if (m) { siteDataRef.value = m.default } @@ -67,6 +75,35 @@ export function initData(route: Route): VitePressData { resolveSiteDataByRoute(siteDataRef.value, route.data.relativePath) ) + const appearance = site.value.appearance // fine with reactivity being lost here, config change triggers a restart + const isDark = + appearance === 'force-dark' + ? ref(true) + : appearance === 'force-auto' + ? usePreferredDark() + : appearance + ? useDark({ + storageKey: APPEARANCE_KEY, + initialValue: () => (appearance === 'dark' ? 'dark' : 'auto'), + ...(typeof appearance === 'object' ? appearance : {}) + }) + : ref(false) + + const hashRef = ref(inBrowser ? location.hash : '') + + if (inBrowser) { + window.addEventListener('hashchange', () => { + hashRef.value = location.hash + }) + } + + watch( + () => route.data, + () => { + hashRef.value = inBrowser ? location.hash : '' + } + ) + return { site, theme: computed(() => site.value.themeConfig), @@ -74,15 +111,14 @@ export function initData(route: Route): VitePressData { frontmatter: computed(() => route.data.frontmatter), params: computed(() => route.data.params), lang: computed(() => site.value.lang), - dir: computed(() => site.value.dir), + dir: computed(() => route.data.frontmatter.dir || site.value.dir), localeIndex: computed(() => site.value.localeIndex || 'root'), - title: computed(() => { - return createTitle(site.value, route.data) - }), - description: computed(() => { - return route.data.description || site.value.description - }), - isDark: ref(false) + title: computed(() => createTitle(site.value, route.data)), + description: computed( + () => route.data.description || site.value.description + ), + isDark, + hash: computed(() => hashRef.value) } } diff --git a/src/client/app/devtools.ts b/src/client/app/devtools.ts index 81b91b66..54998fb1 100644 --- a/src/client/app/devtools.ts +++ b/src/client/app/devtools.ts @@ -1,7 +1,7 @@ -import { setupDevtoolsPlugin } from '@vue/devtools-api' +import { setupDevToolsPlugin } from '@vue/devtools-api' import type { App } from 'vue' -import type { Router } from './router' import type { VitePressData } from './data' +import type { Router } from './router' const COMPONENT_STATE_TYPE = 'VitePress' @@ -10,7 +10,7 @@ export const setupDevtools = ( router: Router, data: VitePressData ): void => { - setupDevtoolsPlugin( + setupDevToolsPlugin( { // fix recursive reference app: app as any, @@ -21,7 +21,8 @@ export const setupDevtools = ( componentStateTypes: [COMPONENT_STATE_TYPE] }, (api) => { - api.on.inspectComponent((payload) => { + // TODO: remove any + api.on.inspectComponent((payload: any) => { payload.instanceData.state.push({ type: COMPONENT_STATE_TYPE, key: 'route', diff --git a/src/client/app/index.ts b/src/client/app/index.ts index e594ab9d..1f1e8069 100644 --- a/src/client/app/index.ts +++ b/src/client/app/index.ts @@ -1,23 +1,22 @@ +import RawTheme from '@theme/index' import { - type App, createApp as createClientApp, createSSRApp, defineComponent, h, onMounted, - watchEffect + watchEffect, + type App } from 'vue' -import RawTheme from '@theme/index' -import { inBrowser, pathToFile } from './utils' -import { type Router, RouterSymbol, createRouter, scrollTo } from './router' -import { siteDataRef, useData } from './data' -import { useUpdateHead } from './composables/head' -import { usePrefetch } from './composables/preFetch' -import { dataSymbol, initData } from './data' -import { Content } from './components/Content' import { ClientOnly } from './components/ClientOnly' -import { useCopyCode } from './composables/copyCode' +import { Content } from './components/Content' import { useCodeGroups } from './composables/codeGroups' +import { useCopyCode } from './composables/copyCode' +import { useUpdateHead } from './composables/head' +import { usePrefetch } from './composables/preFetch' +import { dataSymbol, initData, siteDataRef, useData } from './data' +import { RouterSymbol, createRouter, scrollTo, type Router } from './router' +import { inBrowser, pathToFile } from './utils' function resolveThemeExtends(theme: typeof RawTheme): typeof RawTheme { if (theme.extends) { @@ -39,17 +38,17 @@ const Theme = resolveThemeExtends(RawTheme) const VitePressApp = defineComponent({ name: 'VitePressApp', setup() { - const { site } = useData() + const { site, lang, dir } = useData() // change the language on the HTML element based on the current lang onMounted(() => { watchEffect(() => { - document.documentElement.lang = site.value.lang - document.documentElement.dir = site.value.dir + document.documentElement.lang = lang.value + document.documentElement.dir = dir.value }) }) - if (import.meta.env.PROD) { + if (import.meta.env.PROD && site.value.router.prefetchLinks) { // in prod mode, enable intersectionObserver based pre-fetch usePrefetch() } @@ -60,11 +59,13 @@ const VitePressApp = defineComponent({ useCodeGroups() if (Theme.setup) Theme.setup() - return () => h(Theme.Layout) + return () => h(Theme.Layout!) } }) export async function createApp() { + ;(globalThis as any).__VITEPRESS__ = true + const router = newRouter() const app = newApp() @@ -118,44 +119,54 @@ function newApp(): App { function newRouter(): Router { let isInitialPageLoad = inBrowser - let initialPath: string return createRouter((path) => { let pageFilePath = pathToFile(path) + let pageModule = null - if (isInitialPageLoad) { - initialPath = pageFilePath - } + if (pageFilePath) { + // use lean build if this is the initial page load + if (isInitialPageLoad) { + pageFilePath = pageFilePath.replace(/\.js$/, '.lean.js') + } - // use lean build if this is the initial page load or navigating back - // to the initial loaded path (the static vnodes already adopted the - // static content on that load so no need to re-fetch the page) - if (isInitialPageLoad || initialPath === pageFilePath) { - pageFilePath = pageFilePath.replace(/\.js$/, '.lean.js') + if (import.meta.env.DEV) { + pageModule = import(/*@vite-ignore*/ pageFilePath).catch(() => { + // try with/without trailing slash + // in prod this is handled in src/client/app/utils.ts#pathToFile + const url = new URL(pageFilePath!, 'http://a.com') + const path = + (url.pathname.endsWith('/index.md') + ? url.pathname.slice(0, -9) + '.md' + : url.pathname.slice(0, -3) + '/index.md') + + url.search + + url.hash + return import(/*@vite-ignore*/ path) + }) + } else { + pageModule = import(/*@vite-ignore*/ pageFilePath) + } } if (inBrowser) { isInitialPageLoad = false } - return import(/*@vite-ignore*/ pageFilePath) + return pageModule }, Theme.NotFound) } if (inBrowser) { createApp().then(({ app, router, data }) => { // wait until page component is fetched before mounting - router.go().then(() => { + router.go(location.href, { initialLoad: true }).then(() => { // dynamically update head tags useUpdateHead(router.route, data.site) app.mount('#app') // scroll to hash on new tab during dev if (import.meta.env.DEV && location.hash) { - const target = document.querySelector(decodeURIComponent(location.hash)) - if (target) { - scrollTo(target, location.hash) - } + scrollTo(location.hash) } }) }) diff --git a/src/client/app/router.ts b/src/client/app/router.ts index d8b98168..7121464c 100644 --- a/src/client/app/router.ts +++ b/src/client/app/router.ts @@ -1,31 +1,64 @@ -import { reactive, inject, markRaw, nextTick, readonly } from 'vue' import type { Component, InjectionKey } from 'vue' -import { notFoundPageData } from '../shared' -import type { PageData, PageDataPayload, Awaitable } from '../shared' -import { inBrowser, withBase } from './utils' +import { inject, markRaw, nextTick, reactive, readonly } from 'vue' +import type { Awaitable, PageData, PageDataPayload } from '../shared' +import { notFoundPageData, treatAsHtml } from '../shared' import { siteDataRef } from './data' +import { getScrollOffset, inBrowser, withBase } from './utils' export interface Route { path: string + hash: string + query: string data: PageData component: Component | null } export interface Router { + /** + * Current route. + */ route: Route - go: (href?: string) => Promise - onBeforeRouteChange?: (to: string) => Awaitable - onAfterRouteChanged?: (to: string) => Awaitable + /** + * Navigate to a new URL. + */ + go: ( + to: string, + options?: { + // @internal + initialLoad?: boolean + // Whether to smoothly scroll to the target position. + smoothScroll?: boolean + } + ) => Promise + /** + * Called before the route changes. Return `false` to cancel the navigation. + */ + onBeforeRouteChange?: (to: string) => Awaitable + /** + * Called before the page component is loaded (after the history state is + * updated). Return `false` to cancel the navigation. + */ + onBeforePageLoad?: (to: string) => Awaitable + /** + * Called after the page component is loaded (before the page component is updated). + */ + onAfterPageLoad?: (to: string) => Awaitable + /** + * Called after the route changes. + */ + onAfterRouteChange?: (to: string) => Awaitable } export const RouterSymbol: InjectionKey = Symbol() // we are just using URL to parse the pathname and hash - the base doesn't // matter and is only passed to support same-host hrefs. -const fakeHost = `http://a.com` +const fakeHost = 'http://a.com' const getDefaultRoute = (): Route => ({ path: '/', + hash: '', + query: '', component: null, data: notFoundPageData }) @@ -36,91 +69,74 @@ interface PageModule { } export function createRouter( - loadPageModule: (path: string) => Promise, + loadPageModule: (path: string) => Awaitable, fallbackComponent?: Component ): Router { const route = reactive(getDefaultRoute()) const router: Router = { route, - go - } - - async function go(href: string = inBrowser ? location.href : '/') { - await router.onBeforeRouteChange?.(href) - const url = new URL(href, fakeHost) - if (!siteDataRef.value.cleanUrls) { - // ensure correct deep link so page refresh lands on correct files. - // if cleanUrls is enabled, the server should handle this - if (!url.pathname.endsWith('/') && !url.pathname.endsWith('.html')) { - url.pathname += '.html' - href = url.pathname + url.search + url.hash - } + async go(href, options) { + href = normalizeHref(href) + if ((await router.onBeforeRouteChange?.(href)) === false) return + if (!inBrowser || (await changeRoute(href, options))) await loadPage(href) + syncRouteQueryAndHash() + await router.onAfterRouteChange?.(href) } - if (inBrowser && href !== location.href) { - // save scroll position before changing url - history.replaceState({ scrollPosition: window.scrollY }, document.title) - history.pushState(null, '', href) - } - await loadPage(href) - await router.onAfterRouteChanged?.(href) } let latestPendingPath: string | null = null async function loadPage(href: string, scrollPosition = 0, isRetry = false) { + if ((await router.onBeforePageLoad?.(href)) === false) return + const targetLoc = new URL(href, fakeHost) const pendingPath = (latestPendingPath = targetLoc.pathname) + try { let page = await loadPageModule(pendingPath) + if (!page) throw new Error(`Page not found: ${pendingPath}`) + if (latestPendingPath === pendingPath) { latestPendingPath = null const { default: comp, __pageData } = page - if (!comp) { - throw new Error(`Invalid route component: ${comp}`) - } + if (!comp) throw new Error(`Invalid route component: ${comp}`) + + await router.onAfterPageLoad?.(href) route.path = inBrowser ? pendingPath : withBase(pendingPath) route.component = markRaw(comp) route.data = import.meta.env.PROD ? markRaw(__pageData) : (readonly(__pageData) as PageData) + syncRouteQueryAndHash(targetLoc) if (inBrowser) { nextTick(() => { let actualPathname = siteDataRef.value.base + __pageData.relativePath.replace(/(?:(^|\/)index)?\.md$/, '$1') + if (!siteDataRef.value.cleanUrls && !actualPathname.endsWith('/')) { actualPathname += '.html' } + if (actualPathname !== targetLoc.pathname) { targetLoc.pathname = actualPathname href = actualPathname + targetLoc.search + targetLoc.hash - history.replaceState(null, '', href) + history.replaceState({}, '', href) } - if (targetLoc.hash && !scrollPosition) { - let target: HTMLElement | null = null - try { - target = document.querySelector( - decodeURIComponent(targetLoc.hash) - ) - } catch (e) { - console.warn(e) - } - if (target) { - scrollTo(target, targetLoc.hash) - return - } - } - window.scrollTo(0, scrollPosition) + return scrollTo(targetLoc.hash, false, scrollPosition) }) } } } catch (err: any) { - if (!/fetch/.test(err.message) && !/^\/404(\.html|\/)?$/.test(href)) { + if ( + !/fetch|Page not found/.test(err.message) && + !/^\/404(\.html|\/)?$/.test(href) + ) { console.error(err) } @@ -140,78 +156,85 @@ export function createRouter( latestPendingPath = null route.path = inBrowser ? pendingPath : withBase(pendingPath) route.component = fallbackComponent ? markRaw(fallbackComponent) : null - route.data = notFoundPageData + const relativePath = inBrowser + ? pendingPath + .replace(/(^|\/)$/, '$1index') + .replace(/(\.html)?$/, '.md') + .replace(/^\//, '') + : '404.md' + route.data = { ...notFoundPageData, relativePath } + syncRouteQueryAndHash(targetLoc) } } } + function syncRouteQueryAndHash( + loc: { search: string; hash: string } = inBrowser + ? location + : { search: '', hash: '' } + ) { + route.query = loc.search + route.hash = decodeURIComponent(loc.hash) + } + if (inBrowser) { + if (history.state === null) history.replaceState({}, '') window.addEventListener( 'click', (e) => { - // temporary fix for docsearch action buttons - const button = (e.target as Element).closest('button') - if (button) return + if ( + e.defaultPrevented || + !(e.target instanceof Element) || + e.target.closest('button') || // temporary fix for docsearch action buttons + e.button !== 0 || + e.ctrlKey || + e.shiftKey || + e.altKey || + e.metaKey + ) { + return + } - const link = (e.target as Element | SVGElement).closest< - HTMLAnchorElement | SVGAElement - >('a') + const link = e.target.closest('a') if ( - link && - !link.closest('.vp-raw') && - (link instanceof SVGElement || !link.download) + !link || + link.closest('.vp-raw') || + link.hasAttribute('download') || + link.hasAttribute('target') ) { - const { target } = link - const { href, origin, pathname, hash, search } = new URL( - link.href instanceof SVGAnimatedString - ? link.href.animVal - : link.href, - link.baseURI - ) - const currentUrl = window.location - const extMatch = pathname.match(/\.\w+$/) - // only intercept inbound links - if ( - !e.ctrlKey && - !e.shiftKey && - !e.altKey && - !e.metaKey && - target !== `_blank` && - origin === currentUrl.origin && - // don't intercept if non-html extension is present - !(extMatch && extMatch[0] !== '.html') - ) { - e.preventDefault() - if ( - pathname === currentUrl.pathname && - search === currentUrl.search - ) { - // scroll between hash anchors in the same page - if (hash) { - // avoid duplicate history entries when the hash is same - if (hash !== currentUrl.hash) { - history.pushState(null, '', hash) - // still emit the event so we can listen to it in themes - window.dispatchEvent(new Event('hashchange')) - } - // use smooth scroll when clicking on header anchor links - scrollTo(link, hash, link.classList.contains('header-anchor')) - } - } else { - go(href) - } - } + return + } + + const linkHref = + link.getAttribute('href') ?? + (link instanceof SVGAElement ? link.getAttribute('xlink:href') : null) + if (linkHref == null) return + + const { href, origin, pathname } = new URL(linkHref, link.baseURI) + const currentLoc = new URL(location.href) // copy to keep old data + // only intercept inbound html links + if (origin === currentLoc.origin && treatAsHtml(pathname)) { + e.preventDefault() + router.go(href, { + // use smooth scroll when clicking on header anchor links + smoothScroll: link.classList.contains('header-anchor') + }) } }, { capture: true } ) - window.addEventListener('popstate', (e) => { - loadPage(location.href, (e.state && e.state.scrollPosition) || 0) + window.addEventListener('popstate', async (e) => { + if (e.state === null) return + const href = normalizeHref(location.href) + await loadPage(href, (e.state && e.state.scrollPosition) || 0) + syncRouteQueryAndHash() + await router.onAfterRouteChange?.(href) }) window.addEventListener('hashchange', (e) => { e.preventDefault() + syncRouteQueryAndHash() }) } @@ -222,9 +245,7 @@ export function createRouter( export function useRouter(): Router { const router = inject(RouterSymbol) - if (!router) { - throw new Error('useRouter() is called without provider.') - } + if (!router) throw new Error('useRouter() is called without provider.') return router } @@ -232,61 +253,41 @@ export function useRoute(): Route { return useRouter().route } -export function scrollTo(el: Element, hash: string, smooth = false) { +export function scrollTo(hash: string, smooth = false, scrollPosition = 0) { + if (!hash || scrollPosition) { + window.scrollTo(0, scrollPosition) + return + } + let target: Element | null = null try { - target = el.classList.contains('header-anchor') - ? el - : document.querySelector(decodeURIComponent(hash)) + target = document.getElementById(decodeURIComponent(hash).slice(1)) } catch (e) { console.warn(e) } if (target) { - const scrollOffset = siteDataRef.value.scrollOffset - let offset: number = 0 - if (typeof scrollOffset === 'number') { - offset = scrollOffset - } else if (typeof scrollOffset === 'string') { - offset = tryOffsetSelector(scrollOffset) - } else if (Array.isArray(scrollOffset)) { - for (const selector of scrollOffset) { - const res = tryOffsetSelector(selector) - if (res) { - offset = res - break - } - } - } const targetPadding = parseInt( window.getComputedStyle(target).paddingTop, 10 ) + const targetTop = window.scrollY + target.getBoundingClientRect().top - - offset + + getScrollOffset() + targetPadding - // only smooth scroll if distance is smaller than screen height. - if (!smooth || Math.abs(targetTop - window.scrollY) > window.innerHeight) { - window.scrollTo(0, targetTop) - } else { - window.scrollTo({ - left: 0, - top: targetTop, - behavior: 'smooth' - }) + + function scrollToTarget() { + // only smooth scroll if distance is smaller than screen height. + if (!smooth || Math.abs(targetTop - window.scrollY) > window.innerHeight) + window.scrollTo(0, targetTop) + else window.scrollTo({ left: 0, top: targetTop, behavior: 'smooth' }) } - } -} -function tryOffsetSelector(selector: string): number { - const el = document.querySelector(selector) - if (!el) return 0 - const bot = el.getBoundingClientRect().bottom - if (bot < 0) return 0 - return bot + 24 + requestAnimationFrame(scrollToTarget) + } } function handleHMR(route: Route): void { @@ -294,17 +295,64 @@ function handleHMR(route: Route): void { if (import.meta.hot) { // hot reload pageData import.meta.hot.on('vitepress:pageData', (payload: PageDataPayload) => { - if (shouldHotReload(payload)) { - route.data = payload.pageData - } + if (shouldHotReload(payload)) route.data = payload.pageData }) } } function shouldHotReload(payload: PageDataPayload): boolean { - const payloadPath = payload.path.replace(/(\bindex)?\.md$/, '') + const payloadPath = payload.path.replace(/(?:(^|\/)index)?\.md$/, '$1') const locationPath = location.pathname - .replace(/(\bindex)?\.html$/, '') + .replace(/(?:(^|\/)index)?\.html$/, '') .slice(siteDataRef.value.base.length - 1) return payloadPath === locationPath } + +function normalizeHref(href: string): string { + const url = new URL(href, fakeHost) + url.pathname = url.pathname.replace(/(^|\/)index(\.html)?$/, '$1') + // ensure correct deep link so page refresh lands on correct files. + if (siteDataRef.value.cleanUrls) { + url.pathname = url.pathname.replace(/\.html$/, '') + } else if (!url.pathname.endsWith('/') && !url.pathname.endsWith('.html')) { + url.pathname += '.html' + } + return url.pathname + url.search + url.hash +} + +async function changeRoute( + href: string, + { smoothScroll = false, initialLoad = false } = {} +): Promise { + const loc = normalizeHref(location.href) + const nextUrl = new URL(href, location.origin) + const currentUrl = new URL(loc, location.origin) + + if (href === loc) { + if (!initialLoad) { + scrollTo(nextUrl.hash, smoothScroll) + return false + } + } else { + // save scroll position before changing URL + history.replaceState({ scrollPosition: window.scrollY }, '') + history.pushState({}, '', href) + + if (nextUrl.pathname === currentUrl.pathname) { + // scroll between hash anchors on the same page, avoid duplicate entries + if (nextUrl.hash !== currentUrl.hash) { + window.dispatchEvent( + new HashChangeEvent('hashchange', { + oldURL: currentUrl.href, + newURL: nextUrl.href + }) + ) + scrollTo(nextUrl.hash, smoothScroll) + } + + return false + } + } + + return true +} diff --git a/src/client/app/ssr.ts b/src/client/app/ssr.ts index eb408cc7..338d4aad 100644 --- a/src/client/app/ssr.ts +++ b/src/client/app/ssr.ts @@ -1,12 +1,12 @@ // entry for SSR -import { createApp } from './index' import { renderToString } from 'vue/server-renderer' import type { SSGContext } from '../shared' +import { createApp } from './index' export async function render(path: string) { const { app, router } = await createApp() await router.go(path) - const ctx: SSGContext = { content: '' } + const ctx: SSGContext = { content: '', vpSocialIcons: new Set() } ctx.content = await renderToString(app, ctx) return ctx } diff --git a/src/client/app/theme.ts b/src/client/app/theme.ts index 155ba1a7..0658ce1d 100644 --- a/src/client/app/theme.ts +++ b/src/client/app/theme.ts @@ -1,6 +1,6 @@ -import type { App, Ref, Component } from 'vue' -import type { Router } from './router' +import type { App, Component, Ref } from 'vue' import type { Awaitable, SiteData } from '../shared' +import type { Router } from './router' export interface EnhanceAppContext { app: App @@ -9,7 +9,7 @@ export interface EnhanceAppContext { } export interface Theme { - Layout: Component + Layout?: Component enhanceApp?: (ctx: EnhanceAppContext) => Awaitable extends?: Theme diff --git a/src/client/app/utils.ts b/src/client/app/utils.ts index fe103dc1..b734179c 100644 --- a/src/client/app/utils.ts +++ b/src/client/app/utils.ts @@ -1,29 +1,27 @@ -import { siteDataRef } from './data' +import { tryOnUnmounted } from '@vueuse/core' +import { h, onMounted, shallowRef, type AsyncComponentLoader } from 'vue' import { - inBrowser, EXTERNAL_URL_RE, + inBrowser, sanitizeFileName, type Awaitable } from '../shared' -import { - h, - onMounted, - onUnmounted, - shallowRef, - type AsyncComponentLoader -} from 'vue' +import { siteDataRef } from './data' -export { inBrowser } from '../shared' +export { escapeHtml as _escapeHtml, inBrowser } from '../shared' /** * Join two paths by resolving the slash collision. */ -export function joinPath(base: string, path: string): string { +export function joinPath(base: string, path: string) { return `${base}${path}`.replace(/\/+/g, '/') } +/** + * Append base to internal (non-relative) urls + */ export function withBase(path: string) { - return EXTERNAL_URL_RE.test(path) || path.startsWith('.') + return EXTERNAL_URL_RE.test(path) || !path.startsWith('/') ? path : joinPath(siteDataRef.value.base, path) } @@ -31,7 +29,7 @@ export function withBase(path: string) { /** * Converts a url path to the corresponding js chunk filename. */ -export function pathToFile(path: string): string { +export function pathToFile(path: string) { let pagePath = path.replace(/\.html$/, '') pagePath = decodeURIComponent(pagePath) pagePath = pagePath.replace(/\/$/, '/index') // /foo/ -> /foo/index @@ -57,7 +55,8 @@ export function pathToFile(path: string): string { : pagePath.slice(0, -3) + '_index.md' pageHash = __VP_HASH_MAP__[pagePath.toLowerCase()] } - pagePath = `${base}assets/${pagePath}.${pageHash}.js` + if (!pageHash) return null + pagePath = `${base}${__ASSETS_DIR__}/${pagePath}.${pageHash}.js` } else { // ssr build uses much simpler name mapping pagePath = `./${sanitizeFileName( @@ -77,7 +76,7 @@ export let contentUpdatedCallbacks: (() => any)[] = [] */ export function onContentUpdated(fn: () => any) { contentUpdatedCallbacks.push(fn) - onUnmounted(() => { + tryOnUnmounted(() => { contentUpdatedCallbacks = contentUpdatedCallbacks.filter((f) => f !== fn) }) } @@ -103,3 +102,36 @@ export function defineClientComponent( } } } + +export function getScrollOffset() { + let scrollOffset = siteDataRef.value.scrollOffset + let offset = 0 + let padding = 24 + if (typeof scrollOffset === 'object' && 'padding' in scrollOffset) { + padding = scrollOffset.padding + scrollOffset = scrollOffset.selector + } + if (typeof scrollOffset === 'number') { + offset = scrollOffset + } else if (typeof scrollOffset === 'string') { + offset = tryOffsetSelector(scrollOffset, padding) + } else if (Array.isArray(scrollOffset)) { + for (const selector of scrollOffset) { + const res = tryOffsetSelector(selector, padding) + if (res) { + offset = res + break + } + } + } + + return offset +} + +function tryOffsetSelector(selector: string, padding: number): number { + const el = document.querySelector(selector) + if (!el) return 0 + const bot = el.getBoundingClientRect().bottom + if (bot < 0) return 0 + return bot + padding +} diff --git a/src/client/index.ts b/src/client/index.ts index c8673544..6054daa4 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -1,5 +1,5 @@ // exports in this file are exposed to themes and md files via 'vitepress' -// so the user can do `import { useRoute, useSiteData } from 'vitepress'` +// so the user can do `import { useRoute, useData } from 'vitepress'` // generic types export type { VitePressData } from './app/data' @@ -12,14 +12,16 @@ export type { EnhanceAppContext, Theme } from './app/theme' export type { HeadConfig, Header, PageData, SiteData } from '../../types/shared' // composables -export { useData } from './app/data' +export { dataSymbol, useData } from './app/data' export { useRoute, useRouter } from './app/router' // utilities export { + _escapeHtml, + defineClientComponent, + getScrollOffset, inBrowser, onContentUpdated, - defineClientComponent, withBase } from './app/utils' diff --git a/src/client/shim.d.ts b/src/client/shim.d.ts index 6817bb42..e12889d5 100644 --- a/src/client/shim.d.ts +++ b/src/client/shim.d.ts @@ -3,6 +3,7 @@ declare const __VP_LOCAL_SEARCH__: boolean declare const __ALGOLIA__: boolean declare const __CARBON__: boolean declare const __VUE_PROD_DEVTOOLS__: boolean +declare const __ASSETS_DIR__: string declare module '*.vue' { import type { DefineComponent } from 'vue' @@ -28,7 +29,7 @@ declare module '@localSearchIndex' { } declare module 'mark.js/src/vanilla.js' { - import type { Mark } from 'mark.js' - const mark: Mark + import type Mark from 'mark.js' + const mark: typeof Mark export default mark } diff --git a/src/client/theme-default/Layout.vue b/src/client/theme-default/Layout.vue index e9259258..30ebe491 100644 --- a/src/client/theme-default/Layout.vue +++ b/src/client/theme-default/Layout.vue @@ -1,29 +1,23 @@