diff --git a/.github/workflows/cr.yml b/.github/workflows/cr.yml index 7cc01dbb..ae327e48 100644 --- a/.github/workflows/cr.yml +++ b/.github/workflows/cr.yml @@ -38,9 +38,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 - - uses: pnpm/action-setup@v4 - - uses: actions/setup-node@v6 + - uses: actions/checkout@v7 + - uses: pnpm/action-setup@v6 + - uses: actions/setup-node@v7 with: node-version: 24 cache: pnpm diff --git a/.github/workflows/release-tag.yml b/.github/workflows/release-tag.yml index 1c675000..43dd8b09 100644 --- a/.github/workflows/release-tag.yml +++ b/.github/workflows/release-tag.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v7 - name: Create Release for Tag id: release_tag diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index aa97e0f7..694d2434 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,13 +27,13 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v7 - name: Install pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@v6 - name: Set node version to ${{ matrix.node_version }} - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: ${{ matrix.node_version }} cache: pnpm diff --git a/.prettierignore b/.prettierignore index 32f2a7ad..d23ab1d0 100644 --- a/.prettierignore +++ b/.prettierignore @@ -7,3 +7,6 @@ template temp !CHANGELOG.md .temp + +# generated by scripts/subsetFonts.py +src/client/theme-default/styles/fonts.css diff --git a/CHANGELOG.md b/CHANGELOG.md index 3240a3db..f150ae78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,117 @@ +## [2.0.0-alpha.19](https://github.com/vuejs/vitepress/compare/v2.0.0-alpha.18...v2.0.0-alpha.19) (2026-08-02) + +### Bug Fixes + +- **build:** apply rewrites when computing createContentLoader urls ([9e2148d](https://github.com/vuejs/vitepress/commit/9e2148d75ed966467a438403ad5b0a69df83480b)) +- **build:** clear markdown cache with rewritten path on include change ([5eac447](https://github.com/vuejs/vitepress/commit/5eac4473189228da7a917a1a35a67233c94513c9)), closes [#5035](https://github.com/vuejs/vitepress/issues/5035) +- **build:** compose markdown `preConfig` hook when extending configs ([c39a85a](https://github.com/vuejs/vitepress/commit/c39a85a2ac88dca978d6a7b07fac3353fe0ae7fe)), closes [#5205](https://github.com/vuejs/vitepress/issues/5205) +- **build:** don't apply docsearch css transform to pages matching its filter ([fa0e48c](https://github.com/vuejs/vitepress/commit/fa0e48c8df8f66fb76f7df4d7d662a5c7b3c3c7c)) +- **build:** don't rely on checkout directory name when externalizing types ([e6ba9d8](https://github.com/vuejs/vitepress/commit/e6ba9d8caa3866215095f63b62290f3110e523fd)) +- **build:** report links to pre-rewrite paths of rewritten pages as dead ([3cf3f37](https://github.com/vuejs/vitepress/commit/3cf3f37b17054ff38347d4d0a2e76e03d68e2e7a)) +- **build:** resolve additional configs by source path ([5e4a9e7](https://github.com/vuejs/vitepress/commit/5e4a9e799f620bcd3de973272d8343a515fd4992)) +- **build:** resolve rewrites against externally injected pages too ([769c10e](https://github.com/vuejs/vitepress/commit/769c10ee65a61882724e2b748634326b576bb079)) +- **build:** respect cleanUrls in content loader render ([027f046](https://github.com/vuejs/vitepress/commit/027f0461e073702c2d5b7e96006cf34a51825f45)), closes [#4331](https://github.com/vuejs/vitepress/issues/4331) [#5299](https://github.com/vuejs/vitepress/issues/5299) +- **build:** track include importers by module id ([c961655](https://github.com/vuejs/vitepress/commit/c9616559f55f378b92e2f3b8bac31336db540699)) +- **build:** prevent duplicate IDs in MiniSearch ([#5303](https://github.com/vuejs/vitepress/issues/5303)) ([505278c](https://github.com/vuejs/vitepress/commit/505278c2cb06c5ed4ca094b193d6dc912376818c)) +- **build:** remove stackTraceLimit Infinity for DEBUG ([#5318](https://github.com/vuejs/vitepress/issues/5318)) ([865d04b](https://github.com/vuejs/vitepress/commit/865d04b2528863f265e39e1b05278c9654f8599a)) +- **build:** retry file reads when out of file descriptors ([da71173](https://github.com/vuejs/vitepress/commit/da71173afc8eece9af49ff25ad1bff9bbd676096)) +- **cli:** avoid onAfterConfigResolve ([3fbaf9c](https://github.com/vuejs/vitepress/commit/3fbaf9c4d21e62062490c58c13cbf1b074417004)) +- **client:** make the route the single source of truth for the URL hash ([dcb7a75](https://github.com/vuejs/vitepress/commit/dcb7a75532c5472060ec379d25a5fafbc7932637)) +- **markdown:** preserve user-defined attributes ([3f4530b](https://github.com/vuejs/vitepress/commit/3f4530b0e2b339cc408ab38b8b922a9834bb396e)), closes [#5123](https://github.com/vuejs/vitepress/issues/5123) +- **markdown:** remove extra whitespace from container markup ([b6d9cb8](https://github.com/vuejs/vitepress/commit/b6d9cb83c747f9a021aa277b0c64b5bf3a40bf41)) +- **markdown:** skip circular includes ([3372516](https://github.com/vuejs/vitepress/commit/3372516152df0b871634492ac6d3207bedf89d4e)) +- **markdown:** remove deprecated `cjkFriendly` option ([27762ea](https://github.com/vuejs/vitepress/commit/27762eac86aa5c5d998de128734c2a8c10f78e23)) +- **markdown:** rename image option `lazyLoading` to `lazyLoad` ([078786a](https://github.com/vuejs/vitepress/commit/078786a1b3e0793f55cb14d819df93900041ccb0)) +- **search:** index changed files with srcDir-relative paths in dev ([6b64f35](https://github.com/vuejs/vitepress/commit/6b64f3561b0da8fcf48a6ccff7b08036ad858ef3)), closes [#3374](https://github.com/vuejs/vitepress/issues/3374) +- **search:** only index pages on dev updates ([559fb24](https://github.com/vuejs/vitepress/commit/559fb24a2238b2c0b97c36c808c092dda98bb2f7)) +- **search:** serve a fresh search index after dev updates ([1534a67](https://github.com/vuejs/vitepress/commit/1534a67d866e4922a7eab1a1c166db7f11855c59)) +- **search:** skip pages that fail to render instead of crashing dev server ([3ffefa2](https://github.com/vuejs/vitepress/commit/3ffefa2550d1242da4a798e18cb308cb33ad815b)) +- **theme:** use ul and li for lists ([#5326](https://github.com/vuejs/vitepress/issues/5326)) ([3f99872](https://github.com/vuejs/vitepress/commit/3f99872468f861458f4f37d6115cfd1c1a7b15ae)) +- **theme:** align docsearch breakpoints with the default theme ([90c28d4](https://github.com/vuejs/vitepress/commit/90c28d41ce0a67f6e096ce9fd355f3b0c7b1dab7)), closes [#5213](https://github.com/vuejs/vitepress/issues/5213) +- **theme:** align local search breakpoint ([#5217](https://github.com/vuejs/vitepress/issues/5217)) ([a425113](https://github.com/vuejs/vitepress/commit/a425113572d94c39d0c3369eac5adb7a87cfb798)) +- **theme:** correct anchor scroll margins across viewports ([dabc5e9](https://github.com/vuejs/vitepress/commit/dabc5e95ce210ae14cb33a08e6784826e4e2d544)) +- **theme:** ensure outline marker follows click ([#3879](https://github.com/vuejs/vitepress/issues/3879)) ([31287c0](https://github.com/vuejs/vitepress/commit/31287c0b69b330bc1645268b1bebd21f9a40c238)) +- **theme:** external link icon not showing in navbar links ([225c94a](https://github.com/vuejs/vitepress/commit/225c94afd2c355a33fbbb93871fb9b064da475b8)), closes [#5306](https://github.com/vuejs/vitepress/issues/5306) +- **theme:** pass target and rel to prev/next page links ([#5297](https://github.com/vuejs/vitepress/issues/5297)) ([6b5e770](https://github.com/vuejs/vitepress/commit/6b5e7704a01500d87a3702f7b27f95a4bdcfa10d)) +- **theme:** preserve url params when switching languages ([#5312](https://github.com/vuejs/vitepress/issues/5312)) ([9ee401d](https://github.com/vuejs/vitepress/commit/9ee401d7adefc39fd960990cc032be5464e4eb27)) +- **theme:** prevent TypeError when navigating to page without outline ([#5329](https://github.com/vuejs/vitepress/issues/5329)) ([9376c58](https://github.com/vuejs/vitepress/commit/9376c58abec557dd8c5b63f991a1d1068586f175)) +- **theme:** remove font-synthesis style ([#5309](https://github.com/vuejs/vitepress/issues/5309)) ([c34769c](https://github.com/vuejs/vitepress/commit/c34769c2e67969881b9cc8abbccf6d3cc6a5b647)) +- **theme:** safari not showing external link icon properly ([7118402](https://github.com/vuejs/vitepress/commit/711840222700804dbb6fb39ee9b9580a3e6220e7)) +- **theme:** rebuild the base styles on tailwind's preflight ([f1ee913](https://github.com/vuejs/vitepress/commit/f1ee91335ecc562511f5e97214f41c043e6944fa)) +- **theme:** route cjk punctuation to matching system fonts ([91b06b6](https://github.com/vuejs/vitepress/commit/91b06b67a302ebfa210e888fe9d03d27fb291b31)) +- **theme:** remove deprecated `disableDetailedView` local search option ([cec4998](https://github.com/vuejs/vitepress/commit/cec499869f02313337993a7f2ad381f0f9d9dafd)) +- **theme:** remove deprecated `lastUpdatedText` option ([18d1b47](https://github.com/vuejs/vitepress/commit/18d1b4713c6634cc60e6b4a95430e05d51ec4812)) +- **theme:** remove deprecated `outlineTitle` option ([95c0420](https://github.com/vuejs/vitepress/commit/95c042039c62a9235e223f8da05a2075aa2234d7)) +- **types:** declare Badge as a global component ([ca8ba5b](https://github.com/vuejs/vitepress/commit/ca8ba5baec6c8fa551ee29917bd072f84406e68b)) +- **types:** import EnhanceAppContext from package entry in theme.d.ts ([8ff1f3e](https://github.com/vuejs/vitepress/commit/8ff1f3e2dd34fd443c0fa80cf3962f9d67e81cf5)), closes [#5156](https://github.com/vuejs/vitepress/issues/5156) + +### Features + +- add web-types.json for JetBrains IDE support ([1d448c9](https://github.com/vuejs/vitepress/commit/1d448c9fc1ec90849c2a18c49cab5e275f3dc019)), closes [#5157](https://github.com/vuejs/vitepress/issues/5157) +- auto-add width/height to local images to avoid layout shift ([#5311](https://github.com/vuejs/vitepress/issues/5311)) ([3868b64](https://github.com/vuejs/vitepress/commit/3868b64e419223279eaae800766b244cde9bc85f)) +- **client:** declare $frontmatter and $params as ComponentCustomProperties ([0535009](https://github.com/vuejs/vitepress/commit/0535009f44b2f9ddf8e30b59700bacdb9a9b5e75)) +- **client:** declare Content and ClientOnly components as GlobalComponents ([#5156](https://github.com/vuejs/vitepress/issues/5156)) ([6629577](https://github.com/vuejs/vitepress/commit/6629577b48fe2785cf6865197cb326eff9f2a9d8)), closes [#5154](https://github.com/vuejs/vitepress/issues/5154) +- **cli:** show vite version in startup log ([#5328](https://github.com/vuejs/vitepress/issues/5328)) ([4666fc2](https://github.com/vuejs/vitepress/commit/4666fc277609f8bb916e6a54eb0ac9327784d073)) +- enable metaChunk by default ([#5325](https://github.com/vuejs/vitepress/issues/5325)) ([8e42f31](https://github.com/vuejs/vitepress/commit/8e42f3159a1d5d8576bee0b736f56e943d3cb858)) +- **init:** use async fs in scaffolding ([38b59f9](https://github.com/vuejs/vitepress/commit/38b59f925206120b1a20b1fcfb650b45f8147175)) +- **markdown:** accept booleans for plugin options ([c2be0bf](https://github.com/vuejs/vitepress/commit/c2be0bf936e46c196151b79ba683a30490f2d164)) +- **markdown:** add region marker engine ([b303dd3](https://github.com/vuejs/vitepress/commit/b303dd341df7c0ca1e5b63c086084b2baad68c19)) +- **markdown:** allow disabling table `tabindex` attribute ([bffe1e1](https://github.com/vuejs/vitepress/commit/bffe1e14125220d465a94cc629260e19bff48e0c)) +- **markdown:** support disabling built-in markdown plugins ([b8d9c8f](https://github.com/vuejs/vitepress/commit/b8d9c8f9a92ec4e8c877d6c28fee26b3c379876c)), closes [#4484](https://github.com/vuejs/vitepress/issues/4484) [#4556](https://github.com/vuejs/vitepress/issues/4556) +- **markdown:** support footnotes ([430a890](https://github.com/vuejs/vitepress/commit/430a890a17910593e26e9654b141ef3855ecceac)) +- **markdown:** support GitHub-style task lists ([97f8781](https://github.com/vuejs/vitepress/commit/97f87817ead5b7a26e0dfc535cfd60ec0597d130)), closes [#413](https://github.com/vuejs/vitepress/issues/413) [#1923](https://github.com/vuejs/vitepress/issues/1923) [#3648](https://github.com/vuejs/vitepress/issues/3648) [#5110](https://github.com/vuejs/vitepress/issues/5110) +- **markdown:** support per-locale markdown strings ([faaa4a1](https://github.com/vuejs/vitepress/commit/faaa4a124ed7a5b2f1cfc8f9b7686a3785d2012b)), closes [#4431](https://github.com/vuejs/vitepress/issues/4431) +- **markdown:** support registering custom containers ([962f00e](https://github.com/vuejs/vitepress/commit/962f00e7a3c22dd021729e732e12a758b42aef1c)), closes [#3591](https://github.com/vuejs/vitepress/issues/3591) [#3603](https://github.com/vuejs/vitepress/issues/3603) [#4228](https://github.com/vuejs/vitepress/issues/4228) +- **markdown:** support title-less containers ([4c7a030](https://github.com/vuejs/vitepress/commit/4c7a030bc1eecd0ed441a2f56cde73e59ff90abe)), closes [#4928](https://github.com/vuejs/vitepress/issues/4928) [#4932](https://github.com/vuejs/vitepress/issues/4932) [#4929](https://github.com/vuejs/vitepress/issues/4929) +- **markdown:** rebase relative urls in included files ([6a337ef](https://github.com/vuejs/vitepress/commit/6a337efece9697dcb1e4ae4fe657af97089570f6)) +- **markdown:** group code copy button strings into one option ([2fa0ded](https://github.com/vuejs/vitepress/commit/2fa0dedbb241e901569c2e20690e8e5917f4bd26)), closes [#4431](https://github.com/vuejs/vitepress/issues/4431) +- **markdown:** replace markdown-it-attrs with @mdit/plugin-attrs ([18380b0](https://github.com/vuejs/vitepress/commit/18380b0eb78765f49d86918c86c9fee9e7197135)) +- **markdown:** replace markdown-it-emoji with @mdit/plugin-emoji ([018887f](https://github.com/vuejs/vitepress/commit/018887fa1d03031e9c6cc96606be22df51581e35)) +- **markdown:** replace markdown-it-anchor with @mdit/plugin-anchor ([7550517](https://github.com/vuejs/vitepress/commit/75505179160bf16a88cd5648719615e982c08e41)) +- **markdown:** support `attrs: false` for disabling attrs plugin ([e235dbe](https://github.com/vuejs/vitepress/commit/e235dbeb8aef1213d0de9efafe0ccb758acd267a)) +- **markdown:** support `note`, `important`, `caution` markdown containers ([#5161](https://github.com/vuejs/vitepress/issues/5161)) ([3b560a0](https://github.com/vuejs/vitepress/commit/3b560a0efa8bdbf6f621413b3e8a27b19f4a638f)), closes [#4427](https://github.com/vuejs/vitepress/issues/4427) [#3928](https://github.com/vuejs/vitepress/issues/3928) +- **theme:** allow internal social links ([51ff681](https://github.com/vuejs/vitepress/commit/51ff681f4e5caf7dfff1f5c1c79a70aaf4785081)), closes [#5305](https://github.com/vuejs/vitepress/issues/5305) +- **theme:** cover all Inter glyphs, generate font subsets from a script ([705c1be](https://github.com/vuejs/vitepress/commit/705c1be0f88643f9fdbeb09d1835374d70afbebd)) +- update option stability annotations ([ab1896f](https://github.com/vuejs/vitepress/commit/ab1896fbf4da4b90f900d845a8410b7350ea9edd)) + +### Performance Improvements + +- **build:** reuse lastUpdated from markdown rendering in sitemap generation ([fdd68e3](https://github.com/vuejs/vitepress/commit/fdd68e37a720d2fd898033c5f695e125ee93634b)) +- **md:** bypass gray-matter's unbounded cache ([4f8703d](https://github.com/vuejs/vitepress/commit/4f8703d61ccefb61823d4f7bac67f142759d81ca)) +- **md:** limit the compile cache's memory usage ([2fb6bda](https://github.com/vuejs/vitepress/commit/2fb6bdabf03b617ccfa1d00c9261242bc5d93e56)) +- use hook filters in vite plugins ([fa24c6d](https://github.com/vuejs/vitepress/commit/fa24c6d67b4a572a56ac76aeb9f97ca3cd03170d)) + +### Reverts + +- Revert "fix: prevent DocSearch SVG clipping in WebKit" (#5304) ([c8313a4](https://github.com/vuejs/vitepress/commit/c8313a4bcd24af21cd829d7c4fd3792ecd0c17a7)), closes [#5304](https://github.com/vuejs/vitepress/issues/5304) [#5240](https://github.com/vuejs/vitepress/issues/5240) + +### BREAKING CHANGES + +- `markdown.anchor` options are now typed by `@mdit/plugin-anchor`. Common options (`level`, `slugify`, `permalink`, `getTokensText`, `tabIndex`, etc.) are unchanged, but the deprecated markdown-it-anchor permalink options (`permalinkSymbol`, `renderPermalink`, ...) are no longer accepted. Permalink builders like `headerLink` are named exports of `@mdit/plugin-anchor` instead of properties of the plugin. +- `markdown.attrs` options are now typed by `@mdit/plugin-attrs`: `leftDelimiter`, `rightDelimiter`, and `allowedAttributes` are renamed to `left`, `right`, and `allowed`. A `rule` option is available for toggling individual attribute rules (VitePress disables `fence` by default). +- `markdown.codeCopyButtonTitle` is now `markdown.codeCopyButton.tooltipText`, and its default changed from "Copy Code" to "Copy code". The `--vp-code-copy-copied-text-content` CSS variable and its built-in per-language `:lang()` defaults are removed - set `codeCopyButton.copiedText` (per locale) instead. +- `useData().hash` has been removed. Read the hash from `useRoute()` instead. +- callers of vitepress' build() will now notice the version banner gets printed. To disable that, pass a noop function: + + ```ts + build(root, { + onAfterConfigResolve() {} + }) + ``` + +- custom `themeConfig.i18nRouting` functions now receive the current `Route` as their second argument instead of the hash +- normalize-level defaults differ from the old reset - native select and number-input chrome is restored, headings inherit font size and weight, the hidden attribute is enforced with !important, and every element starts with zero margin/padding and border-style: solid. Sites layering custom CSS on the default theme may notice. +- relative urls in included markdown files resolve against the included file rather than the including page. Partials written for one specific location may need their links updated, or markdown.include.rebaseRelativeUrls set to false to keep resolving them from the including page. Absolute and external urls are unaffected. Note that the marker comments shift the line numbers reported for dead links following an include, which already pointed into the include-expanded source rather than the original file. +- **init:** scaffold() now returns a `Promise` and must be awaited. +- The `defs` property of `markdown.emoji` has been renamed to `definitions`. +- The `markdown.attrs.disable` option has been removed. Set `markdown.attrs` to `false` instead. +- The `markdown.image.lazyLoading` option has been renamed to `markdown.image.lazyLoad`. +- The deprecated `disableDetailedView` option of local search has been removed. Use `detailedView: false` instead. +- The deprecated `markdown.cjkFriendly` option has been removed. Use `markdown.cjkFriendlyEmphasis` instead. +- The deprecated `themeConfig.lastUpdatedText` option has been removed. Use `themeConfig.lastUpdated.text` instead. +- The deprecated `themeConfig.outlineTitle` option has been removed. Use `themeConfig.outline.label` instead. +- The Inter4CJK font family has been renamed to 'Inter Core'. Custom --vp-font-family-base overrides referencing Inter4CJK must be updated. + ## [2.0.0-alpha.18](https://github.com/vuejs/vitepress/compare/v2.0.0-alpha.17...v2.0.0-alpha.18) (2026-07-06) ### Bug Fixes @@ -140,6 +254,7 @@ Users who intentionally reference non-existent files or want to document include - `markdown-it-attrs` is disabled for fenced code blocks. For most users no change is required. If you want to add classes to code blocks, do it using shiki transformers instead. - Rename `cjkFriendly` to `cjkFriendlyEmphasis` in your vitepress config. Most people should be unaffected unless they want to disable the CJK emphasis behavior added v2.0.0-alpha.12. +- `useData().lastUpdated` now defaults to 0 if `lastUpdated` is enabled in config. No change is needed unless you were manually doing strict comparison in your layout or components. ## [2.0.0-alpha.12](https://github.com/vuejs/vitepress/compare/v2.0.0-alpha.11...v2.0.0-alpha.12) (2025-08-20) @@ -819,7 +934,7 @@ Users who intentionally reference non-existent files or want to document include ### BREAKING CHANGES -- 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. +- VitePress now runs on Vite 5. Please refer https://vite.dev/guide/migration for breaking changes and migration guide if you're relying on some Vite-specific things. # [1.0.0-rc.25](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.24...v1.0.0-rc.25) (2023-11-05) diff --git a/README.md b/README.md index 02700308..ed8200dd 100644 --- a/README.md +++ b/README.md @@ -31,9 +31,10 @@ Copyright (c) 2019-present, Yuxi (Evan) You This project would not be possible without the support of these amazing companies and tools. -| | | | -| ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| | | | +| --------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | VoidZero's logo | **[VoidZero](https://voidzero.dev)** | The company behind Vite, Vitest, Rolldown, and Oxc. VoidZero has been a long-time sponsor of VitePress. VitePress itself is built on top of this ecosystem of high-performance JavaScript tooling. | | StackBlitz's logo | **[StackBlitz](https://stackblitz.com)** | Creators of WebContainers and a browser-based development platform. Their technology powers the VitePress playground and provides instant preview releases for our pull requests and commits. | | Algolia's logo | **[Algolia](https://algolia.com)** | An AI-powered search platform that provides fast, scalable search. Algolia powers DocSearch for VitePress. Their team has been a long-time partner in building and maintaining our search integration. | | BrowserStack's logo | **[BrowserStack](https://browserstack.com)** | A cloud-based testing platform for websites and mobile apps. BrowserStack provides the cross-browser and real-device infrastructure used to ensure VitePress works consistently across all browsers. | +| Netlify's logo | **[Netlify](https://netlify.com)** | A platform for building, deploying, and hosting modern web projects. Netlify powers our website deployments with their generous open source plan and provides deploy previews for the pull requests. | diff --git a/__tests__/e2e/.vitepress/config.ts b/__tests__/e2e/.vitepress/config.ts index 441eda1c..7ec72c30 100644 --- a/__tests__/e2e/.vitepress/config.ts +++ b/__tests__/e2e/.vitepress/config.ts @@ -155,9 +155,7 @@ export default defineConfig({ title: 'Example', description: 'An example app using VitePress.', markdown: { - image: { - lazyLoading: true - } + image: { lazyLoad: true } }, themeConfig: { nav, diff --git a/__tests__/e2e/assets/vitepress logo.png b/__tests__/e2e/assets/vitepress logo.png new file mode 100644 index 00000000..6cb0b384 Binary files /dev/null and b/__tests__/e2e/assets/vitepress logo.png differ diff --git a/__tests__/e2e/assets/vitepress.png b/__tests__/e2e/assets/vitepress.png new file mode 100644 index 00000000..6cb0b384 Binary files /dev/null and b/__tests__/e2e/assets/vitepress.png differ diff --git a/__tests__/e2e/env.d.ts b/__tests__/e2e/env.d.ts new file mode 100644 index 00000000..a99cf76c --- /dev/null +++ b/__tests__/e2e/env.d.ts @@ -0,0 +1,5 @@ +declare module '*.vue' { + import type { DefineComponent } from 'vue' + const component: DefineComponent + export default component +} diff --git a/__tests__/e2e/markdown-extensions/index.md b/__tests__/e2e/markdown-extensions/index.md index 3446b4ef..c95d60e0 100644 --- a/__tests__/e2e/markdown-extensions/index.md +++ b/__tests__/e2e/markdown-extensions/index.md @@ -56,6 +56,18 @@ This is a dangerous warning. This is a details block. ::: +::: note +This is a note. +::: + +::: important +This is an important note. +::: + +::: caution +This is a caution note. +::: + ### Custom Title ::: danger STOP diff --git a/__tests__/e2e/tsconfig.json b/__tests__/e2e/tsconfig.json new file mode 100644 index 00000000..44878152 --- /dev/null +++ b/__tests__/e2e/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../tsconfig.json", + "include": ["**/*", ".vitepress/**/*"] +} diff --git a/__tests__/init/init.test.ts b/__tests__/init/init.test.ts index 0066f43d..11ea8c32 100644 --- a/__tests__/init/init.test.ts +++ b/__tests__/init/init.test.ts @@ -39,7 +39,7 @@ afterAll(async () => { test.each(variations)('init %s', async (_, { theme, useTs }) => { const root = getTempRoot() await rm(root, { recursive: true, force: true }) - scaffold({ root, theme, useTs, injectNpmScripts: false }) + await scaffold({ root, theme, useTs, injectNpmScripts: false }) const port = await getPort() const server = await createServer(root, { port }) diff --git a/__tests__/init/tsconfig.json b/__tests__/init/tsconfig.json new file mode 100644 index 00000000..3c43903c --- /dev/null +++ b/__tests__/init/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../tsconfig.json" +} diff --git a/__tests__/tsconfig.json b/__tests__/tsconfig.json index 9cce3a1e..366c4ab8 100644 --- a/__tests__/tsconfig.json +++ b/__tests__/tsconfig.json @@ -1,12 +1,8 @@ { "extends": "../tsconfig.json", "compilerOptions": { + "noEmit": true, "isolatedModules": false, - "types": ["node", "vitest/globals"], - "paths": { - "client/*": ["../src/client/*"], - "node/*": ["../src/node/*"], - "shared/*": ["../src/shared/*"] - } + "types": ["node", "vitest/globals"] } } diff --git a/__tests__/unit/client/theme-default/composables/langs.test.ts b/__tests__/unit/client/theme-default/composables/langs.test.ts index dc91bbe7..39fe021c 100644 --- a/__tests__/unit/client/theme-default/composables/langs.test.ts +++ b/__tests__/unit/client/theme-default/composables/langs.test.ts @@ -1,15 +1,36 @@ import { resolveLocaleLink } from 'client/theme-default/composables/langs' -import type { VitePressData } from 'vitepress' +import type { Route, VitePressData } from 'vitepress' import type { DefaultTheme } from 'vitepress/theme' import { ref } from 'vue' -function createData( - themeConfig: DefaultTheme.Config, - relativePath = 'guide/getting-started.md', - cleanUrls = false, - hash = '#install' +// `currentPage` is the current page's relative path (like +// `route.data.relativePath`, but with a leading slash), plus any query and +// hash of the current URL. +function resolve( + currentPage: string, + { + themeConfig = {}, + cleanUrls = false, + targetLocale = 'fr', + targetLocaleLink = '/fr/', + currentLocaleLink = '/', + linkToCorrespondingPage = true + }: { + themeConfig?: DefaultTheme.Config + cleanUrls?: boolean + targetLocale?: string + targetLocaleLink?: string + currentLocaleLink?: string + linkToCorrespondingPage?: boolean + } = {} ) { - return { + const { pathname, search, hash } = new URL(currentPage, 'http://a.com') + const route = { + data: { relativePath: pathname.slice(1) }, + query: search, + hash + } as Route + const data = { site: ref({ cleanUrls, locales: { @@ -18,52 +39,108 @@ function createData( }, themeConfig }), - page: ref({ relativePath }), - theme: ref(themeConfig), - hash: ref(hash) + theme: ref(themeConfig) } as unknown as VitePressData -} -describe('client/theme-default/composables/langs', () => { - test('resolves corresponding links with the default router', () => { - expect(resolveLocaleLink(createData({}), 'fr', '/fr/', '/', true)).toBe( - '/fr/guide/getting-started.html#install' - ) + return resolveLocaleLink(data, route, { + targetLocale, + targetLocaleLink, + currentLocaleLink, + linkToCorrespondingPage }) +} - test('resolves clean index links with the default router', () => { - expect( - resolveLocaleLink( - createData({}, 'en/guide/index.md', true, '#intro'), - 'fr', - '/fr/', - '/en/', - true - ) - ).toBe('/fr/guide/#intro') - }) +describe('client/theme-default/composables/langs', () => { + describe('resolveLocaleLink', () => { + describe('locale home links (linkToCorrespondingPage: false)', () => { + test('links to the target locale home', () => { + expect( + resolve('/guide/getting-started.md', { + linkToCorrespondingPage: false + }) + ).toBe('/fr/') + }) - test('keeps locale root links when i18n routing is disabled', () => { - expect( - resolveLocaleLink( - createData({ i18nRouting: false }), - 'fr', - '/fr/', - '/', - true - ) - ).toBe('/fr/#install') - }) + test('preserves query and hash', () => { + expect( + resolve('/guide/getting-started.md?a=1#install', { + linkToCorrespondingPage: false + }) + ).toBe('/fr/?a=1#install') + }) - test('uses custom i18n routing functions for corresponding links', () => { - const data = createData({ - i18nRouting(data, hash, targetLocale) { - return `${data.site.value.locales[targetLocale].link}mapped/${data.page.value.relativePath}${hash}` - } + test('ignores custom i18n routing functions', () => { + expect( + resolve('/guide/getting-started.md', { + linkToCorrespondingPage: false, + themeConfig: { i18nRouting: () => '/custom/' } + }) + ).toBe('/fr/') + }) }) - expect(resolveLocaleLink(data, 'fr', '/fr/', '/', true)).toBe( - '/fr/mapped/guide/getting-started.md#install' - ) + describe('corresponding page links (linkToCorrespondingPage: true)', () => { + test('rewrites the current page path into the target locale', () => { + expect(resolve('/guide/getting-started.md#install')).toBe( + '/fr/guide/getting-started.html#install' + ) + }) + + test('drops the .html extension when clean URLs are enabled', () => { + expect( + resolve('/guide/getting-started.md#install', { cleanUrls: true }) + ).toBe('/fr/guide/getting-started#install') + }) + + test('resolves index pages to directory links', () => { + expect(resolve('/guide/index.md')).toBe('/fr/guide/') + expect(resolve('/guide/index.md', { cleanUrls: true })).toBe( + '/fr/guide/' + ) + }) + + test('resolves the site root page to the target locale home', () => { + expect(resolve('/index.md')).toBe('/fr/') + }) + + test('strips the current locale prefix before rewriting', () => { + expect( + resolve('/en/guide/index.md?query#intro', { + currentLocaleLink: '/en/', + cleanUrls: true + }) + ).toBe('/fr/guide/?query#intro') + }) + + test('rewrites into the root locale', () => { + expect( + resolve('/fr/guide/getting-started.md#install', { + targetLocale: 'root', + targetLocaleLink: '/', + currentLocaleLink: '/fr/' + }) + ).toBe('/guide/getting-started.html#install') + }) + + test('links to the target locale home when i18n routing is disabled', () => { + expect( + resolve('/guide/getting-started.md#install', { + themeConfig: { i18nRouting: false } + }) + ).toBe('/fr/#install') + }) + + test('delegates to custom i18n routing functions', () => { + expect( + resolve('/guide/getting-started.md#install', { + themeConfig: { + i18nRouting(data, route, targetLocale) { + return `${data.site.value.locales[targetLocale].link}mapped/${route.data.relativePath}${route.hash}` + } + } + }) + ).toBe('/fr/mapped/guide/getting-started.md#install') + }) + }) }) }) diff --git a/__tests__/unit/client/theme-default/support/sidebar.test.ts b/__tests__/unit/client/theme-default/support/sidebar.test.ts index 7232757c..c5a4d44f 100644 --- a/__tests__/unit/client/theme-default/support/sidebar.test.ts +++ b/__tests__/unit/client/theme-default/support/sidebar.test.ts @@ -188,8 +188,8 @@ describe('client/theme-default/support/sidebar', () => { ] } - expect(hasActiveLink('active-1', item)).toBe(true) - expect(hasActiveLink('inactive', item)).toBe(false) + expect(hasActiveLink('active-1', '', item)).toBe(true) + expect(hasActiveLink('inactive', '', item)).toBe(false) }) test('checks `SidebarItem[]`', () => { @@ -210,9 +210,9 @@ describe('client/theme-default/support/sidebar', () => { } ] - expect(hasActiveLink('active-1', item)).toBe(true) - expect(hasActiveLink('active-3', item)).toBe(true) - expect(hasActiveLink('inactive', item)).toBe(false) + expect(hasActiveLink('active-1', '', item)).toBe(true) + expect(hasActiveLink('active-3', '', item)).toBe(true) + expect(hasActiveLink('inactive', '', item)).toBe(false) }) }) }) diff --git a/__tests__/unit/node/config.test.ts b/__tests__/unit/node/config.test.ts index 22f7d034..df4af72c 100644 --- a/__tests__/unit/node/config.test.ts +++ b/__tests__/unit/node/config.test.ts @@ -1,15 +1,18 @@ import type { MarkdownItAsync } from 'markdown-it-async' -import { mergeConfig } from 'node/config' +import { mergeConfig, type UserConfig } from 'node/config' describe('node/config', () => { - test('merges markdown config hooks from extended configs', async () => { + test('merges markdown hooks from extended configs', async () => { const calls: string[] = [] const md = {} as MarkdownItAsync - const merged = mergeConfig( + const merged = mergeConfig( { markdown: { lineNumbers: true, + preConfig() { + calls.push('base-pre') + }, config() { calls.push('base') } @@ -18,7 +21,10 @@ describe('node/config', () => { { markdown: { attrs: { - allowedAttributes: ['id'] + allowed: ['id'] + }, + async preConfig() { + calls.push('extended-pre') }, async config() { calls.push('extended') @@ -29,11 +35,39 @@ describe('node/config', () => { expect(merged.markdown?.lineNumbers).toBe(true) expect(merged.markdown?.attrs).toEqual({ - allowedAttributes: ['id'] + allowed: ['id'] }) + await merged.markdown?.preConfig?.(md) + await merged.markdown?.config?.(md) + + expect(calls).toEqual(['base-pre', 'extended-pre', 'base', 'extended']) + }) + + test('keeps one-sided markdown hooks when the other config omits them', async () => { + const calls: string[] = [] + const md = {} as MarkdownItAsync + + const merged = mergeConfig( + { + markdown: { + preConfig() { + calls.push('base-pre') + } + } + }, + { + markdown: { + config() { + calls.push('extended') + } + } + } + ) + + await merged.markdown?.preConfig?.(md) await merged.markdown?.config?.(md) - expect(calls).toEqual(['base', 'extended']) + expect(calls).toEqual(['base-pre', 'extended']) }) }) diff --git a/__tests__/unit/node/contentLoader.test.ts b/__tests__/unit/node/contentLoader.test.ts new file mode 100644 index 00000000..197745f6 --- /dev/null +++ b/__tests__/unit/node/contentLoader.test.ts @@ -0,0 +1,51 @@ +import { resolveConfig } from 'node/config' +import { createContentLoader } from 'node/contentLoader' +import { mkdtemp, rm, writeFile } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import path from 'node:path' + +describe('node/contentLoader', () => { + let root: string | undefined + + afterEach(async () => { + if (root) { + await rm(root, { recursive: true, force: true }) + root = undefined + } + delete (global as any).VITEPRESS_CONFIG + }) + + async function setup(cleanUrls: boolean) { + root = await mkdtemp(path.join(tmpdir(), 'vitepress-content-loader-')) + await writeFile( + path.join(root, 'index.md'), + '# Home\n\n[link](./other.md)\n' + ) + await writeFile(path.join(root, 'other.md'), '# Other\n') + + const siteConfig = await resolveConfig(root, 'build', 'production') + siteConfig.cleanUrls = cleanUrls + ;(global as any).VITEPRESS_CONFIG = siteConfig + } + + test('rendered internal links get .html when cleanUrls is false', async () => { + await setup(false) + + const data = await createContentLoader('index.md', { + render: true + }).load() + + expect(data[0].html).toContain('href="./other.html"') + }) + + test('rendered internal links are clean when cleanUrls is true', async () => { + await setup(true) + + const data = await createContentLoader('index.md', { + render: true + }).load() + + expect(data[0].html).toContain('href="./other"') + expect(data[0].html).not.toContain('./other.html') + }) +}) diff --git a/__tests__/unit/node/markdown/markdown.test.ts b/__tests__/unit/node/markdown/markdown.test.ts new file mode 100644 index 00000000..5db12abd --- /dev/null +++ b/__tests__/unit/node/markdown/markdown.test.ts @@ -0,0 +1,206 @@ +import { anchor as anchorPlugin } from '@mdit/plugin-anchor' +import { attrs as attrsPlugin } from '@mdit/plugin-attrs' +import { MarkdownItAsync } from 'markdown-it-async' +import { + createMarkdownRenderer, + disposeMdItInstance, + type MarkdownOptions +} from 'node/markdown/markdown' + +async function render(src: string, options: MarkdownOptions = {}) { + disposeMdItInstance() + const md = await createMarkdownRenderer('.', { + highlight: (code) => code, + ...options + }) + return md.renderAsync(src) +} + +describe('node/markdown/markdown', () => { + describe('disabling built-in plugins', () => { + test('anchor', async () => { + const enabled = await render('# Hello World') + expect(enabled).toContain('id="hello-world"') + expect(enabled).toContain('header-anchor') + + const disabled = await render('# Hello World', { anchor: false }) + expect(disabled).not.toContain('id=') + expect(disabled).not.toContain('header-anchor') + }) + + test('attrs', async () => { + const enabled = await render('## Title {#custom-id}') + expect(enabled).toContain('id="custom-id"') + + const disabled = await render('## Title {#custom-id}', { attrs: false }) + expect(disabled).not.toContain('id="custom-id"') + expect(disabled).toContain('{#custom-id}') + }) + + test('emoji', async () => { + expect(await render(':tada:')).toContain('🎉') + expect(await render(':tada:', { emoji: false })).toContain(':tada:') + }) + + test('tasklist', async () => { + const src = '- [ ] todo' + expect(await render(src)).toContain(' { + const src = '# Title\n\n[[toc]]' + expect(await render(src)).toContain('table-of-contents') + + const disabled = await render(src, { toc: false }) + expect(disabled).not.toContain('table-of-contents') + expect(disabled).toContain('[[toc]]') + }) + + test('preWrapper', async () => { + const src = '```js\nconst a = 1\n```' + const enabled = await render(src) + expect(enabled).toContain('
') + expect(enabled).toContain('class="copy"') + + const disabled = await render(src, { preWrapper: false }) + expect(disabled).not.toContain('
') + expect(disabled).not.toContain('class="copy"') + }) + + test('preWrapper disables line numbers with it', async () => { + const src = '```js\nconst a = 1\n```' + const enabled = await render(src, { lineNumbers: true }) + expect(enabled).toContain('line-numbers-wrapper') + + const disabled = await render(src, { + preWrapper: false, + lineNumbers: true + }) + expect(disabled).not.toContain('line-numbers-wrapper') + }) + + test('snippet', async () => { + const disabled = await render('<<< ./foo.js', { snippet: false }) + expect(disabled).toContain('<<< ./foo.js') + }) + + test('image', async () => { + const src = '![img](/foo.png)' + const enabled = await render(src, { image: { lazyLoad: true } }) + expect(enabled).toContain('loading="lazy"') + + const disabled = await render(src, { image: false }) + expect(disabled).not.toContain('loading="lazy"') + }) + + test('component', async () => { + const src = 'text\n\nmore' + const enabled = await render(src) + expect(enabled).toContain('

\n

') + + const disabled = await render(src, { component: false }) + expect(disabled).toContain('

text\n\nmore

') + }) + + test('tableTabIndex', async () => { + const src = '| a |\n| --- |\n| b |' + expect(await render(src)).toContain('tabindex="0"') + expect(await render(src, { tableTabIndex: false })).not.toContain( + 'tabindex' + ) + }) + + test('cjkFriendlyEmphasis', async () => { + const src = 'これは**「テスト」**です' + expect(await render(src)).toContain('「テスト」') + expect(await render(src, { cjkFriendlyEmphasis: false })).not.toContain( + '' + ) + }) + + test('`true` enables a plugin with its default options', async () => { + const html = await render( + '## Title {#custom-id}\n\n[[toc]]\n\n:tada:\n\n- [ ] todo', + { + anchor: true, + attrs: true, + emoji: true, + tasklist: true, + toc: true, + image: true, + component: true + } + ) + expect(html).toContain('id="custom-id"') + expect(html).toContain('header-anchor') + expect(html).toContain('table-of-contents') + expect(html).toContain('🎉') + expect(html).toContain(' { + test('does not consume fence info', async () => { + // line-highlight / meta syntax must reach the highlighter untouched + const meta = await render('```js{4}\nconst a = 1\n```') + expect(meta).toContain('language-js') + expect(meta).not.toContain('4=""') + + // curly attributes have no effect on fenced code blocks + const backtick = await render('```js {.foo}\nconst a = 1\n```') + expect(backtick).not.toContain('class="foo"') + const tilde = await render('~~~js {.foo}\nconst a = 1\n~~~') + expect(tilde).not.toContain('class="foo"') + }) + + test('applies to inline elements and blocks', async () => { + expect(await render('*hi*{.cls}')).toContain('') + expect(await render('`code`{.cls}')).toContain('class="cls"') + expect(await render('text {.cls}')).toContain('

') + expect(await render('- item\n{.cls}')).toContain('

    ') + expect(await render('| a |\n| --- |\n| b |\n\n{.cls}')).toContain( + ' { + test('renders checkboxes with their checked state', async () => { + const html = await render('- [ ] todo\n- [x] done') + expect(html).toContain('
      ') + expect(html).toContain('
    • ') + + const inputs = html.match(/]*>/g)! + expect(inputs).toHaveLength(2) + expect(inputs[0]).not.toContain('checked') + expect(inputs[1]).toContain('checked') + for (const input of inputs) expect(input).toContain('disabled') + }) + + test('forwards options to the plugin', async () => { + const html = await render('- [ ] todo', { tasklist: { label: false } }) + expect(html).toContain(' { + for (const plugins of [ + [attrsPlugin, anchorPlugin], + [anchorPlugin, attrsPlugin] + ] as const) { + const md = new MarkdownItAsync() + for (const plugin of plugins) md.use(plugin) + expect(await md.renderAsync('## Title {#custom-id}')).toContain( + 'id="custom-id"' + ) + } + }) +}) diff --git a/__tests__/unit/node/markdown/plugins/containers.test.ts b/__tests__/unit/node/markdown/plugins/containers.test.ts new file mode 100644 index 00000000..18e69025 --- /dev/null +++ b/__tests__/unit/node/markdown/plugins/containers.test.ts @@ -0,0 +1,607 @@ +import { + createMarkdownRenderer, + disposeMdItInstance, + type MarkdownOptions +} from 'node/markdown/markdown' +import type { MarkdownEnv } from 'node/shared' + +async function render( + src: string, + options: MarkdownOptions = {}, + env?: Partial +) { + disposeMdItInstance() + const md = await createMarkdownRenderer('.', { + highlight: (code) => code, + ...options + }) + return md.renderAsync(src, env) +} + +describe('node/markdown/plugins/containers', () => { + test('renders built-in containers with default titles', async () => { + const src = [ + 'tip', + 'info', + 'warning', + 'danger', + 'note', + 'important', + 'caution' + ] + .map((t) => `::: ${t}\ncontent of ${t}\n:::`) + .join('\n\n') + expect(await render(src)).toMatchInlineSnapshot(` + "

      TIP

      +

      content of tip

      +
      +

      INFO

      +

      content of info

      +
      +

      WARNING

      +

      content of warning

      +
      +

      DANGER

      +

      content of danger

      +
      +

      NOTE

      +

      content of note

      +
      +

      IMPORTANT

      +

      content of important

      +
      +

      CAUTION

      +

      content of caution

      +
      + " + `) + }) + + test('renders details as a disclosure with summary', async () => { + expect(await render('::: details\nhidden content\n:::')) + .toMatchInlineSnapshot(` + "
      Details +

      hidden content

      +
      + " + `) + }) + + test('renders custom titles, including inline markdown', async () => { + const src = [ + '::: danger STOP', + 'Danger zone, do not proceed', + ':::', + '', + '::: tip A **bold** _title_ with `code`', + 'content', + ':::', + '', + '::: details Click me to toggle the code', + '```js', + "console.log('hi')", + '```', + ':::' + ].join('\n') + expect(await render(src)).toMatchInlineSnapshot(` + "

      STOP

      +

      Danger zone, do not proceed

      +
      +

      A bold title with code

      +

      content

      +
      +
      Click me to toggle the code +
      js
      console.log('hi')
      +      
      +
      + " + `) + }) + + test('resolves reference links in titles', async () => { + const src = [ + '::: tip See [the guide][guide]', + 'content', + ':::', + '', + '[guide]: /guide/' + ].join('\n') + expect(await render(src)).toMatchInlineSnapshot(` + "

      See the guide

      +

      content

      +
      + " + `) + }) + + test('respects custom labels from container options', async () => { + const src = '::: tip\n提示内容\n:::\n\n::: details\n详情内容\n:::' + expect( + await render(src, { + container: { tipLabel: '提示', detailsLabel: '详细信息' } + }) + ).toMatchInlineSnapshot(` + "

      提示

      +

      提示内容

      +
      +
      详细信息 +

      详情内容

      +
      + " + `) + }) + + test('registers custom containers from container options', async () => { + const src = [ + '::: success', + 'You have completed the walkthrough!', + ':::', + '', + '::: success Well done {no-title}', + 'content', + ':::' + ].join('\n') + expect( + await render(src, { + container: { customContainers: { success: 'SUCCESS' } } + }) + ).toMatchInlineSnapshot(` + "

      SUCCESS

      +

      You have completed the walkthrough!

      +
      +
      +

      content

      +
      + " + `) + }) + + test('rejects invalid custom container names', async () => { + for (const name of ['raw', 'v-pre', 'code-group', 'Bad Name', 'UPPER']) { + await expect( + render('text', { container: { customContainers: { [name]: 'X' } } }) + ).rejects.toThrow('Invalid custom container name') + } + }) + + test('supports attrs on the fence line', async () => { + const src = [ + '::: details Click me {open}', + 'content', + ':::', + '', + '::: tip Custom {.extra-class #custom-id}', + 'content', + ':::' + ].join('\n') + expect(await render(src)).toMatchInlineSnapshot(` + "
      Click me +

      content

      +
      +

      Custom

      +

      content

      +
      + " + `) + }) + + test('supports quoted and bare attr values on the fence line', async () => { + expect(await render('::: tip Custom {data-a="b c" data-d=e}\ncontent\n:::')) + .toMatchInlineSnapshot(` + "

      Custom

      +

      content

      +
      + " + `) + }) + + test('skips the title element with a no-title attr', async () => { + const src = [ + '::: tip {no-title}', + 'content', + ':::', + '', + '::: warning Discarded {no-title .extra-class}', + 'content', + ':::', + '', + '::: details {no-title}', + 'still needs its summary', + ':::' + ].join('\n') + expect(await render(src)).toMatchInlineSnapshot(` + "
      +

      content

      +
      +
      +

      content

      +
      +
      Details +

      still needs its summary

      +
      + " + `) + }) + + test('respects attrs plugin options on the fence line', async () => { + const delimiters = await render( + '::: tip Custom %(.extra-class)%\ncontent\n:::', + { attrs: { left: '%(', right: ')%' } } + ) + expect(delimiters).toContain('
      ') + + const allowed = await render( + '::: tip Custom {.extra-class data-x=1}\ncontent\n:::', + { attrs: { allowed: ['class'] } } + ) + expect(allowed).toContain('
      ') + expect(allowed).not.toContain('data-x') + }) + + test('keeps fence line braces verbatim when attrs are disabled', async () => { + expect( + await render('::: details Click me {open}\ncontent\n:::', { + attrs: false + }) + ).toMatchInlineSnapshot(` + "
      Click me {open} +

      content

      +
      + " + `) + }) + + test('renders v-pre and raw containers as plain wrappers', async () => { + const src = [ + '::: v-pre', + '{{ this will be displayed as-is }}', + ':::', + '', + '::: raw', + 'Wraps in a `
      `', + ':::' + ].join('\n') + expect(await render(src)).toMatchInlineSnapshot(` + "
      +

      {{ this will be displayed as-is }}

      +
      +
      +

      Wraps in a <div class="vp-raw">

      +
      + " + `) + }) + + test('renders code groups with tabs', async () => { + const src = [ + '::: code-group', + '', + '```js [config.js]', + 'const a = 1', + '```', + '', + '```ts [config.ts]', + 'const a: number = 1', + '```', + '', + ':::' + ].join('\n') + expect(await render(src)).toMatchInlineSnapshot(` + "
      +
      js
      const a = 1
      +      
      +
      ts
      const a: number = 1
      +      
      +
      + " + `) + }) + + test('supports nesting via longer fences', async () => { + const src = [ + ':::: info Outer', + 'outer content', + '', + '::: details Inner', + 'inner content', + ':::', + '::::' + ].join('\n') + expect(await render(src)).toMatchInlineSnapshot(` + "

      Outer

      +

      outer content

      +
      Inner +

      inner content

      +
      +
      + " + `) + }) + + test('auto-closes unclosed containers', async () => { + expect(await render('::: warning\nno closing fence')) + .toMatchInlineSnapshot(` + "

      WARNING

      +

      no closing fence

      +
      + " + `) + }) + + test('parses fences without a space before the name', async () => { + expect(await render(':::tip\ncontent\n:::')).toMatchInlineSnapshot(` + "

      TIP

      +

      content

      +
      + " + `) + }) + + test('leaves non-container fence lines alone', async () => { + expect(await render('::: unknown\ncontent\n:::')).toMatchInlineSnapshot(` + "

      ::: unknown + content + :::

      + " + `) + }) +}) + +describe('node/markdown/plugins/containers (github alerts)', () => { + test('renders github alerts like containers', async () => { + const src = [ + '> [!NOTE]', + '> note content', + '', + '> [!TIP]', + '> tip content', + '', + '> [!IMPORTANT]', + '> important content', + '', + '> [!WARNING]', + '> warning content', + '', + '> [!CAUTION]', + '> caution content' + ].join('\n') + expect(await render(src)).toMatchInlineSnapshot(` + "

      NOTE

      +

      note content

      +
      +

      TIP

      +

      tip content

      +
      +

      IMPORTANT

      +

      important content

      +
      +

      WARNING

      +

      warning content

      +
      +

      CAUTION

      +

      caution content

      +
      + " + `) + }) + + test('matches markers case-insensitively', async () => { + expect(await render('> [!tip]\n> content')).toMatchInlineSnapshot(` + "

      TIP

      +

      content

      +
      + " + `) + }) + + test('supports custom titles after the marker', async () => { + expect(await render('> [!WARNING] Custom Title\n> content')) + .toMatchInlineSnapshot(` + "

      Custom Title

      +

      content

      +
      + " + `) + }) + + test('respects custom labels from container options', async () => { + expect( + await render('> [!TIP]\n> content', { container: { tipLabel: '提示' } }) + ).toMatchInlineSnapshot(` + "

      提示

      +

      content

      +
      + " + `) + }) + + test('renders custom containers as alerts', async () => { + expect( + await render('> [!SUCCESS]\n> done\n\n> [!success] With title\n> done', { + container: { customContainers: { success: 'SUCCESS' } } + }) + ).toMatchInlineSnapshot(` + "

      SUCCESS

      +

      done

      +
      +

      With title

      +

      done

      +
      + " + `) + }) + + test('supports block content and lazy continuation', async () => { + const src = [ + '> [!NOTE]', + '> first paragraph', + 'lazy continuation', + '>', + '> - list item', + '>', + '> ```js', + '> const a = 1', + '> ```' + ].join('\n') + expect(await render(src)).toMatchInlineSnapshot(` + "

      NOTE

      +

      first paragraph + lazy continuation

      +
        +
      • list item
      • +
      +
      js
      const a = 1
      +      
      +
      + " + `) + }) + + test('converts markers without content', async () => { + expect(await render('> [!NOTE]')).toMatchInlineSnapshot(` + "

      NOTE

      +

      +
      + " + `) + }) + + test('leaves regular blockquotes and unknown markers alone', async () => { + const src = [ + '> just a quote', + '', + '> [!FOO]', + '> not an alert', + '', + 'paragraph [!NOTE] not at blockquote start' + ].join('\n') + expect(await render(src)).toMatchInlineSnapshot(` + "
      +

      just a quote

      +
      +
      +

      [!FOO] + not an alert

      +
      +

      paragraph [!NOTE] not at blockquote start

      + " + `) + }) + + test('can be disabled via gfmAlerts: false', async () => { + expect(await render('> [!NOTE]\n> content', { gfmAlerts: false })) + .toMatchInlineSnapshot(` + "
      +

      [!NOTE] + content

      +
      + " + `) + }) +}) + +describe('node/markdown/plugins/containers (locales)', () => { + const options: MarkdownOptions = { + container: { + tipLabel: 'ROOT TIP', + customContainers: { success: 'SUCCESS' } + }, + locales: { + zh: { + container: { + tipLabel: '提示', + detailsLabel: '详细信息', + customContainers: { success: '成功' } + } + } + } + } + + test('resolves container titles for the active locale', async () => { + const src = + '::: tip\n内容\n:::\n\n::: details\n内容\n:::\n\n::: success\n内容\n:::' + expect(await render(src, options, { localeIndex: 'zh' })) + .toMatchInlineSnapshot(` + "

      提示

      +

      内容

      +
      +
      详细信息 +

      内容

      +
      +

      成功

      +

      内容

      +
      + " + `) + }) + + test('falls back to root titles for other locales', async () => { + const src = '::: tip\ncontent\n:::' + const root = await render(src, options) + expect(await render(src, options, { localeIndex: 'es' })).toBe(root) + expect(root).toMatchInlineSnapshot(` + "

      ROOT TIP

      +

      content

      +
      + " + `) + }) + + test('explicit titles win over locale defaults', async () => { + expect( + await render('::: tip Custom Title\n内容\n:::', options, { + localeIndex: 'zh' + }) + ).toMatchInlineSnapshot(` + "

      Custom Title

      +

      内容

      +
      + " + `) + }) + + test('resolves alert titles for the active locale', async () => { + expect( + await render('> [!TIP]\n> 内容\n\n> [!SUCCESS]\n> 内容', options, { + localeIndex: 'zh' + }) + ).toMatchInlineSnapshot(` + "

      提示

      +

      内容

      +
      +

      成功

      +

      内容

      +
      + " + `) + }) + + test('rejects locale titles for unregistered containers', async () => { + await expect( + render('text', { + locales: { zh: { container: { customContainers: { nope: 'X' } } } } + }) + ).rejects.toThrow('is not registered in the root markdown config') + }) + + test('resolves the code copy button strings for the active locale', async () => { + const src = '```js\nconst a = 1\n```' + const opts: MarkdownOptions = { + codeCopyButton: { copiedText: 'Copied!' }, + locales: { + zh: { + codeCopyButton: { tooltipText: '复制代码', copiedText: '已复制' } + } + } + } + const zh = await render(src, opts, { localeIndex: 'zh' }) + expect(zh).toContain('title="复制代码"') + expect(zh).toContain('data-copied="已复制"') + const es = await render(src, opts, { localeIndex: 'es' }) + expect(es).toContain('title="Copy code"') + expect(es).toContain('data-copied="Copied!"') + const root = await render(src, opts) + expect(root).toContain('title="Copy code"') + expect(root).toContain('data-copied="Copied!"') + }) +}) diff --git a/__tests__/unit/node/markdown/plugins/image.test.ts b/__tests__/unit/node/markdown/plugins/image.test.ts new file mode 100644 index 00000000..c6a346cc --- /dev/null +++ b/__tests__/unit/node/markdown/plugins/image.test.ts @@ -0,0 +1,141 @@ +import path from 'node:path' +import { MarkdownItAsync } from 'markdown-it-async' +import { attrs as attrsPlugin } from '@mdit/plugin-attrs' +import { imagePlugin, type Options } from 'node/markdown/plugins/image' + +const srcDir = path.resolve(import.meta.dirname, '../../../../e2e') +const publicDir = path.join(srcDir, 'public') +const env = { path: path.join(srcDir, 'index.md') } + +function createRenderer(options?: Options) { + const md = new MarkdownItAsync() + + // same registration order as createMarkdownRenderer + imagePlugin(md, publicDir, options) + attrsPlugin(md as any) + + return md +} + +describe('node/markdown/plugins/image', () => { + const md = createRenderer() + + describe('src normalization', () => { + test('default image output', async () => { + const html = await md.renderAsync('![logo](foo.png)') + + expect(html.trim()).toMatchInlineSnapshot( + `"

      logo

      "` + ) + }) + + test.for([ + ['foo.png', './foo.png'], + ['./foo.png', './foo.png'], + ['../foo.png', '../foo.png'], + ['../../foo.png', '../../foo.png'], + ['/foo.png', '/foo.png'], + ['https://example.com/foo.png', 'https://example.com/foo.png'] + ])('normalizes image src: %s → %s', async ([src, expected]) => { + const html = await md.renderAsync(`![logo](${src})`) + + expect(html).toContain(`src="${expected}"`) + }) + }) + + describe('dimensions', () => { + test('adds width and height from local image dimensions', async () => { + const html = await md.renderAsync('![logo](./assets/vitepress.png)', env) + + expect(html).toContain('width="48"') + expect(html).toContain('height="48"') + }) + + test('adds width and height from public image dimensions', async () => { + const html = await md.renderAsync('![logo](/vitepress.png)', env) + + expect(html).toContain('width="48"') + expect(html).toContain('height="48"') + }) + + test('adds width and height when the image url is encoded', async () => { + const html = await md.renderAsync( + '![logo](./assets/vitepress%20logo.png)', + env + ) + + expect(html).toContain('src="./assets/vitepress logo.png"') + expect(html).toContain('width="48"') + expect(html).toContain('height="48"') + }) + + test('does not override explicit width and height', async () => { + const html = await md.renderAsync( + '![logo](/vitepress.png){width=100 height=200}', + env + ) + + expect(html).toContain('width="100"') + expect(html).toContain('height="200"') + }) + + test('scales height proportionally when only width is set', async () => { + const html = await md.renderAsync( + '![logo](/vitepress.png){width=96}', + env + ) + + // 48x48 image scaled to width=96 → height=96 + expect(html).toContain('width="96"') + expect(html).toContain('height="96"') + }) + + test('scales width proportionally when only height is set', async () => { + const html = await md.renderAsync( + '![logo](/vitepress.png){height=24}', + env + ) + + // 48x48 image scaled to height=24 → width=24 + expect(html).toContain('width="24"') + expect(html).toContain('height="24"') + }) + + test('ignores non-numeric width when scaling', async () => { + const html = await md.renderAsync( + '![logo](/vitepress.png){width=50%}', + env + ) + + expect(html).toContain('width="50%"') + expect(html).not.toContain('height=') + }) + + test('does not add dimensions for external images', async () => { + const html = await md.renderAsync( + '![logo](https://example.com/image.png)', + env + ) + + expect(html).not.toContain('width=') + expect(html).not.toContain('height=') + }) + }) + + describe('lazy loading', () => { + const mdLazy = createRenderer({ lazyLoad: true }) + + test('adds loading="lazy" when lazy loading is enabled', async () => { + const html = await mdLazy.renderAsync('![logo](foo.png)') + + expect(html).toContain('loading="lazy"') + }) + + test('does not override user-specified loading strategy', async () => { + const html = await mdLazy.renderAsync('![logo](foo.png){loading=eager}') + + expect(html).toContain('loading="eager"') + expect(html).not.toContain('loading="lazy"') + }) + }) +}) diff --git a/__tests__/unit/node/markdown/plugins/include.test.ts b/__tests__/unit/node/markdown/plugins/include.test.ts new file mode 100644 index 00000000..053bd58e --- /dev/null +++ b/__tests__/unit/node/markdown/plugins/include.test.ts @@ -0,0 +1,534 @@ +import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import path from 'node:path' +import { + createMarkdownRenderer, + disposeMdItInstance, + type MarkdownOptions +} from 'node/markdown/markdown' +import { slash, type MarkdownEnv } from 'node/shared' + +describe('node/markdown/plugins/include', () => { + let root: string + let warnings: string[] + + const logger = { + warn: (msg: string) => { + warnings.push(msg) + } + } + + beforeEach(async () => { + root = await mkdtemp(path.join(tmpdir(), 'vitepress-include-')) + warnings = [] + }) + + afterEach(async () => { + await rm(root, { recursive: true, force: true }) + }) + + async function write(name: string, src: string) { + const file = path.join(root, name) + await mkdir(path.dirname(file), { recursive: true }) + await writeFile(file, src) + } + + async function render( + src: string, + options: MarkdownOptions = {}, + env: Partial = {} + ) { + disposeMdItInstance() + const md = await createMarkdownRenderer( + root, + { highlight: (code) => code, ...options }, + '/', + logger + ) + const fullEnv: MarkdownEnv = { + path: path.join(root, 'index.md'), + relativePath: 'index.md', + cleanUrls: false, + includes: [], + ...env + } + const html = await md.renderAsync(src, fullEnv) + return { html, env: fullEnv } + } + + test('includes a relative markdown file', async () => { + await write('b.md', 'B-content\n') + + const { html, env } = await render('# A\n\n\n') + expect(html).toContain('B-content') + expect(env.includes).toEqual([slash(path.join(root, 'b.md'))]) + expect(env.src).toContain('B-content') + }) + + test('resolves @ against srcDir', async () => { + await write('dir/c.md', 'C-content\n') + + const { html } = await render( + '\n', + {}, + { path: path.join(root, 'sub/index.md') } + ) + expect(html).toContain('C-content') + }) + + test('resolves @ without a slash against srcDir', async () => { + await write('dir/c.md', 'C-content\n') + + const { html } = await render( + '\n', + {}, + { path: path.join(root, 'sub/index.md') } + ) + expect(html).toContain('C-content') + }) + + test('resolves relative includes against the real file path', async () => { + await write('sub/part.md', 'real-content\n') + + const { html } = await render( + '\n', + {}, + { + path: path.join(root, 'rewritten/index.md'), + realPath: path.join(root, 'sub/index.md') + } + ) + expect(html).toContain('real-content') + }) + + test.runIf(process.platform === 'win32')( + 'resolves windows-style paths', + async () => { + await write('dir/c.md', 'C-content\n') + + const relative = await render('\n') + expect(relative.html).toContain('C-content') + + const rooted = await render('\n') + expect(rooted.html).toContain('C-content') + + // watched paths are posix-style for includes + expect(relative.env.includes).toEqual([ + slash(path.join(root, 'dir/c.md')) + ]) + } + ) + + test('handles CRLF sources', async () => { + await write('b.md', 'B-content\n') + + const { html } = await render('# A\r\n\r\n\r\n') + expect(html).toContain('B-content') + }) + + test('expands nested includes with relative resolution', async () => { + await write( + 'sub/inside.md', + 'inside\n\n\n' + ) + await write('sub/subsub/deep.md', 'deep-content\n') + + const { html, env } = await render('\n') + expect(html).toContain('inside') + expect(html).toContain('deep-content') + expect(env.includes).toEqual([ + slash(path.join(root, 'sub/inside.md')), + slash(path.join(root, 'sub/subsub/deep.md')) + ]) + }) + + test('leaves a self-include unexpanded', async () => { + const src = '# A\n\n\n' + await write('index.md', src) + + const { html } = await render(src) + expect(html).toContain('@include: ./index.md') + }) + + test('leaves circular includes unexpanded', async () => { + await write('a.md', 'A-content\n\n\n') + await write('b.md', 'B-content\n\n\n') + + const { html } = await render( + 'A-content\n\n\n', + {}, + { path: path.join(root, 'a.md') } + ) + expect(html).toContain('B-content') + expect(html).toContain('@include: ./a.md') + }) + + test('expands repeated includes outside the ancestor chain', async () => { + await write('b.md', 'B-content\n\n\n') + await write('c.md', 'C-content\n\n\n') + await write('d.md', 'D-content\n') + + const { html } = await render( + '\n\n' + ) + expect(html.match(/D-content/g)).toHaveLength(2) + }) + + test('strips frontmatter of whole-file markdown includes', async () => { + await write('b.md', '---\ntitle: B\n---\n\nB-content\n') + + const { html } = await render('\n') + expect(html).toContain('B-content') + expect(html).not.toContain('title: B') + }) + + test('keeps frontmatter lines in range-only includes', async () => { + await write('b.md', '---\ntitle: B\n---\nline-4\nline-5\n') + + const { html } = await render('\n') + expect(html).toContain('line-4') + expect(html).not.toContain('line-5') + }) + + test('includes regions and strips frontmatter before locating them', async () => { + await write( + 'b.md', + [ + '---', + 'title: B', + '---', + '', + 'region-content', + '', + 'outside-content', + '' + ].join('\n') + ) + + const { html } = await render('\n') + expect(html).toContain('region-content') + expect(html).not.toContain('outside-content') + }) + + test('concatenates all regions with the requested name', async () => { + await write( + 'b.md', + [ + '', + 'first', + '', + 'outside', + '', + 'second', + '', + '' + ].join('\n') + ) + + const { html } = await render('\n') + expect(html).toContain('first') + expect(html).toContain('second') + expect(html).not.toContain('outside') + }) + + test('applies ranges within the extracted region', async () => { + await write( + 'b.md', + [ + '', + 'one', + 'two', + 'three', + '', + '' + ].join('\n') + ) + + const { html } = await render('\n') + expect(html).toContain('two') + expect(html).not.toContain('one') + expect(html).not.toContain('three') + }) + + test('supports ranges with open ends', async () => { + await write('b.md', 'one\ntwo\nthree\n') + + const from = await render('\n') + expect(from.html).toContain('two') + expect(from.html).toContain('three') + expect(from.html).not.toContain('one') + + const to = await render('\n') + expect(to.html).toContain('one') + expect(to.html).toContain('two') + expect(to.html).not.toContain('three') + + const both = await render('\n') + expect(both.html).toContain('two') + expect(both.html).toContain('three') + expect(both.html).not.toContain('one') + }) + + test('includes heading sections by anchor', async () => { + await write( + 'source.md', + [ + '---', + 'description: Source description', + '---', + '# Intro', + '', + 'intro text', + '', + '## Shared', + '', + 'shared before target', + '', + '## Target', + '', + 'target text', + '', + '### Child', + '', + 'child text', + '', + '## Shared', + '', + 'shared after target', + '' + ].join('\n') + ) + + const { html } = await render('\n') + expect(html).toContain('target text') + expect(html).toContain('child text') + expect(html).not.toContain('Source description') + expect(html).not.toContain('intro text') + expect(html).not.toContain('shared before target') + expect(html).not.toContain('shared after target') + }) + + test('includes heading sections with custom ids up to EOF', async () => { + await write( + 'source.md', + ['## My Section {#custom-id}', '', 'section text', ''].join('\n') + ) + + const { html } = await render('\n') + expect(html).toContain('section text') + }) + + test('includes non-markdown files verbatim, also inside fences', async () => { + await write('code.ts', 'const a = 1\nconst b = 2\nconst c = 3\n') + + const fenced = await render( + '```ts\n\n```\n' + ) + expect(fenced.html).toContain('language-ts') + expect(fenced.html).toContain('const b = 2') + expect(fenced.html).toContain('const c = 3') + expect(fenced.html).not.toContain('const a = 1') + }) + + test('includes regions of non-markdown files', async () => { + await write( + 'code.ts', + [ + '// #region part', + 'region line', + '// #endregion part', + 'outside line', + '' + ].join('\n') + ) + + const { html } = await render( + '```ts\n\n```\n' + ) + expect(html).toContain('region line') + expect(html).not.toContain('outside line') + }) + + test('leaves empty include paths untouched', async () => { + const { html } = await render('\n') + expect(html).toContain('@include:') + }) + + test('skips expansion without a file path in env', async () => { + disposeMdItInstance() + const md = await createMarkdownRenderer( + root, + { highlight: (code) => code }, + '/', + logger + ) + const html = await md.renderAsync('\n') + expect(html).toContain('@include: ./b.md') + }) + + test('can be disabled', async () => { + await write('b.md', 'B-content\n') + + const { html } = await render('\n', { + include: false + }) + expect(html).not.toContain('B-content') + expect(html).toContain('@include: ./b.md') + }) + + test('throws when the file is missing, recording it as a dependency', async () => { + const env: MarkdownEnv = { + path: path.join(root, 'index.md'), + relativePath: 'index.md', + cleanUrls: false, + includes: [] + } + disposeMdItInstance() + const md = await createMarkdownRenderer( + root, + { highlight: (code) => code }, + '/', + logger + ) + await expect( + md.renderAsync('\n', env) + ).rejects.toThrow(/Include file not found/) + // the missing file is watched so that creating it recovers the page + expect(env.includes).toEqual([slash(path.join(root, 'missing.md'))]) + }) + + test('throws when neither region nor heading matches', async () => { + await write('b.md', '## Some Heading\n\ncontent\n') + + await expect(render('\n')).rejects.toThrow( + /region or heading "nope" not found/i + ) + }) + + test('throws when the range is out of bounds', async () => { + await write('b.md', 'one\ntwo\nthree\n') + + await expect(render('\n')).rejects.toThrow( + /range/i + ) + await expect(render('\n')).rejects.toThrow( + /range/i + ) + await expect(render('\n')).rejects.toThrow( + /range/i + ) + }) + + test('silent mode renders nothing on errors and warns', async () => { + await write('b.md', 'one\ntwo\n') + + const missing = await render( + 'before\n\n\n\nafter\n', + { include: { silent: true } } + ) + expect(missing.html).toContain('before') + expect(missing.html).toContain('after') + expect(missing.html).not.toContain('@include') + + const region = await render('\n', { + include: { silent: true } + }) + expect(region.html).not.toContain('@include') + + const range = await render('\n', { + include: { silent: true } + }) + expect(range.html).not.toContain('@include') + + expect(warnings).toHaveLength(3) + expect(warnings[0]).toContain('missing.md') + expect(warnings[1]).toContain('nope') + expect(warnings[2]).toContain('b.md') + }) + + test('keeps relative urls as is with rebaseRelativeUrls: false', async () => { + await write('sub/part.md', '![img](./img.png)\n\n[link](./target.md)\n') + + const { html } = await render('\n', { + include: { rebaseRelativeUrls: false } + }) + expect(html).toContain('src="./img.png"') + expect(html).toContain('href="./target.html"') + expect(html).not.toContain('@include-') + }) + + test('rebases relative urls inside included files by default', async () => { + await write('sub/part.md', '![img](./img.png)\n\n[link](./target.md)\n') + + const { html } = await render( + '\n\n[after](./after.md)\n' + ) + expect(html).toContain('src="./sub/img.png"') + expect(html).toContain('href="./sub/target.html"') + // links outside the included content are unaffected + expect(html).toContain('href="./after.html"') + // the internal markers never reach the output + expect(html).not.toContain('@include') + }) + + test('rebases urls through nested includes', async () => { + await write( + 'a/one.md', + 'one\n\n\n\n![oneimg](./one.png)\n' + ) + await write('b/two.md', '![twoimg](./two.png)\n') + + const { html } = await render('\n') + expect(html).toContain('src="./b/two.png"') + expect(html).toContain('src="./a/one.png"') + }) + + test('rebases urls after an include ending with an html block', async () => { + await write( + 'sub/part.md', + '![inside](./inside.png)\n\n
      \ntail\n
      \n' + ) + + const { html } = await render( + '\n\n![after](./after.png)\n\n[after](./after.md)\n' + ) + expect(html).toContain('src="./sub/inside.png"') + // the stack must be popped even though the marker follows an html block + expect(html).toContain('src="./after.png"') + expect(html).toContain('href="./after.html"') + expect(html).not.toContain('@include-') + }) + + test('does not leak rebase markers into fenced includes', async () => { + await write('sub/part.md', 'partial line\n') + + const { html } = await render( + '```md\n\n```\n' + ) + expect(html).toContain('partial line') + expect(html).not.toContain('@include-') + }) + + test('does not leak rebase markers for inline includes', async () => { + await write('sub/part.md', 'partial line\n') + + const { html } = await render( + 'before after\n\n[link](./x.md)\n' + ) + expect(html).toContain('partial line') + expect(html).not.toContain('@include-') + // an inline include leaves the surrounding page urls untouched + expect(html).toContain('href="./x.html"') + }) + + test('does not rebase absolute or external urls', async () => { + await write( + 'sub/part.md', + '[ext](https://example.com/x)\n\n[abs](/abs/target.md)\n' + ) + + const { html } = await render('\n') + expect(html).toContain('href="https://example.com/x"') + expect(html).toContain('href="/abs/target.html"') + }) +}) diff --git a/__tests__/unit/node/markdown/plugins/snippet.test.ts b/__tests__/unit/node/markdown/plugins/snippet.test.ts index ba4b343e..50f389c1 100644 --- a/__tests__/unit/node/markdown/plugins/snippet.test.ts +++ b/__tests__/unit/node/markdown/plugins/snippet.test.ts @@ -1,8 +1,13 @@ +import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import path from 'node:path' import { - dedent, - findRegion, - rawPathToToken -} from 'node/markdown/plugins/snippet' + createMarkdownRenderer, + disposeMdItInstance, + type MarkdownOptions +} from 'node/markdown/markdown' +import { parseSnippetPath } from 'node/markdown/plugins/snippet' +import type { MarkdownEnv } from 'node/shared' const removeEmptyKeys = >(obj: T) => { return Object.fromEntries( @@ -11,7 +16,8 @@ const removeEmptyKeys = >(obj: T) => { } /* prettier-ignore */ -const rawPathTokenMap: [string, Partial<{ filepath: string, extension: string, title: string, region: string, lines: string, lang: string }>][] = [ +const parseSnippetPathMap: [string, Partial<{ filepath: string, extension: string, title: string, region: string, lines: string, lang: string, attrs: string }>][] = [ + // paths may contain spaces and dots, and the title defaults to the file name ['/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' }], @@ -28,298 +34,368 @@ const rawPathTokenMap: [string, Partial<{ filepath: string, extension: string, t ['./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' }], + // the extension comes from the file name, so dots in directories and + // dotfiles resolve, and it is not lowercased + ['/path/to/.extension', { filepath: '/path/to/.extension', extension: 'extension', title: '.extension' }], + ['/path/.to/file.extension', { filepath: '/path/.to/file.extension', extension: 'extension', title: 'file.extension' }], + ['/path/.to/.extension', { filepath: '/path/.to/.extension', extension: 'extension', title: '.extension' }], + ['/path/.to/file', { filepath: '/path/.to/file', title: 'file' }], + ['./script.ps1', { filepath: './script.ps1', extension: 'ps1', title: 'script.ps1' }], + ['./File.TS', { filepath: './File.TS', extension: 'TS', title: 'File.TS' }], + // suffixes that are not alphanumeric are not treated as an extension, so + // the language has to be given explicitly for these + ['./main.c++', { filepath: './main.c++', title: 'main.c++' }], + ['./main.c++ {c++}', { filepath: './main.c++', title: 'main.c++', lang: 'c++' }], + ['@/.vscode/scss.code-snippets', { filepath: '@/.vscode/scss.code-snippets', title: 'scss.code-snippets' }], + // region names may contain dots, dashes, digits and underscores + ['/path/to/file.extension#region', { filepath: '/path/to/file.extension', extension: 'extension', title: 'file.extension', region: 'region' }], + ['./file.ts#my.region', { filepath: './file.ts', extension: 'ts', title: 'file.ts', region: 'my.region' }], + ['./file.ts#complex-name_123', { filepath: './file.ts', extension: 'ts', title: 'file.ts', region: 'complex-name_123' }], + // inside the braces: optional highlight lines, then the language override + // (which may contain special characters), then attributes ['./path/to/file.extension {c#}', { filepath: './path/to/file.extension', extension: 'extension', title: 'file.extension', lang: 'c#' }], + ['./path/to/file {C++}', { filepath: './path/to/file', title: 'file', 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#' }], + ['./file.ts{1 ts:line-numbers}', { filepath: './file.ts', extension: 'ts', title: 'file.ts', lines: '1', lang: 'ts:line-numbers' }], + // everything after the language is kept verbatim, so several attributes and + // quoted values with spaces reach the fence info + ['./file.ts{1,2 ts twoslash}', { filepath: './file.ts', extension: 'ts', title: 'file.ts', lines: '1,2', lang: 'ts', attrs: 'twoslash' }], + ['./file.ts{ts twoslash noext}', { filepath: './file.ts', extension: 'ts', title: 'file.ts', lang: 'ts', attrs: 'twoslash noext' }], + ['./file.ts{1 ts key="a b" twoslash}', { filepath: './file.ts', extension: 'ts', title: 'file.ts', lines: '1', lang: 'ts', attrs: 'key="a b" twoslash' }], + // a lone word in the braces is the language, not an attribute + ['./file.ts{twoslash}', { filepath: './file.ts', extension: 'ts', title: 'file.ts', lang: 'twoslash' }], + // stray whitespace in the braces is tolerated + ['./file.ts{ ts twoslash }', { filepath: './file.ts', extension: 'ts', title: 'file.ts', lang: 'ts', attrs: 'twoslash' }], + ['./file.ts{1, 2}', { filepath: './file.ts', extension: 'ts', title: 'file.ts', lines: '1,2' }], + ['./file.ts{}', { filepath: './file.ts', extension: 'ts', title: 'file.ts' }], + // an explicit title overrides the file name and may itself contain brackets ['/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.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#' }], + ['./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#' }], + ['./file.ts#region{1,2 ts twoslash} [my title]', { filepath: './file.ts', extension: 'ts', title: 'my title', region: 'region', lines: '1,2', lang: 'ts', attrs: 'twoslash' }], + ['./snippet.js [title [with brackets]]', { filepath: './snippet.js', extension: 'js', title: 'title [with brackets]' }], + // the space before the title is optional + ['./foo.js[custom]', { filepath: './foo.js', extension: 'js', title: 'custom' }], + ['./demo.js{1,3}[Demo]', { filepath: './demo.js', extension: 'js', title: 'Demo', lines: '1,3' }], + ['./demo.js#region[Demo]', { filepath: './demo.js', extension: 'js', title: 'Demo', region: 'region' }], + ['@/src/ExampleMod.java{15-21}[java]', { filepath: '@/src/ExampleMod.java', extension: 'java', title: 'java', lines: '15-21' }], + // windows-style separators resolve the file name the same way + ['..\\path to\\file.extension', { filepath: '..\\path to\\file.extension', extension: 'extension', title: 'file.extension' }], + ['C:\\path\\file.ts#region {1 ts}', { filepath: 'C:\\path\\file.ts', extension: 'ts', title: 'file.ts', region: 'region', lines: '1', lang: 'ts' }] ] describe('node/markdown/plugins/snippet', () => { - describe('dedent', () => { - test('when 0-level is minimal, do not remove spaces', () => { - expect( - dedent( - [ - // - 'fn main() {', - ' println!("Hello");', - '}' - ].join('\n') - ) - ).toMatchInlineSnapshot(` - "fn main() { - println!("Hello"); - }" - `) + describe('parseSnippetPath', () => { + test.each(parseSnippetPathMap)('%s', (rawPath, parsed) => { + expect(removeEmptyKeys(parseSnippetPath(rawPath))).toEqual(parsed) }) + }) + + describe('rendering', () => { + let root: string + let warnings: string[] + + const logger = { + warn: (msg: string) => { + warnings.push(msg) + } + } - test('when 4-level is minimal, remove 4 spaces', () => { - expect( - dedent( - [ - // - ' let a = {', - ' value: 42', - ' };' - ].join('\n') - ) - ).toMatchInlineSnapshot(` - "let a = { - value: 42 - };" - `) + beforeEach(async () => { + root = await mkdtemp(path.join(tmpdir(), 'vitepress-snippet-')) + warnings = [] }) - test('when only 1 line is passed, dedent it', () => { - expect(dedent(' let a = 42;')).toEqual('let a = 42;') + afterEach(async () => { + await rm(root, { recursive: true, force: true }) }) - test('handle tabs as well', () => { - expect( - dedent( - [ - // - ' let a = {', - ' value: 42', - ' };' - ].join('\n') - ) - ).toMatchInlineSnapshot(` - "let a = { - value: 42 - };" - `) + async function write(name: string, src: string) { + const file = path.join(root, name) + await mkdir(path.dirname(file), { recursive: true }) + await writeFile(file, src) + } + + async function render( + src: string, + options: MarkdownOptions = {}, + env: Partial = {} + ) { + disposeMdItInstance() + const md = await createMarkdownRenderer( + root, + { highlight: (code) => code, ...options }, + '/', + logger + ) + const fullEnv: MarkdownEnv = { + path: path.join(root, 'index.md'), + relativePath: 'index.md', + cleanUrls: false, + includes: [], + ...env + } + const html = await md.renderAsync(src, fullEnv) + return { html, env: fullEnv } + } + + test('imports a whole file, deriving language and title', async () => { + await write('snip.ts', 'const a = 1\nconst b = 2\n') + + const { html, env } = await render('<<< ./snip.ts') + expect(html).toContain('language-ts') + expect(html).toContain('const a = 1') + expect(html).toContain('const b = 2') + expect(env.includes).toEqual([path.join(root, 'snip.ts')]) }) - }) - describe('rawPathToToken', () => { - test.each(rawPathTokenMap)('%s', (rawPath, token) => { - expect(removeEmptyKeys(rawPathToToken(rawPath))).toEqual(token) + test('resolves @ against srcDir', async () => { + await write('nested/snip.js', 'const nested = 1\n') + + const { html } = await render( + '<<< @/nested/snip.js', + {}, + { path: path.join(root, 'sub/dir/index.md') } + ) + expect(html).toContain('const nested = 1') }) - }) - describe('findRegion', () => { - it('returns null when no region markers are present', () => { - const lines = ['function foo() {', ' console.log("hello");', '}'] - expect(findRegion(lines, 'foo')).toBeNull() + test('resolves @ without a slash against srcDir', async () => { + await write('nested/snip.js', 'const nested = 1\n') + + const { html } = await render( + '<<< @nested/snip.js', + {}, + { path: path.join(root, 'sub/dir/index.md') } + ) + expect(html).toContain('const nested = 1') }) - it('ignores non-matching region names', () => { - const lines = [ - '// #region regionA', - 'some code here', - '// #endregion regionA' - ] - expect(findRegion(lines, 'regionC')).toBeNull() + test('parses a snippet without a space after the marker', async () => { + await write('snip.ts', 'const a = 1\n') + + const { html } = await render('<<<./snip.ts') + expect(html).toContain('const a = 1') }) - 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() + test('does not dedent whole-file imports', async () => { + await write('indented.ts', ' const a = 1\n const b = 2\n') + + const { html } = await render('<<< ./indented.ts') + expect(html).toContain(' const a = 1') }) - 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() + test('passes attrs to the highlighter and keeps them out of the title', async () => { + await write('snip.ts', 'const a = 1\nconst b = 2\n') + + const calls: { lang: string; attrs: string }[] = [] + await render('<<< ./snip.ts{1 ts twoslash} [my title]', { + highlight: (code, lang, attrs) => { + calls.push({ lang, attrs }) + return code + } + }) + + expect(calls).toHaveLength(1) + expect(calls[0].lang).toBe('ts') + expect(calls[0].attrs).toContain('twoslash') + expect(calls[0].attrs).toContain('{1}') + expect(calls[0].attrs).not.toContain('my title') }) - 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!");' - ) - } + test('resolves relative paths against the real file path', async () => { + await write('sub/snip.js', 'const real = 1\n') + + const { html } = await render( + '<<< ./snip.js', + {}, + { + path: path.join(root, 'rewritten/index.md'), + realPath: path.join(root, 'sub/index.md') + } + ) + expect(html).toContain('const real = 1') }) - 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!");' - ) - } + test('concatenates all regions with the requested name', async () => { + await write( + 'regions.ts', + [ + '// #region one', + 'const a = 1', + '// #endregion one', + 'const outside = 2', + '// #region one', + 'const b = 3', + '// #endregion', + '' + ].join('\n') + ) + + const { html } = await render('<<< ./regions.ts#one') + expect(html).toContain('const a = 1') + expect(html).toContain('const b = 3') + expect(html).not.toContain('const outside') }) - 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!");' - ) - } + test('dedents extracted regions', async () => { + await write( + 'indent.ts', + [ + 'function f() {', + ' // #region inner', + ' const x = 1', + ' // #endregion inner', + '}', + '' + ].join('\n') + ) + + const { html } = await render('<<< ./indent.ts#inner') + expect(html).toContain('const x = 1') + expect(html).not.toContain(' const x = 1') }) - 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;' - ) - } + const nested = [ + '// #region outer', + 'let a = 1', + '// #region nested', + 'let b = 2', + '// #endregion nested', + '/* #region css */', + 'let c = 3', + '/* #endregion css */', + '// #endregion outer', + '' + ].join('\n') + + test('strips markers of the matched style by default', async () => { + await write('nested.ts', nested) + + const region = await render('<<< ./nested.ts#outer') + // the double-slash markers matched the region, the css ones did not + expect(region.html).not.toContain('#region nested') + expect(region.html).toContain('#region css') + expect(region.html).toContain('let b = 2') + expect(region.html).toContain('let c = 3') + + // whole-file imports keep their markers + const whole = await render('<<< ./nested.ts') + expect(whole.html).toContain('#region outer') + expect(whole.html).toContain('let a = 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;' - ) - } + test('strips every marker style with stripRegionMarkers: all', async () => { + await write('nested.ts', nested) + + const region = await render('<<< ./nested.ts#outer', { + snippet: { stripRegionMarkers: 'all' } + }) + expect(region.html).not.toContain('#region') + expect(region.html).toContain('let b = 2') + + const whole = await render('<<< ./nested.ts', { + snippet: { stripRegionMarkers: 'all' } + }) + expect(whole.html).not.toContain('#region') + expect(whole.html).toContain('let a = 1') }) - 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

      ' - ) - } + test('keeps marker lines with stripRegionMarkers: false', async () => { + await write('nested.ts', nested) + + const region = await render('<<< ./nested.ts#outer', { + snippet: { stripRegionMarkers: false } + }) + expect(region.html).toContain('#region nested') + expect(region.html).toContain('#region css') }) - 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")' - ) - } + test('applies lang, highlight lines, attrs and title to the fence', async () => { + await write('snip.ts', 'const a = 1\nconst b = 2\n') + + const { html } = await render( + '::: code-group\n\n<<< ./snip.ts{1 js twoslash} [custom title]\n\n:::' + ) + expect(html).toContain('language-js') + expect(html).toContain('custom title') + expect(html).not.toContain('twoslash') }) - 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' - ) - } + test('throws when the file is missing', async () => { + await expect(render('<<< ./missing.ts')).rejects.toThrow( + /Code snippet path not found/ + ) }) - 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;' - ) - } + test('throws when the path is a directory', async () => { + await write('dir/file.ts', 'const a = 1\n') + await expect(render('<<< ./dir')).rejects.toThrow(/directory/) }) - 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' - ) - } + test('throws when the region is missing', async () => { + await write('snip.ts', 'const a = 1\n') + await expect(render('<<< ./snip.ts#nope')).rejects.toThrow( + /region "nope" not found/i + ) }) - 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) + test('silent mode renders nothing and warns', async () => { + await write('snip.ts', 'const a = 1\n') + + const missingFile = await render('<<< ./missing.ts', { + snippet: { silent: true } + }) + expect(missingFile.html).not.toContain(' { + const escaped = await render('\\<<< ./snip.ts') + expect(escaped.html).toContain('<<< ./snip.ts') + + const indented = await render(' <<< ./snip.ts') + expect(indented.html).toContain('<<< ./snip.ts') + expect(indented.env.includes).toEqual([]) + }) + + test.runIf(process.platform === 'win32')( + 'resolves windows-style paths', + async () => { + await write('nested/snip.ts', 'const a = 1\n') + + const relative = await render('<<< .\\nested\\snip.ts') + expect(relative.html).toContain('const a = 1') + + const rooted = await render('<<< @\\nested\\snip.ts') + expect(rooted.html).toContain('const a = 1') + + // the watched path stays platform-native for snippets + expect(relative.env.includes).toEqual([ + path.join(root, 'nested/snip.ts') + ]) } + ) + + test('normalizes CRLF in imported files', async () => { + await write('crlf.ts', 'const a = 1\r\nconst b = 2\r\n') + + const { html } = await render('<<< ./crlf.ts') + expect(html).toContain('const a = 1\nconst b = 2') + expect(html).not.toContain('\r') }) }) }) diff --git a/__tests__/unit/node/markdown/regions.test.ts b/__tests__/unit/node/markdown/regions.test.ts new file mode 100644 index 00000000..f14930bc --- /dev/null +++ b/__tests__/unit/node/markdown/regions.test.ts @@ -0,0 +1,529 @@ +import { + dedent, + findRegions, + markers, + stripRegionMarkers +} from 'node/markdown/regions' + +const extract = (lines: string[], name: string) => + findRegions(lines, name) + .flatMap((r) => lines.slice(r.start, r.end)) + .join('\n') + +describe('node/markdown/regions', () => { + describe('dedent', () => { + test('keeps lines when 0-level is minimal', () => { + expect(dedent(['fn main() {', ' println!("Hello");', '}'])).toEqual([ + 'fn main() {', + ' println!("Hello");', + '}' + ]) + }) + + test('removes the common minimal indent', () => { + expect(dedent([' let a = {', ' value: 42', ' };'])).toEqual([ + 'let a = {', + ' value: 42', + '};' + ]) + }) + + test('dedents a single line', () => { + expect(dedent([' let a = 42;'])).toEqual(['let a = 42;']) + }) + + test('handles tabs', () => { + expect(dedent(['\tlet a = {', '\t\tvalue: 42', '\t};'])).toEqual([ + 'let a = {', + '\tvalue: 42', + '};' + ]) + }) + + test('ignores blank lines when computing the minimal indent', () => { + expect(dedent([' a', '', ' b'])).toEqual(['a', '', 'b']) + }) + + test('keeps whitespace-only input as is', () => { + expect(dedent(['', ' '])).toEqual(['', ' ']) + }) + }) + + describe('findRegions', () => { + it('returns no regions without markers', () => { + const lines = ['function foo() {', ' console.log("hello");', '}'] + expect(findRegions(lines, 'foo')).toHaveLength(0) + }) + + it('ignores non-matching and prefix-matching region names', () => { + const lines = [ + '// #region regionA', + 'some code here', + '// #endregion regionA' + ] + expect(findRegions(lines, 'regionC')).toHaveLength(0) + expect(findRegions(lines, 'region')).toHaveLength(0) + }) + + it('returns no regions for a start marker without a matching end', () => { + const lines = [ + '// #region missingEnd', + 'console.log("inside region");', + 'console.log("still inside");' + ] + expect(findRegions(lines, 'missingEnd')).toHaveLength(0) + }) + + it('returns no regions for an end marker without a preceding start', () => { + const lines = [ + '// #endregion ghostRegion', + 'console.log("stray end marker");' + ] + expect(findRegions(lines, 'ghostRegion')).toHaveLength(0) + }) + + it('ignores non-marker lines containing the word region', () => { + const lines = [ + 'const region = "region"', + '// #region hello', + 'const x = 1', + '// endregion hello is mentioned here without a comment prefix' + ] + expect(findRegions(lines, 'hello')).toHaveLength(0) + }) + + it('detects C#-style markers', () => { + const lines = [ + 'Console.WriteLine("Before region");', + '#region hello', + 'Console.WriteLine("Hello, World!");', + '#endregion hello', + 'Console.WriteLine("After region");' + ] + expect(extract(lines, 'hello')).toBe( + 'Console.WriteLine("Hello, World!");' + ) + }) + + it('closes a named region with an anonymous end marker', () => { + const lines = [ + '#region hello', + 'Console.WriteLine("Hello, World!");', + '#endregion', + 'Console.WriteLine("After region");' + ] + expect(extract(lines, 'hello')).toBe( + 'Console.WriteLine("Hello, World!");' + ) + }) + + it('does not close a region with a differently named end marker', () => { + const lines = [ + '#region hello', + 'Console.WriteLine("Hello, World!");', + '#endregion world' + ] + expect(findRegions(lines, 'hello')).toHaveLength(0) + }) + + it('keeps indentation of indented markers and content', () => { + const lines = [ + ' #region hello', + ' Console.WriteLine("Hello, World!");', + ' #endregion hello' + ] + expect(extract(lines, 'hello')).toBe( + ' Console.WriteLine("Hello, World!");' + ) + }) + + it('detects double-slash markers with and without spacing', () => { + const lines = [ + 'let regexp: RegExp[] = [];', + '// #region foo', + 'let start = -1;', + '//#endregion foo' + ] + expect(extract(lines, 'foo')).toBe('let start = -1;') + }) + + it('detects hash-less double-slash markers like VS Code', () => { + const lines = ['// region foo', 'let start = -1;', '// endregion foo'] + expect(extract(lines, 'foo')).toBe('let start = -1;') + }) + + it('detects CSS-style markers', () => { + const lines = [ + '/* #region foo */', + ' padding-left: 15px;', + '/*#endregion foo*/' + ] + expect(extract(lines, 'foo')).toBe(' padding-left: 15px;') + }) + + it('detects HTML-style markers, with the hash optional', () => { + const lines = [ + '', + '

      Hello world

      ', + '', + '', + '

      Other

      ', + '' + ] + expect(extract(lines, 'foo')).toBe('

      Hello world

      ') + expect(extract(lines, 'bar')).toBe('

      Other

      ') + }) + + it('detects Visual Basic-style markers', () => { + const lines = [ + '#Region VBRegion', + ' Console.WriteLine("Inside region")', + '#End Region VBRegion' + ] + expect(extract(lines, 'VBRegion')).toBe( + ' Console.WriteLine("Inside region")' + ) + }) + + it('ignores the quotes around a Visual Basic region name', () => { + const lines = [ + '#Region "Quoted Name"', + ' Console.WriteLine("Inside region")', + '#End Region', + '#Region "Other"', + ' Console.WriteLine("Other region")', + '#End Region "Other"' + ] + expect(extract(lines, 'Quoted Name')).toBe( + ' Console.WriteLine("Inside region")' + ) + expect(extract(lines, 'Other')).toBe( + ' Console.WriteLine("Other region")' + ) + }) + + it('detects bat-style markers with case-insensitive REM', () => { + const lines = [ + '@REM #region hello', + '@ECHO OFF', + '::#endregion hello', + 'echo out', + 'rem #region hello', + 'exit 0', + 'Rem #endregion hello' + ] + expect(extract(lines, 'hello')).toBe('@ECHO OFF\nexit 0') + }) + + it('detects dash-dash markers, which require the hash', () => { + const lines = [ + '-- #region foo', + 'select 1;', + '-- #endregion foo', + '--#region bar', + 'select 2;', + '--#endregion bar' + ] + expect(extract(lines, 'foo')).toBe('select 1;') + expect(extract(lines, 'bar')).toBe('select 2;') + + // prose comments are not markers + expect(findRegions(['-- region of interest', 'select 1;'], '')).toEqual( + [] + ) + }) + + it('detects pragma markers, allowing space after the hash', () => { + const lines = [ + '#pragma region foo', + 'int a = 1;', + '#pragma endregion foo', + '# pragma region bar', + 'int b = 2;', + '# pragma endregion bar' + ] + expect(extract(lines, 'foo')).toBe('int a = 1;') + expect(extract(lines, 'bar')).toBe('int b = 2;') + }) + + it('detects paren-star markers', () => { + const lines = ['(* #region foo *)', 'let a = 1', '(* #endregion foo *)'] + expect(extract(lines, 'foo')).toBe('let a = 1') + }) + + it('detects shell and python style hash markers', () => { + const lines = [ + '# region hello', + 'echo "inside"', + '#\tendregion hello', + '# #region hello', + 'exit 0', + '# #endregion' + ] + expect(extract(lines, 'hello')).toBe('echo "inside"\nexit 0') + }) + + it('detects JSON key-style markers with two or more slashes', () => { + const lines = [ + '{', + ' "// #region hello": "",', + ' "one": true,', + ' "//#endregion hello": "",', + ' "two": false,', + ' "/// #region hello": "",', + ' "three": true,', + ' "//// #endregion hello": ""', + '}' + ] + expect(extract(lines, 'hello')).toBe(' "one": true,\n "three": true,') + }) + + it('concatenates multiple same-named regions in document order', () => { + const lines = [ + '// #region hello', + 'first region content', + '// #endregion hello', + 'other content', + '// #region hello', + 'second region content', + '// #endregion', + '// #region hello', + 'third region content', + '// #endregion hello' + ] + expect(extract(lines, 'hello')).toBe( + 'first region content\nsecond region content\nthird region content' + ) + }) + + it('merges same-named regions across different comment styles', () => { + const lines = [ + '', + '', + '' + ] + const regions = findRegions(lines, 'shared') + expect(regions).toHaveLength(4) + expect(extract(lines, 'shared')).toBe( + [ + '
      template part
      ', + 'const scriptPart = true', + 'console.log(scriptPart)', + '.style-part {}' + ].join('\n') + ) + }) + + it('tracks nesting of same-named regions across styles', () => { + const lines = [ + '// #region foo', + "console.log('double-slash only');", + '/* #region foo */', + "console.log('nested in both');", + '// #endregion foo', + "console.log('still in outer');", + '/* #endregion foo */', + "console.log('outside');" + ] + const regions = findRegions(lines, 'foo') + expect(regions).toHaveLength(1) + expect(regions[0]).toMatchObject({ start: 1, end: 6 }) + }) + + it('closes the innermost open region with an anonymous end marker', () => { + const lines = [ + '', + '', + '', + '' + ] + expect(extract(lines, 'demo')).toBe( + [ + '', + '' + ].join('\n') + ) + expect(extract(lines, 'state')).toBe('const count = ref(0)') + }) + + it('is not closed by an anonymous end marker of a nested region in a fence', () => { + const lines = [ + '', + 'Use markers like this:', + '', + '```js', + '// #region foo', + 'const a = 1', + '// #endregion', + '```', + '' + ] + expect(extract(lines, 'sample')).toBe( + [ + 'Use markers like this:', + '', + '```js', + '// #region foo', + 'const a = 1', + '// #endregion', + '```' + ].join('\n') + ) + }) + + it('is closed by an anonymous end marker of its own style', () => { + // a region documenting region syntax: the marker inside the fence is + // never closed, and the anonymous end marker belongs to the region + const lines = [ + '', + 'How regions work:', + '', + '```js', + '// #region example', + 'const a = 1', + '```', + '' + ] + expect(extract(lines, 'real')).toBe( + [ + 'How regions work:', + '', + '```js', + '// #region example', + 'const a = 1', + '```' + ].join('\n') + ) + }) + + it('ignores an anonymous end marker with nothing open in its style', () => { + const lines = [ + '', + '// #endregion', + 'body', + '' + ] + expect(extract(lines, 'real')).toBe('// #endregion\nbody') + }) + + it('tolerates an unclosed region nested inside the requested one', () => { + const lines = [ + '// #region outer', + 'const a = 1', + '// #region inner', + 'const b = 2', + '// #endregion outer' + ] + expect(extract(lines, 'outer')).toBe( + ['const a = 1', '// #region inner', 'const b = 2'].join('\n') + ) + }) + + it('keeps differently named nested regions verbatim', () => { + const lines = [ + '// #region foo', + "console.log('line before nested');", + '// #region bar', + "console.log('nested content');", + '// #endregion bar', + '// #endregion foo' + ] + expect(extract(lines, 'foo')).toBe( + [ + "console.log('line before nested');", + '// #region bar', + "console.log('nested content');", + '// #endregion bar' + ].join('\n') + ) + }) + + it('supports special characters in region names', () => { + const lines = [ + '// #region complex-name_123', + 'const x = 1;', + '// #endregion complex-name_123', + '// #region my.region', + 'const y = 2;', + '// #endregion my.region' + ] + expect(extract(lines, 'complex-name_123')).toBe('const x = 1;') + expect(extract(lines, 'my.region')).toBe('const y = 2;') + }) + + it('reports the marker style that opened each region', () => { + const lines = ['// #region foo', 'const x = 1;', '// #endregion foo'] + const [region] = findRegions(lines, 'foo') + expect(markers).toContain(region.marker) + expect(region.marker.start.test('// #region other')).toBe(true) + expect(region.marker.start.test('# region other')).toBe(false) + }) + }) + + describe('stripRegionMarkers', () => { + it('strips marker lines of every style and name by default', () => { + const lines = [ + '// #region name', + 'const a = 0;', + '/* #region HELLO */', + 'const b = 0;', + '//\t#endregion complex_name-123', + 'const c = 0;', + '/*#endregion*/' + ] + expect(stripRegionMarkers(lines)).toEqual([ + 'const a = 0;', + 'const b = 0;', + 'const c = 0;' + ]) + }) + + it('keeps non-marker lines mentioning regions', () => { + const lines = ['const region = "region"', 'let a = 1'] + expect(stripRegionMarkers(lines)).toEqual(lines) + }) + + it('strips only the given marker styles when provided', () => { + const lines = [ + '// #region a', + 'const x = 1', + '// #endregion a', + '# region b', + 'const y = 2', + '# endregion b' + ] + const [region] = findRegions(lines, 'a') + expect(stripRegionMarkers(lines, [region.marker])).toEqual([ + 'const x = 1', + '# region b', + 'const y = 2', + '# endregion b' + ]) + }) + }) +}) diff --git a/__tests__/unit/node/markdownToVue.test.ts b/__tests__/unit/node/markdownToVue.test.ts index 232496df..1d675f31 100644 --- a/__tests__/unit/node/markdownToVue.test.ts +++ b/__tests__/unit/node/markdownToVue.test.ts @@ -31,7 +31,7 @@ describe('node/markdownToVue', () => { siteConfig ) - const result = await render(src, file, 'public') + const result = await render(src, file) expect(result.deadLinks).toContainEqual({ url: './missing', @@ -58,7 +58,7 @@ describe('node/markdownToVue', () => { siteConfig ) - const result = await render(src, file, 'public') + const result = await render(src, file) expect(result.deadLinks).toContainEqual({ url: './missing', @@ -113,7 +113,7 @@ describe('node/markdownToVue', () => { siteConfig ) - const result = await render(src, file, 'public') + const result = await render(src, file) expect(result.vueSrc).toContain('

      target text

      ') expect(result.vueSrc).toContain('

      { siteConfig ) - const result = await render( - '# Home\n', - 'C:/site/docs/en/index.md', - 'public' - ) + const result = await render('# Home\n', 'C:/site/docs/en/index.md') expect(result.pageData.relativePath).toBe('index.md') }) diff --git a/__tests__/unit/node/plugins/localSearchPlugin.test.ts b/__tests__/unit/node/plugins/localSearchPlugin.test.ts index c972795c..ffbf3e46 100644 --- a/__tests__/unit/node/plugins/localSearchPlugin.test.ts +++ b/__tests__/unit/node/plugins/localSearchPlugin.test.ts @@ -1,7 +1,9 @@ import MiniSearch from 'minisearch' import { resolveConfig } from 'node/config' +import { disposeMdItInstance } from 'node/markdown/markdown' +import { createMarkdownToVueRenderFn } from 'node/markdownToVue' import { localSearchPlugin } from 'node/plugins/localSearchPlugin' -import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' +import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import path from 'node:path' @@ -12,6 +14,9 @@ describe('node/plugins/localSearchPlugin', () => { beforeEach(() => { nodeEnv = process.env.NODE_ENV process.env.NODE_ENV = 'production' + // createMarkdownRenderer is a module-level singleton keyed on nothing — + // reset it so each test's config actually reaches the renderer + disposeMdItInstance() }) afterEach(async () => { @@ -62,8 +67,14 @@ describe('node/plugins/localSearchPlugin', () => { const siteConfig = await resolveConfig(root, 'build', 'production') const plugin = await localSearchPlugin(siteConfig) - const indexModule = (await plugin.load?.call( - {} as never, + // vite calls configResolved before any other hook + await (plugin.configResolved as any)?.call( + {}, + { publicDir: siteConfig.publicDir } + ) + + const indexModule = (await (plugin.load as any)?.handler.call( + {}, '/@localSearchIndex' )) as string @@ -73,10 +84,16 @@ describe('node/plugins/localSearchPlugin', () => { expect(indexModule).toContain('"zh": () => import(\'@localSearchIndexzh\')') const rootIndex = loadIndex( - (await plugin.load?.call({} as never, '/@localSearchIndexroot')) as string + (await (plugin.load as any)?.handler.call( + {}, + '/@localSearchIndexroot' + )) as string ) const zhIndex = loadIndex( - (await plugin.load?.call({} as never, '/@localSearchIndexzh')) as string + (await (plugin.load as any)?.handler.call( + {}, + '/@localSearchIndexzh' + )) as string ) expect(rootIndex.search('rootonlytoken')).toMatchObject([ @@ -89,6 +106,126 @@ describe('node/plugins/localSearchPlugin', () => { ]) expect(zhIndex.search('rootonlytoken')).toEqual([]) }) + + test('applies per-locale markdown options (#5350)', async () => { + root = await mkdtemp(path.join(tmpdir(), 'vitepress-local-search-')) + const configDir = path.join(root, '.vitepress') + await mkdir(configDir) + await mkdir(path.join(root, 'zh')) + + const content = '::: tip\ntipcontent\n:::\n' + await writeFile(path.join(root, 'index.md'), `# Home\n\n${content}`) + await writeFile( + path.join(root, 'zh', 'index.md'), + `# Chinese home\n\n${content}` + ) + await writeFile( + path.join(configDir, 'config.ts'), + [ + 'export default {', + ' locales: {', + " root: { label: 'English', lang: 'en' },", + ' zh: {', + " label: 'Chinese',", + " lang: 'zh',", + " markdown: { container: { tipLabel: 'zhtiplabel' } }", + ' }', + ' },', + ' themeConfig: {', + " search: { provider: 'local' }", + ' }', + '}' + ].join('\n') + ) + + const siteConfig = await resolveConfig(root, 'build', 'production') + const plugin = await localSearchPlugin(siteConfig) + + // configResolved hooks run concurrently, so the search plugin may be the + // one that creates the shared markdown renderer — page renders must still + // pick up per-locale options from it + await (plugin.configResolved as any)?.call( + {}, + { publicDir: siteConfig.publicDir } + ) + + const render = await createMarkdownToVueRenderFn( + siteConfig.srcDir, + siteConfig.markdown ?? {}, + siteConfig.site.base, + false, + false, + siteConfig + ) + + const rootFile = path.join(root, 'index.md') + const zhFile = path.join(root, 'zh', 'index.md') + const rootPage = await render(await readFile(rootFile, 'utf-8'), rootFile) + const zhPage = await render(await readFile(zhFile, 'utf-8'), zhFile) + expect(rootPage.vueSrc).toContain('TIP') + expect(zhPage.vueSrc).toContain('zhtiplabel') + + // the indexed text must use the localized labels too + await (plugin.load as any)?.handler.call({}, '/@localSearchIndex') + const rootIndex = loadIndex( + (await (plugin.load as any)?.handler.call( + {}, + '/@localSearchIndexroot' + )) as string + ) + const zhIndex = loadIndex( + (await (plugin.load as any)?.handler.call( + {}, + '/@localSearchIndexzh' + )) as string + ) + expect(zhIndex.search('zhtiplabel')).toHaveLength(1) + expect(rootIndex.search('zhtiplabel')).toEqual([]) + expect(rootIndex.search('tip')).toHaveLength(1) + }) + + test('warns and skips pages that fail to render', async () => { + root = await mkdtemp(path.join(tmpdir(), 'vitepress-local-search-')) + const configDir = path.join(root, '.vitepress') + await mkdir(configDir) + + await writeFile(path.join(root, 'index.md'), '# Home\n\nhealthytoken\n') + await writeFile( + path.join(root, 'broken.md'), + '# Broken\n\n\n' + ) + await writeFile( + path.join(configDir, 'config.ts'), + "export default { themeConfig: { search: { provider: 'local' } } }" + ) + + const siteConfig = await resolveConfig(root, 'build', 'production') + const warn = vi + .spyOn(siteConfig.logger, 'warn') + .mockImplementation(() => {}) + const plugin = await localSearchPlugin(siteConfig) + + await (plugin.configResolved as any)?.call( + {}, + { publicDir: siteConfig.publicDir } + ) + + // the include throws, but indexing the remaining pages must still resolve — + // in dev this runs unawaited and a rejection would take the server down + await (plugin.load as any)?.handler.call({}, '/@localSearchIndex') + + const index = loadIndex( + (await (plugin.load as any)?.handler.call( + {}, + '/@localSearchIndexroot' + )) as string + ) + + expect(index.search('healthytoken')).toHaveLength(1) + expect(warn).toHaveBeenCalledWith( + expect.stringContaining('Failed to index broken.md for search') + ) + }) }) function loadIndex(serializedModule: string) { diff --git a/__tests__/unit/node/utils/fs.test.ts b/__tests__/unit/node/utils/fs.test.ts new file mode 100644 index 00000000..7072a471 --- /dev/null +++ b/__tests__/unit/node/utils/fs.test.ts @@ -0,0 +1,34 @@ +import { mkdtemp, rm, writeFile } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import path from 'node:path' +import { readFile, readTextFile, readTextFileSync } from 'node/utils/fs' + +describe('node/utils/fs', () => { + let root: string + + beforeEach(async () => { + root = await mkdtemp(path.join(tmpdir(), 'vitepress-fs-')) + }) + + afterEach(async () => { + await rm(root, { recursive: true, force: true }) + }) + + test('readFile keeps line endings as is', async () => { + const file = path.join(root, 'crlf.txt') + await writeFile(file, 'a\r\nb\rc\nd') + expect(await readFile(file)).toBe('a\r\nb\rc\nd') + }) + + test('readTextFile normalizes CRLF and CR to LF', async () => { + const file = path.join(root, 'crlf.txt') + await writeFile(file, 'a\r\nb\rc\nd') + expect(await readTextFile(file)).toBe('a\nb\nc\nd') + }) + + test('readTextFileSync normalizes CRLF and CR to LF', async () => { + const file = path.join(root, 'crlf.txt') + await writeFile(file, 'a\r\nb\rc\nd') + expect(readTextFileSync(file)).toBe('a\nb\nc\nd') + }) +}) diff --git a/__tests__/unit/tsconfig.json b/__tests__/unit/tsconfig.json new file mode 100644 index 00000000..f7ff2329 --- /dev/null +++ b/__tests__/unit/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "types": [ + "node", + "vitest/globals", + "vite/client", + "../../src/client/shims.d.ts" + ], + "paths": { + "client/*": ["../../src/client/*"], + "node/*": ["../../src/node/*"], + "shared/*": ["../../src/shared/*"], + "vitepress": ["../../src/client/index.ts"], + "vitepress/theme": ["../../theme.d.ts"] + } + } +} diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index b8093713..1be8a317 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -9,6 +9,13 @@ import { localIconLoader } from 'vitepress-plugin-group-icons' import llmstxt from 'vitepress-plugin-llms' +import { markdown as esMarkdown } from '../es/config' +import { markdown as faMarkdown } from '../fa/config' +import { markdown as jaMarkdown } from '../ja/config' +import { markdown as koMarkdown } from '../ko/config' +import { markdown as ptMarkdown } from '../pt/config' +import { markdown as ruMarkdown } from '../ru/config' +import { markdown as zhMarkdown } from '../zh/config' const prod = !!process.env.NETLIFY const siteUrl = 'https://vitepress.dev' @@ -35,7 +42,6 @@ export default defineConfig({ lastUpdated: true, cleanUrls: true, - metaChunk: true, markdown: { math: true, @@ -51,35 +57,6 @@ export default defineConfig({ } ], 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 '复制代码' - case 'ja': - return 'コードをコピー' - default: - return 'Copy code' - } - })() - return fence(tokens, idx, options, env, self).replace( - '', - `` - ) - } md.use(groupIconMdPlugin) } }, @@ -122,15 +99,16 @@ export default defineConfig({ carbonAds: { code: 'CEBDT27Y', placement: 'vuejsorg' } }, + // prettier-ignore locales: { root: { label: 'English', lang: 'en-US', dir: 'ltr' }, - zh: { label: '简体中文', lang: 'zh-Hans', dir: 'ltr' }, - pt: { label: 'Português', lang: 'pt-BR', dir: 'ltr' }, - ru: { label: 'Русский', lang: 'ru-RU', dir: 'ltr' }, - es: { label: 'Español', lang: 'es', dir: 'ltr' }, - ko: { label: '한국어', lang: 'ko-KR', dir: 'ltr' }, - fa: { label: 'فارسی', lang: 'fa-IR', dir: 'rtl' }, - ja: { label: '日本語', lang: 'ja', dir: 'ltr' } + zh: { label: '简体中文', lang: 'zh-Hans', dir: 'ltr', markdown: zhMarkdown }, + pt: { label: 'Português', lang: 'pt-BR', dir: 'ltr', markdown: ptMarkdown }, + ru: { label: 'Русский', lang: 'ru-RU', dir: 'ltr', markdown: ruMarkdown }, + es: { label: 'Español', lang: 'es', dir: 'ltr', markdown: esMarkdown }, + ko: { label: '한국어', lang: 'ko-KR', dir: 'ltr', markdown: koMarkdown }, + fa: { label: 'فارسی', lang: 'fa-IR', dir: 'rtl', markdown: faMarkdown }, + ja: { label: '日本語', lang: 'ja', dir: 'ltr', markdown: jaMarkdown } }, vite: { @@ -145,10 +123,7 @@ export default defineConfig({ } }), prod && llmstxt({ workDir: 'en', ignoreFiles: ['index.md'] }) - ], - experimental: { - enableNativePlugin: true - } + ] }, // prettier-ignore diff --git a/docs/.vitepress/theme/styles.css b/docs/.vitepress/theme/styles.css index 2635e80d..54c5d424 100644 --- a/docs/.vitepress/theme/styles.css +++ b/docs/.vitepress/theme/styles.css @@ -1,6 +1,27 @@ +@font-face { + font-family: 'Vazirmatn'; + font-style: normal; + font-weight: 100 900; + font-display: swap; + src: url('https://cdn.jsdelivr.net/npm/vazirmatn@33.0.3/fonts/webfonts/Vazirmatn%5Bwght%5D.woff2') + format('woff2'); + /* google fonts' arabic range, plus guillemets and ellipsis so persian + punctuation renders in vazirmatn instead of inter */ + unicode-range: + U+00AB, U+00BB, U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, + U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+2026, U+204F, U+2E41, + U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC, U+102E0-102FB, U+10E60-10E7E, + U+10EC2-10EC4, U+10EFC-10EFF, U+1EE00-1EE03, U+1EE05-1EE1F, U+1EE21-1EE22, + U+1EE24, U+1EE27, U+1EE29-1EE32, U+1EE34-1EE37, U+1EE39, U+1EE3B, U+1EE42, + U+1EE47, U+1EE49, U+1EE4B, U+1EE4D-1EE4F, U+1EE51-1EE52, U+1EE54, U+1EE57, + U+1EE59, U+1EE5B, U+1EE5D, U+1EE5F, U+1EE61-1EE62, U+1EE64, U+1EE67-1EE6A, + U+1EE6C-1EE72, U+1EE74-1EE77, U+1EE79-1EE7C, U+1EE7E, U+1EE80-1EE89, + U+1EE8B-1EE9B, U+1EEA1-1EEA3, U+1EEA5-1EEA9, U+1EEAB-1EEBB, U+1EEF0-1EEF1; +} + :root:where(:lang(fa)) { --vp-font-family-base: - 'Vazirmatn', 'Inter', ui-sans-serif, system-ui, sans-serif, + 'Vazirmatn', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; } @@ -36,8 +57,31 @@ padding: 18px; } -/* used in reference/default-theme-search */ -img[src='/search.png'] { - width: 100%; - aspect-ratio: 1 / 1; +.VPFeature .icon span { + display: inline-block; + width: 1em; + height: 1em; + background-position: center; + background-repeat: no-repeat; + background-size: contain; + + &.memo { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Cpath fill='%23efd8b1' d='M0 20.3S28.2 50.2 31.2 64c0 0 8.1-17.9 32.8-25.4c0 0-8.8-20.6-32.2-37c0 0-23.9 7.2-31.8 18.7'/%3E%3Cpath fill='%23fff6d7' d='M3.2 7.9s22 38.2 22.4 52.5c0 0 11-14.8 36.4-14c0 0-4.8-22.9-24.6-46.3c0-.1-24.5-.9-34.2 7.8'/%3E%3Cg fill='%237d8b91'%3E%3Cpath d='M19.9 9.4c-.3.4.2-.4 0 0'/%3E%3Cpath d='M19.9 9.4c.2-.3.3-.8.6-1.1c.4-.3.8-.1 1.2-.4c.8-.6 1.2-1.6 1.9-2.3c.8-.8 1.8-1.3 2.9-1.6c1.1-.4 2.2-1.2 3.3-1.2c-.5 1.5-1.5 2.8-1.7 4.5c-.1.9 0 1.8.1 2.7c.2-.7.4-1.4.6-2c.4-.9 1.3-.8 2.1-1.1c.8-.4 1.5-1.1 2.2-1.7c.3.5 1.4-.3 1.6.4c.1.3 2.8-.1 3-.2c-.6 0-2.7.1-2.8-.4c-.3-.1-.9-.2-1.3-.2v-.7c-.6.4-1.2.9-1.8 1.4c-.9.7-2 .5-2.9 1.2c.3-1 .9-1.9 1.3-2.9c.2-.4.3-.9.4-1.3s0-.2-.3-.4c-1.4-.4-2.8.7-4 1.2c-1.1.5-2.1 1.1-2.9 1.9c-.5.5-1.3 2.3-2 2.5c-1.4 0-.9 1.3-1.8 1.7c-.5.2-.8.2-1.3.5c-.5.4-1.2 1.1-2 1c0-.6 0-1.2-.2-1.8c-.8.4-1.1 1.1-1.8 1.6c.2-1.6.9-2.9.9-4.6c-.9.6-1.4 1.3-1.9 2.2c-.6 1.1-1.1 2.9-2.3 3.5c0-1.5.7-3 .5-4.6c-.3.8-.3 1.8-.5 2.5c-.2.9-.4 1.8-.4 2.8c2.2-.3 2.6-3.5 3.9-4.9c-.3 1.4-.8 2.7-.7 4.2c.9-.5 1.3-1.5 2.1-2.1c.3.9-.4 2.1 1.1 1.4c.6-.3 1.1-.8 1.7-1.2c.3-.2.9 0 1.2-.5m21.5 4.4c-.4-.4-1.1-.5-1.6-.9c-.6-.5-1.6-.3-2.2-.1c-1.6.4-2.7.8-4.2 0c0 .5.1 2.5-.7 2.4c-.7 0-.5-2.1-.6-2.8c-.4.6-.7 1.1-.7 1.8c0 .5.2.8-.2 1.3c-.6.5-1.5.4-2.2.3c-.2-1.1.1-2.4.2-3.6c-.2 1-.5 2-.7 3.1c-.2.8-.9.9-1.5.7c-.1-.2.1-1 .1-1.2c-.6 1.1-1 2.5-1.8 3.5c-.4.5-1.3 1-1.7.2c-.3-.5-.1-1.2 0-1.8c-.5.6-1 2.3-1.8 2.3c.1-.4.4-.8-.1-1c-.2.4-.4.9-.7 1.4c.2-.6.4-1.3.5-2c-1.3.8-2.1 1.9-2.8 3.2c0-.2.1-.7.1-.9c-.1.4-.9 1.9-.4 2.2c.7-1.1 1.3-2.3 2.3-3.2c-.5 1.5-1.1 2.8-1.4 4.3c.6-.7 1.2-1.5 1.7-2.3c.1-.3.3-.6.4-.9c.3-.8.3-.2.9-.6c.5-.4.8-1.1 1.1-1.7c-.1 1.8 1.4 2.1 2.4.7c.4-.6.7-1.2 1-1.8l.8.2c.4 0 .7 0 1-.2c1.1.4 2.8.5 3.5-.8c1.2 1.3 2-.7 2.1-1.7c1.2.5 2.3-.1 3.5-.5c.7-.2 2-.8 2.5 0c.2.3.7.3 1.2.4M30.8 24.1s.1 0 0 0m0 0c0-.4-.3-.6-.7-.3c-.5.4-.2-.3-.2-.7c0-.5.1-.9.1-1.4c-.2.4-.5.8-.7 1.2c-.4.7-.3 2-1.3 2.1c.2-.5.3-1 .4-1.5c-.5.5-1.1.8-1.1 1.6c0 1-1 3.4-2.3 3.1c.1-2 1.2-3.8 1.7-5.7c-2 1.2-3.7 4.2-3.9 6.4c1-1.7 1.7-3.6 3.1-5c-.4 1.5-.9 2.9-1 4.4c0 .3.8.1.9.1c.7-.2 1.2-.9 1.5-1.5c.1-.2.3-.5.4-.7c.3-.6.4-.2.9-.5c.7-.3.7-1.2 1.4-1.1s2.2-.1 2.7-.4c-.6 0-1.2.1-1.9-.1m-.5-.4l.2.2c-.1 0-.2-.1-.2-.2m13.8 18.7c.5-.7-.2-.1 0 0'/%3E%3Cpath d='M58.4 39.7c-1.8-1.3-3.9-2.1-5.9-3.2c.4.6 1 1.3 1.3 2c-1 .1-.9 1.9-1 1.9c-.5-.3-1.9 0-2.5.1c0-.1 0-.2.1-.3c-1.8 1.2-3.3 3-5.7 2.5c1.1-1.7 2-3.6 1.9-5.7c-1.8.6-2.8 2.3-3.6 3.9c-.2-.6-1-1.1-1.5-.6c-.6.5-.9 1.5-1.1 2.2c-.3.9-.4 1.9-.5 2.8c0 .7-.1.8.6.8c1.7 0 3.2-2 4-3.2c2.2.6 3.5-.4 5.2-1.6c0 .8.6 1.3 1.4 1.1s1.2-1.2 1.8-1.2c.5 0 .8.2 1.3.2s1.1-.1 1.6-.2c-.6-.7-.8-1.2-1-2.1c1.2.3 2.3.6 3.6.6m-16.2 4.9c.2-.2.3-.3 0 0c-.3.2-.2.2-.1.1c-.5.4-1.1.9-1.8.9c0-1.5.2-3.3.9-4.6c.4-.6.9-.8 1.5-.3c.4.4-.1.8-.1 1.2c.1-.2.2-.4.3-.5c.1.6.4 1 1 1.3c-.5.6-1 1.3-1.7 1.9m1.9-2.2c-2.4-1 .7-4.1 2.1-4.7c-.2 1.7-1.1 3.3-2.1 4.7m6.9-.8c-.8.2-.8-.6-.7-1.1c.5.2 1 .4 1.6.5c-.2.3-.5.6-.9.6m2.7-.7v-.1zm.2-.6c.1-.1.1-.3.1-.4c-.3.1-.5.2-.8.3c0-.3-.1-1.1.3-1.2c.8-.4.8.9.9 1.4c-.2 0-.4 0-.5-.1m.9-1.8h-.2c-.1-.1 0-.1.2 0'/%3E%3C/g%3E%3Cpath fill='%23ffce31' d='m35.658 20.801l16.124-16.12l7.565 7.567l-16.124 16.12z'/%3E%3Cpath fill='%23ed4c5c' d='m62.6 2.3l-1-1c-1.8-1.8-4.8-1.8-6.6 0l-3.3 3.3l7.6 7.6l3.3-3.3c1.9-1.8 1.9-4.7 0-6.6'/%3E%3Cpath fill='%2393a2aa' d='m49.703 6.679l2.05-2.05l7.566 7.567l-2.051 2.05z'/%3E%3Cpath fill='%23c7d3d8' d='m50.552 7.527l2.05-2.05l5.94 5.939l-2.05 2.05z'/%3E%3Cpath fill='%23fed0ac' d='m35.6 20.8l-3.3 8.6l2.3 2.3l8.6-3.3z'/%3E%3Cpath fill='%23333' d='M31.8 30.9c-.5 1.2.2 1.8 1.3 1.3l4.2-1.6l-3.9-3.9z'/%3E%3Cpath fill='%23ffdf85' d='M35.672 20.82L49.744 6.75l2.545 2.545l-14.071 14.071z'/%3E%3Cpath fill='%23ff8736' d='m40.656 25.869l14.07-14.074l2.545 2.546l-14.07 14.073z'/%3E%3C/svg%3E"); + } + + &.rocket { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Cg fill='%23ff9d27'%3E%3Cpath d='M10.9 48.7c4-4 4.4-5 6.9-2.5s1.5 2.8-2.5 6.9c-3 3-6.8 2.4-6.8 2.4s-.6-3.8 2.4-6.8'/%3E%3Cpath d='M18.5 52.8c1.6-4.2 2.1-4.7-.2-6s-2.3-.4-3.8 3.8c-1.2 3.1.2 5.9.2 5.9s2.7-.5 3.8-3.7'/%3E%3C/g%3E%3Cpath fill='%23fdf516' d='M16.2 48.9c.9-2.3.9-2.8 2.1-2.1c1.3.7 1 1 .1 3.3c-.6 1.7-2.1 2.1-2.1 2.1s-.7-1.5-.1-3.3'/%3E%3Cpath fill='%23ff9d27' d='M17.1 45.7c-1.3-2.3-1.8-1.8-6-.2c-3.1 1.2-3.7 3.8-3.7 3.8s2.8 1.4 5.9.2c4.2-1.6 5.1-1.6 3.8-3.8'/%3E%3Cg fill='%23fdf516'%3E%3Cpath d='M15 47.8c2.3-.9 2.8-.9 2.1-2.1c-.7-1.3-1-1-3.3-.1c-1.7.6-2.1 2.1-2.1 2.1s1.6.7 3.3.1'/%3E%3Cpath d='M13.9 47.6c2.2-2.2 2.4-2.8 3.8-1.4s.8 1.6-1.4 3.8c-1.7 1.7-3.8 1.3-3.8 1.3s-.2-2 1.4-3.7'/%3E%3C/g%3E%3Cpath fill='%233baacf' d='M18.5 38C12.3 27.6 2 31.9 2 31.9s14.7-14.7 24.6-4.8z'/%3E%3Cpath fill='%23428bc1' d='m23.3 30.3l3.2-3.2C16.7 17.2 2 31.9 2 31.9s12.9-9.2 21.3-1.6'/%3E%3Cpath fill='%233baacf' d='M26 45.5C36.4 51.7 32.1 62 32.1 62s14.7-14.7 4.8-24.6z'/%3E%3Cpath fill='%23428bc1' d='m33.7 40.7l3.2-3.2c9.9 9.9-4.8 24.6-4.8 24.6s9.2-13 1.6-21.4'/%3E%3Cpath fill='%23c5d0d8' d='M48.8 30.9C37.1 42.5 24.2 48.8 19.7 44.3s1.8-17.4 13.4-29.1c13.6-13.6 28.7-13 28.7-13s.5 15.1-13 28.7'/%3E%3Cpath fill='%23dae3ea' d='M45.8 27.6C34.2 39.2 22.6 46.8 19.9 44.1s4.9-14.3 16.5-25.9C50 4.6 62 2 62 2s-2.6 12-16.2 25.6'/%3E%3Cpath fill='%23c94747' d='M24.3 47.5c-.5.5-1.3.5-1.8 0l-6-6c-.5-.5-.5-1.4 0-1.9l1.8-1.8l7.8 7.8z'/%3E%3Cpath fill='%23f15744' d='M22.6 45.7c-.5.5-1.1.7-1.4.4l-3.4-3.4c-.3-.3-.1-.9.4-1.4l1.8-1.8l4.4 4.4z'/%3E%3Cpath fill='%233e4347' d='M20.9 48.2c-.3.3-1 .3-1.3 0l-3.9-3.9c-.3-.3-.2-.9.1-1.2l1.2-1.2l5.1 5.1z'/%3E%3Cpath fill='%2362727a' d='M20.1 47.4c-.3.3-.9.4-1.1.2l-2.7-2.7c-.2-.2-.1-.7.3-1l1.2-1.2l3.5 3.5z'/%3E%3Cpath fill='%23c94747' d='M61.8 2.2S56.4 2 49.1 4.8l10.1 10.1C62 7.6 61.8 2.2 61.8 2.2'/%3E%3Cpath fill='%23f15744' d='M61.8 2.2s-4.3.9-10.8 4.6l6.2 6.2c3.7-6.5 4.6-10.8 4.6-10.8'/%3E%3Ccircle cx='43.5' cy='20.5' r='5' fill='%23edf4f9'/%3E%3Ccircle cx='43.5' cy='20.5' r='3.3' fill='%233baacf'/%3E%3Ccircle cx='33.5' cy='30.5' r='5' fill='%23edf4f9'/%3E%3Ccircle cx='33.5' cy='30.5' r='3.3' fill='%233baacf'/%3E%3Cg fill='%23fff'%3E%3Cpath d='M48.9 6.9c-.3.3-.9.3-1.2 0s-.3-.9 0-1.2s.9-.3 1.2 0s.3.9 0 1.2'/%3E%3Ccircle cx='50.6' cy='8.6' r='.8'/%3E%3Ccircle cx='53' cy='11' r='.8'/%3E%3Ccircle cx='55.3' cy='13.4' r='.8'/%3E%3Ccircle cx='57.7' cy='15.7' r='.8'/%3E%3C/g%3E%3C/svg%3E"); + } + + &.vite { + background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='1 6.8 30 18.4'%3E%3Cmask id='SVGgudELdDz'%3E%3Cpath fill='%23fff' d='M40.05 45.7c-.67.85-2.02.38-2.02-.69v-10.3a2.26 2.26 0 0 0-2.27-2.26H24.4a1.13 1.13 0 0 1-.92-1.8l7.48-10.46c1.07-1.5 0-3.58-1.84-3.58H15.34a1.13 1.13 0 0 1-.92-1.79l9.7-13.57c.2-.3.55-.48.92-.48h28.89c.92 0 1.46 1.04.92 1.79l-7.48 10.47a2.26 2.26 0 0 0 1.84 3.58H60.6c.94 0 1.47 1.09.89 1.83z'/%3E%3C/mask%3E%3Cg fill='none'%3E%3Cg mask='url(%23SVGgudELdDz)' transform='translate(1 6.8)scale(.393)'%3E%3Cpath fill='%239135ff' d='M0 0h62v47H0z'/%3E%3Cg filter='url(%23SVGNp06lekD)'%3E%3Cellipse cx='24.46' cy='37.75' fill='%23eee6ff' rx='5.51' ry='14.7' transform='rotate(89.8 24.46 37.75)'/%3E%3C/g%3E%3Cg filter='url(%23SVGNp06lekD)'%3E%3Cellipse cx='4.76' cy='18.96' fill='%23eee6ff' rx='10.4' ry='29.85' transform='rotate(89.8 4.76 18.96)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='4.24' cy='17.5' fill='%238900ff' rx='5.51' ry='30.49' transform='rotate(89.8 4.24 17.5)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='8.95' cy='35.5' fill='%238900ff' rx='5.51' ry='30.6' transform='rotate(89.8 8.95 35.5)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='10.48' cy='36.65' fill='%238900ff' rx='5.51' ry='30.6' transform='rotate(89.8 10.48 36.65)'/%3E%3C/g%3E%3Cg filter='url(%23SVGNp06lekD)'%3E%3Cellipse cx='67.34' cy='12.3' fill='%23eee6ff' rx='14.07' ry='22.08' transform='rotate(-86.7 67.34 12.3)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='68.44' cy='15.74' fill='%238900ff' rx='3.47' ry='21.5' transform='rotate(-91 68.44 15.74)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='68.44' cy='15.74' fill='%238900ff' rx='3.47' ry='21.5' transform='rotate(-91 68.44 15.74)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='14.59' cy='9.74' fill='%238900ff' rx='4.41' ry='29.11' transform='rotate(39.5 14.6 9.74)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='61.73' cy='-5.32' fill='%238900ff' rx='4.41' ry='29.11' transform='rotate(37.9 61.73 -5.32)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='55.62' cy='7.1' fill='%2300c2ff' rx='5.97' ry='9.67' transform='rotate(37.9 55.62 7.1)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='12.33' cy='39.1' fill='%238900ff' rx='4.41' ry='29.11' transform='rotate(37.9 12.33 39.1)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='12.33' cy='39.1' fill='%238900ff' rx='4.41' ry='29.11' transform='rotate(37.9 12.33 39.1)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='49.86' cy='30.68' fill='%238900ff' rx='4.41' ry='29.11' transform='rotate(37.9 49.86 30.68)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='52.62' cy='33.17' fill='%2300c2ff' rx='5.97' ry='15.3' transform='rotate(37.9 52.62 33.17)'/%3E%3C/g%3E%3C/g%3E%3Cpath fill='%2308060e' d='M3.72 6.8C.1 11.98.08 20 3.72 25.2h2.45c-3.64-5.2-3.62-13.22 0-18.4zm24.56 0h-2.45c3.62 5.18 3.64 13.2 0 18.4h2.45c3.64-5.2 3.62-13.22 0-18.4'/%3E%3Cdefs%3E%3Cfilter id='SVGNp06lekD' width='4' height='4' x='-2' y='-2' color-interpolation-filters='sRGB'%3E%3CfeGaussianBlur stdDeviation='7.66'/%3E%3C/filter%3E%3Cfilter id='SVGQv8P6csY' width='4' height='4' x='-2' y='-2' color-interpolation-filters='sRGB'%3E%3CfeGaussianBlur stdDeviation='4.6'/%3E%3C/filter%3E%3C/defs%3E%3C/g%3E%3C/svg%3E"); + .dark & { + background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='1 6.8 30 18.4'%3E%3Cmask id='SVGgudELdDz'%3E%3Cpath fill='%23fff' d='M40.05 45.7c-.67.85-2.02.38-2.02-.69v-10.3a2.26 2.26 0 0 0-2.27-2.26H24.4a1.13 1.13 0 0 1-.92-1.8l7.48-10.46c1.07-1.5 0-3.58-1.84-3.58H15.34a1.13 1.13 0 0 1-.92-1.79l9.7-13.57c.2-.3.55-.48.92-.48h28.89c.92 0 1.46 1.04.92 1.79l-7.48 10.47a2.26 2.26 0 0 0 1.84 3.58H60.6c.94 0 1.47 1.09.89 1.83z'/%3E%3C/mask%3E%3Cg fill='none'%3E%3Cg mask='url(%23SVGgudELdDz)' transform='translate(1 6.8)scale(.393)'%3E%3Cpath fill='%239135ff' d='M0 0h62v47H0z'/%3E%3Cg filter='url(%23SVGNp06lekD)'%3E%3Cellipse cx='24.46' cy='37.75' fill='%23eee6ff' rx='5.51' ry='14.7' transform='rotate(89.8 24.46 37.75)'/%3E%3C/g%3E%3Cg filter='url(%23SVGNp06lekD)'%3E%3Cellipse cx='4.76' cy='18.96' fill='%23eee6ff' rx='10.4' ry='29.85' transform='rotate(89.8 4.76 18.96)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='4.24' cy='17.5' fill='%238900ff' rx='5.51' ry='30.49' transform='rotate(89.8 4.24 17.5)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='8.95' cy='35.5' fill='%238900ff' rx='5.51' ry='30.6' transform='rotate(89.8 8.95 35.5)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='10.48' cy='36.65' fill='%238900ff' rx='5.51' ry='30.6' transform='rotate(89.8 10.48 36.65)'/%3E%3C/g%3E%3Cg filter='url(%23SVGNp06lekD)'%3E%3Cellipse cx='67.34' cy='12.3' fill='%23eee6ff' rx='14.07' ry='22.08' transform='rotate(-86.7 67.34 12.3)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='68.44' cy='15.74' fill='%238900ff' rx='3.47' ry='21.5' transform='rotate(-91 68.44 15.74)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='68.44' cy='15.74' fill='%238900ff' rx='3.47' ry='21.5' transform='rotate(-91 68.44 15.74)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='14.59' cy='9.74' fill='%238900ff' rx='4.41' ry='29.11' transform='rotate(39.5 14.6 9.74)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='61.73' cy='-5.32' fill='%238900ff' rx='4.41' ry='29.11' transform='rotate(37.9 61.73 -5.32)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='55.62' cy='7.1' fill='%2300c2ff' rx='5.97' ry='9.67' transform='rotate(37.9 55.62 7.1)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='12.33' cy='39.1' fill='%238900ff' rx='4.41' ry='29.11' transform='rotate(37.9 12.33 39.1)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='12.33' cy='39.1' fill='%238900ff' rx='4.41' ry='29.11' transform='rotate(37.9 12.33 39.1)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='49.86' cy='30.68' fill='%238900ff' rx='4.41' ry='29.11' transform='rotate(37.9 49.86 30.68)'/%3E%3C/g%3E%3Cg filter='url(%23SVGQv8P6csY)'%3E%3Cellipse cx='52.62' cy='33.17' fill='%2300c2ff' rx='5.97' ry='15.3' transform='rotate(37.9 52.62 33.17)'/%3E%3C/g%3E%3C/g%3E%3Cpath fill='%23fff' d='M3.72 6.8C.1 11.98.08 20 3.72 25.2h2.45c-3.64-5.2-3.62-13.22 0-18.4zm24.56 0h-2.45c3.62 5.18 3.64 13.2 0 18.4h2.45c3.64-5.2 3.62-13.22 0-18.4'/%3E%3Cdefs%3E%3Cfilter id='SVGNp06lekD' width='4' height='4' x='-2' y='-2' color-interpolation-filters='sRGB'%3E%3CfeGaussianBlur stdDeviation='7.66'/%3E%3C/filter%3E%3Cfilter id='SVGQv8P6csY' width='4' height='4' x='-2' y='-2' color-interpolation-filters='sRGB'%3E%3CfeGaussianBlur stdDeviation='4.6'/%3E%3C/filter%3E%3C/defs%3E%3C/g%3E%3C/svg%3E"); + } + width: 1.3em; + } + + &.vue { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='2 3.92 28 24.15'%3E%3Cpath fill='%2341b883' d='M24.4 3.925H30l-14 24.15L2 3.925h10.71l3.29 5.6l3.22-5.6Z'%3E%3C/path%3E%3Cpath fill='%2341b883' d='m2 3.925l14 24.15l14-24.15h-5.6L16 18.415L7.53 3.925Z'%3E%3C/path%3E%3Cpath fill='%2335495e' d='M7.53 3.925L16 18.485l8.4-14.56h-5.18L16 9.525l-3.29-5.6Z'%3E%3C/path%3E%3C/svg%3E"); + } } diff --git a/docs/en/guide/asset-handling.md b/docs/en/guide/asset-handling.md index 00819d1a..63394fd0 100644 --- a/docs/en/guide/asset-handling.md +++ b/docs/en/guide/asset-handling.md @@ -6,7 +6,7 @@ description: Learn how to reference and handle static assets such as images, med ## Referencing Static Assets -All Markdown files are compiled into Vue components and processed by [Vite](https://vitejs.dev/guide/assets.html). You can, **and should**, reference any assets using relative URLs: +All Markdown files are compiled into Vue components and processed by [Vite](https://vite.dev/guide/assets.html). You can, **and should**, reference any assets using relative URLs: ```md ![An image](./image.png) diff --git a/docs/en/guide/custom-theme.md b/docs/en/guide/custom-theme.md index 8de4c7ab..957c27dc 100644 --- a/docs/en/guide/custom-theme.md +++ b/docs/en/guide/custom-theme.md @@ -62,11 +62,14 @@ import Layout from './Layout.vue' export default { Layout, enhanceApp({ app, router, siteData }) { - // ... + // app.component(...) + // app.use(...) } } ``` +The `enhanceApp` hook allows you to access the [Vue app instance](https://vuejs.org/api/application.html) and other runtime data, which can be used to [register global components](./extending-default-theme.md#registering-global-components), integrate with Vue libraries, etc. + The `router` value is the same VitePress router instance returned by [`useRouter()`](../reference/runtime-api#userouter). To listen for route changes, assign handlers on the router: ```ts [.vitepress/theme/index.ts] @@ -226,10 +229,10 @@ Finally, if the theme provides types for its theme config: ```ts [.vitepress/config.ts] import baseConfig from 'awesome-vitepress-theme/config' -import { defineConfigWithTheme } from 'vitepress' +import { defineConfig } from 'vitepress' import type { ThemeConfig } from 'awesome-vitepress-theme' -export default defineConfigWithTheme({ +export default defineConfig({ extends: baseConfig, themeConfig: { // Type is `ThemeConfig` diff --git a/docs/en/guide/extending-default-theme.md b/docs/en/guide/extending-default-theme.md index 5ff15f5b..8a109e34 100644 --- a/docs/en/guide/extending-default-theme.md +++ b/docs/en/guide/extending-default-theme.md @@ -119,7 +119,7 @@ export default { } satisfies Theme ``` -Since we are using Vite, you can also leverage Vite's [glob import feature](https://vitejs.dev/guide/features.html#glob-import) to auto register a directory of components. +Since we are using Vite, you can also leverage Vite's [glob import feature](https://vite.dev/guide/features.html#glob-import) to auto register a directory of components. ## Layout Slots @@ -309,7 +309,7 @@ Coming soon. ## Overriding Internal Components -You can use Vite's [aliases](https://vitejs.dev/config/shared-options.html#resolve-alias) to replace default theme components with your custom ones: +You can use Vite's [aliases](https://vite.dev/config/shared-options.html#resolve-alias) to replace default theme components with your custom ones: ```ts import { fileURLToPath, URL } from 'node:url' diff --git a/docs/en/guide/getting-started.md b/docs/en/guide/getting-started.md index 31e45695..a181192d 100644 --- a/docs/en/guide/getting-started.md +++ b/docs/en/guide/getting-started.md @@ -45,7 +45,7 @@ $ deno add -D vitepress@next ::: tip NOTE -VitePress is an ESM-only package. Don't use `require()` to import it, and make sure your nearest `package.json` contains `"type": "module"`, or change the file extension of your relevant files like `.vitepress/config.js` to `.mjs`/`.mts`. Refer to [Vite's troubleshooting guide](http://vitejs.dev/guide/troubleshooting.html#this-package-is-esm-only) for more details. Also, inside async CJS contexts, you can use `await import('vitepress')` instead. +VitePress is an ESM-only package. Don't use `require()` to import it, and make sure your nearest `package.json` contains `"type": "module"`, or change the file extension of your relevant files like `.vitepress/config.js` to `.mjs`/`.mts`. Refer to [Vite's troubleshooting guide](http://vite.dev/guide/troubleshooting.html#this-package-is-esm-only) for more details. Also, inside async CJS contexts, you can use `await import('vitepress')` instead. ::: diff --git a/docs/en/guide/i18n.md b/docs/en/guide/i18n.md index 8a57bb78..f7f285e6 100644 --- a/docs/en/guide/i18n.md +++ b/docs/en/guide/i18n.md @@ -57,6 +57,37 @@ Refer [`DefaultTheme.Config`](https://github.com/vuejs/vitepress/blob/main/types **Pro tip:** Config file can be stored at `docs/.vitepress/config/index.ts` too. It might help you organize stuff by creating a configuration file per locale and then merge and export them from `index.ts`. +## Per-locale Markdown Strings + +Strings baked into pages by the markdown renderer - the default titles of [custom containers](./markdown#custom-containers) and [GitHub-flavored alerts](./markdown#github-flavored-alerts), and the strings of the code copy button - can be overridden per locale with the `markdown` key of a locale entry: + +```ts [docs/.vitepress/config.ts] +import { defineConfig } from 'vitepress' + +export default defineConfig({ + locales: { + root: { label: 'English', lang: 'en' }, + zh: { + label: '简体中文', + lang: 'zh-Hans', + markdown: { + container: { + tipLabel: '提示', + warningLabel: '警告' + // ...the other labels, and titles of `customContainers` + }, + codeCopyButton: { + tooltipText: '复制代码', + copiedText: '已复制' + } + } + } + } +}) +``` + +Values fall back to the root-level `markdown` options when a locale leaves them unset. Locale entries can only override the titles of containers registered at the root level - registering new containers per locale is not supported. Also note that since the markdown renderer is created once for the whole site, these can only be declared in the main config file, not in additional configs. + ## Separate directory for each locale The following is a perfectly fine structure: diff --git a/docs/en/guide/markdown.md b/docs/en/guide/markdown.md index 193ab8cf..715e740b 100644 --- a/docs/en/guide/markdown.md +++ b/docs/en/guide/markdown.md @@ -1,5 +1,6 @@ --- description: VitePress built-in Markdown extensions including custom containers, code blocks with syntax highlighting, line highlighting, code groups, and more. +outline: deep --- # Markdown Extensions @@ -100,6 +101,36 @@ For more details, see [Frontmatter](../reference/frontmatter-config). | col 2 is | centered | \$12 | | zebra stripes | are neat | \$1 | +## Task Lists + +**Input** + +```md +- [ ] Write the press release +- [x] Update the website +``` + +**Output** + +- [ ] Write the press release +- [x] Update the website + +## Footnotes + +**Input** + +```md +Footnotes are supported[^1], including inline ones^[This is an inline footnote.]. + +[^1]: Definitions can contain **markdown** and are rendered at the end of the page. +``` + +**Output** + +Footnotes are supported[^1], including inline ones^[This is an inline footnote.]. + +[^1]: Definitions can contain **markdown** and are rendered at the end of the page. + ## Emoji :tada: **Input** @@ -112,7 +143,7 @@ For more details, see [Frontmatter](../reference/frontmatter-config). :tada: :100: -A [list of all emojis](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.mjs) is available. +A [list of all emojis](https://github.com/mdit-plugins/mdit-plugins/blob/main/packages/plugin-emoji/src/data/full.ts) is available. ## Table of Contents @@ -229,9 +260,82 @@ export default defineConfig({ }) ``` +On multilingual sites, these labels can also be overridden per locale - see [Per-locale Markdown Strings](./i18n#per-locale-markdown-strings). + +### Registering New Containers + +Beyond the built-in types, you can register additional containers by mapping their names to their default titles: + +```ts +// config.ts +export default defineConfig({ + // ... + markdown: { + container: { + customContainers: { + success: 'SUCCESS' + } + } + } + // ... +}) +``` + +Registered names work like the built-in ones - including custom titles, attributes, and the [GitHub-style alert syntax](#github-flavored-alerts): + +```md +::: success +You have completed the walkthrough! +::: + +> [!SUCCESS] Custom title +> This renders the same way. +``` + +New containers ship without any styling, so add some in your theme using the container name as the class. For this example, the default theme's palette already provides fitting colors: + +```css +/* .vitepress/theme/custom.css */ +.custom-block.success { + border-color: transparent; + color: var(--vp-c-text-1); + background-color: var(--vp-c-success-soft); +} +``` + +### Nesting + +The `:::` markers follow the same rules as fenced code blocks (` ``` `): a fence is only closed by a matching fence that is **at least as long** as the one that opened it. To nest containers (or to mix them with [code groups](#code-groups)) make the outer fence longer than the ones inside it. + +**Input** + +`````md +:::: info Outer container +This box contains another container. + +::: details Inner container +```js +console.log('Hello, VitePress!') +``` +::: +:::: +````` + +**Output** + +:::: info Outer container +This box contains another container. + +::: details Inner container +```js +console.log('Hello, VitePress!') +``` +::: +:::: + ### Additional Attributes -You can add additional attributes to the custom containers. We use [markdown-it-attrs](https://github.com/arve0/markdown-it-attrs) for this feature, and it is supported on almost all markdown elements. For example, you can set the `open` attribute to make the details block open by default: +You can add additional attributes to the custom containers. We use [@mdit/plugin-attrs](https://mdit-plugins.github.io/attrs.html) for this feature, and it is supported on almost all markdown elements. For example, you can set the `open` attribute to make the details block open by default: **Input** @@ -251,9 +355,25 @@ console.log('Hello, VitePress!') ``` ::: +The special `no-title` attribute renders a container without a title element (it has no effect on `details`, which always needs its summary): + +**Input** + +```md +::: tip {no-title} +Just want to try it out? Skip to the [Quickstart](./getting-started). +::: +``` + +**Output** + +::: tip {no-title} +Just want to try it out? Skip to the [Quickstart](./getting-started). +::: + ### `raw` -This is a special container that can be used to prevent style and router conflicts with VitePress. This is especially useful when you're documenting component libraries. You might also wanna check out [whyframe](https://whyframe.dev/docs/integrations/vitepress) for better isolation. +This is a special container that can be used to prevent style and router conflicts with VitePress. This is especially useful when you're documenting component libraries. **Syntax** @@ -291,7 +411,7 @@ Wraps in a `
      ` ## GitHub-flavored Alerts -VitePress also supports [GitHub-flavored alerts](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts) to render as callouts. They will be rendered the same as the [custom containers](#custom-containers). +VitePress also supports [GitHub-flavored alerts](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts) to render as callouts. They will be rendered the same as the [custom containers](#custom-containers). Unlike on GitHub, text placed right after the marker becomes the title of the alert (`> [!NOTE] Custom Title`), and [containers you registered yourself](#registering-new-containers) work here too. ```md > [!NOTE] @@ -676,6 +796,16 @@ You can also use a [VS Code region](https://code.visualstudio.com/docs/editor/co <<< @/snippets/snippet-with-region.js#snippet{1} +If a file contains multiple regions with the same name, all of them are imported and concatenated — including regions written in different comment styles, such as a `` in the template and a `// #region` in the script of the same Vue SFC. The marker comments delimiting them are removed from the output; set `markdown.snippet.stripRegionMarkers` to `'all'` to also remove markers of other comment styles nested inside the region, or to `false` to keep all of them. + +::: tip +Region names may contain letters, digits, `_`, `-` and `.`. Since the name is taken from the end of the path, a file whose name itself contains a `#` needs an explicit region — write `<<< ./my#file.js#region` rather than `<<< ./my#file.js`. +::: + +::: warning +Importing a file or region that does not exist throws a build error. Set `markdown.snippet.silent: true` to log a warning and render nothing instead. +::: + You can also specify the language inside the braces (`{}`) like this: ```md @@ -690,7 +820,9 @@ You can also specify the language inside the braces (`{}`) like this: <<< @/snippets/snippet.cs{1,2,4-6 c#:line-numbers} ``` -This is helpful if source language cannot be inferred from your file extension. +This is helpful if source language cannot be inferred from your file extension. Only alphanumeric extensions are inferred, so files like `main.c++` or `scss.code-snippets` need the language spelled out this way. + +Anything after the language inside the braces is passed along to the code block as extra attributes — for example, `<<< @/snippets/snippet.ts{ts twoslash}` enables twoslash processing when [`@shikijs/vitepress-twoslash`](https://shiki.style/packages/vitepress#twoslash) is configured. Note that attributes may not contain square brackets. ## Code Groups @@ -898,7 +1030,7 @@ You can also use a [VS Code region](https://code.visualstudio.com/docs/editor/co ``` ::: warning -Note that this does not throw errors if your file is not present. Hence, when using this feature make sure that the contents are being rendered as expected. +Including a missing file, region, heading anchor, or an out-of-range line selection throws a build error. Set `markdown.include.silent: true` to log a warning and skip the inclusion instead. ::: Instead of VS Code regions, you can also use header anchors to include a specific section of the file. For example, if you have a header in your markdown file like this: @@ -948,6 +1080,28 @@ and include it like this: ``` +Relative links and images inside included files resolve from the _included_ file's location, so a partial can link to its neighbors no matter which page includes it. Set `markdown.include.rebaseRelativeUrls: false` to leave them resolving relative to the including page instead. + +### Including Code Files {#including-code-files} + +Since inclusion happens before code blocks are parsed, the directive also works inside fences. Combined with a line range, this lets you show only part of a code file — an alternative to [importing snippets](#import-code-snippets) when regions are not an option: + +**Input** + +````md +```js + +``` +```` + +**Output** + +```js + +``` + +Note that the included lines are inserted verbatim (indentation is preserved), and content containing backticks needs a longer outer fence. + ## Math Equations This is currently opt-in. To enable it, you need to install `markdown-it-mathjax3` and set `markdown.math` to `true` in your config file: @@ -994,14 +1148,14 @@ $$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ ## Image Lazy Loading -You can enable lazy loading for each image added via markdown by setting `lazyLoading` to `true` in your config file: +You can enable lazy loading for each image added via markdown by setting `lazyLoad` to `true` in your config file: ```js export default { markdown: { image: { // image lazy loading is disabled by default - lazyLoading: true + lazyLoad: true } } } @@ -1013,15 +1167,15 @@ VitePress uses [markdown-it](https://github.com/markdown-it/markdown-it) as the ```js import { defineConfig } from 'vitepress' -import markdownItAnchor from 'markdown-it-anchor' +import { headerLink } from '@mdit/plugin-anchor' import markdownItFoo from 'markdown-it-foo' export default defineConfig({ markdown: { - // options for markdown-it-anchor - // https://github.com/valeriangalliat/markdown-it-anchor#usage + // options for @mdit/plugin-anchor + // https://mdit-plugins.github.io/anchor.html anchor: { - permalink: markdownItAnchor.permalink.headerLink() + permalink: headerLink() }, // options for @mdit-vue/plugin-toc diff --git a/docs/en/guide/migration-from-vitepress-0.md b/docs/en/guide/migration-from-vitepress-0.md index 29ab9a2a..342ab1ea 100644 --- a/docs/en/guide/migration-from-vitepress-0.md +++ b/docs/en/guide/migration-from-vitepress-0.md @@ -14,7 +14,7 @@ If you're coming from VitePress 0.x version, there're several breaking changes d - `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`. +- `lastUpdated` option is now split into `config.lastUpdated` and `themeConfig.lastUpdated.text`. - `carbonAds.carbon` is changed to `carbonAds.code`. ## Frontmatter Config diff --git a/docs/en/guide/ssr-compat.md b/docs/en/guide/ssr-compat.md index 99171ad6..f532b16a 100644 --- a/docs/en/guide/ssr-compat.md +++ b/docs/en/guide/ssr-compat.md @@ -39,7 +39,7 @@ onMounted(() => { ### Conditional Import -You can also conditionally import a dependency using the `import.meta.env.SSR` flag (part of [Vite env variables](https://vitejs.dev/guide/env-and-mode.html#env-variables)): +You can also conditionally import a dependency using the `import.meta.env.SSR` flag (part of [Vite env variables](https://vite.dev/guide/env-and-mode.html#env-variables)): ```js if (!import.meta.env.SSR) { diff --git a/docs/en/guide/using-vue.md b/docs/en/guide/using-vue.md index a9b9a389..4d6c7e87 100644 --- a/docs/en/guide/using-vue.md +++ b/docs/en/guide/using-vue.md @@ -204,7 +204,7 @@ Note that this might prevent certain tokens from being syntax highlighted proper ## Using CSS Pre-processors -VitePress has [built-in support](https://vitejs.dev/guide/features.html#css-pre-processors) for CSS pre-processors: `.scss`, `.sass`, `.less`, `.styl` and `.stylus` files. There is no need to install Vite-specific plugins for them, but the corresponding pre-processor itself must be installed: +VitePress has [built-in support](https://vite.dev/guide/features.html#css-pre-processors) for CSS pre-processors: `.scss`, `.sass`, `.less`, `.styl` and `.stylus` files. There is no need to install Vite-specific plugins for them, but the corresponding pre-processor itself must be installed: ``` # .scss and .sass diff --git a/docs/en/guide/what-is-vitepress.md b/docs/en/guide/what-is-vitepress.md index b63eb7ea..91358ac5 100644 --- a/docs/en/guide/what-is-vitepress.md +++ b/docs/en/guide/what-is-vitepress.md @@ -6,17 +6,15 @@ description: VitePress is a static site generator designed for building fast, co VitePress is a [Static Site Generator](https://en.wikipedia.org/wiki/Static_site_generator) (SSG) designed for building fast, content-centric websites. In a nutshell, VitePress takes your source content written in [Markdown](https://en.wikipedia.org/wiki/Markdown), applies a theme to it, and generates static HTML pages that can be easily deployed anywhere. -
      - +::: tip {no-title} Just want to try it out? Skip to the [Quickstart](./getting-started). - -
      +::: ## Use Cases - **Documentation** - VitePress ships with a default theme designed for technical documentation. It powers this page you are reading right now, along with the documentation for [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/) and [many more](https://github.com/search?q=/%22vitepress%22:+/+path:/(?:package%7Cdeno)%5C.jsonc?$/+NOT+is:fork+NOT+is:archived&type=code). + VitePress ships with a default theme designed for technical documentation. It powers this page you are reading right now, along with the documentation for [Vite](https://vite.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/) and [many more](https://github.com/search?q=/%22vitepress%22:+/+path:/(?:package%7Cdeno)%5C.jsonc?$/+NOT+is:fork+NOT+is:archived&type=code). The [official Vue.js documentation](https://vuejs.org/) is also based on VitePress, but uses a custom theme shared between multiple translations. @@ -30,7 +28,7 @@ Just want to try it out? Skip to the [Quickstart](./getting-started). VitePress aims to provide a great Developer Experience (DX) when working with Markdown content. -- **[Vite-Powered:](https://vitejs.dev/)** instant server start, with edits always instantly reflected (<100ms) without page reload. +- **[Vite-Powered:](https://vite.dev/)** instant server start, with edits always instantly reflected (<100ms) without page reload. - **[Built-in Markdown Extensions:](./markdown)** Frontmatter, tables, syntax highlighting... you name it. Specifically, VitePress provides many advanced features for working with code blocks, making it ideal for highly technical documentation. diff --git a/docs/en/index.md b/docs/en/index.md index ce9015b2..93f8f3f6 100644 --- a/docs/en/index.md +++ b/docs/en/index.md @@ -21,16 +21,16 @@ hero: alt: VitePress features: - - icon: 📝 + - icon: title: Focus on your content details: Effortlessly create beautiful documentation sites with just markdown. - - icon: + - icon: title: Enjoy the Vite DX details: Instant server start, lightning fast hot updates, and leverage Vite ecosystem plugins. - - icon: + - icon: title: Customize with Vue details: Use Vue syntax and components directly in markdown, or build custom themes with Vue. - - icon: 🚀 + - icon: title: Ship fast sites details: Fast initial load with static HTML, fast post-load navigation with client-side routing. --- diff --git a/docs/en/reference/default-theme-config.md b/docs/en/reference/default-theme-config.md index cc4ffd0e..02c221ec 100644 --- a/docs/en/reference/default-theme-config.md +++ b/docs/en/reference/default-theme-config.md @@ -25,23 +25,23 @@ export default { ## i18nRouting -- Type: `boolean | ((data: VitePressData, hash: string, targetLocale: string) => string)` +- Type: `boolean | ((data: VitePressData, route: Route, targetLocale: string) => string)` Changing locale to say `zh` will change the URL from `/foo` (or `/en/foo/`) to `/zh/foo`. You can disable this behavior by setting `themeConfig.i18nRouting` to `false`. -Set `themeConfig.i18nRouting` to a function to customize the locale link. The function receives the current VitePress data, the current hash, and the target locale key, and returns the target link. +Set `themeConfig.i18nRouting` to a function to customize the locale link. The function receives the current VitePress data, the current route, and the target locale key, and returns the target link. ```ts import { defineConfig } from 'vitepress' export default defineConfig({ themeConfig: { - i18nRouting(data, hash, targetLocale) { + i18nRouting(data, route, targetLocale) { const target = data.site.value.locales[targetLocale] const targetLink = target.link || (targetLocale === 'root' ? '/' : `/${targetLocale}/`) - return `${targetLink}${data.page.value.relativePath.replace(/\.md$/, '')}${hash}` + return `${targetLink}${route.data.relativePath.replace(/\.md$/, '')}${route.hash}` } } }) diff --git a/docs/en/reference/default-theme-sidebar.md b/docs/en/reference/default-theme-sidebar.md index cd44425d..559cd61d 100644 --- a/docs/en/reference/default-theme-sidebar.md +++ b/docs/en/reference/default-theme-sidebar.md @@ -184,3 +184,63 @@ export default { } } ``` + +## Path Prefix + +When your documentation structure has deep directories or groups located under the same subdirectory, you can use the `base` option to automatically prepend a path prefix to all nested `items` inside that group. This avoids repeating the same path prefix for every `link`. + +The `base` option is supported in both multiple sidebar configurations and nested sidebar groups. + +### In Multiple Sidebars + +You can define `base` at the root of a sidebar section configuration: + +```js {5} +export default { + themeConfig: { + sidebar: { + '/guide/': { + base: '/guide/', + items: [ + // This link is resolved to `/guide/introduction` + { text: 'Introduction', link: 'introduction' }, + // This link is resolved to `/guide/getting-started` + { text: 'Getting Started', link: 'getting-started' } + ] + } + } + } +} +``` + +### In Nested Groups + +You can also use `base` inside nested sidebar groups. It will apply to the immediate children of that group: + +```js{6,13} +export default { + themeConfig: { + sidebar: [ + { + text: 'Reference', + base: '/reference/', + items: [ + // This link is resolved to `/reference/site-config` + { text: 'Site Config', link: 'site-config' }, + { + text: 'Default Theme', + // Nested base overrides the parent path prefix + base: '/reference/default-theme-', + items: [ + // This link is resolved to `/reference/default-theme-nav` + { text: 'Nav', link: 'nav' }, + // This link is resolved to `/reference/default-theme-sidebar` + { text: 'Sidebar', link: 'sidebar' } + ] + } + ] + } + ] + } +} +``` diff --git a/docs/en/reference/runtime-api.md b/docs/en/reference/runtime-api.md index a202b270..b69808ee 100644 --- a/docs/en/reference/runtime-api.md +++ b/docs/en/reference/runtime-api.md @@ -140,7 +140,7 @@ For custom themes, the same router is available from [`enhanceApp`](../guide/cus - **Type**: `(path: string) => string` -Appends the configured [`base`](./site-config#base) to a given URL path. Also see [Base URL](../guide/asset-handling#base-url). +Prepends the configured [`base`](./site-config#base) to a given URL path. Also see [Base URL](../guide/asset-handling#base-url). ## `` diff --git a/docs/en/reference/site-config.md b/docs/en/reference/site-config.md index 4c8c50e6..a9d9c4f1 100644 --- a/docs/en/reference/site-config.md +++ b/docs/en/reference/site-config.md @@ -461,7 +461,7 @@ export default { - Type: `string` - Default: `./.vitepress/cache` -The directory for cache files, relative to [project root](../guide/routing#root-and-source-directory). See also: [cacheDir](https://vitejs.dev/config/shared-options.html#cachedir). +The directory for cache files, relative to [project root](../guide/routing#root-and-source-directory). See also: [cacheDir](https://vite.dev/config/shared-options.html#cachedir). ```ts export default { @@ -503,13 +503,6 @@ 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` @@ -543,7 +536,7 @@ This option injects an inline script that restores users settings from local sto Whether to get the last updated timestamp for each page using Git. The timestamp will be included in each page's page data, accessible via [`useData`](./runtime-api#usedata). -When using the default theme, enabling this option will display each page's last updated time. You can customize the text via [`themeConfig.lastUpdatedText`](./default-theme-config#lastupdatedtext) option. +When using the default theme, enabling this option will display each page's last updated time. You can customize the text via [`themeConfig.lastUpdated.text`](./default-theme-config#lastupdated) option. ## Customization @@ -567,7 +560,7 @@ Set `markdown.headers` to `true` or pass [`@mdit-vue/plugin-headers`](https://gi - Type: `import('vite').UserConfig` -Pass raw [Vite Config](https://vitejs.dev/config/) to internal Vite dev server / bundler. +Pass raw [Vite Config](https://vite.dev/config/) to internal Vite dev server / bundler. ```js export default { diff --git a/docs/es/config.ts b/docs/es/config.ts index 382ad71b..0427767e 100644 --- a/docs/es/config.ts +++ b/docs/es/config.ts @@ -1,9 +1,30 @@ import { createRequire } from 'node:module' -import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' +import { + defineAdditionalConfig, + type DefaultTheme, + type MarkdownLocaleOptions +} from 'vitepress' const require = createRequire(import.meta.url) const pkg = require('vitepress/package.json') +export const markdown: MarkdownLocaleOptions = { + container: { + tipLabel: 'CONSEJO', + infoLabel: 'INFORMACIÓN', + warningLabel: 'ADVERTENCIA', + dangerLabel: 'PELIGRO', + detailsLabel: 'Detalles', + noteLabel: 'NOTA', + importantLabel: 'IMPORTANTE', + cautionLabel: 'PRECAUCIÓN' + }, + codeCopyButton: { + tooltipText: 'Copiar código', + copiedText: 'Copiado' + } +} + export default defineAdditionalConfig({ description: 'Generador de Sitios Estáticos desarrollado con Vite y Vue.', @@ -267,8 +288,6 @@ function searchOptions(): Partial { afterToolCallText: 'Buscado', stoppedStreamingText: 'Has detenido esta respuesta', errorTitleText: 'Error de chat', - threadDepthExceededMessage: - 'Esta conversación se ha cerrado para mantener respuestas precisas.', startNewConversationButtonText: 'Iniciar una nueva conversación' } } diff --git a/docs/es/guide/asset-handling.md b/docs/es/guide/asset-handling.md index c3580347..30c9034d 100644 --- a/docs/es/guide/asset-handling.md +++ b/docs/es/guide/asset-handling.md @@ -6,7 +6,7 @@ description: Aprende cómo referenciar y manejar recursos estáticos como imáge ## 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: +Todos los archivos Markdown son compilados en componentes Vue y procesados por [Vite](https://vite.dev/guide/assets.html). Usted puede **y debe** referenciar cualquier asset usando URLs relativas: ```md ![Una imagen](./imagen.png) diff --git a/docs/es/guide/extending-default-theme.md b/docs/es/guide/extending-default-theme.md index b9b9a67f..1e4a7885 100644 --- a/docs/es/guide/extending-default-theme.md +++ b/docs/es/guide/extending-default-theme.md @@ -119,7 +119,7 @@ export default { } 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. +Como estamos usando Vite, puede también aprovechar la [funcionalidad de importación glob](https://vite.dev/guide/features.html#glob-import) de Vite para registrar automaticamente un directorio de componetes. ## _Slots_ en el Layout {#layout-slots} @@ -309,7 +309,7 @@ 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: +Puede usar los [aliases](https://vite.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' diff --git a/docs/es/guide/getting-started.md b/docs/es/guide/getting-started.md index 10408445..9461c808 100644 --- a/docs/es/guide/getting-started.md +++ b/docs/es/guide/getting-started.md @@ -41,7 +41,7 @@ $ bun add -D vitepress@next ::: tip NOTA -VitePress es un paquete apenas para ESM. No use `require()` para importarlo, y asegurese de que el `package.json` más cercano contiene `"type": "module"`, o cambie la extensión de archivo de sus archivos relevantes como `.vitepress/config.js` a `.mjs`/`.mts`. Consulte la [Guía de resolución de problemas Vite](http://vitejs.dev/guide/troubleshooting.html#this-package-is-esm-only) para más detalles. Además de eso, dentro de contextos de JavaScript asíncronos, puede usar `await import('vitepress')`. +VitePress es un paquete apenas para ESM. No use `require()` para importarlo, y asegurese de que el `package.json` más cercano contiene `"type": "module"`, o cambie la extensión de archivo de sus archivos relevantes como `.vitepress/config.js` a `.mjs`/`.mts`. Consulte la [Guía de resolución de problemas Vite](http://vite.dev/guide/troubleshooting.html#this-package-is-esm-only) para más detalles. Además de eso, dentro de contextos de JavaScript asíncronos, puede usar `await import('vitepress')`. ::: diff --git a/docs/es/guide/markdown.md b/docs/es/guide/markdown.md index 17a9eae3..25e819b1 100644 --- a/docs/es/guide/markdown.md +++ b/docs/es/guide/markdown.md @@ -1,5 +1,6 @@ --- description: Extensiones Markdown integradas en VitePress, incluyendo contenedores personalizados, bloques de código con resaltado de sintaxis, resaltado de líneas, grupos de código y más. +outline: deep --- # Extensiones Markdown {#markdown-extensions} @@ -112,7 +113,7 @@ Para más detalles, vea [Frontmatter](../reference/frontmatter-config). :tada: :100: -Una [lista de todos los emojis](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.mjs) está disponible. +Una [lista de todos los emojis](https://github.com/mdit-plugins/mdit-plugins/blob/main/packages/plugin-emoji/src/data/full.ts) está disponible. ## Tabla de Contenido (TOC) @@ -232,7 +233,7 @@ export default defineConfig({ ### `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. +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. **Sintaxis** @@ -888,14 +889,14 @@ $$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ ## _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: +Puede activar la "carga perezosa" para cada imagen adicionada via markdown definiendo `lazyLoad` como `true` en su archivo de configuración: ```js export default { markdown: { image: { // la carga perezosa de imagenes está desactivada por defecto - lazyLoading: true + lazyLoad: true } } } @@ -907,15 +908,15 @@ VitePress usa [markdown-it](https://github.com/markdown-it/markdown-it) como int ```js import { defineConfig } from 'vitepress' -import markdownItAnchor from 'markdown-it-anchor' +import { headerLink } from '@mdit/plugin-anchor' import markdownItFoo from 'markdown-it-foo' export default defineConfig({ markdown: { - // opciones para markdown-it-anchor - // https://github.com/valeriangalliat/markdown-it-anchor#usage + // opciones para @mdit/plugin-anchor + // https://mdit-plugins.github.io/anchor.html anchor: { - permalink: markdownItAnchor.permalink.headerLink() + permalink: headerLink() }, // opciones para @mdit-vue/plugin-toc diff --git a/docs/es/guide/ssr-compat.md b/docs/es/guide/ssr-compat.md index 38021653..77ca3dac 100644 --- a/docs/es/guide/ssr-compat.md +++ b/docs/es/guide/ssr-compat.md @@ -39,7 +39,7 @@ onMounted(() => { ### Importación Condicional {#conditional-import} -También puede importar una dependencia condicionalmente utilizando la bandera `import.meta.env.SSR` (que forma parte de las [variables de entorno Vite](https://vitejs.dev/guide/env-and-mode.html#env-variables)): +También puede importar una dependencia condicionalmente utilizando la bandera `import.meta.env.SSR` (que forma parte de las [variables de entorno Vite](https://vite.dev/guide/env-and-mode.html#env-variables)): ```js if (!import.meta.env.SSR) { diff --git a/docs/es/guide/using-vue.md b/docs/es/guide/using-vue.md index 2682acfd..7d6fe5a2 100644 --- a/docs/es/guide/using-vue.md +++ b/docs/es/guide/using-vue.md @@ -204,7 +204,7 @@ Observe que esto puede impedir que ciertos tokens sean realzados correctamente. ## Usando Preprocesadores CSS {#using-css-pre-processors} -VitePress poseé [soporte embutido](https://vitejs.dev/guide/features.html#css-pre-processors) para preprocesadores CSS: archivos `.scss`, `.sass`, `.less`, `.styl` e `.stylus`. No es necesario instalar plugins específicos de Vite para ellos, pero el propio preprocesados correspondiente debe ser instalado: +VitePress poseé [soporte embutido](https://vite.dev/guide/features.html#css-pre-processors) para preprocesadores CSS: archivos `.scss`, `.sass`, `.less`, `.styl` e `.stylus`. No es necesario instalar plugins específicos de Vite para ellos, pero el propio preprocesados correspondiente debe ser instalado: ``` # .scss e .sass diff --git a/docs/es/guide/what-is-vitepress.md b/docs/es/guide/what-is-vitepress.md index 22c4b946..03f8d865 100644 --- a/docs/es/guide/what-is-vitepress.md +++ b/docs/es/guide/what-is-vitepress.md @@ -6,17 +6,15 @@ description: VitePress es un generador de sitios estáticos diseñado para crear VitePress es un [Generador de Sitios Estáticos](https://en.wikipedia.org/wiki/Static_site_generator) (SSG) diseñado para construir sitios web rápidos y enfocados en el contenido. En pocas palabras, VitePress toma tu contenido fuente escrito en [Markdown](https://en.wikipedia.org/wiki/Markdown), le aplica un tema y genera páginas HTML estáticas que se pueden desplegar fácilmente en cualquier lugar. -
      - +::: tip {no-title} ¿Quieres probarlo? Ve directo al [Inicio Rápido](./getting-started). - -
      +::: ## Casos de Uso {#use-cases} - **Documentación** - VitePress incluye un tema por defecto diseñado para documentación técnica. Este tema es el que se utiliza en la página que estás leyendo ahora, así como en la documentación de [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/) y [muchos otros](https://github.com/search?q=/%22vitepress%22:+/+path:/(?:package%7Cdeno)%5C.jsonc?$/+NOT+is:fork+NOT+is:archived&type=code). + VitePress incluye un tema por defecto diseñado para documentación técnica. Este tema es el que se utiliza en la página que estás leyendo ahora, así como en la documentación de [Vite](https://vite.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/) y [muchos otros](https://github.com/search?q=/%22vitepress%22:+/+path:/(?:package%7Cdeno)%5C.jsonc?$/+NOT+is:fork+NOT+is:archived&type=code). La [documentación oficial Vue.js](https://vuejs.org/) también está basada en VitePress, pero utiliza un tema personalizado compartido entre varias traducciones. @@ -30,7 +28,7 @@ VitePress es un [Generador de Sitios Estáticos](https://en.wikipedia.org/wiki/S VitePress busca ofrecer una excelente Experiencia de Desarrollador (DX) al trabajar con contenido Markdown. -- **[Con tecnología Vite:](https://vitejs.dev/)** inicio instantáneo del servidor, con los cambios reflejados al instante (<100ms) sin recargar la página. +- **[Con tecnología Vite:](https://vite.dev/)** inicio instantáneo del servidor, con los cambios reflejados al instante (<100ms) sin recargar la página. - **[Extensiones Markdown Integradas:](./markdown)** Frontmatter, tablas, destaque de sintaxis... tú decides. Específicamente, VitePress proporciona muchos recursos para trabajar con bloques de código, tornándolo ideal para documentación altamente técnica. diff --git a/docs/es/index.md b/docs/es/index.md index b4c8673f..1eb31f82 100644 --- a/docs/es/index.md +++ b/docs/es/index.md @@ -21,16 +21,16 @@ hero: alt: VitePress features: - - icon: 📝 + - icon: title: Concéntrese en su contenido details: Cree lindos sitios de documentación apenas con markdown. - - icon: + - icon: title: Disfruta de la experiencia Vite details: Inicio instantaneo de servidor, actualizaciones ultrarrápidas, y plugins del ecosistema Vite. - - icon: + - icon: title: Personaliza con Vue details: Usa la sintaxis y componentes Vue directamente en markdown, o construye temas personalizados con Vue. - - icon: 🚀 + - 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/site-config.md b/docs/es/reference/site-config.md index 21792600..7bc0c751 100644 --- a/docs/es/reference/site-config.md +++ b/docs/es/reference/site-config.md @@ -430,7 +430,7 @@ export default { - 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). +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://vite.dev/config/shared-options.html#cachedir). ```ts export default { @@ -503,7 +503,7 @@ Esta opción inyecta un script en línea que restaura la configuración de los u 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). +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.lastUpdated.text`](./default-theme-config#lastupdated). ## Personalización {#customization} @@ -525,7 +525,7 @@ Consulte la [declaración de tipo y jsdocs](https://github.com/vuejs/vitepress/b - Tipo: `import('vite').UserConfig` -Pase la [Configuración Vite](https://vitejs.dev/config/) sin procesar al servidor interno / empaquetador Vite. +Pase la [Configuración Vite](https://vite.dev/config/) sin procesar al servidor interno / empaquetador Vite. ```js export default { diff --git a/docs/fa/config.ts b/docs/fa/config.ts index c3b34727..a59bc6a5 100644 --- a/docs/fa/config.ts +++ b/docs/fa/config.ts @@ -1,17 +1,39 @@ import { createRequire } from 'node:module' -import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' +import { + defineAdditionalConfig, + type DefaultTheme, + type MarkdownLocaleOptions +} from 'vitepress' const require = createRequire(import.meta.url) const pkg = require('vitepress/package.json') +export const markdown: MarkdownLocaleOptions = { + container: { + tipLabel: 'نکته', + infoLabel: 'اطلاعات', + warningLabel: 'اخطار', + dangerLabel: 'خطر', + detailsLabel: 'جزئیات', + noteLabel: 'یادداشت', + importantLabel: 'مهم', + cautionLabel: 'احتیاط' + }, + codeCopyButton: { + tooltipText: 'کپی کد', + copiedText: 'کپی شد' + } +} + export default defineAdditionalConfig({ description: 'ژنراتور استاتیک وب‌سایت با Vite و Vue', - // 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' }], + [ + 'link', + // for the vazirmatn font-face defined in .vitepress/theme/styles.css + { rel: 'preconnect', href: 'https://cdn.jsdelivr.net', crossorigin: '' } + ] ], themeConfig: { @@ -264,8 +286,6 @@ function searchOptions(): Partial { afterToolCallText: 'جستجو برای', stoppedStreamingText: 'شما این پاسخ را متوقف کردید', errorTitleText: 'خطای گفتگو', - threadDepthExceededMessage: - 'برای حفظ دقت پاسخ ها، این گفت وگو بسته شد.', startNewConversationButtonText: 'شروع گفت وگوی جدید' } } diff --git a/docs/fa/guide/asset-handling.md b/docs/fa/guide/asset-handling.md index cda20c7d..ade26214 100644 --- a/docs/fa/guide/asset-handling.md +++ b/docs/fa/guide/asset-handling.md @@ -6,7 +6,7 @@ description: نحوه ارجاع و مدیریت منابع ایستا مانن ## ارجاع به منابع ایستا {#referencing-static-assets} -تمام فایل‌های Markdown به کامپوننت‌های Vue تبدیل و توسط [Vite](https://vitejs.dev/guide/assets.html) پردازش می‌شوند. شما می‌توانید، **و باید**، هر نوع دارایی را با استفاده از URL‌های نسبی مرجع قرار دهید: +تمام فایل‌های Markdown به کامپوننت‌های Vue تبدیل و توسط [Vite](https://vite.dev/guide/assets.html) پردازش می‌شوند. شما می‌توانید، **و باید**، هر نوع دارایی را با استفاده از URL‌های نسبی مرجع قرار دهید: ```md ![تصویر](./image.png) diff --git a/docs/fa/guide/deploy.md b/docs/fa/guide/deploy.md index 47d33b5b..30de6e9c 100644 --- a/docs/fa/guide/deploy.md +++ b/docs/fa/guide/deploy.md @@ -189,7 +189,7 @@ Cache-Control: max-age=31536000,immutable uses: actions/deploy-pages@v4 ``` -::: warning هشدار + ::: warning هشدار مطمئن شوید که گزینه `base` در ویت‌پرس به‌درستی پیکربندی شده است. برای اطلاعات بیشتر به [تنظیم مسیر پایه عمومی](#setting-a-public-base-path) مراجعه کنید. ::: diff --git a/docs/fa/guide/extending-default-theme.md b/docs/fa/guide/extending-default-theme.md index 76418ed2..ccea29a6 100644 --- a/docs/fa/guide/extending-default-theme.md +++ b/docs/fa/guide/extending-default-theme.md @@ -119,7 +119,7 @@ export default { } satisfies Theme ``` -از آنجا که از Vite استفاده می‌کنیم، می‌توانید از ویژگی [import glob](https://vitejs.dev/guide/features.html#glob-import) در Vite برای خودکار ثبت یک پوشه از مولفه‌ها استفاده کنید. +از آنجا که از Vite استفاده می‌کنیم، می‌توانید از ویژگی [import glob](https://vite.dev/guide/features.html#glob-import) در Vite برای خودکار ثبت یک پوشه از مولفه‌ها استفاده کنید. ## slot ‌های طرح {#layout-slots} @@ -311,7 +311,7 @@ provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => { ## جایگزینی کامپوننت‌های داخلی {#overriding-internal-components} -شما می‌توانید با استفاده از [alias های Vite](https://vitejs.dev/config/shared-options.html#resolve-alias)، کامپوننت‌های تم پیش‌فرض را با کامپوننت‌های سفارشی خود جایگزین کنید: +شما می‌توانید با استفاده از [alias های Vite](https://vite.dev/config/shared-options.html#resolve-alias)، کامپوننت‌های تم پیش‌فرض را با کامپوننت‌های سفارشی خود جایگزین کنید: ```ts import { fileURLToPath, URL } from 'node:url' diff --git a/docs/fa/guide/getting-started.md b/docs/fa/guide/getting-started.md index d9d7d660..97775e0d 100644 --- a/docs/fa/guide/getting-started.md +++ b/docs/fa/guide/getting-started.md @@ -41,7 +41,7 @@ $ bun add -D vitepress@next ::: tip نکته -ویت‌پرس یک بسته فقط ESM است. از `require()` برای وارد کردن آن استفاده نکنید و اطمینان حاصل کنید که نزدیک‌ترین `package.json` شما شامل `"type": "module"` است، یا پسوند فایل‌های مربوطه خود مانند `.vitepress/config.js` را به `.mjs`/`.mts` تغییر دهید. برای جزئیات بیشتر به [راهنمای عیب‌یابی Vite](http://vitejs.dev/guide/troubleshooting.html#this-package-is-esm-only) مراجعه کنید. همچنین، در زمینه‌های async CJS می‌توانید از `await import('vitepress')` استفاده کنید. +ویت‌پرس یک بسته فقط ESM است. از `require()` برای وارد کردن آن استفاده نکنید و اطمینان حاصل کنید که نزدیک‌ترین `package.json` شما شامل `"type": "module"` است، یا پسوند فایل‌های مربوطه خود مانند `.vitepress/config.js` را به `.mjs`/`.mts` تغییر دهید. برای جزئیات بیشتر به [راهنمای عیب‌یابی Vite](http://vite.dev/guide/troubleshooting.html#this-package-is-esm-only) مراجعه کنید. همچنین، در زمینه‌های async CJS می‌توانید از `await import('vitepress')` استفاده کنید. ::: diff --git a/docs/fa/guide/markdown.md b/docs/fa/guide/markdown.md index 05072193..e4f369e0 100644 --- a/docs/fa/guide/markdown.md +++ b/docs/fa/guide/markdown.md @@ -1,5 +1,6 @@ --- description: افزونه‌های داخلی Markdown در ویت‌پرس شامل کانتینرهای سفارشی، بلوک‌های کد با هایلایت، گروه‌های کد و موارد دیگر. +outline: deep --- # افزونه‌های Markdown {#markdown-extensions} @@ -112,7 +113,7 @@ lang: fa-IR :tada: :100: -یک [لیست از همه اموجی ها](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.mjs) در دسترس است. +یک [لیست از همه اموجی ها](https://github.com/mdit-plugins/mdit-plugins/blob/main/packages/plugin-emoji/src/data/full.ts) در دسترس است. ## فهرست مطالب {#table-of-contents} @@ -880,14 +881,14 @@ $$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ ## بارگذاری lazy تصویر {#image-lazy-loading} -می‌توانید بارگذاری تنبلی را برای هر تصویر اضافه شده از طریق Markdown با تنظیم `lazyLoading` به `true` در فایل پیکربندی فعال کنید: +می‌توانید بارگذاری تنبلی را برای هر تصویر اضافه شده از طریق Markdown با تنظیم `lazyLoad` به `true` در فایل پیکربندی فعال کنید: ```js export default { markdown: { image: { // بارگذاری تنبلی تصویر به طور پیش‌فرض غیرفعال است - lazyLoading: true + lazyLoad: true } } } @@ -899,15 +900,15 @@ export default { ```js import { defineConfig } from 'vitepress' -import markdownItAnchor from 'markdown-it-anchor' +import { headerLink } from '@mdit/plugin-anchor' import markdownItFoo from 'markdown-it-foo' export default defineConfig({ markdown: { - // گزینه‌های markdown-it-anchor - // https://github.com/valeriangalliat/markdown-it-anchor#usage + // گزینه‌های @mdit/plugin-anchor + // https://mdit-plugins.github.io/anchor.html anchor: { - permalink: markdownItAnchor.permalink.headerLink() + permalink: headerLink() }, // گزینه‌های @mdit-vue/plugin-toc diff --git a/docs/fa/guide/migration-from-vitepress-0.md b/docs/fa/guide/migration-from-vitepress-0.md index 211bb0f9..131e0d2b 100644 --- a/docs/fa/guide/migration-from-vitepress-0.md +++ b/docs/fa/guide/migration-from-vitepress-0.md @@ -14,7 +14,7 @@ - `repo`، `repoLabel`، `docsDir`، `docsBranch`، `editLinks`، `editLinkText` به منظور API انعطاف‌پذیرتر حذف شده‌اند. - برای اضافه کردن لینک GitHub با آیکون به نوار ناوبری، از ویژگی [پیوندهای اجتماعی](../reference/default-theme-nav#navigation-links) استفاده کنید. - برای اضافه کردن ویژگی "ویرایش این صفحه"، از ویژگی [پیوند ویرایش](../reference/default-theme-edit-link) استفاده کنید. -- گزینه `lastUpdated` حالا به `config.lastUpdated` و `themeConfig.lastUpdatedText` تقسیم شده است. +- گزینه `lastUpdated` حالا به `config.lastUpdated` و `themeConfig.lastUpdated.text` تقسیم شده است. - `carbonAds.carbon` به `carbonAds.code` تغییر کرده است. ## پیکربندی Frontmatter diff --git a/docs/fa/guide/ssr-compat.md b/docs/fa/guide/ssr-compat.md index 75e698a7..76f91f90 100644 --- a/docs/fa/guide/ssr-compat.md +++ b/docs/fa/guide/ssr-compat.md @@ -39,7 +39,7 @@ onMounted(() => { ### وارد کردن شرطی {#conditional-import} -می‌توانید همچنین وابستگی را با استفاده از `import.meta.env.SSR` (قسمتی از [متغیرهای env Vite](https://vitejs.dev/guide/env-and-mode.html#env-variables)) به شرط وارد کنید: +می‌توانید همچنین وابستگی را با استفاده از `import.meta.env.SSR` (قسمتی از [متغیرهای env Vite](https://vite.dev/guide/env-and-mode.html#env-variables)) به شرط وارد کنید: ```js if (!import.meta.env.SSR) { diff --git a/docs/fa/guide/using-vue.md b/docs/fa/guide/using-vue.md index 1b618f60..d0b25e46 100644 --- a/docs/fa/guide/using-vue.md +++ b/docs/fa/guide/using-vue.md @@ -205,7 +205,7 @@ Hello {{ 1 + 1 }} ## استفاده از پیش‌پردازنده‌های CSS {#using-css-pre-processors} -ویت‌پرس از [پشتیبانی داخلی](https://vitejs.dev/guide/features.html#css-pre-processors) برای پیش‌پردازنده‌های CSS مانند فایل‌های `.scss`، `.sass`، `.less`، `.styl` و `.stylus` پشتیبانی می‌کند. برای استفاده از آنها نیازی به نصب پلاگین‌های خاص Vite نیست، اما خود پیش‌پردازنده مربوطه باید نصب شده باشد: +ویت‌پرس از [پشتیبانی داخلی](https://vite.dev/guide/features.html#css-pre-processors) برای پیش‌پردازنده‌های CSS مانند فایل‌های `.scss`، `.sass`، `.less`، `.styl` و `.stylus` پشتیبانی می‌کند. برای استفاده از آنها نیازی به نصب پلاگین‌های خاص Vite نیست، اما خود پیش‌پردازنده مربوطه باید نصب شده باشد: ``` # .scss و .sass diff --git a/docs/fa/guide/what-is-vitepress.md b/docs/fa/guide/what-is-vitepress.md index 44fde866..4ad21397 100644 --- a/docs/fa/guide/what-is-vitepress.md +++ b/docs/fa/guide/what-is-vitepress.md @@ -6,17 +6,15 @@ description: ویت‌پرس یک تولیدکننده سایت ایستا بر ویت‌پرس یک [تولید کننده سایت ایستا](https://en.wikipedia.org/wiki/Static_site_generator) (SSG) است که برای ساخت وب‌سایت‌های سریع و محتوا محور طراحی شده است. به طور خلاصه، ویت‌پرس محتوای منبع شما که به زبان [Markdown](https://en.wikipedia.org/wiki/Markdown) نوشته شده است را گرفته، یک تم بر روی آن اعمال می‌کند و صفحات HTML ایستا تولید می‌کند که به راحتی در هر جایی قابل استقرار هستند. -
      - +::: tip {no-title} فقط می‌خواهید آن را امتحان کنید؟ به [شروع سریع](./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://github.com/search?q=/%22vitepress%22:+/+path:/(?:package%7Cdeno)%5C.jsonc?$/+NOT+is:fork+NOT+is:archived&type=code) با استفاده از ویت‌پرس ساخته شده‌اند. + ویت‌پرس با یک تم پیش‌فرض طراحی شده برای مستندات فنی ارائه می‌شود. این صفحه‌ای که اکنون در حال خواندن آن هستید و همچنین مستندات [Vite](https://vite.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://github.com/search?q=/%22vitepress%22:+/+path:/(?:package%7Cdeno)%5C.jsonc?$/+NOT+is:fork+NOT+is:archived&type=code) با استفاده از ویت‌پرس ساخته شده‌اند. [مستندات رسمی Vue.js](https://vuejs.org/) نیز بر پایه ویت‌پرس ساخته شده است، اما از یک تم سفارشی که بین چندین ترجمه مشترک است استفاده می‌کند. @@ -30,7 +28,7 @@ description: ویت‌پرس یک تولیدکننده سایت ایستا بر ویت‌پرس هدف ارائه یک تجربه عالی برای توسعه دهنده (DX) هنگام کار با محتوای Markdown را دارد. -- **[قدرت گرفته از Vite:](https://vitejs.dev/)** شروع سرور فوری، با بازتاب ویرایش‌ها به صورت آنی (<100ms) بدون بارگذاری مجدد صفحه. +- **[قدرت گرفته از Vite:](https://vite.dev/)** شروع سرور فوری، با بازتاب ویرایش‌ها به صورت آنی (<100ms) بدون بارگذاری مجدد صفحه. - **[افزونه‌های داخلی Markdown:](./markdown)** استفاده از Frontmatter، جداول، syntax highlighting... هرچه که بخواهید. ویت‌پرس به ویژه ویژگی‌های پیشرفته زیادی برای کار با بلوک‌های کد فراهم می‌کند، که آن را برای مستندات فنی بسیار مناسب می‌کند. diff --git a/docs/fa/index.md b/docs/fa/index.md index d36e6a2c..c8f263fd 100644 --- a/docs/fa/index.md +++ b/docs/fa/index.md @@ -21,16 +21,16 @@ hero: alt: ویت‌پرس features: - - icon: 📝 + - icon: title: تمرکز روی محتوا details: ایجاد سایت‌های مستند‌سازی زیبا بدون زحمت و فقط با Markdown - - icon: + - icon: title: لذت از تجربه توسعه با Vite details: شروع فوری سرور، به‌روزرسانی‌های سریع و استفاده از افزونه‌های اکوسیستم Vite - - icon: + - icon: title: شخصی‌سازی با Vue details: استفاده مستقیم از syntax و کامپوننت‌های Vue در Markdown، یا ایجاد تم‌های شخصی به کمک Vue - - icon: 🚀 + - icon: title: ارسال سایت های سریع details: بارگذاری اولیه سریع با HTML ایستا، ناوبری سریع پس از بارگیری با مسیریابی سمت کلاینت --- diff --git a/docs/fa/reference/site-config.md b/docs/fa/reference/site-config.md index 2fd3cdc5..072cfa08 100644 --- a/docs/fa/reference/site-config.md +++ b/docs/fa/reference/site-config.md @@ -432,7 +432,7 @@ export default { - نوع: `string` - پیش‌فرض: `./.vitepress/cache` -دایرکتوری برای فایل‌های کش، نسبت به [ریشه پروژه](../guide/routing#root-and-source-directory). همچنین ببینید: [cacheDir](https://vitejs.dev/config/shared-options.html#cachedir). +دایرکتوری برای فایل‌های کش، نسبت به [ریشه پروژه](../guide/routing#root-and-source-directory). همچنین ببینید: [cacheDir](https://vite.dev/config/shared-options.html#cachedir). ```ts export default { @@ -474,13 +474,6 @@ export default { } ``` -### metaChunk {#metachunk} - -- نوع: `boolean` -- پیش‌فرض: `false` - -زمانی که به `true` تنظیم شود، فراداده‌های صفحات را به یک قسمت جداگانه جاوااسکریپت استخراج می‌کند به جای درون‌گذاری آن در HTML اولیه. این کار باعث کاهش بار HTML هر صفحه می‌شود و فراداده‌های صفحات قابل کش شدن می‌شود، که منجر به کاهش پهنای باند سرور می‌شود وقتی که صفحات زیادی در سایت دارید. - ### mpa {#mpa} - نوع: `boolean` @@ -514,7 +507,7 @@ export default { آیا زمان آخرین به‌روزرسانی برای هر صفحه با استفاده از Git دریافت شود. این زمان در داده‌های هر صفحه گنجانده خواهد شد و از طریق [`useData`](./runtime-api#usedata) قابل دسترسی خواهد بود. -وقتی از تم پیش‌فرض استفاده می‌کنید، فعال کردن این گزینه زمان آخرین به‌روزرسانی هر صفحه را نمایش می‌دهد. می‌توانید متن را از طریق گزینه [`themeConfig.lastUpdatedText`](./default-theme-config#lastupdatedtext) سفارشی کنید. +وقتی از تم پیش‌فرض استفاده می‌کنید، فعال کردن این گزینه زمان آخرین به‌روزرسانی هر صفحه را نمایش می‌دهد. می‌توانید متن را از طریق گزینه [`themeConfig.lastUpdated.text`](./default-theme-config#lastupdated) سفارشی کنید. ## سفارشی‌سازی {#customization} @@ -536,7 +529,7 @@ export default { - نوع: `import('vite').UserConfig` -پیکربندی خام [Vite Config](https://vitejs.dev/config/) را به سرور توسعه داخلی / بسته‌بند Vite ارسال کنید. +پیکربندی خام [Vite Config](https://vite.dev/config/) را به سرور توسعه داخلی / بسته‌بند Vite ارسال کنید. ```js export default { diff --git a/docs/ja/config.ts b/docs/ja/config.ts index bc92b006..e997b9dd 100644 --- a/docs/ja/config.ts +++ b/docs/ja/config.ts @@ -1,9 +1,30 @@ import { createRequire } from 'node:module' -import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' +import { + defineAdditionalConfig, + type DefaultTheme, + type MarkdownLocaleOptions +} from 'vitepress' const require = createRequire(import.meta.url) const pkg = require('vitepress/package.json') +export const markdown: MarkdownLocaleOptions = { + container: { + tipLabel: 'ヒント', + infoLabel: '情報', + warningLabel: '警告', + dangerLabel: '危険', + detailsLabel: '詳細', + noteLabel: 'メモ', + importantLabel: '重要', + cautionLabel: '注意' + }, + codeCopyButton: { + tooltipText: 'コードをコピー', + copiedText: 'コピー完了' + } +} + export default defineAdditionalConfig({ description: 'Vite と Vue による静的サイトジェネレーター', @@ -231,8 +252,6 @@ function searchOptions(): Partial { afterToolCallText: '検索しました', stoppedStreamingText: 'この応答を停止しました', errorTitleText: 'チャットエラー', - threadDepthExceededMessage: - '回答の正確性を保つため、この会話は終了しました。', startNewConversationButtonText: '新しい会話を開始' } } diff --git a/docs/ja/guide/asset-handling.md b/docs/ja/guide/asset-handling.md index 319963ca..42ae9d61 100644 --- a/docs/ja/guide/asset-handling.md +++ b/docs/ja/guide/asset-handling.md @@ -6,7 +6,7 @@ description: VitePressで画像、メディア、フォントなどの静的ア ## 静的アセットの参照 {#referencing-static-assets} -すべての Markdown ファイルは Vue コンポーネントにコンパイルされ、[Vite](https://vitejs.dev/guide/assets.html) によって処理されます。Markdown 内では、相対 URL を使ってアセットを参照することが **推奨されます**。 +すべての Markdown ファイルは Vue コンポーネントにコンパイルされ、[Vite](https://vite.dev/guide/assets.html) によって処理されます。Markdown 内では、相対 URL を使ってアセットを参照することが **推奨されます**。 ```md ![画像](./image.png) diff --git a/docs/ja/guide/extending-default-theme.md b/docs/ja/guide/extending-default-theme.md index 8e26243c..2abe4d84 100644 --- a/docs/ja/guide/extending-default-theme.md +++ b/docs/ja/guide/extending-default-theme.md @@ -122,7 +122,7 @@ export default { } satisfies Theme ``` -Vite を使っているため、Vite の [glob import 機能](https://vitejs.dev/guide/features.html#glob-import) を利用してディレクトリ内のコンポーネントを自動登録することもできます。 +Vite を使っているため、Vite の [glob import 機能](https://vite.dev/guide/features.html#glob-import) を利用してディレクトリ内のコンポーネントを自動登録することもできます。 ## レイアウトスロット {#layout-slots} @@ -311,7 +311,7 @@ provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => { ## 内部コンポーネントの置き換え {#overriding-internal-components} -Vite の [エイリアス](https://vitejs.dev/config/shared-options.html#resolve-alias) を使って、デフォルトテーマのコンポーネントを独自のものに置き換えられます。 +Vite の [エイリアス](https://vite.dev/config/shared-options.html#resolve-alias) を使って、デフォルトテーマのコンポーネントを独自のものに置き換えられます。 ```ts import { fileURLToPath, URL } from 'node:url' diff --git a/docs/ja/guide/getting-started.md b/docs/ja/guide/getting-started.md index 5e164aa1..91a85076 100644 --- a/docs/ja/guide/getting-started.md +++ b/docs/ja/guide/getting-started.md @@ -40,7 +40,7 @@ $ bun add -D vitepress@next ::: ::: tip 注意 -VitePress は ESM 専用パッケージです。`require()` を使ってインポートせず、最も近い `package.json` に `"type": "module"` を含めるか、`.vitepress/config.js` を `.mjs` / `.mts` に変更してください。詳しくは [Vite のトラブルシューティングガイド](http://vitejs.dev/guide/troubleshooting.html#this-package-is-esm-only) を参照してください。また、非同期 CJS コンテキスト内では `await import('vitepress')` を使用できます。 +VitePress は ESM 専用パッケージです。`require()` を使ってインポートせず、最も近い `package.json` に `"type": "module"` を含めるか、`.vitepress/config.js` を `.mjs` / `.mts` に変更してください。詳しくは [Vite のトラブルシューティングガイド](http://vite.dev/guide/troubleshooting.html#this-package-is-esm-only) を参照してください。また、非同期 CJS コンテキスト内では `await import('vitepress')` を使用できます。 ::: ### セットアップウィザード {#setup-wizard} diff --git a/docs/ja/guide/markdown.md b/docs/ja/guide/markdown.md index fc839fc3..190e3182 100644 --- a/docs/ja/guide/markdown.md +++ b/docs/ja/guide/markdown.md @@ -1,5 +1,6 @@ --- description: VitePress組み込みのMarkdown拡張機能。カスタムコンテナ、コードブロックのシンタックスハイライト、行ハイライト、コードグループなど。 +outline: deep --- # Markdown 拡張 {#markdown-extensions} @@ -110,7 +111,7 @@ lang: ja-JP :tada: :100: -すべての絵文字の [一覧はこちら](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.mjs)。 +すべての絵文字の [一覧はこちら](https://github.com/mdit-plugins/mdit-plugins/blob/main/packages/plugin-emoji/src/data/full.ts)。 ## 目次 {#table-of-contents} @@ -229,7 +230,7 @@ export default defineConfig({ ### 追加属性 {#additional-attributes} -カスタムコンテナには追加の属性を付与できます。この機能には [markdown-it-attrs](https://github.com/arve0/markdown-it-attrs) を使用しており、ほぼすべての Markdown 要素でサポートされます。たとえば `open` 属性を付けると、details ブロックをデフォルトで開いた状態にできます。 +カスタムコンテナには追加の属性を付与できます。この機能には [@mdit/plugin-attrs](https://mdit-plugins.github.io/attrs.html) を使用しており、ほぼすべての Markdown 要素でサポートされます。たとえば `open` 属性を付けると、details ブロックをデフォルトで開いた状態にできます。 **入力** @@ -251,7 +252,7 @@ console.log('こんにちは、VitePress!') ### `raw` -これは、VitePress でのスタイルやルーターの衝突を防ぐための特別なコンテナです。コンポーネントライブラリのドキュメント化に特に有用です。より強力な分離が必要であれば、[whyframe](https://whyframe.dev/docs/integrations/vitepress) も検討してください。 +これは、VitePress でのスタイルやルーターの衝突を防ぐための特別なコンテナです。コンポーネントライブラリのドキュメント化に特に有用です。 **構文** @@ -996,14 +997,14 @@ $$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ ## 画像の遅延読み込み {#image-lazy-loading} -Markdown で追加した各画像に対して遅延読み込みを有効化するには、設定ファイルで `lazyLoading` を `true` にします: +Markdown で追加した各画像に対して遅延読み込みを有効化するには、設定ファイルで `lazyLoad` を `true` にします: ```js export default { markdown: { image: { // 既定では画像の遅延読み込みは無効 - lazyLoading: true + lazyLoad: true } } } @@ -1015,15 +1016,15 @@ VitePress は Markdown レンダラーとして [markdown-it](https://github.com ```js import { defineConfig } from 'vitepress' -import markdownItAnchor from 'markdown-it-anchor' +import { headerLink } from '@mdit/plugin-anchor' import markdownItFoo from 'markdown-it-foo' export default defineConfig({ markdown: { - // markdown-it-anchor のオプション - // https://github.com/valeriangalliat/markdown-it-anchor#usage + // @mdit/plugin-anchor のオプション + // https://mdit-plugins.github.io/anchor.html anchor: { - permalink: markdownItAnchor.permalink.headerLink() + permalink: headerLink() }, // @mdit-vue/plugin-toc のオプション diff --git a/docs/ja/guide/ssr-compat.md b/docs/ja/guide/ssr-compat.md index ec94a4a4..01a58c38 100644 --- a/docs/ja/guide/ssr-compat.md +++ b/docs/ja/guide/ssr-compat.md @@ -39,7 +39,7 @@ onMounted(() => { ### 条件付きインポート {#conditional-import} -[`import.meta.env.SSR`](https://vitejs.dev/guide/env-and-mode.html#env-variables) フラグ(Vite の環境変数の一部)を使って、依存関係を条件付きでインポートすることもできます。 +[`import.meta.env.SSR`](https://vite.dev/guide/env-and-mode.html#env-variables) フラグ(Vite の環境変数の一部)を使って、依存関係を条件付きでインポートすることもできます。 ```js if (!import.meta.env.SSR) { diff --git a/docs/ja/guide/using-vue.md b/docs/ja/guide/using-vue.md index 9cbc7608..cdbbb01f 100644 --- a/docs/ja/guide/using-vue.md +++ b/docs/ja/guide/using-vue.md @@ -203,7 +203,7 @@ Hello {{ 1 + 1 }} ## CSS プリプロセッサの利用 {#using-css-pre-processors} -VitePress は CSS プリプロセッサ(`.scss`、`.sass`、`.less`、`.styl`、`.stylus`)を[標準サポート](https://vitejs.dev/guide/features.html#css-pre-processors)しています。Vite 固有のプラグインは不要ですが、各プリプロセッサ本体のインストールは必要です。 +VitePress は CSS プリプロセッサ(`.scss`、`.sass`、`.less`、`.styl`、`.stylus`)を[標準サポート](https://vite.dev/guide/features.html#css-pre-processors)しています。Vite 固有のプラグインは不要ですが、各プリプロセッサ本体のインストールは必要です。 ``` # .scss / .sass diff --git a/docs/ja/guide/what-is-vitepress.md b/docs/ja/guide/what-is-vitepress.md index 1920adaf..88e8c9d9 100644 --- a/docs/ja/guide/what-is-vitepress.md +++ b/docs/ja/guide/what-is-vitepress.md @@ -6,17 +6,15 @@ description: VitePressはViteとVueを基盤とした、高速でコンテンツ VitePress は、高速でコンテンツ中心の Web サイトを構築するための [静的サイトジェネレーター(SSG)](https://en.wikipedia.org/wiki/Static_site_generator) です。要するに、VitePress は [Markdown](https://en.wikipedia.org/wiki/Markdown) で書かれたソースコンテンツにテーマを適用し、どこにでも簡単にデプロイできる静的 HTML ページを生成します。 -
      - +::: tip {no-title} まずは試してみたい? [クイックスタート](./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://github.com/search?q=/%22vitepress%22:+/+path:/(?:package%7Cdeno)%5C.jsonc?$/+NOT+is:fork+NOT+is:archived&type=code)のドキュメントサイトで使われています。 + VitePress には技術ドキュメント向けに設計されたデフォルトテーマが同梱されています。今あなたが読んでいるこのページのほか、[Vite](https://vite.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://github.com/search?q=/%22vitepress%22:+/+path:/(?:package%7Cdeno)%5C.jsonc?$/+NOT+is:fork+NOT+is:archived&type=code)のドキュメントサイトで使われています。 [公式の Vue.js ドキュメント](https://vuejs.org/) も VitePress をベースにしています(複数言語で共有されるカスタムテーマを使用)。 @@ -30,7 +28,7 @@ VitePress は、高速でコンテンツ中心の Web サイトを構築する VitePress は、Markdown コンテンツを扱う際の優れた開発体験(DX)を目指しています。 -- **[Vite 駆動](https://vitejs.dev/)**:即時サーバー起動、編集はページリロードなしで常に瞬時(<100ms)に反映。 +- **[Vite 駆動](https://vite.dev/)**:即時サーバー起動、編集はページリロードなしで常に瞬時(<100ms)に反映。 - **[ビルトインの Markdown 拡張](./markdown)**:Frontmatter、表、シンタックスハイライト…必要なものはひと通り。特にコードブロック周りの機能が充実しており、高度な技術ドキュメントに最適です。 diff --git a/docs/ja/index.md b/docs/ja/index.md index b5be770b..665ad78e 100644 --- a/docs/ja/index.md +++ b/docs/ja/index.md @@ -21,16 +21,16 @@ hero: alt: VitePress features: - - icon: 📝 + - icon: title: コンテンツに集中 details: Markdown だけで、美しいドキュメントサイトを簡単に作成できます。 - - icon: + - icon: title: Vite の開発体験を享受 details: 即時サーバー起動、超高速ホットリロード、そして Vite エコシステムのプラグイン活用。 - - icon: + - icon: title: Vue でカスタマイズ details: Markdown 内で直接 Vue 構文やコンポーネントを利用したり、Vue で独自テーマを構築できます。 - - icon: 🚀 + - icon: title: 高速サイトを公開 details: 静的 HTML による高速初期ロードと、クライアントサイドルーティングによる快適なページ遷移。 --- diff --git a/docs/ja/reference/site-config.md b/docs/ja/reference/site-config.md index 44636f89..6d7c3130 100644 --- a/docs/ja/reference/site-config.md +++ b/docs/ja/reference/site-config.md @@ -430,7 +430,7 @@ export default { - 型: `string` - 既定値: `./.vitepress/cache` -キャッシュファイル用ディレクトリ([プロジェクトルート](../guide/routing#root-and-source-directory) からの相対パス)。参考: [cacheDir](https://vitejs.dev/config/shared-options.html#cachedir) +キャッシュファイル用ディレクトリ([プロジェクトルート](../guide/routing#root-and-source-directory) からの相対パス)。参考: [cacheDir](https://vite.dev/config/shared-options.html#cachedir) ```ts export default { @@ -472,13 +472,6 @@ export default { } ``` -### metaChunk - -- 型: `boolean` -- 既定値: `false` - -`true` にすると、各ページのメタデータを初期 HTML にインラインせず、別の JavaScript チャンクに抽出します。これにより各ページの HTML ペイロードが小さくなり、メタデータをキャッシュ可能にすることで、多数のページがあるサイトでサーバ帯域を削減できます。 - ### mpa - 型: `boolean` @@ -512,7 +505,7 @@ export default { Git を使って各ページの最終更新時刻を取得します。タイムスタンプは各ページのデータに含まれ、[`useData`](./runtime-api#usedata) から参照できます。 -デフォルトテーマ使用時にこのオプションを有効にすると、各ページの最終更新時刻が表示されます。テキストは [`themeConfig.lastUpdatedText`](./default-theme-config#lastupdatedtext) でカスタマイズ可能です。 +デフォルトテーマ使用時にこのオプションを有効にすると、各ページの最終更新時刻が表示されます。テキストは [`themeConfig.lastUpdated.text`](./default-theme-config#lastupdated) でカスタマイズ可能です。 ## カスタマイズ {#customization} @@ -534,7 +527,7 @@ export default { - 型: `import('vite').UserConfig` -内部の Vite 開発サーバ/バンドラへ生の [Vite Config](https://vitejs.dev/config/) を渡します。 +内部の Vite 開発サーバ/バンドラへ生の [Vite Config](https://vite.dev/config/) を渡します。 ```js export default { diff --git a/docs/ko/config.ts b/docs/ko/config.ts index 7a275cd3..af4b435f 100644 --- a/docs/ko/config.ts +++ b/docs/ko/config.ts @@ -1,9 +1,30 @@ import { createRequire } from 'node:module' -import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' +import { + defineAdditionalConfig, + type DefaultTheme, + type MarkdownLocaleOptions +} from 'vitepress' const require = createRequire(import.meta.url) const pkg = require('vitepress/package.json') +export const markdown: MarkdownLocaleOptions = { + container: { + tipLabel: '팁', + infoLabel: '정보', + warningLabel: '경고', + dangerLabel: '위험', + detailsLabel: '세부 정보', + noteLabel: '노트', + importantLabel: '중요', + cautionLabel: '주의' + }, + codeCopyButton: { + tooltipText: '코드 복사', + copiedText: '복사됨' + } +} + export default defineAdditionalConfig({ description: 'Vite 및 Vue 기반 정적 사이트 생성기.', @@ -303,8 +324,6 @@ function searchOptions(): Partial { afterToolCallText: '검색함', stoppedStreamingText: '이 응답을 중지했습니다', errorTitleText: '채팅 오류', - threadDepthExceededMessage: - '정확성을 유지하기 위해 이 대화는 종료되었습니다.', startNewConversationButtonText: '새 대화 시작' } } diff --git a/docs/ko/guide/asset-handling.md b/docs/ko/guide/asset-handling.md index 5d7a9bbb..3b9efb02 100644 --- a/docs/ko/guide/asset-handling.md +++ b/docs/ko/guide/asset-handling.md @@ -6,7 +6,7 @@ description: VitePress에서 이미지, 미디어, 글꼴 등 정적 에셋을 ## 정적 에셋 참조하기 {#referencing-static-assets} -모든 마크다운 파일은 Vue 컴포넌트로 컴파일되어 [Vite](https://vitejs.dev/guide/assets.html)에 의해 처리됩니다. 모든 에셋은 상대 URL을 사용하여 참조할 수 있으며, **참조해야 합니다**: +모든 마크다운 파일은 Vue 컴포넌트로 컴파일되어 [Vite](https://vite.dev/guide/assets.html)에 의해 처리됩니다. 모든 에셋은 상대 URL을 사용하여 참조할 수 있으며, **참조해야 합니다**: ```md ![이미지](./image.png) diff --git a/docs/ko/guide/extending-default-theme.md b/docs/ko/guide/extending-default-theme.md index e87bfa1a..2c450b8b 100644 --- a/docs/ko/guide/extending-default-theme.md +++ b/docs/ko/guide/extending-default-theme.md @@ -119,7 +119,7 @@ export default { } satisfies Theme ``` -Vite를 사용하므로, Vite의 [glob import 기능](https://vitejs.dev/guide/features.html#glob-import)을 활용하여 컴포넌트 디렉터리를 자동으로 등록할 수 있습니다. +Vite를 사용하므로, Vite의 [glob import 기능](https://vite.dev/guide/features.html#glob-import)을 활용하여 컴포넌트 디렉터리를 자동으로 등록할 수 있습니다. ## 레이아웃 슬롯 {#layout-slots} @@ -309,7 +309,7 @@ provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => { ## 내부 컴포넌트 재정의하기 {#overriding-internal-components} -Vite의 [별칭](https://vitejs.dev/config/shared-options.html#resolve-alias)을 사용하여 기본 테마 컴포넌트를 커스텀 컴포넌트로 대체할 수 있습니다: +Vite의 [별칭](https://vite.dev/config/shared-options.html#resolve-alias)을 사용하여 기본 테마 컴포넌트를 커스텀 컴포넌트로 대체할 수 있습니다: ```ts import { fileURLToPath, URL } from 'node:url' diff --git a/docs/ko/guide/getting-started.md b/docs/ko/guide/getting-started.md index ca6e743b..807dca71 100644 --- a/docs/ko/guide/getting-started.md +++ b/docs/ko/guide/getting-started.md @@ -41,7 +41,7 @@ $ bun add -D vitepress@next ::: tip 참고 -VitePress는 ESM 전용 패키지입니다. `require()`를 사용하여 가져오지 마시고, `package.json`에 `"type": "module"`이 포함되어 있는지 확인하거나, 관련 파일(예: `.vitepress/config.js`)의 확장자를 `.mjs`/`.mts`로 변경하세요. 자세한 내용은 [Vite 문제 해결 가이드](http://vitejs.dev/ko/guide/troubleshooting.html#this-package-is-esm-only)를 참고하세요. 또한, 비동기 CJS 컨텍스트에서는 `await import('vitepress')`를 사용할 수 있습니다. +VitePress는 ESM 전용 패키지입니다. `require()`를 사용하여 가져오지 마시고, `package.json`에 `"type": "module"`이 포함되어 있는지 확인하거나, 관련 파일(예: `.vitepress/config.js`)의 확장자를 `.mjs`/`.mts`로 변경하세요. 자세한 내용은 [Vite 문제 해결 가이드](http://vite.dev/ko/guide/troubleshooting.html#this-package-is-esm-only)를 참고하세요. 또한, 비동기 CJS 컨텍스트에서는 `await import('vitepress')`를 사용할 수 있습니다. ::: diff --git a/docs/ko/guide/markdown.md b/docs/ko/guide/markdown.md index 12d832df..f0c7ce91 100644 --- a/docs/ko/guide/markdown.md +++ b/docs/ko/guide/markdown.md @@ -1,5 +1,6 @@ --- description: 커스텀 컨테이너, 구문 강조 코드 블록, 라인 하이라이팅, 코드 그룹 등 VitePress 내장 마크다운 확장 기능을 소개합니다. +outline: deep --- # 마크다운 확장 기능 {#markdown-extensions} @@ -112,7 +113,7 @@ lang: en-US :tada: :100: -[모든 이모지의 목록](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.mjs)이 제공됩니다. +[모든 이모지의 목록](https://github.com/mdit-plugins/mdit-plugins/blob/main/packages/plugin-emoji/src/data/full.ts)이 제공됩니다. ## 목차 {#table-of-contents} @@ -231,7 +232,7 @@ export default defineConfig({ ### `raw` -이것은 VitePress와 스타일 및 라우터 충돌을 방지하기 위해 사용할 수 있는 특별한 컨테이너입니다. 컴포넌트 라이브러리를 문서화할 때 특히 유용합니다. 더 나은 분리를 위해 [whyframe](https://whyframe.dev/docs/integrations/vitepress)을 참고해 볼 수 있습니다. +이것은 VitePress와 스타일 및 라우터 충돌을 방지하기 위해 사용할 수 있는 특별한 컨테이너입니다. 컴포넌트 라이브러리를 문서화할 때 특히 유용합니다. **문법** @@ -925,14 +926,14 @@ $$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ ## 이미지 지연 로딩 {#image-lazy-loading} -마크다운을 통해 추가된 각 이미지에 대해 지연 로딩을 활성화하려면 구성 파일에서 `lazyLoading`을 `true`로 설정하세요: +마크다운을 통해 추가된 각 이미지에 대해 지연 로딩을 활성화하려면 구성 파일에서 `lazyLoad`을 `true`로 설정하세요: ```js export default { markdown: { image: { // 이미지 지연 로딩은 기본적으로 비활성화 되어 있습니다 - lazyLoading: true + lazyLoad: true } } } @@ -944,15 +945,15 @@ VitePress는 마크다운 렌더러로 [markdown-it](https://github.com/markdown ```js import { defineConfig } from 'vitepress' -import markdownItAnchor from 'markdown-it-anchor' +import { headerLink } from '@mdit/plugin-anchor' import markdownItFoo from 'markdown-it-foo' export default defineConfig({ markdown: { - // markdown-it-anchor의 옵션 - // https://github.com/valeriangalliat/markdown-it-anchor#usage + // @mdit/plugin-anchor의 옵션 + // https://mdit-plugins.github.io/anchor.html anchor: { - permalink: markdownItAnchor.permalink.headerLink() + permalink: headerLink() }, // @mdit-vue/plugin-toc의 옵션 diff --git a/docs/ko/guide/migration-from-vitepress-0.md b/docs/ko/guide/migration-from-vitepress-0.md index f3ba5293..d1dad78c 100644 --- a/docs/ko/guide/migration-from-vitepress-0.md +++ b/docs/ko/guide/migration-from-vitepress-0.md @@ -14,7 +14,7 @@ If you're coming from VitePress 0.x version, there're several breaking changes d - `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`. +- `lastUpdated` option is now split into `config.lastUpdated` and `themeConfig.lastUpdated.text`. - `carbonAds.carbon` is changed to `carbonAds.code`. ## Frontmatter Config {#frontmatter-config} diff --git a/docs/ko/guide/ssr-compat.md b/docs/ko/guide/ssr-compat.md index 9e58ec18..a2e9cc63 100644 --- a/docs/ko/guide/ssr-compat.md +++ b/docs/ko/guide/ssr-compat.md @@ -39,7 +39,7 @@ onMounted(() => { ### 조건부 가져오기 {#conditional-import} -`import.meta.env.SSR` 플래그([Vite 환경 변수](https://vitejs.dev/guide/env-and-mode.html#env-variables)의 일부)를 사용하여 종속성을 조건부로 "import" 할 수도 있습니다: +`import.meta.env.SSR` 플래그([Vite 환경 변수](https://vite.dev/guide/env-and-mode.html#env-variables)의 일부)를 사용하여 종속성을 조건부로 "import" 할 수도 있습니다: ```js if (!import.meta.env.SSR) { diff --git a/docs/ko/guide/using-vue.md b/docs/ko/guide/using-vue.md index 9f595b7f..5c93dabc 100644 --- a/docs/ko/guide/using-vue.md +++ b/docs/ko/guide/using-vue.md @@ -204,7 +204,7 @@ Vue 보간 문법을 회피하려면, `` 또는 다른 엘리먼트에 `v- ## CSS 전처리기 사용하기 {#using-css-pre-processors} -VitePress는 CSS 전처리기인 `.scss`, `.sass`, `.less`, `.styl`, `.stylus` 파일에 대해 [기본 지원](https://vitejs.dev/guide/features.html#css-pre-processors)을 제공합니다. 이를 위해 Vite 전용 플러그인을 설치할 필요는 없지만, 해당 전처리기 자체는 설치해야 합니다: +VitePress는 CSS 전처리기인 `.scss`, `.sass`, `.less`, `.styl`, `.stylus` 파일에 대해 [기본 지원](https://vite.dev/guide/features.html#css-pre-processors)을 제공합니다. 이를 위해 Vite 전용 플러그인을 설치할 필요는 없지만, 해당 전처리기 자체는 설치해야 합니다: ``` # .scss 및 .sass diff --git a/docs/ko/guide/what-is-vitepress.md b/docs/ko/guide/what-is-vitepress.md index 2c2cdaf2..fc34e9af 100644 --- a/docs/ko/guide/what-is-vitepress.md +++ b/docs/ko/guide/what-is-vitepress.md @@ -6,17 +6,15 @@ description: VitePress는 Vite와 Vue로 구동되는 빠르고 콘텐츠 중심 VitePress는 빠르고 컨텐츠 중심의 웹사이트를 구축하기 위해 설계된 [정적 사이트 생성기](https://en.wikipedia.org/wiki/Static_site_generator) (SSG)입니다. 다시말해 VitePress는 [마크다운](https://en.wikipedia.org/wiki/Markdown)으로 작성된 소스 컨텐츠를 가져와서 테마를 적용하고, 어디에나 쉽게 배포할 수 있는 정적 HTML 페이지를 생성합니다. -
      - +::: tip {no-title} 그냥 한번 사용해보고 싶으신가요? [빠른 시작](./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://github.com/search?q=/%22vitepress%22:+/+path:/(?:package%7Cdeno)%5C.jsonc?$/+NOT+is:fork+NOT+is:archived&type=code) 문서는 모두 이 테마를 기반으로 합니다. + VitePress는 기술 문서를 위해 설계된 기본 테마가 함께 제공됩니다. 지금 읽고 있는 이 페이지와 [Vite](https://vite.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://github.com/search?q=/%22vitepress%22:+/+path:/(?:package%7Cdeno)%5C.jsonc?$/+NOT+is:fork+NOT+is:archived&type=code) 문서는 모두 이 테마를 기반으로 합니다. [Vue.js 공식 문서](https://vuejs.org/)도 VitePress 기반으로 되어 있으며, 여러 번역본에 걸쳐 공유되는 커스텀 테마를 사용합니다. @@ -30,7 +28,7 @@ VitePress는 빠르고 컨텐츠 중심의 웹사이트를 구축하기 위해 VitePress는 마크다운 컨텐츠를 다룰 때 훌륭한 개발자 경험(DX)을 제공하고자 합니다. -- **[Vite로 작동](https://vitejs.dev/)**: 즉각적인 서버 시작 가능, 페이지 새로고침 없이 즉시(<100ms) 수정 사항 반영. +- **[Vite로 작동](https://vite.dev/)**: 즉각적인 서버 시작 가능, 페이지 새로고침 없이 즉시(<100ms) 수정 사항 반영. - **[내장된 마크다운 확장 기능](./markdown)**: 서문, 표, 구문 강조 등 무엇이든 가능. 특히 VitePress는 코드 블록 작업을 위한 고급 기능을 많이 제공하여 기술적 문서에 이상적. diff --git a/docs/ko/index.md b/docs/ko/index.md index d5a6c1a2..fa302470 100644 --- a/docs/ko/index.md +++ b/docs/ko/index.md @@ -21,16 +21,16 @@ hero: alt: VitePress features: - - icon: 📝 + - icon: title: 콘텐츠에 집중 details: 마크다운으로만 아름다운 문서 사이트를 쉽게 만들기. - - icon: + - icon: title: Vite DX(개발자 경험) 즐겨보기 details: 즉각적인 서버 시작, 매우 빠른 업데이트, Vite 생태계 플러그인을 활용. - - icon: + - icon: title: Vue로 커스터마이징 details: Vue 문법과 컴포넌트를 마크다운에서 직접 사용하거나 Vue로 커스텀 테마를 구축. - - icon: 🚀 + - icon: title: 웹사이트를 빠르게 제공 details: 정적 HTML로 빠른 초기 로딩, 클라이언트 측 라우팅을 통한 빠른 탐색. --- diff --git a/docs/ko/reference/site-config.md b/docs/ko/reference/site-config.md index f22569a9..074cf43f 100644 --- a/docs/ko/reference/site-config.md +++ b/docs/ko/reference/site-config.md @@ -430,7 +430,7 @@ export default { - 타입: `string` - 기본값: `./.vitepress/cache` -캐시 파일을 위한 디렉터리입니다. [프로젝트 루트](../guide/routing#root-and-source-directory)에 상대적입니다. [cacheDir](https://vitejs.dev/config/shared-options.html#cachedir)을 참고하세요. +캐시 파일을 위한 디렉터리입니다. [프로젝트 루트](../guide/routing#root-and-source-directory)에 상대적입니다. [cacheDir](https://vite.dev/config/shared-options.html#cachedir)을 참고하세요. ```ts export default { @@ -472,13 +472,6 @@ export default { } ``` -### metaChunk - -- 타입: `boolean` -- 기본값: `false` - -`true`로 설정하면 페이지 메타데이터를 초기 HTML에 인라인으로 삽입하는 대신 별도의 JavaScript 청크로 추출합니다. 이렇게 하면 각 페이지의 HTML 페이로드가 작아지고 페이지 메타데이터를 캐시할 수 있어, 사이트에 많은 페이지가 있을 때 서버 대역폭을 줄일 수 있습니다. - ### mpa - 타입: `boolean` @@ -512,7 +505,7 @@ export default { 각 페이지의 마지막 업데이트 타임스탬프를 Git을 사용하여 가져올지 여부를 설정합니다. 타임스탬프는 각 페이지의 페이지 데이터에 포함되며, [`useData`](./runtime-api#usedata)를 통해 접근할 수 있습니다. -기본 테마를 사용할 때, 이 옵션을 활성화하면 각 페이지의 마지막 업데이트 시간이 표시됩니다. [`themeConfig.lastUpdatedText`](./default-theme-config#lastupdatedtext) 옵션을 통해 텍스트를 커스터마이징할 수 있습니다. +기본 테마를 사용할 때, 이 옵션을 활성화하면 각 페이지의 마지막 업데이트 시간이 표시됩니다. [`themeConfig.lastUpdated.text`](./default-theme-config#lastupdated) 옵션을 통해 텍스트를 커스터마이징할 수 있습니다. ## 커스터마이징 {#customization} @@ -534,7 +527,7 @@ export default { - 타입: `import('vite').UserConfig` -내부 Vite 개발 서버/번들러에 직접 [Vite 구성](https://vitejs.dev/config/)을 전달합니다. +내부 Vite 개발 서버/번들러에 직접 [Vite 구성](https://vite.dev/config/)을 전달합니다. ```js export default { diff --git a/docs/package.json b/docs/package.json index c7540b08..9c2be9c1 100644 --- a/docs/package.json +++ b/docs/package.json @@ -12,10 +12,10 @@ "devDependencies": { "@lunariajs/core": "^0.1.1", "markdown-it-mathjax3": "^4.3.2", - "open-cli": "^8.0.0", + "open-cli": "^9.0.0", "postcss-rtlcss": "^6.0.0", "vitepress": "workspace:*", - "vitepress-plugin-group-icons": "^1.7.5", - "vitepress-plugin-llms": "^1.13.2" + "vitepress-plugin-group-icons": "^1.7.6", + "vitepress-plugin-llms": "^1.13.4" } } diff --git a/docs/pt/config.ts b/docs/pt/config.ts index 193eb2f4..cb0afb9d 100644 --- a/docs/pt/config.ts +++ b/docs/pt/config.ts @@ -1,9 +1,30 @@ import { createRequire } from 'node:module' -import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' +import { + defineAdditionalConfig, + type DefaultTheme, + type MarkdownLocaleOptions +} from 'vitepress' const require = createRequire(import.meta.url) const pkg = require('vitepress/package.json') +export const markdown: MarkdownLocaleOptions = { + container: { + tipLabel: 'DICA', + infoLabel: 'INFORMAÇÃO', + warningLabel: 'AVISO', + dangerLabel: 'PERIGO', + detailsLabel: 'Detalhes', + noteLabel: 'NOTA', + importantLabel: 'IMPORTANTE', + cautionLabel: 'CUIDADO' + }, + codeCopyButton: { + tooltipText: 'Copiar código', + copiedText: 'Copiado' + } +} + export default defineAdditionalConfig({ description: 'Gerador de Site Estático desenvolvido com Vite e Vue.', @@ -264,8 +285,6 @@ function searchOptions(): Partial { afterToolCallText: 'Pesquisado', stoppedStreamingText: 'Você interrompeu esta resposta', errorTitleText: 'Erro no chat', - threadDepthExceededMessage: - 'Esta conversa foi encerrada para manter respostas precisas.', startNewConversationButtonText: 'Iniciar uma nova conversa' } } diff --git a/docs/pt/guide/asset-handling.md b/docs/pt/guide/asset-handling.md index f7b4a937..620beb49 100644 --- a/docs/pt/guide/asset-handling.md +++ b/docs/pt/guide/asset-handling.md @@ -6,7 +6,7 @@ description: Aprenda a referenciar e manipular ativos estáticos como imagens, m ## 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: +Todos os arquivos Markdown são compilados em componentes Vue e processados por [Vite](https://vite.dev/guide/assets.html). Você pode **e deve** referenciar quaisquer ativos usando URLs relativas: ```md ![Uma imagem](./imagem.png) diff --git a/docs/pt/guide/extending-default-theme.md b/docs/pt/guide/extending-default-theme.md index 31527390..99db5b75 100644 --- a/docs/pt/guide/extending-default-theme.md +++ b/docs/pt/guide/extending-default-theme.md @@ -119,7 +119,7 @@ export default { } 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. +Como estamos usando Vite, você também pode aproveitar a [funcionalidade de importação glob](https://vite.dev/guide/features.html#glob-import) do Vite para registrar automaticamente um diretório de componentes. ## _Slots_ no Layout {#layout-slots} @@ -309,7 +309,7 @@ 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: +Você pode usar os [aliases](https://vite.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' diff --git a/docs/pt/guide/getting-started.md b/docs/pt/guide/getting-started.md index 056626ff..5f083143 100644 --- a/docs/pt/guide/getting-started.md +++ b/docs/pt/guide/getting-started.md @@ -41,7 +41,7 @@ $ bun add -D vitepress@next ::: tip NOTA -VitePress é um pacote apenas para ESM. Não use `require()` para importá-lo, e certifique de que o `package.json` mais próximo contém `"type": "module"`, ou mude a extensão do arquivo de seus arquivos releavantes como `.vitepress/config.js` para `.mjs`/`.mts`. Refira-se ao [Guia de resolução de problemas Vite](http://vitejs.dev/guide/troubleshooting.html#this-package-is-esm-only) para mais detalhes. Além disso, dentro de contextos de JavaScript comum assíncronos, você pode usar `await import('vitepress')`. +VitePress é um pacote apenas para ESM. Não use `require()` para importá-lo, e certifique de que o `package.json` mais próximo contém `"type": "module"`, ou mude a extensão do arquivo de seus arquivos releavantes como `.vitepress/config.js` para `.mjs`/`.mts`. Refira-se ao [Guia de resolução de problemas Vite](http://vite.dev/guide/troubleshooting.html#this-package-is-esm-only) para mais detalhes. Além disso, dentro de contextos de JavaScript comum assíncronos, você pode usar `await import('vitepress')`. ::: diff --git a/docs/pt/guide/markdown.md b/docs/pt/guide/markdown.md index 2d46ce29..29058709 100644 --- a/docs/pt/guide/markdown.md +++ b/docs/pt/guide/markdown.md @@ -1,5 +1,6 @@ --- description: Extensões Markdown integradas do VitePress, incluindo containers personalizados, blocos de código com destaque de sintaxe, grupos de código e mais. +outline: deep --- # Extensões Markdown {#markdown-extensions} @@ -112,7 +113,7 @@ Para mais detalhes, veja [Frontmatter](../reference/frontmatter-config). :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. +Uma [lista de todos os emojis](https://github.com/mdit-plugins/mdit-plugins/blob/main/packages/plugin-emoji/src/data/full.ts) está disponível. ## Tabela de Conteúdo (TOC) @@ -231,7 +232,7 @@ export default defineConfig({ ### `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. +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. **Sintaxe** @@ -887,14 +888,14 @@ $$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ ## _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: +Você pode ativar o "carregamento folgado" para cada imagem adicionada via markdown definindo `lazyLoad` 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 + lazyLoad: true } } } @@ -906,15 +907,15 @@ VitePress usa [markdown-it](https://github.com/markdown-it/markdown-it) como int ```js import { defineConfig } from 'vitepress' -import markdownItAnchor from 'markdown-it-anchor' +import { headerLink } from '@mdit/plugin-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 + // opções para @mdit/plugin-anchor + // https://mdit-plugins.github.io/anchor.html anchor: { - permalink: markdownItAnchor.permalink.headerLink() + permalink: headerLink() }, // opções para @mdit-vue/plugin-toc diff --git a/docs/pt/guide/ssr-compat.md b/docs/pt/guide/ssr-compat.md index fcd36f38..ecd95d81 100644 --- a/docs/pt/guide/ssr-compat.md +++ b/docs/pt/guide/ssr-compat.md @@ -39,7 +39,7 @@ onMounted(() => { ### 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)): +Você também pode importar condicionalmente uma dependência usando o sinalizador `import.meta.env.SSR` (parte das [variáveis de ambiente Vite](https://vite.dev/guide/env-and-mode.html#env-variables)): ```js if (!import.meta.env.SSR) { diff --git a/docs/pt/guide/using-vue.md b/docs/pt/guide/using-vue.md index 5878bebc..d4fdd415 100644 --- a/docs/pt/guide/using-vue.md +++ b/docs/pt/guide/using-vue.md @@ -203,7 +203,7 @@ Observe que isso pode impedir que certos tokens sejam realçados corretamente. ## Usando Pré-processadores CSS {#using-css-pre-processors} -O VitePress possui [suporte embutido](https://vitejs.dev/guide/features.html#css-pre-processors) para pré-processadores CSS: arquivos `.scss`, `.sass`, `.less`, `.styl` e `.stylus`. Não é necessário instalar plugins específicos do Vite para eles, mas o próprio pré-processador correspondente deve ser instalado: +O VitePress possui [suporte embutido](https://vite.dev/guide/features.html#css-pre-processors) para pré-processadores CSS: arquivos `.scss`, `.sass`, `.less`, `.styl` e `.stylus`. Não é necessário instalar plugins específicos do Vite para eles, mas o próprio pré-processador correspondente deve ser instalado: ``` # .scss e .sass diff --git a/docs/pt/guide/what-is-vitepress.md b/docs/pt/guide/what-is-vitepress.md index 45b83db9..3119c893 100644 --- a/docs/pt/guide/what-is-vitepress.md +++ b/docs/pt/guide/what-is-vitepress.md @@ -6,17 +6,15 @@ description: VitePress é um gerador de sites estáticos projetado para criar si 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. -
      - +::: tip {no-title} 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://github.com/search?q=/%22vitepress%22:+/+path:/(?:package%7Cdeno)%5C.jsonc?$/+NOT+is:fork+NOT+is:archived&type=code). + 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://vite.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://github.com/search?q=/%22vitepress%22:+/+path:/(?:package%7Cdeno)%5C.jsonc?$/+NOT+is:fork+NOT+is:archived&type=code). 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. @@ -30,7 +28,7 @@ Quer apenas experimentar? Pule para o [Início Rápido](./getting-started). 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. +- **[Alimentado por Vite:](https://vite.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. diff --git a/docs/pt/index.md b/docs/pt/index.md index ca621454..6143921b 100644 --- a/docs/pt/index.md +++ b/docs/pt/index.md @@ -21,16 +21,16 @@ hero: alt: VitePress features: - - icon: 📝 + - icon: title: Foco no seu conteúdo details: Cria sites de documentação belos e sem esforço apenas com markdown. - - icon: + - icon: title: Aproveite a experiência Vite details: Início de servidor instantâneo, atualizações ultrarrápidas, e plugins do ecossistema Vite. - - icon: + - icon: title: Personalize com Vue details: Use sintaxe e componentes Vue diretamente em markdown, ou construa temas personalizados com Vue. - - icon: 🚀 + - 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/site-config.md b/docs/pt/reference/site-config.md index 88b639f3..068fb43f 100644 --- a/docs/pt/reference/site-config.md +++ b/docs/pt/reference/site-config.md @@ -430,7 +430,7 @@ export default { - 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). +O diretório para arquivos de cache, relativo à [raiz do projeto](../guide/routing#root-and-source-directory). Veja também: [cacheDir](https://vite.dev/config/shared-options.html#cachedir). ```ts export default { @@ -503,7 +503,7 @@ Esta opção injeta um script em linha que restaura as configurações dos usuá 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). +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.lastUpdated.text`](./default-theme-config#lastupdated). ## Personalização {#customization} @@ -525,7 +525,7 @@ Verifique a [declaração de tipo e jsdocs](https://github.com/vuejs/vitepress/b - Tipo: `import('vite').UserConfig` -Passe a [Configuração Vite](https://vitejs.dev/config/) crua para o servidor interno / empacotador Vite. +Passe a [Configuração Vite](https://vite.dev/config/) crua para o servidor interno / empacotador Vite. ```js export default { diff --git a/docs/public/robots.txt b/docs/public/robots.txt new file mode 100644 index 00000000..375c46f4 --- /dev/null +++ b/docs/public/robots.txt @@ -0,0 +1,5 @@ +User-agent: * +Content-Signal: search=yes, ai-train=yes, ai-input=yes +Disallow: + +Sitemap: https://vitepress.dev/sitemap.xml diff --git a/docs/ru/config.ts b/docs/ru/config.ts index 86f8452a..f880f54b 100644 --- a/docs/ru/config.ts +++ b/docs/ru/config.ts @@ -1,9 +1,30 @@ import { createRequire } from 'node:module' -import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' +import { + defineAdditionalConfig, + type DefaultTheme, + type MarkdownLocaleOptions +} from 'vitepress' const require = createRequire(import.meta.url) const pkg = require('vitepress/package.json') +export const markdown: MarkdownLocaleOptions = { + container: { + tipLabel: 'СОВЕТ', + infoLabel: 'ИНФОРМАЦИЯ', + warningLabel: 'ПРЕДУПРЕЖДЕНИЕ', + dangerLabel: 'ОПАСНОСТЬ', + detailsLabel: 'Подробная информация', + noteLabel: 'ЗАМЕТКА', + importantLabel: 'ВАЖНО', + cautionLabel: 'ВНИМАНИЕ' + }, + codeCopyButton: { + tooltipText: 'Скопировать код', + copiedText: 'Скопировано' + } +} + export default defineAdditionalConfig({ description: 'Генератор статических сайтов на основе Vite и Vue.', @@ -262,8 +283,6 @@ function searchOptions(): Partial { afterToolCallText: 'Искал', stoppedStreamingText: 'Вы остановили этот ответ', errorTitleText: 'Ошибка чата', - threadDepthExceededMessage: - 'Этот разговор закрыт, чтобы сохранить точность ответов.', startNewConversationButtonText: 'Начать новый разговор' } } diff --git a/docs/ru/guide/asset-handling.md b/docs/ru/guide/asset-handling.md index 692e2c97..b2f26719 100644 --- a/docs/ru/guide/asset-handling.md +++ b/docs/ru/guide/asset-handling.md @@ -6,7 +6,7 @@ description: Узнайте, как ссылаться на статически ## Ссылки на статические ресурсы {#referencing-static-assets} -Все файлы Markdown компилируются в компоненты Vue и обрабатываются [Vite](https://vitejs.dev/guide/assets.html). Вы можете, **и должны**, ссылаться на любые ресурсы, используя относительные URL: +Все файлы Markdown компилируются в компоненты Vue и обрабатываются [Vite](https://vite-docs.ru/guide/assets.html). Вы можете, **и должны**, ссылаться на любые ресурсы, используя относительные URL: ```md ![Изображение](./image.png) diff --git a/docs/ru/guide/custom-theme.md b/docs/ru/guide/custom-theme.md index 3cb62035..24d75bae 100644 --- a/docs/ru/guide/custom-theme.md +++ b/docs/ru/guide/custom-theme.md @@ -62,11 +62,14 @@ import Layout from './Layout.vue' export default { Layout, enhanceApp({ app, router, siteData }) { - // ... + // app.component(...) + // app.use(...) } } ``` +Хук `enhanceApp` предоставляет доступ к [экземпляру приложения Vue](https://ru.vuejs.org/api/application.html) и другим данным времени выполнения. Это позволяет, например, [регистрировать глобальные компоненты](./extending-default-theme.md#registering-global-components), интегрироваться с библиотеками Vue и выполнять другие подобные задачи. + Значение `router` представляет собой тот же экземпляр маршрутизатора VitePress, который возвращает [`useRouter()`](../reference/runtime-api#userouter). Чтобы отслеживать изменения маршрутов, назначьте обработчики для маршрутизатора: ```ts [.vitepress/theme/index.ts] @@ -226,10 +229,10 @@ export default { ```ts [.vitepress/config.ts] import baseConfig from 'awesome-vitepress-theme/config' -import { defineConfigWithTheme } from 'vitepress' +import { defineConfig } from 'vitepress' import type { ThemeConfig } from 'awesome-vitepress-theme' -export default defineConfigWithTheme({ +export default defineConfig({ extends: baseConfig, themeConfig: { // Тип `ThemeConfig` diff --git a/docs/ru/guide/extending-default-theme.md b/docs/ru/guide/extending-default-theme.md index c3883625..0d1320a6 100644 --- a/docs/ru/guide/extending-default-theme.md +++ b/docs/ru/guide/extending-default-theme.md @@ -120,7 +120,7 @@ export default { } satisfies Theme ``` -Поскольку мы используем Vite, можно применять [глобальную функцию импорта](https://vitejs.dev/guide/features.html#glob-import) Vite для автоматической регистрации каталога компонентов. +Поскольку мы используем Vite, можно применять [глобальную функцию импорта](https://vite-docs.ru/guide/features.html#glob-import) Vite для автоматической регистрации каталога компонентов. ## Слоты макета {#layout-slots} @@ -310,7 +310,7 @@ provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => { ## Переопределение внутренних компонентов {#overriding-internal-components} -Вы можете использовать [псевдонимы](https://vitejs.dev/config/shared-options.html#resolve-alias) Vite, чтобы заменить стандартные компоненты темы на свои собственные: +Вы можете использовать [псевдонимы](https://vite-docs.ru/config/shared-options.html#resolve-alias) Vite, чтобы заменить стандартные компоненты темы на свои собственные: ```ts import { fileURLToPath, URL } from 'node:url' diff --git a/docs/ru/guide/getting-started.md b/docs/ru/guide/getting-started.md index e88ddc00..e589707d 100644 --- a/docs/ru/guide/getting-started.md +++ b/docs/ru/guide/getting-started.md @@ -45,7 +45,7 @@ $ deno add -D vitepress@next ::: tip ПРИМЕЧАНИЕ -VitePress — это пакет, предназначенный только для ESM. Не используйте `require()` для импорта, и убедитесь, что ближайший `package.json` содержит `"type": "module"`, или измените расширение соответствующих файлов, например, `.vitepress/config.js` на `.mjs`/`.mts`. Более подробную информацию см. в [Руководстве по устранению неполадок Vite](https://vitejs.dev/guide/troubleshooting.html#this-package-is-esm-only). Кроме того, внутри асинхронных контекстов CJS можно использовать `await import('vitepress')` вместо этого. +VitePress — это пакет, предназначенный только для ESM. Не используйте `require()` для импорта, и убедитесь, что ближайший `package.json` содержит `"type": "module"`, или измените расширение соответствующих файлов, например, `.vitepress/config.js` на `.mjs`/`.mts`. Более подробную информацию см. в [Руководстве по устранению неполадок Vite](https://vite-docs.ru/guide/troubleshooting.html#this-package-is-esm-only). Кроме того, внутри асинхронных контекстов CJS можно использовать `await import('vitepress')` вместо этого. ::: diff --git a/docs/ru/guide/i18n.md b/docs/ru/guide/i18n.md index 87858c68..6ef839fe 100644 --- a/docs/ru/guide/i18n.md +++ b/docs/ru/guide/i18n.md @@ -57,6 +57,37 @@ interface LocaleSpecificConfig { **Совет:** Конфигурационный файл можно хранить и в `docs/.vitepress/config/index.ts`. Это может помочь вам организовать работу, создав конфигурационный файл для каждой локали, а затем объединить и экспортировать их из `index.ts`. +## Локализованные Markdown-строки {#per-locale-markdown-strings} + +Строки, встраиваемые в страницы Markdown-рендерером, — стандартные заголовки [пользовательских контейнеров](./markdown#custom-containers), [оповещений в стиле GitHub](./markdown#github-flavored-alerts), а также строки кнопки копирования кода — можно переопределить для каждой локали с помощью ключа `markdown` в записи соответствующей локали: + +```ts [docs/.vitepress/config.ts] +import { defineConfig } from 'vitepress' + +export default defineConfig({ + locales: { + root: { label: 'English', lang: 'en' }, + zh: { + label: 'Русский', + lang: 'ru', + markdown: { + container: { + tipLabel: 'Подсказка', + warningLabel: 'Предупреждение' + // ...остальные метки, а также заголовки `customContainers` + }, + codeCopyButton: { + tooltipText: 'Копировать код', + copiedText: 'Скопировано' + } + } + } + } +}) +``` + +Если значение не задано для конкретной локали, используется соответствующее значение из параметров `markdown` корневого уровня. Записи локалей могут переопределять только заголовки контейнеров, зарегистрированных на корневом уровне — регистрация новых контейнеров отдельно для каждой локали не поддерживается. Также обратите внимание, что, поскольку Markdown-рендерер создаётся один раз для всего сайта, эти параметры можно объявлять только в основном файле конфигурации, а не в дополнительных конфигурационных файлах. + ## Отдельный каталог для каждой локали {#separate-directory-for-each-locale} Пример многоязычной структуры: diff --git a/docs/ru/guide/markdown.md b/docs/ru/guide/markdown.md index 836f2e11..ae58bfb8 100644 --- a/docs/ru/guide/markdown.md +++ b/docs/ru/guide/markdown.md @@ -1,5 +1,6 @@ --- description: Встроенные расширения Markdown в VitePress, включая пользовательские контейнеры, блоки кода с подсветкой синтаксиса, выделение строк, группы кода и многое другое. +outline: deep --- # Расширения Markdown {#markdown-extensions} @@ -62,7 +63,7 @@ VitePress поставляется со встроенными расширен Исходящие ссылки автоматически получают значение `target="_blank" rel="noreferrer"`: -- [vuejs.org](https://vuejs.org) +- [vuejs.org](https://ru.vuejs.org) - [VitePress on GitHub](https://github.com/vuejs/vitepress) ## Метаданные {#frontmatter} @@ -100,6 +101,36 @@ lang: ru-RU | столбец 2 | отцентрован | \$12 | | полосатые строки | как полоски у зебры | \$1 | +## Списки задач {#task-lists} + +**Разметка** + +```md +- [ ] Написать пресс-релиз +- [x] Обновить сайт +``` + +**Результат** + +- [ ] Написать пресс-релиз +- [x] Обновить сайт + +## Сноски {#footnotes} + +**Разметка** + +```md +Сноски поддерживаются[^1], включая встроенные^[Это встроенная сноска.]. + +[^1]: Определения могут содержать **Markdown** и отображаются в конце страницы. +``` + +**Результат** + +Сноски поддерживаются[^1], включая встроенные^[Это встроенная сноска.]. + +[^1]: Определения могут содержать **Markdown** и отображаются в конце страницы. + ## Эмодзи :tada: {#emoji} **Разметка** @@ -112,7 +143,7 @@ lang: ru-RU :tada: :100: -[Список всех эмодзи](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.mjs). +[Список всех эмодзи](https://github.com/mdit-plugins/mdit-plugins/blob/main/packages/plugin-emoji/src/data/full.ts). ## Оглавление {#table-of-contents} @@ -233,9 +264,82 @@ export default defineConfig({ }) ``` +На многоязычных сайтах эти метки также можно переопределить для каждой локали отдельно — см. раздел [Локализованные Markdown-строки](./i18n#per-locale-markdown-strings). + +### Регистрация новых контейнеров {#registering-new-containers} + +Помимо встроенных типов, вы можете зарегистрировать дополнительные контейнеры, сопоставив их имена с их заголовками по умолчанию: + +```ts +// config.ts +export default defineConfig({ + // ... + markdown: { + container: { + customContainers: { + success: 'УСПЕШНО' + } + } + } + // ... +}) +``` + +Зарегистрированные имена работают так же, как и встроенные — включая пользовательские заголовки, атрибуты и [синтаксис оповещений в стиле GitHub](#github-flavored-alerts): + +```md +::: +Вы успешно завершили руководство! +::: + +> [!SUCCESS] Пользовательский заголовок +> Этот вариант отображается точно так же. +``` + +Для новых контейнеров стили по умолчанию отсутствуют, поэтому добавьте их в своей теме, используя имя контейнера в качестве класса. В этом примере палитра темы по умолчанию уже содержит подходящие цвета: + +```css +/* .vitepress/theme/custom.css */ +.custom-block.success { + border-color: transparent; + color: var(--vp-c-text-1); + background-color: var(--vp-c-success-soft); +} +``` + +### Вложенность {#nesting} + +Маркеры `:::` подчиняются тем же правилам, что и ограждения блоков кода (` ``` `): ограждение закрывается только соответствующим маркером, который имеет **не меньшую длину**, чем открывающий. Чтобы вкладывать контейнеры друг в друга (или сочетать их с [группами кодов](#code-groups)), сделайте внешнее ограждение длиннее внутренних. + +**Разметка** + +`````md +:::: info Внешний контейнер +Этот блок содержит ещё один контейнер. + +::: details Внутренний контейнер +```js +console.log('Привет, VitePress!') +``` +::: +:::: +````` + +**Результат** + +:::: info Внешний контейнер +Этот блок содержит ещё один контейнер. + +::: details Внутренний контейнер +```js +console.log('Привет, VitePress!') +``` +::: +:::: + ### Дополнительные атрибуты {#additional-attributes} -Вы можете добавить дополнительные атрибуты к пользовательским контейнерам. Мы используем [markdown-it-attrs](https://github.com/arve0/markdown-it-attrs) для этой функции, и она поддерживается почти для всех элементов Markdown. Например, можно установить атрибут `open`, чтобы сделать блок подробностей открытым по умолчанию: +Вы можете добавить дополнительные атрибуты к пользовательским контейнерам. Мы используем [@mdit/plugin-attrs](https://mdit-plugins.github.io/attrs.html) для этой функции, и она поддерживается почти для всех элементов Markdown. Например, можно установить атрибут `open`, чтобы сделать блок подробностей открытым по умолчанию: **Разметка** @@ -255,9 +359,25 @@ console.log('Привет, VitePress!') ``` ::: +Специальный атрибут `no-title` отображает контейнер без элемента заголовка (он не влияет на `details`, поскольку этому контейнеру всегда требуется сводка): + +**Разметка** + +```md +::: tip {no-title} +Хотите просто попробовать? Перейдите сразу к разделу [Первые шаги](./getting-started). +::: +``` + +**Результат** + +::: tip {no-title} +Хотите просто попробовать? Перейдите сразу к разделу [Первые шаги](./getting-started). +::: + ### `raw` {#raw} -Это специальный контейнер, который можно использовать для предотвращения конфликтов стилей и маршрутизаторов с VitePress. Это особенно полезно при документировании библиотек компонентов. Вы также можете посмотреть [whyframe](https://whyframe.dev/docs/integrations/vitepress) для лучшей изоляции. +Это специальный контейнер, который можно использовать для предотвращения конфликтов стилей и маршрутизаторов с VitePress. Это особенно полезно при документировании библиотек компонентов. **Синтаксис** @@ -295,7 +415,7 @@ console.log('Привет, VitePress!') ## Оповещения в стиле GitHub {#github-flavored-alerts} -VitePress также поддерживает [Оповещения в стиле GitHub](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts) для отображения в виде вставок. Они будут отображаться так же, как и [пользовательские контейнеры](#custom-containers). +VitePress также поддерживает [Оповещения в стиле GitHub](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts) для отображения в виде вставок. Они будут отображаться так же, как и [пользовательские контейнеры](#custom-containers). В отличие от GitHub, текст, размещённый сразу после маркера, становится заголовком оповещения (`> [!NOTE] Пользовательский заголовок`), и здесь также работают [контейнеры, зарегистрированные вами самостоятельно](#registering-new-containers). ```md > [!NOTE] @@ -678,6 +798,16 @@ const line4 = 'Строка 4' <<< @/snippets/snippet-with-region.js#snippet{1} +Если файл содержит несколько регионов с одинаковым именем, все они импортируются и объединяются — включая регионы, записанные с использованием разных стилей комментариев, например `` в шаблоне и `// #region` в скрипте одного и того же однофайлового компонента Vue. Комментарии-маркеры, ограничивающие регионы, удаляются из результата. Установите `markdown.snippet.stripRegionMarkers` в `'all'`, чтобы также удалить маркеры других стилей комментариев, вложенные в регион, или в `false`, чтобы сохранить все маркеры. + +:::tip +Имена регионов могут содержать буквы, цифры, символы `_`, `-` и `.`. Поскольку имя региона берётся из конца пути, для файла, имя которого само содержит символ `#`, необходимо явно указать регион — используйте `<<< ./my#file.js#region` вместо `<<< ./my#file.js`. +::: + +:::warning +Импорт файла или региона, который не существует, вызывает ошибку сборки. Установите `markdown.snippet.silent: true`, чтобы вместо этого записывать предупреждение в журнал и ничего не выводить. +::: + Кроме того, можно указать язык внутри фигурных скобок (`{}`) следующим образом: ```md @@ -692,7 +822,9 @@ const line4 = 'Строка 4' <<< @/snippets/snippet.cs{1,2,4-6 c#:line-numbers} ``` -Это полезно, если исходный язык нельзя определить по расширению вашего файла. +Это полезно, если исходный язык нельзя определить по расширению вашего файла. Автоматически определяются только буквенно-цифровые расширения, поэтому для таких файлов, как `main.c++` или `scss.code-snippets`, язык необходимо указывать явно. + +Всё, что следует после языка внутри фигурных скобок, передаётся в блок кода как дополнительные атрибуты. Например, `<<< @/snippets/snippet.ts{ts twoslash}` включает обработку twoslash, если настроен пакет [`@shikijs/vitepress-twoslash`](https://shiki.style/packages/vitepress#twoslash). Обратите внимание, что атрибуты не могут содержать квадратные скобки. ## Группы кодов {#code-groups} @@ -900,7 +1032,7 @@ export default config ``` ::: warning ПРЕДУПРЕЖДЕНИЕ -Обратите внимание, что это не приводит к ошибкам, если ваш файл отсутствует. Поэтому при использовании этой функции убедитесь, что содержимое отображается так, как ожидается. +Включение файла, региона, якоря заголовка или диапазона строк, который не существует, приводит к ошибке сборки. Установите `markdown.include.silent: true`, чтобы вместо этого выводить предупреждение в журнал и пропускать включение. ::: Вместо регионов VS Code вы также можете использовать якоря заголовков, чтобы включить определённый раздел файла. Например, если у вас есть заголовок в вашем markdown-файле, например: @@ -950,6 +1082,28 @@ export default config ``` +Относительные ссылки и изображения внутри включаемых файлов разрешаются относительно расположения **включаемого** файла, поэтому частичный файл может ссылаться на соседние файлы независимо от того, с какой страницы он подключён. Установите `markdown.include.rebaseRelativeUrls: false`, чтобы они вместо этого разрешались относительно страницы, которая выполняет включение. + +### Включение файлов с кодом {#including-code-files} + +Поскольку включение выполняется до разбора блоков кода, эта директива также работает внутри кодовых ограждений. В сочетании с диапазоном строк это позволяет показывать только часть файла с кодом — это альтернатива [импорту сниппетов](#import-code-snippets), когда использование регионов невозможно: + +**Разметка** + +````md +```js + +``` +```` + +**Результат** + +```js + +``` + +Обратите внимание, что включаемые строки вставляются дословно (отступы сохраняются), а если содержимое включает символы обратных кавычек (`` ` ``), необходимо использовать более длинное внешнее ограждение блока кода. + ## Математические уравнения {#math-equations} В настоящее время эта фича предоставляется по желанию. Чтобы включить её, вам нужно установить `markdown-it-mathjax3` и установить значение `true` для опции `markdown.math` в вашем файле конфигурации: @@ -996,14 +1150,14 @@ $$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ ## Ленивая загрузка изображений {#image-lazy-loading} -Вы можете включить ленивую загрузку для каждого изображения, добавленного через markdown, установив значение `true` для опции `lazyLoading` в вашем файле конфигурации: +Вы можете включить ленивую загрузку для каждого изображения, добавленного через markdown, установив значение `true` для опции `lazyLoad` в вашем файле конфигурации: ```js export default { markdown: { image: { // ленивая загрузка изображений отключена по умолчанию - lazyLoading: true + lazyLoad: true } } } @@ -1015,15 +1169,15 @@ VitePress использует [markdown-it](https://github.com/markdown-it/mark ```js import { defineConfig } from 'vitepress' -import markdownItAnchor from 'markdown-it-anchor' +import { headerLink } from '@mdit/plugin-anchor' import markdownItFoo from 'markdown-it-foo' export default defineConfig({ markdown: { - // опции для markdown-it-anchor - // https://github.com/valeriangalliat/markdown-it-anchor#usage + // опции для @mdit/plugin-anchor + // https://mdit-plugins.github.io/anchor.html anchor: { - permalink: markdownItAnchor.permalink.headerLink() + permalink: headerLink() }, // опции для @mdit-vue/plugin-toc diff --git a/docs/ru/guide/migration-from-vitepress-0.md b/docs/ru/guide/migration-from-vitepress-0.md index 4d5c7426..5c339a57 100644 --- a/docs/ru/guide/migration-from-vitepress-0.md +++ b/docs/ru/guide/migration-from-vitepress-0.md @@ -14,7 +14,7 @@ - `repo`, `repoLabel`, `docsDir`, `docsBranch`, `editLinks`, `editLinkText` удалены в пользу более гибкого api. - Для добавления ссылки GitHub с иконкой в навигацию используйте функцию [Социальные ссылки](../reference/default-theme-nav#navigation-links). - Для добавления ссылки «Редактировать эту страницу» используйте функцию [Ссылка для редактирования](../reference/default-theme-edit-link). -- Опция `lastUpdated` теперь разделена на `config.lastUpdated` и `themeConfig.lastUpdatedText`. +- Опция `lastUpdated` теперь разделена на `config.lastUpdated` и `themeConfig.lastUpdated.text`. - Опция `carbonAds.carbon` заменена на `carbonAds.code`. ## Конфигурация метаданных diff --git a/docs/ru/guide/ssr-compat.md b/docs/ru/guide/ssr-compat.md index 5473d368..b9fa9aa7 100644 --- a/docs/ru/guide/ssr-compat.md +++ b/docs/ru/guide/ssr-compat.md @@ -37,9 +37,9 @@ onMounted(() => { ``` -### Условный импорт {#conditional-import} +### Импорт по условию {#conditional-import} -Вы также можете условно импортировать зависимость с помощью флага `import.meta.env.SSR` (часть [env-переменных Vite](https://vitejs.dev/guide/env-and-mode.html#env-variables)): +Вы также можете условно импортировать зависимость с помощью флага `import.meta.env.SSR` (часть [переменных окружения Vite](https://vite-docs.ru/guide/env-and-mode.html#env-variables)): ```js if (!import.meta.env.SSR) { diff --git a/docs/ru/guide/using-vue.md b/docs/ru/guide/using-vue.md index f0e933b1..cc4022f2 100644 --- a/docs/ru/guide/using-vue.md +++ b/docs/ru/guide/using-vue.md @@ -201,7 +201,7 @@ HTML, обёрнутый ``, будет отображаться как е ## Использование препроцессоров CSS {#using-css-pre-processors} -VitePress имеет [встроенную поддержку](https://vitejs.dev/guide/features.html#css-pre-processors) для препроцессоров CSS: файлы `.scss`, `.sass`, `.less`, `.styl` и `.stylus`. Для них не нужно устанавливать специфические для Vite плагины, но сам соответствующий препроцессор должен быть установлен: +VitePress имеет [встроенную поддержку](https://vite-docs.ru/guide/features.html#css-pre-processors) для препроцессоров CSS: файлы `.scss`, `.sass`, `.less`, `.styl` и `.stylus`. Для них не нужно устанавливать специфические для Vite плагины, но сам соответствующий препроцессор должен быть установлен: ::: code-group diff --git a/docs/ru/guide/what-is-vitepress.md b/docs/ru/guide/what-is-vitepress.md index ea21140c..e0d33a64 100644 --- a/docs/ru/guide/what-is-vitepress.md +++ b/docs/ru/guide/what-is-vitepress.md @@ -6,11 +6,9 @@ description: VitePress — это генератор статических са VitePress — это [Генератор статических сайтов](https://ru.wikipedia.org/wiki/%D0%93%D0%B5%D0%BD%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B_%D1%81%D1%82%D0%B0%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D1%85_%D1%81%D0%B0%D0%B9%D1%82%D0%BE%D0%B2) (ГСС), предназначенный для быстрого создания сайтов, ориентированных на контент. В двух словах, VitePress берёт ваш исходный контент, написанный на [Markdown](https://ru.wikipedia.org/wiki/Markdown), применяет к нему тему и генерирует статические HTML-страницы, которые можно легко развернуть в любом месте. -
      - +::: tip {no-title} Хотите попробовать прямо сейчас? Перейдите к главе [Первые шаги](./getting-started). - -
      +::: ## Примеры использования {#use-cases} @@ -18,7 +16,7 @@ VitePress — это [Генератор статических сайтов](ht VitePress поставляется с темой по умолчанию, предназначенной для технической документации. Именно она обеспечивает работу этой страницы, которую вы сейчас читаете, а также документации для [Vite](https://vite-docs.ru/), [Rollup](https://rollupjs.org/), [Pinia](https://pinia-ru.netlify.app), [VueUse](https://vueuse.org/), [Vitest](https://vitest.dev/), [D3](https://d3js.org/), [UnoCSS](https://unocss.dev/), [Iconify](https://iconify.design/) и [многих других](https://github.com/search?q=/%22vitepress%22:+/+path:/(?:package%7Cdeno)%5C.jsonc?$/+NOT+is:fork+NOT+is:archived&type=code). - [Официальная документация Vue.js](https://vuejs.org/) также основана на VitePress, но использует кастомную тему, общую для нескольких переводов. + [Официальная документация Vue.js](https://ru.vuejs.org/) также основана на VitePress, но использует кастомную тему, общую для нескольких переводов. - **Блоги, портфолио и маркетинговые сайты** @@ -30,7 +28,7 @@ VitePress — это [Генератор статических сайтов](ht VitePress стремится обеспечить отличные возможности для разработчиков при работе с содержимым в формате Markdown. -- **[На базе Vite:](https://vitejs.dev/)** мгновенный запуск сервера, правки всегда отражаются мгновенно (<100 мс) без перезагрузки страницы. +- **[На базе Vite:](https://vite-docs.ru/)** мгновенный запуск сервера, правки всегда отражаются мгновенно (<100 мс) без перезагрузки страницы. - **[Встроенные расширения Markdown:](./markdown)** Frontmatter, таблицы, подсветка синтаксиса... называйте как хотите. В частности, VitePress предоставляет множество расширенных возможностей для работы с блоками кода, что делает его идеальным для создания технической документации. diff --git a/docs/ru/index.md b/docs/ru/index.md index 2fb82def..5d151a85 100644 --- a/docs/ru/index.md +++ b/docs/ru/index.md @@ -21,16 +21,16 @@ hero: alt: VitePress features: - - icon: 📝 + - icon: title: Сосредоточьтесь на своем контенте details: Легко создавайте красивые сайты с документацией, используя только Markdown. - - icon: + - icon: title: Наслаждайтесь опытом разработчиков Vite details: Мгновенный запуск сервера, молниеносные горячие обновления и использование плагинов экосистемы Vite. - - icon: + - icon: title: Настройка с помощью Vue details: Используйте синтаксис Vue и компоненты прямо в Markdown или создавайте собственные темы с помощью Vue. - - icon: 🚀 + - icon: title: Быстрый запуск веб-сайтов details: Быстрая начальная загрузка с помощью статического HTML, быстрая навигация после загрузки с помощью маршрутизации на стороне клиента. --- diff --git a/docs/ru/reference/default-theme-config.md b/docs/ru/reference/default-theme-config.md index 796b5bb4..afd17954 100644 --- a/docs/ru/reference/default-theme-config.md +++ b/docs/ru/reference/default-theme-config.md @@ -25,23 +25,23 @@ export default { ## i18nRouting -- Тип: `boolean | ((data: VitePressData, hash: string, targetLocale: string) => string)` +- Тип: `boolean | ((data: VitePressData, route: Route, targetLocale: string) => string)` При смене локали на `ru` URL изменится с `/foo` (или `/en/foo/`) на `/ru/foo`. Вы можете отключить это поведение, установив для параметра `themeConfig.i18nRouting` значение `false`. -Установите для `themeConfig.i18nRouting` функцию, чтобы настроить ссылки для переключения локали. Эта функция получает текущие данные VitePress, текущий хеш и ключ целевой локали, а затем возвращает ссылку для перехода на неё. +Установите для `themeConfig.i18nRouting` функцию, чтобы настроить ссылку локали. Эта функция получает текущие данные VitePress, текущий маршрут и ключ целевой локали, а затем возвращает целевую ссылку. ```ts import { defineConfig } from 'vitepress' export default defineConfig({ themeConfig: { - i18nRouting(data, hash, targetLocale) { + i18nRouting(data, route, targetLocale) { const target = data.site.value.locales[targetLocale] const targetLink = target.link || (targetLocale === 'root' ? '/' : `/${targetLocale}/`) - return `${targetLink}${data.page.value.relativePath.replace(/\.md$/, '')}${hash}` + return `${targetLink}${route.data.relativePath.replace(/\.md$/, '')}${route.hash}` } } }) diff --git a/docs/ru/reference/default-theme-sidebar.md b/docs/ru/reference/default-theme-sidebar.md index f1e0e5f9..b77ed922 100644 --- a/docs/ru/reference/default-theme-sidebar.md +++ b/docs/ru/reference/default-theme-sidebar.md @@ -182,3 +182,63 @@ export default { } } ``` + +## Префикс пути {#path-prefix} + +Если структура вашей документации содержит глубоко вложенные каталоги или группы, расположенные в одном подкаталоге, вы можете использовать параметр `base`, чтобы автоматически добавлять префикс пути ко всем вложенным элементам `items` внутри этой группы. Это избавляет от необходимости повторять один и тот же префикс пути для каждого `link`. + +Параметр `base` поддерживается как в конфигурациях с несколькими боковыми панелями, так и во вложенных группах боковой панели. + +### В нескольких боковых панелях {#in-multiple-sidebars} + +Вы можете определить `base` в корне конфигурации раздела боковой панели: + +```js {5} +export default { + themeConfig: { + sidebar: { + '/guide/': { + base: '/guide/', + items: [ + // Эта ссылка будет разрешена в `/guide/introduction` + { text: 'Введение', link: 'introduction' }, + // Эта ссылка будет разрешена в `/guide/getting-started` + { text: 'Первые шаги', link: 'getting-started' } + ] + } + } + } +} +``` + +### Во вложенных группах {#in-nested-groups} + +Параметр `base` также можно использовать во вложенных группах боковой панели. Он применяется к непосредственным дочерним элементам этой группы: + +```js{6,13} +export default { + themeConfig: { + sidebar: [ + { + text: 'Справочник', + base: '/reference/', + items: [ + // Эта ссылка будет разрешена в `/reference/site-config` + { text: 'Конфигурация сайта', link: 'site-config' }, + { + text: 'Тема по умолчанию', + // Вложенный `base` переопределяет префикс пути родительской группы + base: '/reference/default-theme-', + items: [ + // Эта ссылка будет разрешена в `/reference/default-theme-nav` + { text: 'Навигация', link: 'nav' }, + // Эта ссылка будет разрешена в `/reference/default-theme-sidebar` + { text: 'Сайдбар', link: 'sidebar' } + ] + } + ] + } + ] + } +} +``` diff --git a/docs/ru/reference/site-config.md b/docs/ru/reference/site-config.md index b04a3bdd..6c593eda 100644 --- a/docs/ru/reference/site-config.md +++ b/docs/ru/reference/site-config.md @@ -461,7 +461,7 @@ export default { - Тип: `string` - По умолчанию: `./.vitepress/cache` -Каталог для файлов кэша, относительно [корня проекта](../guide/routing#root-and-source-directory). См. также: [cacheDir](https://vitejs.dev/config/shared-options.html#cachedir). +Каталог для файлов кэша, относительно [корня проекта](../guide/routing#root-and-source-directory). См. также: [cacheDir](https://vite-docs.ru/config/shared-options.html#cachedir). ```ts export default { @@ -503,13 +503,6 @@ export default { } ``` -### metaChunk {#metachunk} - -- Тип: `boolean` -- По умолчанию: `false` - -Если установлено значение `true`, метаданные страницы извлекаются в отдельный фрагмент JavaScript, а не вставляются в исходный HTML. Это уменьшает полезную нагрузку HTML каждой страницы и делает метаданные страниц кэшируемыми, что позволяет снизить пропускную способность сервера при наличии большого количества страниц на сайте. - ### mpa {#mpa} - Тип: `boolean` @@ -543,7 +536,7 @@ export default { Получать ли временную метку последнего обновления для каждой страницы с помощью Git. Временная метка будет включена в данные каждой страницы, доступные через [`useData`](./runtime-api#usedata). -При использовании темы по умолчанию включение этой опции приведёт к отображению времени последнего обновления каждой страницы. Вы можете настроить текст с помощью опции [`themeConfig.lastUpdatedText`](./default-theme-config#lastupdatedtext). +При использовании темы по умолчанию включение этой опции приведёт к отображению времени последнего обновления каждой страницы. Вы можете настроить текст с помощью опции [`themeConfig.lastUpdated.text`](./default-theme-config#lastupdated). ## Кастомизация {#customization} @@ -567,7 +560,7 @@ export default { - Тип: `import('vite').UserConfig` -Передаёт необработанную [конфигурацию Vite](https://vitejs.dev/config/) внутреннему серверу разработки / сборщику Vite. +Передаёт необработанную [конфигурацию Vite](https://vite-docs.ru/config/) внутреннему серверу разработки / сборщику Vite. ```js export default { diff --git a/docs/snippets/algolia-i18n.ts b/docs/snippets/algolia-i18n.ts index c57816c3..0dfa5107 100644 --- a/docs/snippets/algolia-i18n.ts +++ b/docs/snippets/algolia-i18n.ts @@ -89,7 +89,6 @@ export default defineConfig({ afterToolCallText: '已搜索', stoppedStreamingText: '你已停止此回复', errorTitleText: '聊天错误', - threadDepthExceededMessage: '为保持回答准确,此对话已关闭。', startNewConversationButtonText: '开始新的对话' } } diff --git a/docs/tsconfig.json b/docs/tsconfig.json new file mode 100644 index 00000000..c3617830 --- /dev/null +++ b/docs/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "noEmit": true, + "types": ["node"] + }, + "include": ["**/*", ".vitepress/**/*"] +} diff --git a/docs/zh/config.ts b/docs/zh/config.ts index 9769c1a9..e558711b 100644 --- a/docs/zh/config.ts +++ b/docs/zh/config.ts @@ -1,9 +1,30 @@ import { createRequire } from 'node:module' -import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' +import { + defineAdditionalConfig, + type DefaultTheme, + type MarkdownLocaleOptions +} from 'vitepress' const require = createRequire(import.meta.url) const pkg = require('vitepress/package.json') +export const markdown: MarkdownLocaleOptions = { + container: { + tipLabel: '提示', + infoLabel: '信息', + warningLabel: '警告', + dangerLabel: '危险', + detailsLabel: '详细信息', + noteLabel: '注意', + importantLabel: '重要', + cautionLabel: '小心' + }, + codeCopyButton: { + tooltipText: '复制代码', + copiedText: '已复制' + } +} + export default defineAdditionalConfig({ description: '由 Vite 和 Vue 驱动的静态站点生成器', @@ -250,7 +271,6 @@ function searchOptions(): Partial { afterToolCallText: '已搜索', stoppedStreamingText: '你已停止此回复', errorTitleText: '聊天错误', - threadDepthExceededMessage: '为保持回答准确,此对话已关闭。', startNewConversationButtonText: '开始新的对话' } } diff --git a/docs/zh/guide/asset-handling.md b/docs/zh/guide/asset-handling.md index 2d0328dc..209a96d3 100644 --- a/docs/zh/guide/asset-handling.md +++ b/docs/zh/guide/asset-handling.md @@ -6,7 +6,7 @@ description: 了解如何在 VitePress 中引用和处理静态资源,如图 ## 引用静态资源 {#referencing-static-assets} -所有的 Markdown 文件都会被编译成 Vue 组件,并由 [Vite](https://cn.vitejs.dev/guide/assets.html) 处理。可以**并且应该**使用相对路径来引用资源: +所有的 Markdown 文件都会被编译成 Vue 组件,并由 [Vite](https://cn.vite.dev/guide/assets.html) 处理。可以**并且应该**使用相对路径来引用资源: ```md ![An image](./image.png) diff --git a/docs/zh/guide/extending-default-theme.md b/docs/zh/guide/extending-default-theme.md index 88488fa7..974fca81 100644 --- a/docs/zh/guide/extending-default-theme.md +++ b/docs/zh/guide/extending-default-theme.md @@ -119,7 +119,7 @@ export default { } satisfies Theme ``` -因为我们使用 Vite,还可以利用 Vite 的 [glob 导入功能](https://cn.vitejs.dev/guide/features.html#glob-import)来自动注册一个组件目录。 +因为我们使用 Vite,还可以利用 Vite 的 [glob 导入功能](https://cn.vite.dev/guide/features.html#glob-import)来自动注册一个组件目录。 ## 布局插槽 {#layout-slots} @@ -308,7 +308,7 @@ provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => { ## 重写内部组件 {#overriding-internal-components} -可以使用 Vite 的 [aliases](https://vitejs.dev/config/shared-options.html#resolve-alias) 来用自定义组件替换默认主题的组件: +可以使用 Vite 的 [aliases](https://vite.dev/config/shared-options.html#resolve-alias) 来用自定义组件替换默认主题的组件: ```ts import { fileURLToPath, URL } from 'node:url' diff --git a/docs/zh/guide/getting-started.md b/docs/zh/guide/getting-started.md index 847c117a..1f4bf0c1 100644 --- a/docs/zh/guide/getting-started.md +++ b/docs/zh/guide/getting-started.md @@ -41,7 +41,7 @@ $ bun add -D vitepress@next ::: tip 注意 -VitePress 是仅 ESM 的软件包。不要使用 `require()` 导入它,并确保最新的 `package.json` 包含 `"type": "module"`,或者更改相关文件的文件扩展名,例如 `.vitepress/config.js` 到 `.mjs`/`.mts`。更多详情请参考 [Vite 故障排除指南](http://vitejs.dev/guide/troubleshooting.html#this-package-is-esm-only)。此外,在异步 CJS 上下文中,可以使用 `await import('vitepress')` 代替。 +VitePress 是仅 ESM 的软件包。不要使用 `require()` 导入它,并确保最新的 `package.json` 包含 `"type": "module"`,或者更改相关文件的文件扩展名,例如 `.vitepress/config.js` 到 `.mjs`/`.mts`。更多详情请参考 [Vite 故障排除指南](http://vite.dev/guide/troubleshooting.html#this-package-is-esm-only)。此外,在异步 CJS 上下文中,可以使用 `await import('vitepress')` 代替。 ::: diff --git a/docs/zh/guide/markdown.md b/docs/zh/guide/markdown.md index 1ae240f7..2476c713 100644 --- a/docs/zh/guide/markdown.md +++ b/docs/zh/guide/markdown.md @@ -1,5 +1,6 @@ --- description: VitePress 内置的 Markdown 扩展,包括自定义容器、代码块语法高亮、行高亮、代码组等功能。 +outline: deep --- # Markdown 扩展 {#markdown-extensions} @@ -112,7 +113,7 @@ lang: en-US :tada: :100: -这里可以找到[所有支持的 emoji 列表](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.mjs)。 +这里可以找到[所有支持的 emoji 列表](https://github.com/mdit-plugins/mdit-plugins/blob/main/packages/plugin-emoji/src/data/full.ts)。 ## 目录表 (TOC) {#table-of-contents} @@ -231,7 +232,7 @@ export default defineConfig({ ### `raw` -这是一个特殊的容器,可以用来防止与 VitePress 的样式和路由冲突。这在记录组件库时特别有用。可能还想查看 [whyframe](https://whyframe.dev/docs/integrations/vitepress) 以获得更好的隔离。 +这是一个特殊的容器,可以用来防止与 VitePress 的样式和路由冲突。这在记录组件库时特别有用。 **语法** @@ -888,14 +889,14 @@ $$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ ## 图片懒加载 {#image-lazy-loading} -通过在配置文件中将 `lazyLoading` 设置为 `true`,可以为通过 markdown 添加的每张图片启用懒加载。 +通过在配置文件中将 `lazyLoad` 设置为 `true`,可以为通过 markdown 添加的每张图片启用懒加载。 ```js export default { markdown: { image: { // 默认禁用;设置为 true 可为所有图片启用懒加载。 - lazyLoading: true + lazyLoad: true } } } @@ -907,15 +908,15 @@ VitePress 使用 [markdown-it](https://github.com/markdown-it/markdown-it) 作 ```js import { defineConfig } from 'vitepress' -import markdownItAnchor from 'markdown-it-anchor' +import { headerLink } from '@mdit/plugin-anchor' import markdownItFoo from 'markdown-it-foo' export default defineConfig({ markdown: { - // markdown-it-anchor 的选项 - // https://github.com/valeriangalliat/markdown-it-anchor#usage + // @mdit/plugin-anchor 的选项 + // https://mdit-plugins.github.io/anchor.html anchor: { - permalink: markdownItAnchor.permalink.headerLink() + permalink: headerLink() }, // @mdit-vue/plugin-toc 的选项 // https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-toc#options diff --git a/docs/zh/guide/migration-from-vitepress-0.md b/docs/zh/guide/migration-from-vitepress-0.md index 64f9460e..34656f00 100644 --- a/docs/zh/guide/migration-from-vitepress-0.md +++ b/docs/zh/guide/migration-from-vitepress-0.md @@ -14,7 +14,7 @@ - 删除了 `repo`、`repoLabel`、`docsDir`、`docsBranch`、`editLinks`、`editLinkText`,以支持更灵活的 API。 - 要将带有图标的 GitHub 链接添加到导航,请使用 [社交链接](../reference/default-theme-config#nav) 功能。 - 要添加“编辑此页面”功能,请使用 [编辑链接](../reference/default-theme-edit-link) 功能。 -- `lastUpdated` 选项现在分为 `config.lastUpdated` 和 `themeConfig.lastUpdatedText`。 +- `lastUpdated` 选项现在分为 `config.lastUpdated` 和 `themeConfig.lastUpdated.text`。 - `carbonAds.carbon` 更改为 `carbonAds.code`。 ## frontmatter 配置 {#frontmatter-config} diff --git a/docs/zh/guide/ssr-compat.md b/docs/zh/guide/ssr-compat.md index c4f4dfd8..16b567cc 100644 --- a/docs/zh/guide/ssr-compat.md +++ b/docs/zh/guide/ssr-compat.md @@ -39,7 +39,7 @@ onMounted(() => { ### 条件导入 {#conditional-import} -也可以使用 `import.meta.env.SSR` 标志 ([Vite 环境变量](https://cn.vitejs.dev/guide/env-and-mode.html#env-variables)的一部分) 来有条件地导入依赖项: +也可以使用 `import.meta.env.SSR` 标志 ([Vite 环境变量](https://cn.vite.dev/guide/env-and-mode.html#env-variables)的一部分) 来有条件地导入依赖项: ```js if (!import.meta.env.SSR) { diff --git a/docs/zh/guide/using-vue.md b/docs/zh/guide/using-vue.md index 6c378a8d..de868f39 100644 --- a/docs/zh/guide/using-vue.md +++ b/docs/zh/guide/using-vue.md @@ -204,7 +204,7 @@ Hello {{ 1 + 1 }} ## 使用 CSS 预处理器 {#using-css-pre-processors} -VitePress [内置支持](https://cn.vitejs.dev/guide/features.html#css-pre-processors) CSS 预处理器:`.scss`、`.sass`、.`less`、`.styl` 和 `.stylus` 文件。无需为它们安装 Vite 专用插件,但必须安装相应的预处理器: +VitePress [内置支持](https://cn.vite.dev/guide/features.html#css-pre-processors) CSS 预处理器:`.scss`、`.sass`、.`less`、`.styl` 和 `.stylus` 文件。无需为它们安装 Vite 专用插件,但必须安装相应的预处理器: ``` # .scss and .sass diff --git a/docs/zh/guide/what-is-vitepress.md b/docs/zh/guide/what-is-vitepress.md index 25fdc01c..54203b48 100644 --- a/docs/zh/guide/what-is-vitepress.md +++ b/docs/zh/guide/what-is-vitepress.md @@ -6,17 +6,15 @@ description: VitePress 是一个专为构建快速、以内容为中心的网站 VitePress 是一个[静态站点生成器](https://en.wikipedia.org/wiki/Static_site_generator) (SSG),专为构建快速、以内容为中心的站点而设计。简而言之,VitePress 获取用 Markdown 编写的内容,对其应用主题,并生成可以轻松部署到任何地方的静态 HTML 页面。 -
      - +::: tip {no-title} 只是想尝试一下?跳到[快速开始](./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://github.com/search?q=/%22vitepress%22:+/+path:/(?:package%7Cdeno)%5C.jsonc?$/+NOT+is:fork+NOT+is:archived&type=code)文档都是基于这个主题的。 + VitePress 附带一个专为技术文档设计的默认主题。你现在正在阅读的这个页面以及 [Vite](https://vite.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://github.com/search?q=/%22vitepress%22:+/+path:/(?:package%7Cdeno)%5C.jsonc?$/+NOT+is:fork+NOT+is:archived&type=code)文档都是基于这个主题的。 [Vue.js 官方文档](https://cn.vuejs.org/)也是基于 VitePress 的。但是为了可以在不同的翻译文档之间切换,它自定义了自己的主题。 @@ -30,7 +28,7 @@ VitePress 是一个[静态站点生成器](https://en.wikipedia.org/wiki/Static_ VitePress 旨在使用 Markdown 生成内容时提供出色的开发体验。 -- **[Vite 驱动](https://cn.vitejs.dev/)**:即时服务器启动,始终立即反映 (<100ms) 编辑变化,无需重新加载页面。 +- **[Vite 驱动](https://cn.vite.dev/)**:即时服务器启动,始终立即反映 (<100ms) 编辑变化,无需重新加载页面。 - **[内置 Markdown 扩展](./markdown)**:frontmatter、表格、语法高亮……应有尽有。具体来说,VitePress 提供了许多用于处理代码块的高级功能,使其真正成为技术文档的理想选择。 diff --git a/docs/zh/index.md b/docs/zh/index.md index 6be83546..55275f6a 100644 --- a/docs/zh/index.md +++ b/docs/zh/index.md @@ -21,16 +21,16 @@ hero: alt: VitePress features: - - icon: 📝 + - icon: title: 专注内容 details: 只需 Markdown 即可轻松创建美观的文档站点。 - - icon: + - icon: title: 享受 Vite 无可比拟的体验 details: 服务器即时启动,闪电般的热更新,还可以使用基于 Vite 生态的插件。 - - icon: + - icon: title: 使用 Vue 自定义 details: 直接在 Markdown 中使用 Vue 语法和组件,或者使用 Vue 组件构建自定义主题。 - - icon: 🚀 + - icon: title: 速度真的很快! details: 采用静态 HTML 实现快速的页面初次加载,使用客户端路由实现快速的页面切换导航。 --- diff --git a/docs/zh/reference/default-theme-sidebar.md b/docs/zh/reference/default-theme-sidebar.md index d6cb585c..b98c46e4 100644 --- a/docs/zh/reference/default-theme-sidebar.md +++ b/docs/zh/reference/default-theme-sidebar.md @@ -182,3 +182,63 @@ export default { } } ``` + +## 路径前缀 {#path-prefix} + +当文档结构具有较深的目录,或者多个分组位于同一个子目录下时,可以使用 `base` 选项为该分组下的所有嵌套 `items` 拼接的一个路径前缀。 + +这样可以避免为每个 `link` 重复书写相同的路径。`base` 选项既支持在多侧边栏配置中使用,也支持在嵌套的侧边栏分组中使用。 + +### 在多侧边栏中使用 {#in-multiple-sidebars} + +可以在多侧边栏配置的根部定义 `base`: + +```js {5} +export default { + themeConfig: { + sidebar: { + '/guide/': { + base: '/guide/', + items: [ + // 实际解析为 `/guide/introduction` + { text: 'Introduction', link: 'introduction' }, + // 实际解析为 `/guide/getting-started` + { text: 'Getting Started', link: 'getting-started' } + ] + } + } + } +} +``` + +### 在嵌套分组中使用 {#in-nested-groups} + +也可以在嵌套的侧边栏分组内部使用 `base`,它将作用于该分组的直接子项: + +```js {6,13} +export default { + themeConfig: { + sidebar: [ + { + text: 'Reference', + base: '/reference/', + items: [ + // 实际解析为 `/reference/site-config` + { text: 'Site Config', link: 'site-config' }, + { + text: 'Default Theme', + // 嵌套的 base 会覆盖父级的路径前缀 + base: '/reference/default-theme-', + items: [ + // 实际解析为 `/reference/default-theme-nav` + { text: 'Nav', link: 'nav' }, + // 实际解析为 `/reference/default-theme-sidebar` + { text: 'Sidebar', link: 'sidebar' } + ] + } + ] + } + ] + } +} +``` diff --git a/docs/zh/reference/site-config.md b/docs/zh/reference/site-config.md index cdafd736..2f3571a2 100644 --- a/docs/zh/reference/site-config.md +++ b/docs/zh/reference/site-config.md @@ -430,7 +430,7 @@ export default { - 类型:`string` - 默认值: `./.vitepress/cache` -缓存文件的目录,相对于[项目根目录](../guide/routing#root-and-source-directory)。另请参阅:[cacheDir](https://vitejs.dev/config/shared-options.html#cachedir)。 +缓存文件的目录,相对于[项目根目录](../guide/routing#root-and-source-directory)。另请参阅:[cacheDir](https://vite.dev/config/shared-options.html#cachedir)。 ```ts export default { @@ -472,13 +472,6 @@ export default { } ``` -### metaChunk - -- 类型:`boolean` -- 默认值:`false` - -当设置为 `true` 时,将页面元数据提取到单独的 JavaScript 块中,而不是内联在初始 HTML 中。这使每个页面的 HTML 负载更小,并使页面元数据可缓存,从而当站点中有很多页面时可以减少服务器带宽。 - ### mpa - 类型:`boolean` @@ -510,7 +503,7 @@ export default { 是否使用 Git 获取每个页面的最后更新时间戳。时间戳将包含在每个页面的页面数据中,可通过 [`useData`](./runtime-api#usedata) 访问。 -使用默认主题时,启用此选项将显示每个页面的最后更新时间。可以通过 [`themeConfig.lastUpdatedText`](./default-theme-config#lastupdatedtext) 选项自定义文本。 +使用默认主题时,启用此选项将显示每个页面的最后更新时间。可以通过 [`themeConfig.lastUpdated.text`](./default-theme-config#lastupdated) 选项自定义文本。 ## 自定义 {#customization} @@ -532,7 +525,7 @@ export default { - 类型:`import('vite').UserConfig` -将原始 [Vite 配置](https://vitejs.dev/config/)传递给内部 Vite 开发服务器 / bundler。 +将原始 [Vite 配置](https://vite.dev/config/)传递给内部 Vite 开发服务器 / bundler。 ```js export default { diff --git a/package.json b/package.json index 99fd0c10..54693436 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vitepress", - "version": "2.0.0-alpha.18", + "version": "2.0.0-alpha.19", "description": "Vite & Vue powered static site generator", "keywords": [ "vite", @@ -37,6 +37,7 @@ }, "main": "dist/node/index.js", "types": "types/index.d.ts", + "web-types": "./dist/web-types.json", "bin": { "vitepress": "bin/vitepress.js" }, @@ -58,11 +59,12 @@ "dev:node": "DEV=true pnpm build:node -w", "dev:shared": "node scripts/copyShared.ts", "dev:watch": "node scripts/watchAndCopy.ts", - "build": "pnpm build:prepare && pnpm build:client && pnpm build:node", + "build": "pnpm build:prepare && pnpm build:client && pnpm build:node && node scripts/genWebTypes.ts", "build:prepare": "pnpm clean && node scripts/copyShared.ts", "build:client": "vue-tsc --noEmit -p src/client && tsc -p src/client && node scripts/copyClient.ts", "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": "pnpm --aggregate-output --reporter=append-only '/^test:(types|unit|e2e|init)$/'", + "test:types": "tsc -p __tests__/unit && tsc -p __tests__/e2e && tsc -p __tests__/init && vue-tsc -p docs", "test:unit": "vitest run -r __tests__/unit", "test:unit:watch": "vitest -r __tests__/unit", "test:e2e": "pnpm test:e2e-dev && pnpm test:e2e-build", @@ -96,31 +98,29 @@ "*": "prettier --experimental-cli --ignore-unknown --write" }, "dependencies": { - "@docsearch/css": "^4.6.3", - "@docsearch/js": "^4.6.3", - "@docsearch/sidepanel-js": "^4.6.3", - "@iconify-json/simple-icons": "^1.2.87", - "@shikijs/core": "^4.3.0", - "@shikijs/transformers": "^4.3.0", - "@shikijs/types": "^4.3.0", + "@docsearch/css": "^4.7.0", + "@docsearch/js": "^4.7.0", + "@docsearch/sidepanel-js": "^4.7.0", + "@iconify-json/simple-icons": "^1.2.92", + "@shikijs/core": "^4.4.1", + "@shikijs/transformers": "^4.4.1", + "@shikijs/types": "^4.4.1", "@types/markdown-it": "^14.1.2", - "@vitejs/plugin-vue": "^6.0.7", - "@vue/devtools-api": "^8.1.4", - "@vue/shared": "^3.5.39", - "@vueuse/core": "^14.3.0", - "@vueuse/integrations": "^14.3.0", + "@vitejs/plugin-vue": "^6.0.8", + "@vue/devtools-api": "^8.2.1", + "@vue/shared": "^3.5.40", + "@vueuse/core": "^14.4.0", + "@vueuse/integrations": "^14.4.0", "focus-trap": "^8.2.2", "mark.js": "8.11.1", "minisearch": "^7.2.0", - "shiki": "^4.3.0", - "vite": "^8.1.3", - "vue": "^3.5.39" + "shiki": "^4.4.1", + "vite": "^8.2.0", + "vue": "^3.5.40" }, "devDependencies": { - "@clack/prompts": "^1.6.0", - "@emnapi/core": "^1.11.1", - "@emnapi/runtime": "^1.11.1", - "@iconify/utils": "^3.1.3", + "@clack/prompts": "^1.7.0", + "@iconify/utils": "^3.1.4", "@mdit-vue/plugin-component": "^3.0.2", "@mdit-vue/plugin-frontmatter": "^3.0.2", "@mdit-vue/plugin-headers": "^3.0.2", @@ -128,7 +128,14 @@ "@mdit-vue/plugin-title": "^3.0.2", "@mdit-vue/plugin-toc": "^3.0.2", "@mdit-vue/shared": "^3.0.2", + "@mdit/plugin-anchor": "^1.1.3", + "@mdit/plugin-attrs": "^1.1.1", + "@mdit/plugin-container": "^1.0.2", + "@mdit/plugin-emoji": "^1.1.1", + "@mdit/plugin-footnote": "^1.0.2", + "@mdit/plugin-tasklist": "^1.0.2", "@polka/compression": "^1.0.0-next.28", + "@rolldown/pluginutils": "^1.0.1", "@rollup/plugin-alias": "^6.0.0", "@rollup/plugin-commonjs": "^29.0.3", "@rollup/plugin-json": "^6.1.0", @@ -137,49 +144,41 @@ "@types/cross-spawn": "^6.0.6", "@types/lodash.template": "^4.5.3", "@types/mark.js": "^8.11.12", - "@types/markdown-it-attrs": "^4.1.3", - "@types/markdown-it-container": "^4.0.0", - "@types/markdown-it-emoji": "^3.0.1", "@types/minimist": "^1.2.5", - "@types/node": "^25.9.4", + "@types/node": "^26.1.2", "@types/picomatch": "^4.0.3", - "@types/prompts": "^2.4.9", "@types/semver": "^7.7.1", "chokidar": "^5.0.0", - "conventional-changelog": "^7.2.1", - "conventional-changelog-angular": "^8.3.1", + "conventional-changelog": "^8.1.0", + "conventional-changelog-angular": "^9.2.1", "cross-spawn": "^7.0.6", "esbuild": "^0.27.7", "get-port": "^7.2.0", "gray-matter": "^4.0.3", - "lint-staged": "^16.4.0", + "image-size": "^2.0.2", + "lint-staged": "^17.3.0", "lodash.template": "^4.18.1", - "lru-cache": "^11.5.1", - "markdown-it": "^14.2.0", - "markdown-it-anchor": "^9.2.0", + "lru-cache": "^11.5.2", + "markdown-it": "^14.3.0", "markdown-it-async": "^2.2.0", - "markdown-it-attrs": "4.3.1", "markdown-it-cjk-friendly": "^2.0.2", - "markdown-it-container": "^4.0.0", - "markdown-it-emoji": "^3.0.0", "markdown-it-mathjax3": "^4.3.2", "minimist": "^1.2.8", - "nanoid": "^5.1.16", - "obug": "^2.1.3", + "nanoid": "^6.0.0", + "obug": "^2.1.4", "ora": "^9.4.1", - "p-map": "^7.0.4", + "p-map": "^7.0.6", "package-directory": "^8.2.0", "path-to-regexp": "^6.3.0", "picocolors": "^1.1.1", - "picomatch": "^4.0.4", - "playwright-chromium": "^1.61.1", + "picomatch": "^4.0.5", + "playwright-chromium": "^1.62.1", "polka": "^1.0.0-next.28", "postcss": "^8.5.6", "postcss-selector-parser": "^7.1.4", - "prettier": "^3.9.0", - "prompts": "^2.4.2", + "prettier": "^3.9.6", "punycode": "^2.3.1", - "rollup": "^4.62.2", + "rollup": "^4.62.3", "rollup-plugin-dts": "6.1.1", "rollup-plugin-esbuild": "^6.2.1", "semver": "^7.8.5", @@ -188,9 +187,9 @@ "sitemap": "^9.0.1", "tinyglobby": "^0.2.17", "typescript": "^5.9.3", - "vitest": "^4.1.9", - "vue-tsc": "^3.3.5", - "wait-on": "^9.0.10" + "vitest": "^4.1.10", + "vue-tsc": "^3.3.9", + "wait-on": "^9.1.0" }, "peerDependencies": { "markdown-it-mathjax3": "^4", @@ -204,5 +203,5 @@ "optional": true } }, - "packageManager": "pnpm@10.33.0" + "packageManager": "pnpm@11.18.0" } diff --git a/patches/@types__markdown-it-attrs@4.1.3.patch b/patches/@types__markdown-it-attrs@4.1.3.patch deleted file mode 100644 index 4ea21c1d..00000000 --- a/patches/@types__markdown-it-attrs@4.1.3.patch +++ /dev/null @@ -1,23 +0,0 @@ -diff --git a/index.d.ts b/index.d.ts -index 41d4a858c6ece5a61a2088733cf8b333b45603d8..2cb19bcd8fc76ae82ebe87af742916e17f49334b 100644 ---- a/index.d.ts -+++ b/index.d.ts -@@ -1,3 +1,15 @@ --import MarkdownIt = require("markdown-it"); --declare function attrs(md: MarkdownIt): void; --export = attrs; -+import type MarkdownIt from 'markdown-it' -+ -+export interface MarkdownItAttrsOptions { -+ /** left delimiter, default is `{`(left curly bracket) */ -+ leftDelimiter?: string -+ /** right delimiter, default is `}`(right curly bracket) */ -+ rightDelimiter?: string -+ /** rule of allowed attribute, empty means no limit */ -+ allowedAttributes?: (string | RegExp)[] -+} -+ -+export default function attrsPlugin( -+ md: MarkdownIt, -+ options?: MarkdownItAttrsOptions -+): void diff --git a/patches/@types__mdurl@2.0.0.patch b/patches/@types__mdurl@2.0.0.patch deleted file mode 100644 index d128d01c..00000000 --- a/patches/@types__mdurl@2.0.0.patch +++ /dev/null @@ -1,19 +0,0 @@ -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 deleted file mode 100644 index ac4498e4..00000000 --- a/patches/markdown-it-anchor@9.2.0.patch +++ /dev/null @@ -1,17 +0,0 @@ -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/patches/markdown-it-attrs@4.3.1.patch b/patches/markdown-it-attrs@4.3.1.patch deleted file mode 100644 index 5a630c14..00000000 --- a/patches/markdown-it-attrs@4.3.1.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff --git a/patterns.js b/patterns.js -index e56a3b785df29e726194f2b30e86bb19a78ef902..e1f6211b92cbb2bbbe2a3c317dd9e5f1f41ab8d1 100644 ---- a/patterns.js -+++ b/patterns.js -@@ -28,7 +28,8 @@ module.exports = options => { - { - shift: 0, - block: true, -- info: utils.hasDelimiters('end', options) -+ info: utils.hasDelimiters('end', options), -+ markup: (str) => !/^[`~]{3,}$/.test(str) - } - ], - transform: (tokens, i) => { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6775cb74..59e05bea 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,66 +4,49 @@ settings: autoInstallPeers: false excludeLinksFromLockfile: false -overrides: - ora>string-width: ^5 - -patchedDependencies: - '@types/markdown-it-attrs': - hash: ef05082c7886d283042ddf9103f1408fc36fd8665ef278c82b3da0659441dfb6 - path: patches/@types__markdown-it-attrs@4.1.3.patch - '@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 - markdown-it-attrs@4.3.1: - hash: 12883b753541724964b5246a739df34c4b76db10415bbb63c35dce408cfe977e - path: patches/markdown-it-attrs@4.3.1.patch - importers: .: dependencies: '@docsearch/css': - specifier: ^4.6.3 - version: 4.6.3 + specifier: ^4.7.0 + version: 4.7.0 '@docsearch/js': - specifier: ^4.6.3 - version: 4.6.3 + specifier: ^4.7.0 + version: 4.7.0 '@docsearch/sidepanel-js': - specifier: ^4.6.3 - version: 4.6.3 + specifier: ^4.7.0 + version: 4.7.0 '@iconify-json/simple-icons': - specifier: ^1.2.87 - version: 1.2.87 + specifier: ^1.2.92 + version: 1.2.92 '@shikijs/core': - specifier: ^4.3.0 - version: 4.3.0 + specifier: ^4.4.1 + version: 4.4.1 '@shikijs/transformers': - specifier: ^4.3.0 - version: 4.3.0 + specifier: ^4.4.1 + version: 4.4.1 '@shikijs/types': - specifier: ^4.3.0 - version: 4.3.0 + specifier: ^4.4.1 + version: 4.4.1 '@types/markdown-it': specifier: ^14.1.2 version: 14.1.2 '@vitejs/plugin-vue': - specifier: ^6.0.7 - version: 6.0.7(vite@8.1.3(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0))(vue@3.5.39(typescript@5.9.3)) + specifier: ^6.0.8 + version: 6.0.8(vite@8.2.0(@types/node@26.1.2)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0))(vue@3.5.40(typescript@5.9.3)) '@vue/devtools-api': - specifier: ^8.1.4 - version: 8.1.4 + specifier: ^8.2.1 + version: 8.2.1 '@vue/shared': - specifier: ^3.5.39 - version: 3.5.39 + specifier: ^3.5.40 + version: 3.5.40 '@vueuse/core': - specifier: ^14.3.0 - version: 14.3.0(vue@3.5.39(typescript@5.9.3)) + specifier: ^14.4.0 + version: 14.4.0(vue@3.5.40(typescript@5.9.3)) '@vueuse/integrations': - specifier: ^14.3.0 - version: 14.3.0(axios@1.18.1)(focus-trap@8.2.2)(vue@3.5.39(typescript@5.9.3)) + specifier: ^14.4.0 + version: 14.4.0(axios@1.19.0(debug@4.4.3))(focus-trap@8.2.2)(vue@3.5.40(typescript@5.9.3)) focus-trap: specifier: ^8.2.2 version: 8.2.2 @@ -74,27 +57,21 @@ importers: specifier: ^7.2.0 version: 7.2.0 shiki: - specifier: ^4.3.0 - version: 4.3.0 + specifier: ^4.4.1 + version: 4.4.1 vite: - specifier: ^8.1.3 - version: 8.1.3(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0) + specifier: ^8.2.0 + version: 8.2.0(@types/node@26.1.2)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0) vue: - specifier: ^3.5.39 - version: 3.5.39(typescript@5.9.3) + specifier: ^3.5.40 + version: 3.5.40(typescript@5.9.3) devDependencies: '@clack/prompts': - specifier: ^1.6.0 - version: 1.6.0 - '@emnapi/core': - specifier: ^1.11.1 - version: 1.11.1 - '@emnapi/runtime': - specifier: ^1.11.1 - version: 1.11.1 + specifier: ^1.7.0 + version: 1.7.0 '@iconify/utils': - specifier: ^3.1.3 - version: 3.1.3 + specifier: ^3.1.4 + version: 3.1.4 '@mdit-vue/plugin-component': specifier: ^3.0.2 version: 3.0.2 @@ -116,24 +93,45 @@ importers: '@mdit-vue/shared': specifier: ^3.0.2 version: 3.0.2 + '@mdit/plugin-anchor': + specifier: ^1.1.3 + version: 1.1.3(markdown-it@14.3.0) + '@mdit/plugin-attrs': + specifier: ^1.1.1 + version: 1.1.1(markdown-it@14.3.0) + '@mdit/plugin-container': + specifier: ^1.0.2 + version: 1.0.2(markdown-it@14.3.0) + '@mdit/plugin-emoji': + specifier: ^1.1.1 + version: 1.1.1(markdown-it@14.3.0) + '@mdit/plugin-footnote': + specifier: ^1.0.2 + version: 1.0.2(markdown-it@14.3.0) + '@mdit/plugin-tasklist': + specifier: ^1.0.2 + version: 1.0.2(markdown-it@14.3.0) '@polka/compression': specifier: ^1.0.0-next.28 version: 1.0.0-next.28 + '@rolldown/pluginutils': + specifier: ^1.0.1 + version: 1.0.1 '@rollup/plugin-alias': specifier: ^6.0.0 - version: 6.0.0(rollup@4.62.2) + version: 6.0.0(rollup@4.62.3) '@rollup/plugin-commonjs': specifier: ^29.0.3 - version: 29.0.3(rollup@4.62.2) + version: 29.0.3(rollup@4.62.3) '@rollup/plugin-json': specifier: ^6.1.0 - version: 6.1.0(rollup@4.62.2) + version: 6.1.0(rollup@4.62.3) '@rollup/plugin-node-resolve': specifier: ^16.0.3 - version: 16.0.3(rollup@4.62.2) + version: 16.0.3(rollup@4.62.3) '@rollup/plugin-replace': specifier: ^6.0.3 - version: 6.0.3(rollup@4.62.2) + version: 6.0.3(rollup@4.62.3) '@types/cross-spawn': specifier: ^6.0.6 version: 6.0.6 @@ -143,27 +141,15 @@ importers: '@types/mark.js': specifier: ^8.11.12 version: 8.11.12 - '@types/markdown-it-attrs': - specifier: ^4.1.3 - version: 4.1.3(patch_hash=ef05082c7886d283042ddf9103f1408fc36fd8665ef278c82b3da0659441dfb6) - '@types/markdown-it-container': - specifier: ^4.0.0 - version: 4.0.0 - '@types/markdown-it-emoji': - specifier: ^3.0.1 - version: 3.0.1 '@types/minimist': specifier: ^1.2.5 version: 1.2.5 '@types/node': - specifier: ^25.9.4 - version: 25.9.4 + specifier: ^26.1.2 + version: 26.1.2 '@types/picomatch': specifier: ^4.0.3 version: 4.0.3 - '@types/prompts': - specifier: ^2.4.9 - version: 2.4.9 '@types/semver': specifier: ^7.7.1 version: 7.7.1 @@ -171,11 +157,11 @@ importers: specifier: ^5.0.0 version: 5.0.0 conventional-changelog: - specifier: ^7.2.1 - version: 7.2.1(conventional-commits-filter@5.0.0) + specifier: ^8.1.0 + version: 8.1.0(conventional-commits-filter@6.0.1) conventional-changelog-angular: - specifier: ^8.3.1 - version: 8.3.1 + specifier: ^9.2.1 + version: 9.2.1 cross-spawn: specifier: ^7.0.6 version: 7.0.6 @@ -188,36 +174,27 @@ importers: gray-matter: specifier: ^4.0.3 version: 4.0.3 + image-size: + specifier: ^2.0.2 + version: 2.0.2 lint-staged: - specifier: ^16.4.0 - version: 16.4.0 + specifier: ^17.3.0 + version: 17.3.0 lodash.template: specifier: ^4.18.1 version: 4.18.1 lru-cache: - specifier: ^11.5.1 - version: 11.5.1 + specifier: ^11.5.2 + version: 11.5.2 markdown-it: - specifier: ^14.2.0 - version: 14.2.0 - markdown-it-anchor: - specifier: ^9.2.0 - version: 9.2.0(patch_hash=cdc28e7c329be30688ad192126ba505446611fbe526ad51483e4b1287aa35cf9)(@types/markdown-it@14.1.2)(markdown-it@14.2.0) + specifier: ^14.3.0 + version: 14.3.0 markdown-it-async: specifier: ^2.2.0 version: 2.2.0 - markdown-it-attrs: - specifier: 4.3.1 - version: 4.3.1(patch_hash=12883b753541724964b5246a739df34c4b76db10415bbb63c35dce408cfe977e)(markdown-it@14.2.0) markdown-it-cjk-friendly: specifier: ^2.0.2 - version: 2.0.2(@types/markdown-it@14.1.2)(markdown-it@14.2.0) - markdown-it-container: - specifier: ^4.0.0 - version: 4.0.0 - markdown-it-emoji: - specifier: ^3.0.0 - version: 3.0.0 + version: 2.0.2(@types/markdown-it@14.1.2)(markdown-it@14.3.0) markdown-it-mathjax3: specifier: ^4.3.2 version: 4.3.2 @@ -225,17 +202,17 @@ importers: specifier: ^1.2.8 version: 1.2.8 nanoid: - specifier: ^5.1.16 - version: 5.1.16 + specifier: ^6.0.0 + version: 6.0.0 obug: - specifier: ^2.1.3 - version: 2.1.3 + specifier: ^2.1.4 + version: 2.1.4 ora: specifier: ^9.4.1 version: 9.4.1 p-map: - specifier: ^7.0.4 - version: 7.0.4 + specifier: ^7.0.6 + version: 7.0.6 package-directory: specifier: ^8.2.0 version: 8.2.0 @@ -246,38 +223,35 @@ importers: specifier: ^1.1.1 version: 1.1.1 picomatch: - specifier: ^4.0.4 - version: 4.0.4 + specifier: ^4.0.5 + version: 4.0.5 playwright-chromium: - specifier: ^1.61.1 - version: 1.61.1 + specifier: ^1.62.1 + version: 1.62.1 polka: specifier: ^1.0.0-next.28 version: 1.0.0-next.28 postcss: specifier: ^8.5.6 - version: 8.5.15 + version: 8.5.25 postcss-selector-parser: specifier: ^7.1.4 version: 7.1.4 prettier: - specifier: ^3.9.0 - version: 3.9.0 - prompts: - specifier: ^2.4.2 - version: 2.4.2 + specifier: ^3.9.6 + version: 3.9.6 punycode: specifier: ^2.3.1 version: 2.3.1 rollup: - specifier: ^4.62.2 - version: 4.62.2 + specifier: ^4.62.3 + version: 4.62.3 rollup-plugin-dts: specifier: 6.1.1 - version: 6.1.1(rollup@4.62.2)(typescript@5.9.3) + version: 6.1.1(rollup@4.62.3)(typescript@5.9.3) rollup-plugin-esbuild: specifier: ^6.2.1 - version: 6.2.1(esbuild@0.27.7)(rollup@4.62.2) + version: 6.2.1(esbuild@0.27.7)(rollup@4.62.3) semver: specifier: ^7.8.5 version: 7.8.5 @@ -297,14 +271,14 @@ importers: specifier: ^5.9.3 version: 5.9.3 vitest: - specifier: ^4.1.9 - version: 4.1.9(@types/node@25.9.4)(vite@8.1.3(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0)) + specifier: ^4.1.10 + version: 4.1.10(@types/node@26.1.2)(vite@8.2.0(@types/node@26.1.2)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0)) vue-tsc: - specifier: ^3.3.5 - version: 3.3.5(typescript@5.9.3) + specifier: ^3.3.9 + version: 3.3.9(typescript@5.9.3) wait-on: - specifier: ^9.0.10 - version: 9.0.10 + specifier: ^9.1.0 + version: 9.1.0(debug@4.4.3) __tests__/e2e: devDependencies: @@ -327,23 +301,27 @@ importers: specifier: ^4.3.2 version: 4.3.2 open-cli: - specifier: ^8.0.0 - version: 8.0.0 + specifier: ^9.0.0 + version: 9.0.0 postcss-rtlcss: specifier: ^6.0.0 - version: 6.0.0(postcss@8.5.16) + version: 6.0.0(postcss@8.5.25) vitepress: specifier: workspace:* version: link:.. vitepress-plugin-group-icons: - specifier: ^1.7.5 - version: 1.7.5(vite@8.1.3(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0)) + specifier: ^1.7.6 + version: 1.7.6(vite@8.2.0(@types/node@26.1.2)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0)) vitepress-plugin-llms: - specifier: ^1.13.2 - version: 1.13.2 + specifier: ^1.13.4 + version: 1.13.4 packages: + '@11ty/gray-matter@2.1.0': + resolution: {integrity: sha512-fNdBOb3MgDz/1UCIoeY4wDuGbp+/3s5y6UrsyfMabECbh/CVycj7Er33JXqSxRwxrRKXcGE1Jipuq/1mODInsQ==} + engines: {node: '>=11'} + '@antfu/install-pkg@1.1.0': resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==} @@ -368,46 +346,53 @@ packages: resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} engines: {node: '>=6.9.0'} + '@borewit/text-codec@0.2.2': + resolution: {integrity: sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==} + '@clack/core@0.3.5': resolution: {integrity: sha512-5cfhQNH+1VQ2xLQlmzXMqUoiaH0lRBq9/CLW9lTyMbuKLC3+xEK01tHVvyut++mLOn5urSHmkm6I0Lg9MaJSTQ==} - '@clack/core@1.4.2': - resolution: {integrity: sha512-0Ty/1Gfm+Kb07sXcuESjyKfwEhSy4Ns1AgeEisHb/bDY5fWme0tTeTkU14T1Gmcs17YIjB/teiDe4uaCghbYqQ==} + '@clack/core@1.4.3': + resolution: {integrity: sha512-/kr3UWNtdJfxZtPgDqUOmG2pvwlmcLGheex5yiZKdwbzZJxhV+HMNR9QNmyY5cGwTNV6LrR7Jtp+KjhUAP1qBQ==} engines: {node: '>= 20.12.0'} - '@clack/prompts@1.6.0': - resolution: {integrity: sha512-EYlRokl8szrP9Z25qT5aepMdBjzBvHF9ZEhzIiUBc9guz/T31EqRgvD0QSgZcpE93xiwrr+OkB4nz0BZyF6fSA==} + '@clack/prompts@1.7.0': + resolution: {integrity: sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A==} engines: {node: '>= 20.12.0'} - '@conventional-changelog/git-client@2.7.0': - resolution: {integrity: sha512-j7A8/LBEQ+3rugMzPXoKYzyUPpw/0CBQCyvtTR7Lmu4olG4yRC/Tfkq79Mr3yuPs0SUitlO2HwGP3gitMJnRFw==} - engines: {node: '>=18'} + '@conventional-changelog/git-client@3.1.0': + resolution: {integrity: sha512-Tqa/gHco2WJWa740NRjOrfKVvzIqxkZpecb8bemaQ8sKM5PXb1UK4uTyTb/1wIqNuOVaDOFxyBdhTIQZn6gdjQ==} + engines: {node: '>=22'} peerDependencies: - conventional-commits-filter: ^5.0.0 - conventional-commits-parser: ^6.4.0 + conventional-commits-filter: ^6.0.1 + conventional-commits-parser: ^7.0.1 peerDependenciesMeta: conventional-commits-filter: optional: true conventional-commits-parser: optional: true - '@docsearch/css@4.6.3': - resolution: {integrity: sha512-nlOwcXcsNAptQl4vlL4MA78qNJKO0Qlds5GuBjCoePgkebTXLSf8Qt1oyZ3YBshYupKXG9VRGEsk1zr23d+bzQ==} + '@conventional-changelog/template@1.2.1': + resolution: {integrity: sha512-TzlTVpKPjaqW6qOYjQcYUDuGsLCNsvFHVBXkYGTAnf5V37jCWrE5haKNXzz0WZUtVHjrpV76L1buANjwXMfT8w==} + engines: {node: '>=22'} + + '@docsearch/css@4.7.0': + resolution: {integrity: sha512-Sk5xkdRFeE7PeWjG9l4AfTwdvMfr9wHiwNNCpHXT4v4SNyNMKdHGvEILc31BgaVFGDDNbv5u/a73tofRiwbEZw==} - '@docsearch/js@4.6.3': - resolution: {integrity: sha512-qUIX2b4Apew3tv4F0qhmgShsl/Lfw4m6mqv/5/5dWNxwTcDdLMp2s3YwZ+NMGh3IKCg0pBaXm7Q5VdyU5Rj+cQ==} + '@docsearch/js@4.7.0': + resolution: {integrity: sha512-x5lCqu1tetgsJFkjQ6VSocbHldsRkGEgwg5N98Vx21sq/V5wcmj4u226PY9k+TEpIgQ772zlYbPLTPicWyGnpA==} - '@docsearch/sidepanel-js@4.6.3': - resolution: {integrity: sha512-grGSmvXzG0if+mrzdIKykvpIAuEQ9u0sEJ2eLRRCaQfJvsWqh2C2/aY04bIzWvDh7myi5rvl8D+tUNsVrjYQ3A==} + '@docsearch/sidepanel-js@4.7.0': + resolution: {integrity: sha512-A8r34jCU8kcIk2viECEn2msA28ojUF1BLi/3v5OWWc5G2N3jOuuumBXoeYjfr8dA0UxgFSy5R2bt12dnFJQSyA==} - '@emnapi/core@1.11.1': - resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} + '@emnapi/core@2.0.0-alpha.3': + resolution: {integrity: sha512-AZypUeJ/yByuxyS7BlSNRDOMLMlROYtjYdIAuBmJssVz1UJDSeYxLrdizhXCFYhedC5bqd/ASy8EuNXbVVXp9g==} - '@emnapi/runtime@1.11.1': - resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} + '@emnapi/runtime@2.0.0-alpha.3': + resolution: {integrity: sha512-hFPAhMUjJD9BSyCANEISPOogeXC9Zo9ZQl7L6vKnaVsMkCtzznaW/naYypeyl0Gv5rYfWYsZbpixTMpjDJzQeA==} - '@emnapi/wasi-threads@1.2.2': - resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} + '@emnapi/wasi-threads@2.0.1': + resolution: {integrity: sha512-9DsSk+o5NBX0CCJT8s0EROGSGxjR/tKu6aBTaVyq+SjAEQH4XcdcRxPBRzsBLizTTJ49MJjF+jgu3qnO9GLQcQ==} '@esbuild/aix-ppc64@0.27.7': resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} @@ -588,17 +573,17 @@ packages: '@iconify-json/logos@1.2.11': resolution: {integrity: sha512-fOo4pGEatuyuCFNL+cwquYMa2Im0oJHRHV7lt/Qqs5Ode/lPImHCQcfTtPzZj7qYMPb/h8YHN3TG54uEowrjNQ==} - '@iconify-json/simple-icons@1.2.87': - resolution: {integrity: sha512-8YciStObhSji3OZFmWAWK6kBujyqO5bLCxeDwLxf3CR3F4PVelq7keC2LBvgTqviWzSTysj5/g4PCFLiAMVGsw==} + '@iconify-json/simple-icons@1.2.92': + resolution: {integrity: sha512-hR0ozxR97t1dzWw+esoxFijZ15gagt7EIgF3CNifu2yICXhS7gnun4Y+j+odJQtNSl7wvqMdoLbViIShwe/fdw==} - '@iconify-json/vscode-icons@1.2.62': - resolution: {integrity: sha512-3oE1VGq1GUl3veCET78kvC0NDpKYVo1s6RgJgwo6EWEyfJY28H9PoGaNaTpbbH6HSOsxTJyGfNobALiqnKcNjQ==} + '@iconify-json/vscode-icons@1.2.67': + resolution: {integrity: sha512-/fObxEkBtqK2e1qf1IRjuZ4drWknAnzykdT2ngGAKESf35tCcj0Lx3MdsxYBneE5YbgvsUfOl0hbZ59R5s19vw==} '@iconify/types@2.0.0': resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} - '@iconify/utils@3.1.3': - resolution: {integrity: sha512-LPKOXPn/zV+zis1oOfGWogaXVpqUybF3ZS6SCZIsz8vg0ivVp9+fVqyYB7xq0aiST/VhUQYGO1qo6uoYSiEJqw==} + '@iconify/utils@3.1.4': + resolution: {integrity: sha512-b1S7B1k9ohZ+iNTi2ATxbRYG9fTrJmUT0rc46bvVnNxqNRGW7dyo/vRREwyniI5IRN2RSJHDcm+s3BjWrSAjHw==} '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} @@ -646,11 +631,68 @@ packages: resolution: {integrity: sha512-00aAZ0F0NLik6I6Yba2emGbHLxv+QYrPH00qQ5dFKXlAo1Ll2RHDXwY7nN2WAfrx2pP+WrvSRFTGFCNGdzBDHw==} engines: {node: '>=20.0.0'} - '@napi-rs/wasm-runtime@1.1.6': - resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + '@mdit/helper@1.0.1': + resolution: {integrity: sha512-zAzShsRZmkqjuoOFg6/zTCYVpvghj9a30Cl/eOGkE0xzRJJJG8T18eqb2lgceQhjVLWHK02HNVkzyfNHc429lQ==} + engines: {node: '>=22'} + peerDependencies: + markdown-it: ^14.2.0 + peerDependenciesMeta: + markdown-it: + optional: true + + '@mdit/plugin-anchor@1.1.3': + resolution: {integrity: sha512-lkB9c+NTR//ZLv4MgrDb2ewYulr/WOCWPx0aQC/HbccWJc0JVPMeYwalWfzj517pvKbHGQdOpGRTcFcnn+NG0g==} peerDependencies: - '@emnapi/core': ^1.7.1 - '@emnapi/runtime': ^1.7.1 + markdown-it: ^14.2.0 + + '@mdit/plugin-attrs@1.1.1': + resolution: {integrity: sha512-DgBqzdg8stCGtCsQUJLWhHsyk2HnNp/2d/h5WV9Op2lMGnHA8hjOgnHbmwp0AD8djfv+uUCD6VlOCw3y4L/rGQ==} + engines: {node: '>=22'} + peerDependencies: + markdown-it: ^14.2.0 + peerDependenciesMeta: + markdown-it: + optional: true + + '@mdit/plugin-container@1.0.2': + resolution: {integrity: sha512-gCpqmadamWVbDI7+OgkywDGjfgqxrjZo3U+iK+sH7vERnZyX4sx1X65pXbqrem8Q5/4yO5t0d+kWkPC733ceRw==} + engines: {node: '>=22'} + peerDependencies: + markdown-it: ^14.2.0 + peerDependenciesMeta: + markdown-it: + optional: true + + '@mdit/plugin-emoji@1.1.1': + resolution: {integrity: sha512-8guVkqXImO/V4eCKMxrKot7EO3HI9sIsS2fqFYBQUpy2j3HbsItvsx5QXKf71Nzyr6WKxpznDas/tewrbC2pcg==} + engines: {node: '>=22'} + peerDependencies: + markdown-it: ^14.2.0 + peerDependenciesMeta: + markdown-it: + optional: true + + '@mdit/plugin-footnote@1.0.2': + resolution: {integrity: sha512-G7pzoczbzVph9s9eyLuG9T24//ub9vK7A8jFCESQIzZj83ZJF3BHs7r/wcQx4KzmH+kDpLiAbhvzT/Y3+7OUig==} + engines: {node: '>=22'} + peerDependencies: + markdown-it: ^14.2.0 + + '@mdit/plugin-tasklist@1.0.2': + resolution: {integrity: sha512-h+WCr/h+K0pbyZdJnrPEpgeMFlffzqfviY3TDmj7PdZiVAS1YF1s95+tt9bvmJWKPrALV/IgePxsu5LWnODMmw==} + engines: {node: '>=22'} + peerDependencies: + markdown-it: ^14.2.0 + peerDependenciesMeta: + markdown-it: + optional: true + + '@napi-rs/wasm-runtime@1.2.2': + resolution: {integrity: sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} + peerDependencies: + '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.3 + '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.3 '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -664,8 +706,8 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@oxc-project/types@0.138.0': - resolution: {integrity: sha512-1a7ZKmrRTCoN1XMZ4L0PyyqrMnrNlLyPuOkdSX2MZg7IiIGRUyurNhAm73ptDOraoBcIordsIGKNPKUzy3ZmfA==} + '@oxc-project/types@0.142.0': + resolution: {integrity: sha512-7W+2q5AKQVU36fkaryontrHn3YDt1RyUYXatw9i5H8ocYe2sPKSFB6eS8WNPeRKiN1qAWWZUPm7gwFzJGrccqQ==} '@polka/compression@1.0.0-next.28': resolution: {integrity: sha512-aDmrBhgHJtxE+jy145WfhW9WmTAFmES/dNnn1LAs8UnnkFgBUj4T8I4ScQ9+rOkpDZStvnVP5iqhN3tvt7O1NA==} @@ -674,97 +716,96 @@ packages: '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} - '@rolldown/binding-android-arm64@1.1.4': - resolution: {integrity: sha512-EZLpf/8y7GXkkra90ML47kzik/GMP3EMcE9bPyHmRfxLC6z9+aW5A8poCsoxjrT5GfEcNAAvWwUHjvP1pUQkfw==} + '@rolldown/binding-android-arm64@1.2.1': + resolution: {integrity: sha512-02hOeOSryYxVrOIphmLAsqnCJWxwlzFk+pEt/N/i6OgT3lShHO7xGCU5cpgchRDHboAEbSjzgGh+O/u1GswQmA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.1.4': - resolution: {integrity: sha512-aUi+HBvmYb7j8krl1+qJgkG8C17fO79gk3c+jPw4S8glRFc1DTija9S3EyaTSQUm5GJXYKDAsugBEhFHH2vYiQ==} + '@rolldown/binding-darwin-arm64@1.2.1': + resolution: {integrity: sha512-fMsTOnN0OjFm3CyppWPitKnc8UlliVARUULW6cfU6AIqjdtgmSFWSk9vecHzZduv/yMWIHDlRhM1e8Iff9uAfA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.1.4': - resolution: {integrity: sha512-F7hHC3gwY11+vByKPRWqwGbeXWVgKmL+pTGCinaEhdihzBV2aQ0fvZOch9cXYUOKuKKq429HeYXOqQLc7wFCEg==} + '@rolldown/binding-darwin-x64@1.2.1': + resolution: {integrity: sha512-1wjKdz/XLGKHaTNHjQveQ/B23TKx4ItAqm1JbyVuvNPc4Ze0Fb48s49TAd/2zcplPl8okE/UbTgmlVfwT7eFeQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.1.4': - resolution: {integrity: sha512-sI5yw+7s92SK6odiEhD5lKCBlWcpjHS5qyqpVQbZAJ0fIzEUXrmbl3DH2ybR3PZogulNJF+COLtmA8hUfvkCCQ==} + '@rolldown/binding-freebsd-x64@1.2.1': + resolution: {integrity: sha512-Fa0jHR07E7YBN4vOEsbVf2briYNsuOowfLJaXULZM0ldMlaCaj2LJgLMbMe4iacRyZmvR8efFhgR9wKuGclQUg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.1.4': - resolution: {integrity: sha512-mCi0OKgEieFircrtVYmQAFGszRtMnZ6fpZAXrxanXAu7lqZcsK1E1RAaZNG0uKAnxox3B1f4EyQNnoyMfN1vAA==} + '@rolldown/binding-linux-arm-gnueabihf@1.2.1': + resolution: {integrity: sha512-pzkgu1SSHGgRRyRZ4fbmSgmajbVt+epaLP99NDjFft69v/ypfTi6swBMiVdh2EkQ0OSnHE1lZDM7DRGkyAzUpA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.1.4': - resolution: {integrity: sha512-B9Ial3Kv5sh0SHnB1g/QWcUQCEvCF6QKGAl4zXypYj65mVI+B4AhFBwPtSN7pDrJeIx8Z7zdy4ntx+wQABom7w==} + '@rolldown/binding-linux-arm64-gnu@1.2.1': + resolution: {integrity: sha512-QI5SEDY8cbiYWHx0VO4vIc3UlS6a32vXHjU8Qy/17adEmZIPuByJg13UEvo9c/UCiUkdcVWY83C+b+JrwnNyUg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-arm64-musl@1.1.4': - resolution: {integrity: sha512-lZVym0PuHE1KZ22gmFTC15lAkrg9iTszR617oYRB/iPY1A56ywoJzVKOJBKaot5RiikCObmur6pogpse3gRcng==} + '@rolldown/binding-linux-arm64-musl@1.2.1': + resolution: {integrity: sha512-Sm41FyCeXqmYcERoYOCbGIL5hNfd8w9LQ7Y61Bev48HkcjaJqV/iiVOaiDxjVTRMS+QKrZmD8cfPt4uMVnvM+A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@rolldown/binding-linux-ppc64-gnu@1.1.4': - resolution: {integrity: sha512-t2DNiLJWNTbnEHyUzTumldML6ET4/g16467LZoDDJ3tSxGvguL5/NyC2lCsNKuyRycg9XeDQF5SSv+TNOhQEXg==} + '@rolldown/binding-linux-ppc64-gnu@1.2.1': + resolution: {integrity: sha512-2x+WhXTGl9yJYPbltW/BSEPTVz9OIWQyER4N+gJEDWkkn904eRcBzELqh/Hf7K0w/ubGbKNMv0ZC+94QK/IFEg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-s390x-gnu@1.1.4': - resolution: {integrity: sha512-0WIRnL1Uw4BvTZRLQt+PVgo6ZKTJadlC2btP+/EOXv2f/DWbY0rEgl+y834mIVwP1FkTlWVTrGGJXf12lru7EQ==} + '@rolldown/binding-linux-s390x-gnu@1.2.1': + resolution: {integrity: sha512-eEjmQpuRQayHPWWnywaWHkFT3ToPbP3RYy42VVd/B9aBGDA+Ol25EIWHxKQST3IiWJjikCWUF7KtbfqwZrzVwQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-gnu@1.1.4': - resolution: {integrity: sha512-JWtGshGfX+oENAKonoNkqEJX+7hC8yfhi9GUyPX1VX4mdh1y5r+ZiJLR5XzAB0aoP6s/PcILsGjKq8O0mm24bw==} + '@rolldown/binding-linux-x64-gnu@1.2.1': + resolution: {integrity: sha512-/Orga1fZYkLc/56jBICcHrKchl8Z2UKdDSr3LG9ToWO1lQ6a4Livk9Xz+9WN91zsz5QR3XQz2NNoSDEvP6qadw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-musl@1.1.4': - resolution: {integrity: sha512-rT6yQcxUuXs4CnbofqwHRRV0iem349rLMYpTjkgQGLjrY4ado/eDzwPZPTCgTOlF6Nkp8NEv70yLMTn6qkWxsQ==} + '@rolldown/binding-linux-x64-musl@1.2.1': + resolution: {integrity: sha512-xxBJRL+0q0Kce7orznGWLuylHDY65vuARXZRpX+hPdv+DqK2c3NlCsVA98tlWzWNEE7yPqA/1NQ5nnCrj49Y5A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@rolldown/binding-openharmony-arm64@1.1.4': - resolution: {integrity: sha512-KXMGoboq5cyaCQjDA4GLuRiOwBQ0EyFnJoVViLeZ45/3rFItRODEr+NdsBcVpll40hhNArlm/speWGRvj08LzA==} + '@rolldown/binding-openharmony-arm64@1.2.1': + resolution: {integrity: sha512-M6AdXIXw3s+/8XpKMzdGDEXGS1S7kwUsy+rcTIUIOx5Ge4nXKCtAFHFV9YKkXvGcC5WMoTjAteLzlsQROVI0Yw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.1.4': - resolution: {integrity: sha512-5K83rb36oJiY7BCyE9zLZtGcPV4g5wvq+xwdO0XPIwDVZI8cyB/AUjkNXGb92/rnmezEkjMOpgY61rtwjQtFwg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [wasm32] + '@rolldown/binding-wasm32-wasi@1.2.1': + resolution: {integrity: sha512-/TX0SoRGojHzSAHpfVBbavRVSazg5U3h3Y3VXfcc0cdugq6kxdqw8LPGFiPr+/7gE/60zRcsOY2Vi9b9eT0jww==} + engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} - '@rolldown/binding-win32-arm64-msvc@1.1.4': - resolution: {integrity: sha512-PnWBtw3TV5KOg69HQQDR0mnQuyCmSGR2pAB4DC1rPF808fgKeTUMj2EOEyKATpgiuxuR5APQmiDO7PDgEjTFSA==} + '@rolldown/binding-win32-arm64-msvc@1.2.1': + resolution: {integrity: sha512-EvRrivJieyHG+AO9lleZWgq+g0+S7oV2C51yuqlcyU/R9net+sI4Pj0F+lUoP2bEr6TWX3SqFaaS0SzfLxSzkw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.1.4': - resolution: {integrity: sha512-M1lpniBePobTfsa7Ks9a199e1akxsXn+GYBUKsEzv3YFzOm1HJAMNwKI3qr0Zq+mxwx9gOZoTdP1yXRYsZUocQ==} + '@rolldown/binding-win32-x64-msvc@1.2.1': + resolution: {integrity: sha512-Z4eCmn5QJ/5+azF9knpLWKfVd9aidn0mAe9TpJgvBLId9Ax3t0+JVxBmT25Bv7NBbVW1TZyKjQjQReouMeH5UQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -826,174 +867,174 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.62.2': - resolution: {integrity: sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==} + '@rollup/rollup-android-arm-eabi@4.62.3': + resolution: {integrity: sha512-c0wdcekXtQvvn5Tsrk/+op/gUArrbWaFduBnTLP2l1cKLSQs4diMWjJw3m6A0DdzT8dAAX95KpkJ3qynCePbmw==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.62.2': - resolution: {integrity: sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==} + '@rollup/rollup-android-arm64@4.62.3': + resolution: {integrity: sha512-3YjElDdWN+qXAFbJ/CzPV+0wspLqh54k/I6GfdYtEJRqg7buSgc1yPM3B+93j1M4neobtkATHZTmxK2AMVGfnA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.62.2': - resolution: {integrity: sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==} + '@rollup/rollup-darwin-arm64@4.62.3': + resolution: {integrity: sha512-Pch2pFNOxxz1hTjypIdPyRTR6riiwRl84+VcN9djS680fw+Co1nAJINrdpqp7KV0NvyuU8ilZXZCjd7ykJl1GQ==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.62.2': - resolution: {integrity: sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==} + '@rollup/rollup-darwin-x64@4.62.3': + resolution: {integrity: sha512-LEuncFUHFiF8t4yZVZvvZA1wk0pjAscRnsrn1EfTEmN4HXotBi2YtcnLRyaK6UbuczW7xZS5ES+81Rdz8Z0T6g==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.62.2': - resolution: {integrity: sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==} + '@rollup/rollup-freebsd-arm64@4.62.3': + resolution: {integrity: sha512-zvBUvsQUpOWALdDsk6qbS8bXf2VxmPisuudNDrY7x0p0jBdsoZl8HsHczIOgkQiZldmcacMKtBzpoGVNeIe2bQ==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.62.2': - resolution: {integrity: sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==} + '@rollup/rollup-freebsd-x64@4.62.3': + resolution: {integrity: sha512-C2KmNrcSem/AMg984H/dev+si0lieQGdXdR/lYGJnuumXnFb9Y7QdiI62obFdLlxRYLBv4P0eUVIDbD4c1vVvw==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.62.2': - resolution: {integrity: sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==} + '@rollup/rollup-linux-arm-gnueabihf@4.62.3': + resolution: {integrity: sha512-ggXnsTAEzNQx74XpunRsiZ9aBZDsI7XIa0hm2nzR9f4WzH5/f/d73ZSDaC5ejJ8YLY4NW+V3wr0tjOaeCq8hqA==} cpu: [arm] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm-musleabihf@4.62.2': - resolution: {integrity: sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==} + '@rollup/rollup-linux-arm-musleabihf@4.62.3': + resolution: {integrity: sha512-2vng+FlzNUhKZxtej3IUqJgbZoQk2M/dwQM20+ULV0R/E/8tr9/P6uEf2iiGIk4HL0zMKh5Jry7mUHdUOvyGgA==} cpu: [arm] os: [linux] libc: [musl] - '@rollup/rollup-linux-arm64-gnu@4.62.2': - resolution: {integrity: sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==} + '@rollup/rollup-linux-arm64-gnu@4.62.3': + resolution: {integrity: sha512-LLLFZKt4/Nraf9rxDkhiU8QVgLF4WmCkfr0L4fj0fPfIZFBib0DeiFk1hhaYKd03LFAFJcxHslhDFlNJLylf5Q==} cpu: [arm64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm64-musl@4.62.2': - resolution: {integrity: sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==} + '@rollup/rollup-linux-arm64-musl@4.62.3': + resolution: {integrity: sha512-WJkdQCvS9sWNOUBJZfQRKpZGFBztRzcowI+nndmflKgU4XY+3a420FgTOSKTsVqJbnzSxeT4vaJalpOaPo2YCQ==} cpu: [arm64] os: [linux] libc: [musl] - '@rollup/rollup-linux-loong64-gnu@4.62.2': - resolution: {integrity: sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==} + '@rollup/rollup-linux-loong64-gnu@4.62.3': + resolution: {integrity: sha512-PwHXCCS2n64/1Ot6rP1YEYA02MGYBcQlr8CSZZyrUG2O7NH6NklYmvr9v3Jy+5e/eDeNchc/ukmKJi9LuflMIQ==} cpu: [loong64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-loong64-musl@4.62.2': - resolution: {integrity: sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==} + '@rollup/rollup-linux-loong64-musl@4.62.3': + resolution: {integrity: sha512-vUjxINQu3RC8NZS3ykk1gN65gIz8pAopOq2HXuZhiIxHdx7TFvDG+jgrdSgInu1Eza4/Rfi2VzZgyIgEH4WOaw==} cpu: [loong64] os: [linux] libc: [musl] - '@rollup/rollup-linux-ppc64-gnu@4.62.2': - resolution: {integrity: sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==} + '@rollup/rollup-linux-ppc64-gnu@4.62.3': + resolution: {integrity: sha512-wzko4aJ13+0G3kGnviCg5gnXFKd40izKsrf2uOw12US4XqprkDrmwOpeW14aSNa37V8bfPcz5Fkob6LZ3BAPmA==} cpu: [ppc64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-ppc64-musl@4.62.2': - resolution: {integrity: sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==} + '@rollup/rollup-linux-ppc64-musl@4.62.3': + resolution: {integrity: sha512-8120ue0JUMSwy11stlwnfdX3pPd+WZYGCDBwEHWtIHi6pOpZmsEF5QKB7a/UN+XFdqvobxz98kv8RTqikyCEBw==} cpu: [ppc64] os: [linux] libc: [musl] - '@rollup/rollup-linux-riscv64-gnu@4.62.2': - resolution: {integrity: sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==} + '@rollup/rollup-linux-riscv64-gnu@4.62.3': + resolution: {integrity: sha512-XLFHnR3tXMjbOCh2vtVJHmxt+995uJsTERQyseFDRA0xxMxyTZPLa3OIUlyFaO4mF/Lu0FjmWHCuPXJT1n/IOg==} cpu: [riscv64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-riscv64-musl@4.62.2': - resolution: {integrity: sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==} + '@rollup/rollup-linux-riscv64-musl@4.62.3': + resolution: {integrity: sha512-se6yXvNGMIl0f+RQzyh7XAmia8/9kplQx424wnG2w0C1oi6XgO6Y8otKhdXFHbHs88Ihavzmvh1NWjuovE76BQ==} cpu: [riscv64] os: [linux] libc: [musl] - '@rollup/rollup-linux-s390x-gnu@4.62.2': - resolution: {integrity: sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==} + '@rollup/rollup-linux-s390x-gnu@4.62.3': + resolution: {integrity: sha512-gNoxRefktVIiGflpONuxWWXZAzIQG++z9qHO3xKwk4WdDMuQja3JHGfE1u0i3PfPDyvhypdk+WrgIJqLhGG7sg==} cpu: [s390x] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-gnu@4.62.2': - resolution: {integrity: sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==} + '@rollup/rollup-linux-x64-gnu@4.62.3': + resolution: {integrity: sha512-V4KtWtQfAFMU7+9/A/VDps/VI8CHd3cYz0L8sgJzz8qK7eY7wI4ruFD82UYIYvW9Z4DtlTfhQcsl4XyPHW5uSg==} cpu: [x64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-musl@4.62.2': - resolution: {integrity: sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==} + '@rollup/rollup-linux-x64-musl@4.62.3': + resolution: {integrity: sha512-LBx9LYXvj2CBkMkjLdNAWLwH0MLMin7do2VcVo9kVPibGLkY0BQQut2fv7NVqkXqZ/CrAu9LqDHVV1xHCMpCPw==} cpu: [x64] os: [linux] libc: [musl] - '@rollup/rollup-openbsd-x64@4.62.2': - resolution: {integrity: sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==} + '@rollup/rollup-openbsd-x64@4.62.3': + resolution: {integrity: sha512-ABVf3Q0RCu7NcyCCOZQI0pJ3GuSdfSl8EXcy88QtdceIMIoCUdfhsJChZ64L9zVM2aJHjde1Bhn5uqSRcX9ySA==} cpu: [x64] os: [openbsd] - '@rollup/rollup-openharmony-arm64@4.62.2': - resolution: {integrity: sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==} + '@rollup/rollup-openharmony-arm64@4.62.3': + resolution: {integrity: sha512-+2Cy/ldweGBLlPIKsQLF8U5N44a0KDdbrk1rAjHOM9M2K+kGdIVjHLmmrZIcx+9Ny3ke/1JomCsDI1ocb11+sg==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.62.2': - resolution: {integrity: sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==} + '@rollup/rollup-win32-arm64-msvc@4.62.3': + resolution: {integrity: sha512-dtZvzc8BedpSaFNy75x6uiWwAGTH+aZHDtdrqP6qk+WcLJrfti6sGje1ZJ9UxyzDLF23d/mV+PaMwuC0hL7UVA==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.62.2': - resolution: {integrity: sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==} + '@rollup/rollup-win32-ia32-msvc@4.62.3': + resolution: {integrity: sha512-Rj8Ra4noo+aYy7sKBggCx0407mws34kAb1ySyWuq5DAtFBQdkSwnsjCgPrhPe9cvgBKZIukpE+CVHvORCS93kQ==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.62.2': - resolution: {integrity: sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==} + '@rollup/rollup-win32-x64-gnu@4.62.3': + resolution: {integrity: sha512-vp7N084ew/odXn2gi/mzm9mUkQu9l6AiN6dt4IeUM2Uvm9o+cVmP+YkqbMOteLbiGgqBBlJZjIMYVCfOOIVbVQ==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.62.2': - resolution: {integrity: sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==} + '@rollup/rollup-win32-x64-msvc@4.62.3': + resolution: {integrity: sha512-MOG/3gTOn4Fwf574RVOaY61I5o6P90legkFADiTyn1hyjNydT+cerU2rLUwPdZkKKyJ+iT+K9p7WXK4LM1Ka6g==} cpu: [x64] os: [win32] - '@shikijs/core@4.3.0': - resolution: {integrity: sha512-EooU3i9F6IAE8kEu+AnGf9DFZWkQBZ+hJn3tLVbsH+61mtQiva5biai66fAA6nvFPXkLgvrh7BrR7YcJU83xQQ==} + '@shikijs/core@4.4.1': + resolution: {integrity: sha512-VeR2CY6Nn9/WbisoYLOQZ7HZOnwTrpBuOw4wExjqLnBCi62BNWynBUO6K2uPIASPFJwAv7cX1fUu+LrPlSstcw==} engines: {node: '>=20'} - '@shikijs/engine-javascript@4.3.0': - resolution: {integrity: sha512-hTv/KiFf2tpiqlACPiztGGurEARWIutB8YUhcrA1pUC7VzzwKO+g5crUocrLztrZ5ro5Z4hbXg7bYclETn3gSQ==} + '@shikijs/engine-javascript@4.4.1': + resolution: {integrity: sha512-6U4lJBh8LTvIkEVqRHv/rr3ruwtO6IweFQt1ME1ntHJMGHS+6N86vfYGO1o8c/DtOCTia2lfhdQBtBrps1sDfQ==} engines: {node: '>=20'} - '@shikijs/engine-oniguruma@4.3.0': - resolution: {integrity: sha512-1vMdN3gHfnKfLYwecUI2ITJI4RhHt96xEaJumVn7Heb0IlJ8WQMIH0Voak+2j22BpSNKdnOfB/pCTPnPm2gq7A==} + '@shikijs/engine-oniguruma@4.4.1': + resolution: {integrity: sha512-p23RugMKss0r5DAtRJW1yAXUDl60JvhQYV20yuxei//26JyDSJefV3umyWzzwep2weblMnJGDYahuti6XkcMgA==} engines: {node: '>=20'} - '@shikijs/langs@4.3.0': - resolution: {integrity: sha512-rnlqFbBRSys9bT4gl/5rw9RnS0W/I84ZldXPkO7cvlEMoV85TyF/aU01N7/NbSR776RNLjrJKjfFUXJR6wN1Cg==} + '@shikijs/langs@4.4.1': + resolution: {integrity: sha512-xb2kCMloBCIraIy2fS5MW0t/BxVY3q2nDyQKBoeSeq6KNrQbShHetCFlw2n35fGIJ6t3+hXDLQogP5ir9O9bvA==} engines: {node: '>=20'} - '@shikijs/primitive@4.3.0': - resolution: {integrity: sha512-CPkz64PTa5diRW1ggzMZH9VM/du4RNChYgVtgqrFcgruvIybmCvySv8GkiHSczUHXYuuR8TdKEwFx+UnZMpgdg==} + '@shikijs/primitive@4.4.1': + resolution: {integrity: sha512-ko2OfDoG89YuQ7xL5LtcQiWKb7NIv1Ephb7g48TVU198OzAMLC8lXVEwaJGHK4sUMYrfAGJDqYmNLOLiW/Kz8w==} engines: {node: '>=20'} - '@shikijs/themes@4.3.0': - resolution: {integrity: sha512-Avgt05YiT+Y3prjIc9lmQxhJzHBcCfR6cjiFW4OyaMBbt2A6trX5rfjUzx+Vj/mE9qpArYjatnqo9XPjQNW/AQ==} + '@shikijs/themes@4.4.1': + resolution: {integrity: sha512-wudOaoFro+/Zl9gQv2W1Ur5XlVduqvTuYLI483Xi0wgc1A+cy1hfB2r6ac6ufBgF+ID7KJEW7L41MHrzQ4wH+w==} engines: {node: '>=20'} - '@shikijs/transformers@4.3.0': - resolution: {integrity: sha512-5/elhJEcUrxdyQ95SSx0HzrnbzVPuipk6TYiXZL67tHhw8J+4N5shzmrTYyCaudiSnpuuwPdpaVtciwRFwSA7A==} + '@shikijs/transformers@4.4.1': + resolution: {integrity: sha512-Sb9Eehas+5EhClpFgNuklwY3aWf354FLaKRCiAWmjdNbHAjoQUpv6WmSj+N19eTXO6GLIWh1dIOH9dxyauhVWw==} engines: {node: '>=20'} - '@shikijs/types@4.3.0': - resolution: {integrity: sha512-oc8b9U2SYvofKZk8e/737nIX0qwf6eV2vHFATeObAu7r+mUVpLs8Re0BmVkIjAWAYgkmG/CzLNo7rzuBzRu/wQ==} + '@shikijs/types@4.4.1': + resolution: {integrity: sha512-GOwCLQDHM5EjGUWNPrhzJbr6JP8V/Dx/CDVkWvbZ1Avw5JFnNUckrgbLmE07qtg4WlW7Q7QFndhjIkeU9XMPvw==} engines: {node: '>=20'} '@shikijs/vscode-textmate@10.0.2': @@ -1005,21 +1046,29 @@ packages: '@simple-git/argv-parser@1.1.1': resolution: {integrity: sha512-Q9lBcfQ+VQCpQqGJFHe5yooOS5hGdLFFbJ5R+R5aDsnkPCahtn1hSkMcORX65J2Z5lxSkD0lQorMsncuBQxYUw==} - '@simple-libs/child-process-utils@1.0.2': - resolution: {integrity: sha512-/4R8QKnd/8agJynkNdJmNw2MBxuFTRcNFnE5Sg/G+jkSsV8/UBgULMzhizWWW42p8L5H7flImV2ATi79Ove2Tw==} - engines: {node: '>=18'} + '@simple-libs/child-process-utils@2.0.0': + resolution: {integrity: sha512-dvNoRKLijXnD0XoJAz94pbNuB5GQgDr55UhpSPhffDkTT0Cmcqh9jSCOtwfT2d4H6MI9E7c4SgtMuJXZ6F3c6A==} + engines: {node: '>=22'} - '@simple-libs/hosted-git-info@1.0.2': - resolution: {integrity: sha512-aAmGQdMH+ZinytKuA2832u0ATeOFNYNk4meBEXtB5xaPotUgggYNhq5tYU/v17wEbmTW5P9iHNqNrFyrhnqBAg==} - engines: {node: '>=18'} + '@simple-libs/hosted-git-info@2.0.0': + resolution: {integrity: sha512-55XwK/GYgV58PuN8lZFhI1qRxdKoMLJocXl/yM1EPqazFDmM4QWY7q6BxPCPDNKTNunj794DSD4h0H7SrqUdMg==} + engines: {node: '>=22'} - '@simple-libs/stream-utils@1.2.0': - resolution: {integrity: sha512-KxXvfapcixpz6rVEB6HPjOUZT22yN6v0vI0urQSk1L8MlEWPDFCZkhw2xmkyoTGYeFw7tWTZd7e3lVzRZRN/EA==} - engines: {node: '>=18'} + '@simple-libs/normalize-package-data@1.0.0': + resolution: {integrity: sha512-/EOmFBekV9tGee8gac/k+5Ox3twkypNqh5TfxA9vTkmcJkjm6f1xqrlstDNOrEhTvnYyVtU6Du2ZhY/IV1+9GA==} + engines: {node: '>=22'} + + '@simple-libs/stream-utils@2.0.0': + resolution: {integrity: sha512-fCTuZK4QBa+39Oz9l4OGfJfz+GpwCp3AqO7Zch3to99xHPgstVsRFpeQ8LNd2o1Gv8raL2mCFwiaHh7bFSp5DQ==} + engines: {node: '>=22'} '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@tokenizer/inflate@0.4.1': + resolution: {integrity: sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==} + engines: {node: '>=18'} + '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} @@ -1041,8 +1090,8 @@ packages: '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} - '@types/hast@3.0.4': - resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + '@types/hast@3.0.5': + resolution: {integrity: sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==} '@types/jquery@4.0.1': resolution: {integrity: sha512-9a59A/tycXgYuPABcp6/3spSShn0NT2UOM4EfHvMumjYi4lJWTsK5SZWjhx3yRm9IHGCeWXdV2YfNsrWrft/CA==} @@ -1059,15 +1108,6 @@ packages: '@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@4.0.0': - resolution: {integrity: sha512-GmD8OECLfzPHv8VyvFRzslqdwXoDBJ2H40fxXFjrarbqvJZSB/BJKZXN5e3k7Mx7GQanSNzTYhzeS3H9o0gAOw==} - - '@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==} @@ -1083,21 +1123,15 @@ packages: '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - '@types/node@24.13.2': - resolution: {integrity: sha512-fRa09kZTgu8o71KFcDjUFuc7F+dEbZYZmkI0mg5YBTRs0yMKjYHsq/c0urDKeDb+D5qVgXOdFcuu+DZPKOITwA==} - - '@types/node@25.9.4': - resolution: {integrity: sha512-dszCsrKb5U7ZsVZBWiHFklTloVl0mSEnWH/iZXfZUlI4rzCUnsvGmgqfuVRHL54ugE7/wRuxEIXRa2iMZ+BG6g==} + '@types/node@24.13.3': + resolution: {integrity: sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==} - '@types/normalize-package-data@2.4.4': - resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + '@types/node@26.1.2': + resolution: {integrity: sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg==} '@types/picomatch@4.0.3': resolution: {integrity: sha512-iG0T6+nYJ9FAPmx9SsUlnwcq1ZVRuCXcVEvWnntoPlrOpwtSTKNDC9uVAxTsC3PUvJ+99n4RpAcNgBbHX3JSnQ==} - '@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==} @@ -1113,21 +1147,21 @@ packages: '@types/web-bluetooth@0.0.21': resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==} - '@ungap/structured-clone@1.3.2': - resolution: {integrity: sha512-5jsZFwgR5rTdKwidH9Qmat75RKwqfpKlWWB1frDkljN127mwqBu8K0PYo7/hFpF03IEJpfVPpCQDY/eDx3iHvA==} + '@ungap/structured-clone@1.3.3': + resolution: {integrity: sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==} - '@vitejs/plugin-vue@6.0.7': - resolution: {integrity: sha512-km+p+XdSz9Sxm5rqUbqcSfZYaAniKxWBj1KURl+Jr7UaPvvX7BmaWMdP69I5rrFDeQGyxAG7NXdc57vz+snhWg==} + '@vitejs/plugin-vue@6.0.8': + resolution: {integrity: sha512-0ZjgOg7oO6farnNGup7yvoM/YXZV84OZxHAwtflItNa/6zzQyVb5LNxyea3FEKEX2XlagIKzrlH7wwxkKgtiew==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 vue: ^3.2.25 - '@vitest/expect@4.1.9': - resolution: {integrity: sha512-vl/rYsUKcBr3SnQn166+XR5ZQcgMx3DQhFWdfli/cWpLnLUmbxZvyrJZotLFUryib+LtArYMSTJ5RbQ57ZqrlA==} + '@vitest/expect@4.1.10': + resolution: {integrity: sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==} - '@vitest/mocker@4.1.9': - resolution: {integrity: sha512-EVkXzBjrPGM+cK8/ANWgBrkUCfJfb38/EfTSO8h7pWvKkyPkpWxvR7BkD2MyItMF62C97zAEoqdpUixwR/e+Rw==} + '@vitest/mocker@4.1.10': + resolution: {integrity: sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==} peerDependencies: msw: ^2.4.9 vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -1137,20 +1171,20 @@ packages: vite: optional: true - '@vitest/pretty-format@4.1.9': - resolution: {integrity: sha512-s0iufns3iIFitdgm+YR7g1whCAaGtXz459VS9/PqyKDEEFgYIhsHOQmXgIgDuYCt7DeQmiZT0Qe2OA2p4ZPu5A==} + '@vitest/pretty-format@4.1.10': + resolution: {integrity: sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==} - '@vitest/runner@4.1.9': - resolution: {integrity: sha512-KXLMDtc7oe70+3mJfGrPUWPesswH+3sTxAMAMl8DG7I8IUQT4XW718dY5ID3vPUcmlu27CcKfY4P3h3I29SLJg==} + '@vitest/runner@4.1.10': + resolution: {integrity: sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==} - '@vitest/snapshot@4.1.9': - resolution: {integrity: sha512-Jc7RKGNBo8Z28WYIm0Niej4xdSPByRf6mU58VpHQkd6Zh05rlnA+twjbK5HyeIGHxrzsc3mJgS43uM0CZKzaIA==} + '@vitest/snapshot@4.1.10': + resolution: {integrity: sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==} - '@vitest/spy@4.1.9': - resolution: {integrity: sha512-fHpsS6mIi+PiEW+vcRVOMkX1oSaPKne3VOclSFICPcGOmfKgXPU5iAah+wcNcj2xPrCCmfq99IDGf+EojhhvhA==} + '@vitest/spy@4.1.10': + resolution: {integrity: sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==} - '@vitest/utils@4.1.9': - resolution: {integrity: sha512-A51o8ymO5PpqlWNnBP9ZHPXDIpuMtTLlGSjN7la4US+LJzoUMyhwjA5QXlm39JexgwHKW4Xjs8Z2d3dLCXOeuA==} + '@vitest/utils@4.1.10': + resolution: {integrity: sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==} '@volar/language-core@2.4.28': resolution: {integrity: sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==} @@ -1161,54 +1195,52 @@ packages: '@volar/typescript@2.4.28': resolution: {integrity: sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==} - '@vue/compiler-core@3.5.39': - resolution: {integrity: sha512-16KBTEXAJCpDr0mwlw+AZyhu8iyC7R3S2vBwsI7QnWJU6X3WKc9VKeNEZpiMdZ569qWhz9574L3vV55qRL0Vtw==} + '@vue/compiler-core@3.5.40': + resolution: {integrity: sha512-39E8IgOhTbVDnoJFMKc2DvYnypcZwUqgUhQkccva/0m6FUwtIKSGV7n1hpVmYcFaoRAwf9pBcwnKlCEsN63ZEQ==} - '@vue/compiler-dom@3.5.39': - resolution: {integrity: sha512-oQPigALqYbNxTNPvNgSOe+czwVExfbVF02lz8jP0S3AXJiu3jxYDygNUiqSep4ezzW8XgnubqH63My2A7JR/vg==} + '@vue/compiler-dom@3.5.40': + resolution: {integrity: sha512-pwkx4vqlqOspFstrcmzwkKLePVMD3PT65imRzLhanU2V1Fj4K13g6OXjanOyzw3aTAuRk84BOmY8f3rEHqPaVA==} - '@vue/compiler-sfc@3.5.39': - resolution: {integrity: sha512-d0ki86iOyN8LoZPBmk5SJWNwHP19CnDDCfuo//+2WJa2g5Ke0Jay983PIBIcSSzldC68I8DrD5GrHV3OSDfodg==} + '@vue/compiler-sfc@3.5.40': + resolution: {integrity: sha512-gIf497P4kpuALcvs5n3AEg1Vdn0pSY4XbjASIfHNYF1/MP3T2Mf2STERTubysBxCRxzJGJYtF/O7vwJrxFB3Vw==} - '@vue/compiler-ssr@3.5.39': - resolution: {integrity: sha512-Ce7/wvwMHai74bdszfXExdazFigYnlF9zgCmEQUcM1j0fOymlouZ7XilTYNo8oUjhlnjYOZbGrcYKuqjz89Ucw==} + '@vue/compiler-ssr@3.5.40': + resolution: {integrity: sha512-rrE5xiXG663+vHCHa3J9p2z5OcBRjXmoqenprJxAFQxg5pSshzeBiCE6pu46axapRJ2Adk0YDA2BRZVjiHXnhg==} - '@vue/devtools-api@8.1.4': - resolution: {integrity: sha512-zphdXRe0VxWfUWH2KLcNV4xWUMxjxASyxCjFS/wRHVYfJCMBulq1ce3RHGkYRxghoVBqwCzOw1TWIIfvIWCY1w==} + '@vue/devtools-api@8.2.1': + resolution: {integrity: sha512-6u4vXBlIBAC1wMplIZgpyPn7uh/s4Bf6F5bMzvLv+EdJ0aHs/+4B7Ygv864EStQSjRbsRzTko/kUG1A1IejQ3A==} - '@vue/devtools-kit@8.1.4': - resolution: {integrity: sha512-+GLBwY63hZ46sqTlgXgvd8IcZTpWe0PZzbJgs63ii/8uTYVwg1q9bdIR9xx8ReKcrdWS01RGCbC971jYPvjRCA==} + '@vue/devtools-kit@8.2.1': + resolution: {integrity: sha512-FIGIuq3AWReEpbAHY/cRGeHDfI0qOb8OCQ3YjbEAX04uaxIDbGc9rhkbVcG7rnfHPXE3RsU5KrWOu9V/okd8AQ==} - '@vue/devtools-shared@8.1.4': - resolution: {integrity: sha512-Earc/zrg0w0Md4KdrvgRR1vC5F17Zn+VzqTNI7PXYXz0fPJDVWENe7fv6NHi6Ja9Sq6Ce6SYUdc2FlXU0OMkjQ==} + '@vue/devtools-shared@8.2.1': + resolution: {integrity: sha512-Fkac7lUdGReh6pVOi3AYPRGe82LQqRmAfThW7RRligOAP0ZA/Z1z9XLHDM9dv34pV2HRc79DK8uKPeG2fLnA/g==} - '@vue/language-core@3.3.5': - resolution: {integrity: sha512-UkKu5nhX89fg4VhlG/FOeI10G3cj/7radKT/cy9BT4Q9qJmJlSTAc/dP63Xqs29aypN4f39xUV6PsLNk/dcD6g==} + '@vue/language-core@3.3.9': + resolution: {integrity: sha512-in/68oAa4BCtVY6n/nkuhLIkV8DHYd2UivedJ6cMZ6UYtlq9jaoaSNUBHYCVO44z3nKg7MdE5OBoHKt5SxeBKQ==} - '@vue/reactivity@3.5.39': - resolution: {integrity: sha512-TpsuBJ9gGlZa5d23XcM2y8EXanz9dZeVDQBXRwzy46ItgvM+rWpzs+UVM0wcRLxGvcav0HE5jz2gNL53xlRAog==} + '@vue/reactivity@3.5.40': + resolution: {integrity: sha512-B7ot9UlUZOi1zbq61/LvE88ZLTV8IlajTdiZTAEiDQgrnIMIZoPr9kGw0Zw46ObW62O9+H/Be3kMbfb7kYPQZA==} - '@vue/runtime-core@3.5.39': - resolution: {integrity: sha512-9GLtNyRvPAUMbX+7ono0RC2j0guo2LXVi8LvcmAooImACUKm0oFf0jjwbX8/H0AE/t1nxhAkn8RSl9PMCzzxZw==} + '@vue/runtime-core@3.5.40': + resolution: {integrity: sha512-KAZLweuZ6uUJPK1PMSQPgBU5gCjgrrfjUhSglmU9NhH+Zjepa8cnwSydPWDWHDwOgY4g3VcZ+PljbiHlURNCbw==} - '@vue/runtime-dom@3.5.39': - resolution: {integrity: sha512-7Y6aAGboKcXAZ3ECuUy7RrS5yy2r47dhTp2SKaJmYxjopImaVFaNa5Ne66NwGovsrxVAl5S5rwc7m22UG7Lmww==} + '@vue/runtime-dom@3.5.40': + resolution: {integrity: sha512-ZfrX8ssZQds900L9pr8AuK05ddnMsR4MPMZr8cPN9GoqoPWcXLhjvvbIA2SMv+7a97sJ1vv9pj/zxK0Cq/eEFQ==} - '@vue/server-renderer@3.5.39': - resolution: {integrity: sha512-yZSakiAGw85rZfG7UM8akMnIF+FmeiNk47uvHf2nVBBSe+dIKUhZuZq9+XgJhbV3nS5Z4ALH23/MpXofW+mbcw==} - peerDependencies: - vue: 3.5.39 + '@vue/server-renderer@3.5.40': + resolution: {integrity: sha512-XNJym9WpevhTVt1HuwOrCRJ5Q+9z4BjTMrDtjTrvx74SmUll8spNTw6whWJa9mEkO4PKn5TihI/bm/8ds2QVJw==} - '@vue/shared@3.5.39': - resolution: {integrity: sha512-l1rrBtBfTnmxvtsvdQDXltUUy8S1Y+ZaqdfUzmAnJkTd8Z8rv5v/ytW+TKiqEOWyHPoqtPlNFSs0lhRmYVSHVA==} + '@vue/shared@3.5.40': + resolution: {integrity: sha512-WxnBtruIqOoV3rA4jeKDWzrYI5h7Cp4+pjwDi8kWGHz+IslhiN+wguLVVhtv2l8VoU02rzDCVfDjgCl1lNpZVg==} - '@vueuse/core@14.3.0': - resolution: {integrity: sha512-aHfz47g0ZhMtTVHmIzMVpJy8ePhhOy68GY5bv110+5DVtZ+W7BsOx+m61UNQqfrWyPztIHIanWa3E2tib3NFIw==} + '@vueuse/core@14.4.0': + resolution: {integrity: sha512-X4WHz1HlCzCBoYXesUkifzzWBAcZgXG8Fi5iNPQg/epdzOB3gu8Fawj3hvuwYR1nGcXGnvxwYYcUC/71++svtQ==} peerDependencies: vue: ^3.5.0 - '@vueuse/integrations@14.3.0': - resolution: {integrity: sha512-76I5FT2ESvCmCaSwapI+a/u/CFtNXmzl9f9lNp1hRtx8vKB8hfiokJr8IvQqcQG5ckGXElyXK516b54ozV3MvA==} + '@vueuse/integrations@14.4.0': + resolution: {integrity: sha512-oJz9qTgczvA7L1nXQFRU7h8tQbOCoiceqvMMhT9XYMyOGTqLJ2rEa09PON+nD2t48sZUfeOmg4eaWJXV4sZb/w==} peerDependencies: async-validator: ^4 axios: ^1 @@ -1249,11 +1281,11 @@ packages: universal-cookie: optional: true - '@vueuse/metadata@14.3.0': - resolution: {integrity: sha512-BwxmbAzwAVF50+MW57GXOUEV61nFBGnlBvrTqj49PqWJu3uw7hdu72ztXeZ33RdZtDY6kO+bfCAE1PCn88Tktw==} + '@vueuse/metadata@14.4.0': + resolution: {integrity: sha512-swx/255R6JyHZFJhx845iz5CRWDZdCfvkZOpACWc5+c5WHcG24mv8gUT1WIdFQaHt6dq79rvILd9QnCWiyVm9g==} - '@vueuse/shared@14.3.0': - resolution: {integrity: sha512-bZpge9eSXwa4ToSiqJ7j6KRwhAsneMFoSz3LMWKQDkqimm3D/tbFlrklrs/IOqC8tEcYmXQZJ6N0UrjhBirVCg==} + '@vueuse/shared@14.4.0': + resolution: {integrity: sha512-JRgY90Sz8DDtPMsaDflvPMp9xYk69JZAmbuDvAquUVXKr2gEjqtzGNTTthLfckH0BzBqvnu31gb4a8TGLRe79g==} peerDependencies: vue: ^3.5.0 @@ -1261,10 +1293,6 @@ packages: resolution: {integrity: sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw==} engines: {node: '>=14.6'} - abort-controller@3.0.0: - resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} - engines: {node: '>=6.5'} - agent-base@6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} @@ -1276,10 +1304,6 @@ packages: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} - ansi-escapes@7.3.0: - resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==} - engines: {node: '>=18'} - ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -1292,10 +1316,6 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - ansi-styles@6.2.3: - resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} - engines: {node: '>=12'} - arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} @@ -1305,8 +1325,9 @@ packages: 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==} + argue-cli@3.1.0: + resolution: {integrity: sha512-DhBpBfXL4SS2uC0N922MMajKR3CdrTG0u2or1PNYgXMsrSzViJrbtvT0nCLlLGUI0plam/ZZCs7aAauHtW9thw==} + engines: {node: '>=22'} assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} @@ -1315,8 +1336,8 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - axios@1.18.1: - resolution: {integrity: sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==} + axios@1.19.0: + resolution: {integrity: sha512-ht/iuYZXEjFxLH/Hkezgd7m6JKlHHXEUSneaDz8uZe1Gj5QZtCnpyDsckvAiEnT89OEbCLmnte4R4sn7P0EKFw==} bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} @@ -1325,26 +1346,20 @@ packages: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} - base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - birpc@2.9.0: resolution: {integrity: sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==} boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - brace-expansion@5.0.6: - resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} - engines: {node: 18 || 20 || >=22} + brace-expansion@5.0.9: + resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==} + engines: {node: 20 || >=22} 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'} @@ -1392,10 +1407,6 @@ packages: resolution: {integrity: sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw==} engines: {node: '>=18.20'} - cli-truncate@5.2.0: - resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==} - engines: {node: '>=20'} - cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -1407,9 +1418,6 @@ packages: 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'} @@ -1421,10 +1429,6 @@ packages: resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} engines: {node: '>=18'} - commander@14.0.3: - resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} - engines: {node: '>=20'} - commander@6.2.1: resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} engines: {node: '>= 6'} @@ -1432,34 +1436,31 @@ packages: commondir@1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - compare-func@2.0.0: - resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} + conventional-changelog-angular@9.2.1: + resolution: {integrity: sha512-oWSL6ZhnXbYraOFTK3PgRAQJ8fADDAEv5K6AdeyQPLvjFmhG8+ejL0jZZp/R7vTmGJaBvZEE+sE7dB4bCv7sAw==} + engines: {node: '>=22'} - conventional-changelog-angular@8.3.1: - resolution: {integrity: sha512-6gfI3otXK5Ph5DfCOI1dblr+kN3FAm5a97hYoQkqNZxOaYa5WKfXH+AnpsmS+iUH2mgVC2Cg2Qw9m5OKcmNrIg==} - engines: {node: '>=18'} + conventional-changelog-preset-loader@6.0.1: + resolution: {integrity: sha512-GZ8E3RQzXQb3JFy0pKl8oeSf7ENIhvAMvJr+PlWkavZOesLHHdhkfNJ4SvW35eo1Fu2+EyVxWQ1tVvtzAG2iWg==} + engines: {node: '>=22'} - conventional-changelog-preset-loader@5.0.0: - resolution: {integrity: sha512-SetDSntXLk8Jh1NOAl1Gu5uLiCNSYenB5tm0YVeZKePRIgDW9lQImromTwLa3c/Gae298tsgOM+/CYT9XAl0NA==} - engines: {node: '>=18'} - - conventional-changelog-writer@8.4.0: - resolution: {integrity: sha512-HHBFkk1EECxxmCi4CTu091iuDpQv5/OavuCUAuZmrkWpmYfyD816nom1CvtfXJ/uYfAAjavgHvXHX291tSLK8g==} - engines: {node: '>=18'} + conventional-changelog-writer@9.2.0: + resolution: {integrity: sha512-eACD5BaAQCYjeI3RExkCZopNaaIuXzCP4kaAb2lEFXcGa/KOuxJfj8v/SnjhvF6377pYn0A2Gji+6GhwUK8rEA==} + engines: {node: '>=22'} hasBin: true - conventional-changelog@7.2.1: - resolution: {integrity: sha512-smcpqCeNRCAoL586/Iql8GfVsduP1JDrr7SAzKHWM5C5voDzKhc3QtqwVWeKMhvVw4iYfAr+znz1TF4kPXVm3A==} - engines: {node: '>=18'} + conventional-changelog@8.1.0: + resolution: {integrity: sha512-idt1JK+3+Nt7gqH/d/sEYWdDeR+5XPov/jssmFN6XxmYSRlonTWSDWhWUPkmm0zbwYjtVdt+4My5aiPkKyvocw==} + engines: {node: '>=22'} hasBin: true - conventional-commits-filter@5.0.0: - resolution: {integrity: sha512-tQMagCOC59EVgNZcC5zl7XqO30Wki9i9J3acbUvkaosCT6JX3EeFwJD7Qqp4MCikRnzS18WXV3BLIQ66ytu6+Q==} - engines: {node: '>=18'} + conventional-commits-filter@6.0.1: + resolution: {integrity: sha512-cs+LadpH7Kpw0M3k8wurk+sOVVDAENA0iK4OBOrkL94j5lEVYRJ4j3zd2bhY9qgzyrPqthdcYT3axzRN7AliMg==} + engines: {node: '>=22'} - conventional-commits-parser@6.4.0: - resolution: {integrity: sha512-tvRg7FIBNlyPzjdG8wWRlPHQJJHI7DylhtRGeU9Lq+JuoPh5BKpPRX83ZdLrvXuOSu5Eo/e7SzOQhU4Hd2Miuw==} - engines: {node: '>=18'} + conventional-commits-parser@7.1.1: + resolution: {integrity: sha512-B0f42jI++V5Vb7qK+DDw68r0dNxz5hk+RdKUkx2NOi39emc9hsHa3u2M3doF7QQhRFzCrAj7uM90teG+RBTaYQ==} + engines: {node: '>=22'} hasBin: true convert-source-map@2.0.0: @@ -1548,26 +1549,13 @@ packages: 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.6.0: - resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} - 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==} @@ -1579,10 +1567,6 @@ packages: resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} 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'} @@ -1594,8 +1578,8 @@ packages: es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} - es-module-lexer@2.3.0: - resolution: {integrity: sha512-KLdwQm2NvGLDkQDCGvmiQrhkd0JbMzXthwQAUgWjQuQdBLFa3eiBP5arXZyA+f8x+x7OXgud6bq2rxjGtHV2tw==} + es-module-lexer@2.3.1: + resolution: {integrity: sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==} es-object-atoms@1.1.2: resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} @@ -1637,17 +1621,6 @@ packages: 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.4: - resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} - - events@3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} - expect-type@1.4.0: resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} engines: {node: '>=12.0.0'} @@ -1690,9 +1663,9 @@ packages: picomatch: optional: true - file-type@18.7.0: - resolution: {integrity: sha512-ihHtXRzXEziMrQ56VSgU7wkxh55iNchFkosu7Y9/S+tXHdKyrGjVK0ujbqNnsxzea+78MaLhN6PGmfYSAv1ACw==} - engines: {node: '>=14.16'} + file-type@21.3.4: + resolution: {integrity: sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g==} + engines: {node: '>=20'} fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} @@ -1750,10 +1723,6 @@ packages: 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-tsconfig@4.14.0: resolution: {integrity: sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==} @@ -1769,11 +1738,6 @@ packages: resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} engines: {node: '>=6.0'} - handlebars@4.7.9: - resolution: {integrity: sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==} - engines: {node: '>=0.4.7'} - hasBin: true - has-symbols@1.1.0: resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} @@ -1795,10 +1759,6 @@ packages: hookable@5.5.3: resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} - hosted-git-info@8.1.0: - resolution: {integrity: sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==} - engines: {node: ^18.17.0 || >=20.5.0} - html-void-elements@3.0.0: resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} @@ -1815,6 +1775,11 @@ packages: ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + image-size@2.0.2: + resolution: {integrity: sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w==} + engines: {node: '>=16.x'} + hasBin: true + import-meta-resolve@4.2.0: resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} @@ -1839,14 +1804,14 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-fullwidth-code-point@5.1.0: - resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} - engines: {node: '>=18'} - is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} + is-in-ssh@1.0.0: + resolution: {integrity: sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==} + engines: {node: '>=20'} + is-inside-container@1.0.0: resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} engines: {node: '>=14.16'} @@ -1863,10 +1828,6 @@ packages: 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'} @@ -1904,6 +1865,10 @@ packages: resolution: {integrity: sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog==} hasBin: true + js-yaml@4.3.0: + resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==} + hasBin: true + juice@8.1.0: resolution: {integrity: sha512-FLzurJrx5Iv1e7CfBSZH68dC04EEvXvvVvPYB7Vx1WAuhCp1ZPIMtqxc+WTWxVkpTIC2Ach/GAv0rQbtGf6YMA==} engines: {node: '>=10.0.0'} @@ -1913,96 +1878,88 @@ packages: 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'} - - lightningcss-android-arm64@1.32.0: - resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + lightningcss-android-arm64@1.33.0: + resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [android] - lightningcss-darwin-arm64@1.32.0: - resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + lightningcss-darwin-arm64@1.33.0: + resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] - lightningcss-darwin-x64@1.32.0: - resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + lightningcss-darwin-x64@1.33.0: + resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] - lightningcss-freebsd-x64@1.32.0: - resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + lightningcss-freebsd-x64@1.33.0: + resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] - lightningcss-linux-arm-gnueabihf@1.32.0: - resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + lightningcss-linux-arm-gnueabihf@1.33.0: + resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] - lightningcss-linux-arm64-gnu@1.32.0: - resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + lightningcss-linux-arm64-gnu@1.33.0: + resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] libc: [glibc] - lightningcss-linux-arm64-musl@1.32.0: - resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + lightningcss-linux-arm64-musl@1.33.0: + resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] libc: [musl] - lightningcss-linux-x64-gnu@1.32.0: - resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + lightningcss-linux-x64-gnu@1.33.0: + resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] libc: [glibc] - lightningcss-linux-x64-musl@1.32.0: - resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + lightningcss-linux-x64-musl@1.33.0: + resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] libc: [musl] - lightningcss-win32-arm64-msvc@1.32.0: - resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + lightningcss-win32-arm64-msvc@1.33.0: + resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] - lightningcss-win32-x64-msvc@1.32.0: - resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + lightningcss-win32-x64-msvc@1.33.0: + resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] - lightningcss@1.32.0: - resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + lightningcss@1.33.0: + resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} engines: {node: '>= 12.0.0'} - linkify-it@5.0.1: - resolution: {integrity: sha512-wVoTjP4Q6R0NW5hiZkVJaFZPWgtXfoGF+6LucL3/FtiNjmcHhYjEr5f1Kqjirc1nBW07J/ZuRFumqr2oqccEWg==} + linkify-it@5.0.2: + resolution: {integrity: sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==} - lint-staged@16.4.0: - resolution: {integrity: sha512-lBWt8hujh/Cjysw5GYVmZpFHXDCgZzhrOm8vbcUdobADZNOK/bRshr2kM3DfgrrtR1DQhfupW9gnIXOfiFi+bw==} - engines: {node: '>=20.17'} + lint-staged@17.3.0: + resolution: {integrity: sha512-woZS3vNe3UKqBaLPvbLOtKRY4tLANpWQhom12MGWqC8Mh1lCOO+WgSwmX2amjJAqTY9BkXYW87fCUH5H9Ph6xw==} + engines: {node: '>=22.22.1'} hasBin: true - listr2@9.0.5: - resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==} - engines: {node: '>=20.0.0'} - lodash._reinterpolate@3.0.0: resolution: {integrity: sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==} @@ -2020,18 +1977,11 @@ packages: resolution: {integrity: sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==} 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==} - lru-cache@10.4.3: - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - - lru-cache@11.5.1: - resolution: {integrity: sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==} + lru-cache@11.5.2: + resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==} engines: {node: 20 || >=22} magic-string@0.30.21: @@ -2040,21 +1990,9 @@ packages: 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-cjk-friendly@2.0.2: resolution: {integrity: sha512-KXCl6sd129UqkAiRDb+NcAHrxC9xRa2WsGIsMMvtp2y1YlbeIaNYzArX2zfDoGhOjsyNMfJrGO7xGBss27YQSA==} engines: {node: '>=18'} @@ -2065,17 +2003,11 @@ packages: '@types/markdown-it': optional: true - 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.2.0: - resolution: {integrity: sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==} + markdown-it@14.3.0: + resolution: {integrity: sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw==} hasBin: true markdown-title@1.0.2: @@ -2108,19 +2040,15 @@ packages: mdast-util-to-string@4.0.0: resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} - mdurl@2.0.0: - resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + mdurl@2.1.0: + resolution: {integrity: sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg==} 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'} + meow@14.1.0: + resolution: {integrity: sha512-EDYo6VlmtnumlcBCbh1gLJ//9jvM/ndXHfVXIFrZVr6fGcwTUyCTFNTLCKuY3ffbK8L/+3Mzqnd58RojiZqHVw==} + engines: {node: '>=20'} merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} @@ -2220,8 +2148,8 @@ packages: resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} engines: {node: '>=18'} - minimatch@10.2.5: - resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + minimatch@10.2.6: + resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} engines: {node: 18 || 20 || >=22} minimist@1.2.8: @@ -2243,19 +2171,16 @@ packages: muggle-string@0.4.1: resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} - nanoid@3.3.15: - resolution: {integrity: sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==} + nanoid@3.3.16: + resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - nanoid@5.1.16: - resolution: {integrity: sha512-kVrnsrJqMR8+oLJnGEmSWw9BivK5mt7H3FZatVRjrc5wGqFYuBxX1yG7+A7Gi5AefkX6t/oCkizcQgpu0cY1dQ==} - engines: {node: ^18 || >=20} + nanoid@6.0.0: + resolution: {integrity: sha512-mkUH+rPkwU2qPadJ0oJZOjeZ5Mxn8Q1UhevwkTRWNuUZzyia3h4rhzK39hxaHTk0o2OxB8W2SQ6A8k23ZDi1pQ==} + engines: {node: ^22 || ^24 || >=26} 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} @@ -2265,15 +2190,11 @@ packages: encoding: optional: true - normalize-package-data@7.0.1: - resolution: {integrity: sha512-linxNAT6M0ebEYZOx2tO6vBEFsVgnPpv+AVjk0wJHfaUIbq31Jm3T6vvZaarnOeWDh8ShnwXuaAyM7WT3RzErA==} - engines: {node: ^18.17.0 || >=20.5.0} - nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - obug@2.1.3: - resolution: {integrity: sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==} + obug@2.1.4: + resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==} engines: {node: '>=12.20.0'} onetime@7.0.0: @@ -2286,29 +2207,29 @@ packages: oniguruma-to-es@4.3.6: resolution: {integrity: sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==} - open-cli@8.0.0: - resolution: {integrity: sha512-3muD3BbfLyzl+aMVSEfn2FfOqGdPYR0O4KNnxXsLEPE2q9OSjBfJAaB6XKbrUzLgymoSMejvb5jpXJfru/Ko2A==} - engines: {node: '>=18'} + open-cli@9.0.0: + resolution: {integrity: sha512-4UHkLVm4tUM/ardg66uY3x1icgfCnunks5eFVFBzASO3b13Ow2Md3xs9YT7yXWFjXOBpauIeh/N9fvbziU1wkg==} + engines: {node: '>=22'} hasBin: true - open@10.2.0: - resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==} - engines: {node: '>=18'} + open@11.0.0: + resolution: {integrity: sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==} + engines: {node: '>=20'} ora@9.4.1: resolution: {integrity: sha512-6VlU9MLXbjVQD04AZCMX28hVtA5bUoadvUqO76MUCVA0ilwJbMiHsITRPfyVm6p/BC0Av/BXMujx39WCe1LEqw==} engines: {node: '>=20'} - p-map@7.0.4: - resolution: {integrity: sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==} + p-map@7.0.6: + resolution: {integrity: sha512-I4Prw6ivkd6p8PiYR1tXASOAOBzIJwu0TB7fqaX0c/8c3QAehNYmX57EijyGGGBt3c/BIowGwV03RVBtXvHEVg==} engines: {node: '>=18'} package-directory@8.2.0: resolution: {integrity: sha512-qJSu5Mo6tHmRxCy2KCYYKYgcfBdUpy9dwReaZD/xwf608AUk/MoRtIOWzgDtUeGeC7n/55yC3MI1Q+MbSoektw==} engines: {node: '>=18'} - package-manager-detector@1.6.0: - resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==} + package-manager-detector@1.8.0: + resolution: {integrity: sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==} parse5-htmlparser2-tree-adapter@6.0.1: resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} @@ -2332,10 +2253,6 @@ packages: pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - peek-readable@5.4.2: - resolution: {integrity: sha512-peBp3qZyuS6cNIJ2akRNG1uo1WJ1d0wTxg/fxMdZ0BqCVhx242bSFHM9eNqflfJVS9SsgkzgT/1UgnsurBOTMg==} - engines: {node: '>=14.16'} - perfect-debounce@2.1.0: resolution: {integrity: sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==} @@ -2346,18 +2263,18 @@ packages: resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} engines: {node: '>=8.6'} - picomatch@4.0.4: - resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + picomatch@4.0.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} engines: {node: '>=12'} - playwright-chromium@1.61.1: - resolution: {integrity: sha512-YK3K8JakUv5Hq5WjY6oU/XwuD/041s9XVtoTKTrZHYRY72DOAsni/iXye7iBS8lgYWUZENt/6tBnpmhaSg72ug==} - engines: {node: '>=18'} + playwright-chromium@1.62.1: + resolution: {integrity: sha512-yRMzeViD44qD1ZVMNupp82NJQNjumZ02W5r7+DmtD5+7aP9+v66a0PsAk63ewpVDH1GxMf/J/mO+TS1sTaK29w==} + engines: {node: '>=20'} hasBin: true - playwright-core@1.61.1: - resolution: {integrity: sha512-h7Qlt6m4REp25qvIdvbDtVmD4LqVXfpRxhORv9L0jzETM05p4fuPJ3dKyuSXQxDSbXnmS79HAgi9589lGSpLkg==} - engines: {node: '>=18'} + playwright-core@1.62.1: + resolution: {integrity: sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==} + engines: {node: '>=20'} hasBin: true polka@1.0.0-next.28: @@ -2374,31 +2291,23 @@ packages: resolution: {integrity: sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg==} engines: {node: '>=4'} - postcss@8.5.15: - resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} + postcss@8.5.25: + resolution: {integrity: sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==} engines: {node: ^10 || ^12 || >=14} - postcss@8.5.16: - resolution: {integrity: sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==} - engines: {node: ^10 || ^12 || >=14} + powershell-utils@0.1.0: + resolution: {integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==} + engines: {node: '>=20'} - prettier@3.9.0: - resolution: {integrity: sha512-LjIqSIC5VYLzs9WedVmJ2ljNAGnU+DteIClbahu4L/DBeWjZ6iT/k1lAYyu9JUh+1xINxWadaPw/Pl63y/agAw==} + prettier@3.9.6: + resolution: {integrity: sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==} engines: {node: '>=14'} hasBin: true - pretty-bytes@7.1.0: - resolution: {integrity: sha512-nODzvTiYVRGRqAOvE84Vk5JDPyyxsVk0/fbA/bq7RqlnhksGpset09XTxbpvLTIjoaF7K8Z8DG8yHtKGTPSYRw==} + pretty-bytes@7.1.1: + resolution: {integrity: sha512-X+vn9z8nOFZQlxOLmfJ0iKDdMD7jYTsTW12OAlCpdoE3Igik6L37pugIZi+N3usuyp5McfgKPWi12q3zvHLeGQ==} engines: {node: '>=20'} - 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.2.0: resolution: {integrity: sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==} @@ -2417,14 +2326,6 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - 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@5.0.0: resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} engines: {node: '>= 20.19.0'} @@ -2474,11 +2375,8 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rfdc@1.4.1: - resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - - rolldown@1.1.4: - resolution: {integrity: sha512-IjZYiLxZwpnhwhdBH2ugdTGVSdhCQUmLxLoqyjiL0JxYjyRst+5a0P3xfrTxJ5F638j4Mvvw5FAX5XE6eHpXbA==} + rolldown@1.2.1: + resolution: {integrity: sha512-4FKJhg8d3OiyQOA6Q1Q0hoFFpW9/OoX+VsHzpECsdsIZoOArrAK90gl59YK/Z+gnDel45bgJZK03ozH/9bCqEw==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -2496,8 +2394,8 @@ packages: esbuild: '>=0.18.0' rollup: ^1.20.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 - rollup@4.62.2: - resolution: {integrity: sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==} + rollup@4.62.3: + resolution: {integrity: sha512-Gu0c0iH9FzgX1L1t7ByIbbS3Vmdz+6KHm/EsqmmC71gUQ82yvZRkTK6XzrFObSka91WUVdynqp6nsfilzr5k6Q==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -2516,11 +2414,8 @@ packages: 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.6.0: - resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} + sax@1.6.1: + resolution: {integrity: sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==} engines: {node: '>=11.0.0'} section-matter@1.0.0: @@ -2540,8 +2435,8 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - shiki@4.3.0: - resolution: {integrity: sha512-NKKjWzR6LIGL3sXBrWDw9sDS9cxx42/DkysaNqJEeOWE8Kix5gpak0bc00OfDVEO4oyXSyz8+aRaqKoBD1yo7A==} + shiki@4.4.1: + resolution: {integrity: sha512-rFP+iYKzjLEIqiMiKANhARqiAbk4deDhWnBtnUO/K0D0dPxMGDH4N0FVfBY/VeI+lPrV4wNGCHQZp7EOr7NNBw==} engines: {node: '>=20'} siginfo@2.0.0: @@ -2570,14 +2465,6 @@ packages: engines: {node: '>=20.19.5', npm: '>=10.8.2'} hasBin: true - slice-ansi@7.1.2: - resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} - engines: {node: '>=18'} - - slice-ansi@8.0.0: - resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==} - engines: {node: '>=20'} - slick@1.12.2: resolution: {integrity: sha512-4qdtOGcBjral6YIBCWJ0ljFSKNLz9KkhbWtuGvUyRowl1kxfuE1x/Z/aJcaiilpb3do9bl5K7/1h9XC5wWpY/A==} @@ -2585,25 +2472,9 @@ packages: 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.23: - resolution: {integrity: sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==} - speech-rule-engine@4.1.4: resolution: {integrity: sha512-i/VCLG1fvRc95pMHRqG4aQNscv+9aIsqA2oI7ZQS51sTdUcDHYX6cpT8/tqZ+enjs1tKVwbRBWgxut9SWn+f9g==} hasBin: true @@ -2614,8 +2485,8 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - std-env@4.1.0: - resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} + std-env@4.2.0: + resolution: {integrity: sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==} stdin-discarder@0.3.2: resolution: {integrity: sha512-eCPu1qRxPVkl5605OTWF8Wz40b4Mf45NY5LQmVPQ599knfs5QhASUm9GbJ5BDMDOXgrnh0wyEdvzmL//YMlw0A==} @@ -2629,21 +2500,10 @@ packages: 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-width@8.2.1: - resolution: {integrity: sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==} + string-width@8.2.2: + resolution: {integrity: sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==} engines: {node: '>=20'} - 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==} @@ -2663,9 +2523,9 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - strtok3@7.1.1: - resolution: {integrity: sha512-mKX8HA/cdBqMKUr0MMZAFssCkIGoZeSCMXgnt79yKxNFguMLVFgRe6wB+fsL0NmoHDbeyZXczy7vEPSoo3rkzg==} - engines: {node: '>=16'} + strtok3@10.3.5: + resolution: {integrity: sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==} + engines: {node: '>=18'} supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} @@ -2693,20 +2553,20 @@ packages: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} - tinyrainbow@3.1.0: - resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} + tinyrainbow@3.1.1: + resolution: {integrity: sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==} 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==} + token-types@6.1.2: + resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==} engines: {node: '>=14.16'} - tokenx@1.3.0: - resolution: {integrity: sha512-NLdXTEZkKiO0gZuLtMoZKjCXTREXeZZt8nnnNeyoXtNZAfG/GKGSbQtLU5STspc0rMSwcA+UJfWZkbNU01iKmQ==} + tokenx@1.6.0: + resolution: {integrity: sha512-CKTjk345ajvBAUp5xUI9a5KKN0zU0lBueVHQbCskH1Hp6WkUKsPW2qGCYNs0pxNyfzxfo+IIjdt2W4sMbw/qBw==} totalist@3.0.1: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} @@ -2744,10 +2604,9 @@ packages: uc.micro@2.1.0: resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} - uglify-js@3.19.3: - resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} - engines: {node: '>=0.8.0'} - hasBin: true + uint8array-extras@1.5.0: + resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} + engines: {node: '>=18'} ultramatter@0.0.4: resolution: {integrity: sha512-1f/hO3mR+/Hgue4eInOF/Qm/wzDqwhYha4DxM0hre9YIUyso3fE2XtrAU6B4njLqTC8CM49EZaYgsVSa+dXHGw==} @@ -2755,8 +2614,8 @@ packages: undici-types@7.18.2: resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} - undici-types@7.24.6: - resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} + undici-types@8.3.0: + resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==} unified@11.0.5: resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} @@ -2794,22 +2653,19 @@ packages: 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.3: resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} vfile@6.0.3: resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} - vite@8.1.3: - resolution: {integrity: sha512-Ds+gBRbj0lwRO2Y5hwnUBdxSwlAve9LeRyU4sNnAr0ewW0gWF0n5bgXgUzbgZ49MV9BVUAQUFYVcDUcilUExMA==} + vite@8.2.0: + resolution: {integrity: sha512-pn+CFpM0lwDeKwmOq1ZaBK/9sjorZcgqxki6MbY/jPEVd9vichIlmlD4HmQ5wdP5EgqQCFRaACBxMC7uEGc6lQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: '@types/node': ^20.19.0 || >=22.12.0 - '@vitejs/devtools': ^0.3.0 + '@vitejs/devtools': ^0.4.0 esbuild: ^0.27.0 || ^0.28.0 jiti: '>=1.21.0' less: ^4.0.0 @@ -2846,32 +2702,32 @@ packages: yaml: optional: true - vitepress-plugin-group-icons@1.7.5: - resolution: {integrity: sha512-QzcroUuIiVKyXpmEiiHVbfRTQIy9Zbwxpk5JC/zavO8mavitwumz2RZWlwTchMCCHducYyPptkYvXvdnNUWkog==} + vitepress-plugin-group-icons@1.7.6: + resolution: {integrity: sha512-fXSpQAYHpFpEsZLKWQAwbRx/+0uRSHmY58YNAQcz0AVirGsM6w22jtSmQhOGLEj8ZKyeRtTJrpx6otUI6wvoaQ==} peerDependencies: vite: '>=3' peerDependenciesMeta: vite: optional: true - vitepress-plugin-llms@1.13.2: - resolution: {integrity: sha512-2O4s0I5pjEZzgnoWgBPCZCyhah9FH5uQB6lGADazMoyF1URJshtG04ZnmX+cbmQmniN3T5JzdJO9B4q8JHDKOQ==} + vitepress-plugin-llms@1.13.4: + resolution: {integrity: sha512-3/L1ceexjpJirWWGlfvqx2hmaDTFGSkSHrn3y2C7RZm6lNa/vmvU49Ayr4GxLYQfOFfo9CP6rsWdD+6rEbnIxA==} engines: {node: '>=18'} - vitest@4.1.9: - resolution: {integrity: sha512-nE3/LEyc0z87uHYLZebqCUOaJr2hdtuPp7BQ4BosVFnfltxgAvMG08NyrSGlPpOUWvR27c5flSmYFTNr78L9GQ==} + vitest@4.1.10: + resolution: {integrity: sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==} engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@opentelemetry/api': ^1.9.0 '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.1.9 - '@vitest/browser-preview': 4.1.9 - '@vitest/browser-webdriverio': 4.1.9 - '@vitest/coverage-istanbul': 4.1.9 - '@vitest/coverage-v8': 4.1.9 - '@vitest/ui': 4.1.9 + '@vitest/browser-playwright': 4.1.10 + '@vitest/browser-preview': 4.1.10 + '@vitest/browser-webdriverio': 4.1.10 + '@vitest/coverage-istanbul': 4.1.10 + '@vitest/coverage-v8': 4.1.10 + '@vitest/ui': 4.1.10 happy-dom: '*' jsdom: '*' vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -2902,22 +2758,22 @@ packages: vscode-uri@3.1.0: resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} - vue-tsc@3.3.5: - resolution: {integrity: sha512-Rzh/G2MmNlMSAMTiQEjDrsb4dgB/jbtEM47rVN2NtidF1dfb/q4w4QvpQBtW5+y3y5H27Hjh7deVwk+YB02fNg==} + vue-tsc@3.3.9: + resolution: {integrity: sha512-TS3Y1ux/IRoE8OCP2PpACAeOseuIs0UvWrcr7u+w3PmfY+SlCfEf8zjrBgnQksHUgLpthi5vHlffcQTQTdPBZA==} hasBin: true peerDependencies: typescript: '>=5.0.0' - vue@3.5.39: - resolution: {integrity: sha512-xmZCYabFGcirU8r0fTuvl/LICc1OU620rnqepaJDL/a141ZigkG7AyaxQLdqJ02ZRYzWe6YPaDHeQx7MfknQfA==} + vue@3.5.40: + resolution: {integrity: sha512-+8PJ4SJXdn/cHGImF4CKdxlWHIN5Dkt7DoufRREM6h6uVCx2m7QxgcEQmmzyOK8A9mcafg7sFbJFYsdFVubTig==} peerDependencies: typescript: '*' peerDependenciesMeta: typescript: optional: true - wait-on@9.0.10: - resolution: {integrity: sha512-rCoJEhvMr0X6alHmwc9abbrA5ZrLZFKpFQVKPNFwl2h7DapXOGdmimIHDtLOWhT4PjhZhxFEtZoQgEXbkDWdZw==} + wait-on@9.1.0: + resolution: {integrity: sha512-PymrLXHLBM1Ju/Xspb2ADUhbPSMvbnuNvy/mN2hWtpbJ3da0h3Ky1LqwKPG5QSVR57liyO0iUpfipYl/s5qNvA==} engines: {node: '>=20.0.0'} hasBin: true @@ -2948,20 +2804,13 @@ packages: 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@9.0.2: - resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} - engines: {node: '>=18'} - - wsl-utils@0.1.0: - resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==} - engines: {node: '>=18'} + wsl-utils@0.3.1: + resolution: {integrity: sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==} + engines: {node: '>=20'} y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} @@ -2980,8 +2829,8 @@ packages: resolution: {integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==} engines: {node: '>=12'} - yoctocolors@2.1.2: - resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} + yoctocolors@2.2.0: + resolution: {integrity: sha512-xYqdZFUK/VYazNl/oCDYN+3WloWQwMfZxBoiNt6qNyk+xfOdi598muWE42rNZFp1kNOiqW936q5RhUdnpqElSg==} engines: {node: '>=18'} zod@3.25.76: @@ -2992,9 +2841,14 @@ packages: snapshots: + '@11ty/gray-matter@2.1.0': + dependencies: + js-yaml: 4.3.0 + section-matter: 1.0.0 + '@antfu/install-pkg@1.1.0': dependencies: - package-manager-detector: 1.6.0 + package-manager-detector: 1.8.0 tinyexec: 1.2.4 '@babel/code-frame@7.29.7': @@ -3017,50 +2871,57 @@ snapshots: '@babel/helper-string-parser': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 + '@borewit/text-codec@0.2.2': {} + '@clack/core@0.3.5': dependencies: picocolors: 1.1.1 sisteransi: 1.0.5 - '@clack/core@1.4.2': + '@clack/core@1.4.3': dependencies: fast-wrap-ansi: 0.2.2 sisteransi: 1.0.5 - '@clack/prompts@1.6.0': + '@clack/prompts@1.7.0': dependencies: - '@clack/core': 1.4.2 + '@clack/core': 1.4.3 fast-string-width: 3.0.2 fast-wrap-ansi: 0.2.2 sisteransi: 1.0.5 - '@conventional-changelog/git-client@2.7.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0)': + '@conventional-changelog/git-client@3.1.0(conventional-commits-filter@6.0.1)(conventional-commits-parser@7.1.1)': dependencies: - '@simple-libs/child-process-utils': 1.0.2 - '@simple-libs/stream-utils': 1.2.0 + '@simple-libs/child-process-utils': 2.0.0 + '@simple-libs/stream-utils': 2.0.0 semver: 7.8.5 optionalDependencies: - conventional-commits-filter: 5.0.0 - conventional-commits-parser: 6.4.0 + conventional-commits-filter: 6.0.1 + conventional-commits-parser: 7.1.1 + + '@conventional-changelog/template@1.2.1': {} - '@docsearch/css@4.6.3': {} + '@docsearch/css@4.7.0': {} - '@docsearch/js@4.6.3': {} + '@docsearch/js@4.7.0': {} - '@docsearch/sidepanel-js@4.6.3': {} + '@docsearch/sidepanel-js@4.7.0': {} - '@emnapi/core@1.11.1': + '@emnapi/core@2.0.0-alpha.3': dependencies: - '@emnapi/wasi-threads': 1.2.2 + '@emnapi/wasi-threads': 2.0.1 tslib: 2.8.1 + optional: true - '@emnapi/runtime@1.11.1': + '@emnapi/runtime@2.0.0-alpha.3': dependencies: tslib: 2.8.1 + optional: true - '@emnapi/wasi-threads@1.2.2': + '@emnapi/wasi-threads@2.0.1': dependencies: tslib: 2.8.1 + optional: true '@esbuild/aix-ppc64@0.27.7': optional: true @@ -3160,17 +3021,17 @@ snapshots: dependencies: '@iconify/types': 2.0.0 - '@iconify-json/simple-icons@1.2.87': + '@iconify-json/simple-icons@1.2.92': dependencies: '@iconify/types': 2.0.0 - '@iconify-json/vscode-icons@1.2.62': + '@iconify-json/vscode-icons@1.2.67': dependencies: '@iconify/types': 2.0.0 '@iconify/types@2.0.0': {} - '@iconify/utils@3.1.3': + '@iconify/utils@3.1.4': dependencies: '@antfu/install-pkg': 1.1.0 '@iconify/types': 2.0.0 @@ -3204,54 +3065,95 @@ snapshots: '@mdit-vue/plugin-component@3.0.2': dependencies: '@types/markdown-it': 14.1.2 - markdown-it: 14.2.0 + markdown-it: 14.3.0 '@mdit-vue/plugin-frontmatter@3.0.2': dependencies: '@mdit-vue/types': 3.0.2 '@types/markdown-it': 14.1.2 gray-matter: 4.0.3 - markdown-it: 14.2.0 + markdown-it: 14.3.0 '@mdit-vue/plugin-headers@3.0.2': dependencies: '@mdit-vue/shared': 3.0.2 '@mdit-vue/types': 3.0.2 '@types/markdown-it': 14.1.2 - markdown-it: 14.2.0 + markdown-it: 14.3.0 '@mdit-vue/plugin-sfc@3.0.2': dependencies: '@mdit-vue/types': 3.0.2 '@types/markdown-it': 14.1.2 - markdown-it: 14.2.0 + markdown-it: 14.3.0 '@mdit-vue/plugin-title@3.0.2': dependencies: '@mdit-vue/shared': 3.0.2 '@mdit-vue/types': 3.0.2 '@types/markdown-it': 14.1.2 - markdown-it: 14.2.0 + markdown-it: 14.3.0 '@mdit-vue/plugin-toc@3.0.2': dependencies: '@mdit-vue/shared': 3.0.2 '@mdit-vue/types': 3.0.2 '@types/markdown-it': 14.1.2 - markdown-it: 14.2.0 + markdown-it: 14.3.0 '@mdit-vue/shared@3.0.2': dependencies: '@mdit-vue/types': 3.0.2 '@types/markdown-it': 14.1.2 - markdown-it: 14.2.0 + markdown-it: 14.3.0 '@mdit-vue/types@3.0.2': {} - '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + '@mdit/helper@1.0.1(markdown-it@14.3.0)': + dependencies: + '@types/markdown-it': 14.1.2 + optionalDependencies: + markdown-it: 14.3.0 + + '@mdit/plugin-anchor@1.1.3(markdown-it@14.3.0)': dependencies: - '@emnapi/core': 1.11.1 - '@emnapi/runtime': 1.11.1 + '@types/markdown-it': 14.1.2 + markdown-it: 14.3.0 + + '@mdit/plugin-attrs@1.1.1(markdown-it@14.3.0)': + dependencies: + '@mdit/helper': 1.0.1(markdown-it@14.3.0) + '@types/markdown-it': 14.1.2 + optionalDependencies: + markdown-it: 14.3.0 + + '@mdit/plugin-container@1.0.2(markdown-it@14.3.0)': + dependencies: + '@types/markdown-it': 14.1.2 + optionalDependencies: + markdown-it: 14.3.0 + + '@mdit/plugin-emoji@1.1.1(markdown-it@14.3.0)': + dependencies: + '@types/markdown-it': 14.1.2 + optionalDependencies: + markdown-it: 14.3.0 + + '@mdit/plugin-footnote@1.0.2(markdown-it@14.3.0)': + dependencies: + '@types/markdown-it': 14.1.2 + markdown-it: 14.3.0 + + '@mdit/plugin-tasklist@1.0.2(markdown-it@14.3.0)': + dependencies: + '@types/markdown-it': 14.1.2 + optionalDependencies: + markdown-it: 14.3.0 + + '@napi-rs/wasm-runtime@1.2.2(@emnapi/core@2.0.0-alpha.3)(@emnapi/runtime@2.0.0-alpha.3)': + dependencies: + '@emnapi/core': 2.0.0-alpha.3 + '@emnapi/runtime': 2.0.0-alpha.3 '@tybys/wasm-util': 0.10.3 optional: true @@ -3267,227 +3169,227 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@oxc-project/types@0.138.0': {} + '@oxc-project/types@0.142.0': {} '@polka/compression@1.0.0-next.28': {} '@polka/url@1.0.0-next.29': {} - '@rolldown/binding-android-arm64@1.1.4': + '@rolldown/binding-android-arm64@1.2.1': optional: true - '@rolldown/binding-darwin-arm64@1.1.4': + '@rolldown/binding-darwin-arm64@1.2.1': optional: true - '@rolldown/binding-darwin-x64@1.1.4': + '@rolldown/binding-darwin-x64@1.2.1': optional: true - '@rolldown/binding-freebsd-x64@1.1.4': + '@rolldown/binding-freebsd-x64@1.2.1': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.1.4': + '@rolldown/binding-linux-arm-gnueabihf@1.2.1': optional: true - '@rolldown/binding-linux-arm64-gnu@1.1.4': + '@rolldown/binding-linux-arm64-gnu@1.2.1': optional: true - '@rolldown/binding-linux-arm64-musl@1.1.4': + '@rolldown/binding-linux-arm64-musl@1.2.1': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.1.4': + '@rolldown/binding-linux-ppc64-gnu@1.2.1': optional: true - '@rolldown/binding-linux-s390x-gnu@1.1.4': + '@rolldown/binding-linux-s390x-gnu@1.2.1': optional: true - '@rolldown/binding-linux-x64-gnu@1.1.4': + '@rolldown/binding-linux-x64-gnu@1.2.1': optional: true - '@rolldown/binding-linux-x64-musl@1.1.4': + '@rolldown/binding-linux-x64-musl@1.2.1': optional: true - '@rolldown/binding-openharmony-arm64@1.1.4': + '@rolldown/binding-openharmony-arm64@1.2.1': optional: true - '@rolldown/binding-wasm32-wasi@1.1.4': + '@rolldown/binding-wasm32-wasi@1.2.1': dependencies: - '@emnapi/core': 1.11.1 - '@emnapi/runtime': 1.11.1 - '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + '@emnapi/core': 2.0.0-alpha.3 + '@emnapi/runtime': 2.0.0-alpha.3 + '@napi-rs/wasm-runtime': 1.2.2(@emnapi/core@2.0.0-alpha.3)(@emnapi/runtime@2.0.0-alpha.3) optional: true - '@rolldown/binding-win32-arm64-msvc@1.1.4': + '@rolldown/binding-win32-arm64-msvc@1.2.1': optional: true - '@rolldown/binding-win32-x64-msvc@1.1.4': + '@rolldown/binding-win32-x64-msvc@1.2.1': optional: true '@rolldown/pluginutils@1.0.1': {} - '@rollup/plugin-alias@6.0.0(rollup@4.62.2)': + '@rollup/plugin-alias@6.0.0(rollup@4.62.3)': optionalDependencies: - rollup: 4.62.2 + rollup: 4.62.3 - '@rollup/plugin-commonjs@29.0.3(rollup@4.62.2)': + '@rollup/plugin-commonjs@29.0.3(rollup@4.62.3)': dependencies: - '@rollup/pluginutils': 5.4.0(rollup@4.62.2) + '@rollup/pluginutils': 5.4.0(rollup@4.62.3) commondir: 1.0.1 estree-walker: 2.0.2 - fdir: 6.5.0(picomatch@4.0.4) + fdir: 6.5.0(picomatch@4.0.5) is-reference: 1.2.1 magic-string: 0.30.21 - picomatch: 4.0.4 + picomatch: 4.0.5 optionalDependencies: - rollup: 4.62.2 + rollup: 4.62.3 - '@rollup/plugin-json@6.1.0(rollup@4.62.2)': + '@rollup/plugin-json@6.1.0(rollup@4.62.3)': dependencies: - '@rollup/pluginutils': 5.4.0(rollup@4.62.2) + '@rollup/pluginutils': 5.4.0(rollup@4.62.3) optionalDependencies: - rollup: 4.62.2 + rollup: 4.62.3 - '@rollup/plugin-node-resolve@16.0.3(rollup@4.62.2)': + '@rollup/plugin-node-resolve@16.0.3(rollup@4.62.3)': dependencies: - '@rollup/pluginutils': 5.4.0(rollup@4.62.2) + '@rollup/pluginutils': 5.4.0(rollup@4.62.3) '@types/resolve': 1.20.2 deepmerge: 4.3.1 is-module: 1.0.0 resolve: 1.22.12 optionalDependencies: - rollup: 4.62.2 + rollup: 4.62.3 - '@rollup/plugin-replace@6.0.3(rollup@4.62.2)': + '@rollup/plugin-replace@6.0.3(rollup@4.62.3)': dependencies: - '@rollup/pluginutils': 5.4.0(rollup@4.62.2) + '@rollup/pluginutils': 5.4.0(rollup@4.62.3) magic-string: 0.30.21 optionalDependencies: - rollup: 4.62.2 + rollup: 4.62.3 - '@rollup/pluginutils@5.4.0(rollup@4.62.2)': + '@rollup/pluginutils@5.4.0(rollup@4.62.3)': dependencies: '@types/estree': 1.0.9 estree-walker: 2.0.2 - picomatch: 4.0.4 + picomatch: 4.0.5 optionalDependencies: - rollup: 4.62.2 + rollup: 4.62.3 - '@rollup/rollup-android-arm-eabi@4.62.2': + '@rollup/rollup-android-arm-eabi@4.62.3': optional: true - '@rollup/rollup-android-arm64@4.62.2': + '@rollup/rollup-android-arm64@4.62.3': optional: true - '@rollup/rollup-darwin-arm64@4.62.2': + '@rollup/rollup-darwin-arm64@4.62.3': optional: true - '@rollup/rollup-darwin-x64@4.62.2': + '@rollup/rollup-darwin-x64@4.62.3': optional: true - '@rollup/rollup-freebsd-arm64@4.62.2': + '@rollup/rollup-freebsd-arm64@4.62.3': optional: true - '@rollup/rollup-freebsd-x64@4.62.2': + '@rollup/rollup-freebsd-x64@4.62.3': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.62.2': + '@rollup/rollup-linux-arm-gnueabihf@4.62.3': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.62.2': + '@rollup/rollup-linux-arm-musleabihf@4.62.3': optional: true - '@rollup/rollup-linux-arm64-gnu@4.62.2': + '@rollup/rollup-linux-arm64-gnu@4.62.3': optional: true - '@rollup/rollup-linux-arm64-musl@4.62.2': + '@rollup/rollup-linux-arm64-musl@4.62.3': optional: true - '@rollup/rollup-linux-loong64-gnu@4.62.2': + '@rollup/rollup-linux-loong64-gnu@4.62.3': optional: true - '@rollup/rollup-linux-loong64-musl@4.62.2': + '@rollup/rollup-linux-loong64-musl@4.62.3': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.62.2': + '@rollup/rollup-linux-ppc64-gnu@4.62.3': optional: true - '@rollup/rollup-linux-ppc64-musl@4.62.2': + '@rollup/rollup-linux-ppc64-musl@4.62.3': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.62.2': + '@rollup/rollup-linux-riscv64-gnu@4.62.3': optional: true - '@rollup/rollup-linux-riscv64-musl@4.62.2': + '@rollup/rollup-linux-riscv64-musl@4.62.3': optional: true - '@rollup/rollup-linux-s390x-gnu@4.62.2': + '@rollup/rollup-linux-s390x-gnu@4.62.3': optional: true - '@rollup/rollup-linux-x64-gnu@4.62.2': + '@rollup/rollup-linux-x64-gnu@4.62.3': optional: true - '@rollup/rollup-linux-x64-musl@4.62.2': + '@rollup/rollup-linux-x64-musl@4.62.3': optional: true - '@rollup/rollup-openbsd-x64@4.62.2': + '@rollup/rollup-openbsd-x64@4.62.3': optional: true - '@rollup/rollup-openharmony-arm64@4.62.2': + '@rollup/rollup-openharmony-arm64@4.62.3': optional: true - '@rollup/rollup-win32-arm64-msvc@4.62.2': + '@rollup/rollup-win32-arm64-msvc@4.62.3': optional: true - '@rollup/rollup-win32-ia32-msvc@4.62.2': + '@rollup/rollup-win32-ia32-msvc@4.62.3': optional: true - '@rollup/rollup-win32-x64-gnu@4.62.2': + '@rollup/rollup-win32-x64-gnu@4.62.3': optional: true - '@rollup/rollup-win32-x64-msvc@4.62.2': + '@rollup/rollup-win32-x64-msvc@4.62.3': optional: true - '@shikijs/core@4.3.0': + '@shikijs/core@4.4.1': dependencies: - '@shikijs/primitive': 4.3.0 - '@shikijs/types': 4.3.0 + '@shikijs/primitive': 4.4.1 + '@shikijs/types': 4.4.1 '@shikijs/vscode-textmate': 10.0.2 - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 hast-util-to-html: 9.0.5 - '@shikijs/engine-javascript@4.3.0': + '@shikijs/engine-javascript@4.4.1': dependencies: - '@shikijs/types': 4.3.0 + '@shikijs/types': 4.4.1 '@shikijs/vscode-textmate': 10.0.2 oniguruma-to-es: 4.3.6 - '@shikijs/engine-oniguruma@4.3.0': + '@shikijs/engine-oniguruma@4.4.1': dependencies: - '@shikijs/types': 4.3.0 + '@shikijs/types': 4.4.1 '@shikijs/vscode-textmate': 10.0.2 - '@shikijs/langs@4.3.0': + '@shikijs/langs@4.4.1': dependencies: - '@shikijs/types': 4.3.0 + '@shikijs/types': 4.4.1 - '@shikijs/primitive@4.3.0': + '@shikijs/primitive@4.4.1': dependencies: - '@shikijs/types': 4.3.0 + '@shikijs/types': 4.4.1 '@shikijs/vscode-textmate': 10.0.2 - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 - '@shikijs/themes@4.3.0': + '@shikijs/themes@4.4.1': dependencies: - '@shikijs/types': 4.3.0 + '@shikijs/types': 4.4.1 - '@shikijs/transformers@4.3.0': + '@shikijs/transformers@4.4.1': dependencies: - '@shikijs/core': 4.3.0 - '@shikijs/types': 4.3.0 + '@shikijs/core': 4.4.1 + '@shikijs/types': 4.4.1 - '@shikijs/types@4.3.0': + '@shikijs/types@4.4.1': dependencies: '@shikijs/vscode-textmate': 10.0.2 - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 '@shikijs/vscode-textmate@10.0.2': {} @@ -3497,16 +3399,28 @@ snapshots: dependencies: '@simple-git/args-pathspec': 1.0.3 - '@simple-libs/child-process-utils@1.0.2': + '@simple-libs/child-process-utils@2.0.0': dependencies: - '@simple-libs/stream-utils': 1.2.0 + '@simple-libs/stream-utils': 2.0.0 - '@simple-libs/hosted-git-info@1.0.2': {} + '@simple-libs/hosted-git-info@2.0.0': {} - '@simple-libs/stream-utils@1.2.0': {} + '@simple-libs/normalize-package-data@1.0.0': + dependencies: + '@simple-libs/hosted-git-info': 2.0.0 + semver: 7.8.5 + + '@simple-libs/stream-utils@2.0.0': {} '@standard-schema/spec@1.1.0': {} + '@tokenizer/inflate@0.4.1': + dependencies: + debug: 4.4.3 + token-types: 6.1.2 + transitivePeerDependencies: + - supports-color + '@tokenizer/token@0.3.0': {} '@tybys/wasm-util@0.10.3': @@ -3521,7 +3435,7 @@ snapshots: '@types/cross-spawn@6.0.6': dependencies: - '@types/node': 25.9.4 + '@types/node': 26.1.2 '@types/debug@4.1.13': dependencies: @@ -3531,7 +3445,7 @@ snapshots: '@types/estree@1.0.9': {} - '@types/hast@3.0.4': + '@types/hast@3.0.5': dependencies: '@types/unist': 3.0.3 @@ -3549,55 +3463,36 @@ snapshots: dependencies: '@types/jquery': 4.0.1 - '@types/markdown-it-attrs@4.1.3(patch_hash=ef05082c7886d283042ddf9103f1408fc36fd8665ef278c82b3da0659441dfb6)': - dependencies: - '@types/markdown-it': 14.1.2 - - '@types/markdown-it-container@4.0.0': - dependencies: - '@types/markdown-it': 14.1.2 - - '@types/markdown-it-emoji@3.0.1': - dependencies: - '@types/markdown-it': 14.1.2 - '@types/markdown-it@14.1.2': dependencies: '@types/linkify-it': 5.0.0 - '@types/mdurl': 2.0.0(patch_hash=3460e7d18ce390685cf4b8d8237fb20df9ad952c1336f479995a508a6395bfa4) + '@types/mdurl': 2.0.0 '@types/mdast@4.0.4': dependencies: '@types/unist': 3.0.3 - '@types/mdurl@2.0.0(patch_hash=3460e7d18ce390685cf4b8d8237fb20df9ad952c1336f479995a508a6395bfa4)': {} + '@types/mdurl@2.0.0': {} '@types/minimist@1.2.5': {} '@types/ms@2.1.0': {} - '@types/node@24.13.2': + '@types/node@24.13.3': dependencies: undici-types: 7.18.2 - '@types/node@25.9.4': + '@types/node@26.1.2': dependencies: - undici-types: 7.24.6 - - '@types/normalize-package-data@2.4.4': {} + undici-types: 8.3.0 '@types/picomatch@4.0.3': {} - '@types/prompts@2.4.9': - dependencies: - '@types/node': 25.9.4 - kleur: 3.0.3 - '@types/resolve@1.20.2': {} '@types/sax@1.2.7': dependencies: - '@types/node': 25.9.4 + '@types/node': 26.1.2 '@types/semver@7.7.1': {} @@ -3605,54 +3500,54 @@ snapshots: '@types/web-bluetooth@0.0.21': {} - '@ungap/structured-clone@1.3.2': {} + '@ungap/structured-clone@1.3.3': {} - '@vitejs/plugin-vue@6.0.7(vite@8.1.3(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0))(vue@3.5.39(typescript@5.9.3))': + '@vitejs/plugin-vue@6.0.8(vite@8.2.0(@types/node@26.1.2)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0))(vue@3.5.40(typescript@5.9.3))': dependencies: '@rolldown/pluginutils': 1.0.1 - vite: 8.1.3(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0) - vue: 3.5.39(typescript@5.9.3) + vite: 8.2.0(@types/node@26.1.2)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0) + vue: 3.5.40(typescript@5.9.3) - '@vitest/expect@4.1.9': + '@vitest/expect@4.1.10': dependencies: '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@vitest/spy': 4.1.9 - '@vitest/utils': 4.1.9 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 chai: 6.2.2 - tinyrainbow: 3.1.0 + tinyrainbow: 3.1.1 - '@vitest/mocker@4.1.9(vite@8.1.3(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0))': + '@vitest/mocker@4.1.10(vite@8.2.0(@types/node@26.1.2)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0))': dependencies: - '@vitest/spy': 4.1.9 + '@vitest/spy': 4.1.10 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.1.3(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0) + vite: 8.2.0(@types/node@26.1.2)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0) - '@vitest/pretty-format@4.1.9': + '@vitest/pretty-format@4.1.10': dependencies: - tinyrainbow: 3.1.0 + tinyrainbow: 3.1.1 - '@vitest/runner@4.1.9': + '@vitest/runner@4.1.10': dependencies: - '@vitest/utils': 4.1.9 + '@vitest/utils': 4.1.10 pathe: 2.0.3 - '@vitest/snapshot@4.1.9': + '@vitest/snapshot@4.1.10': dependencies: - '@vitest/pretty-format': 4.1.9 - '@vitest/utils': 4.1.9 + '@vitest/pretty-format': 4.1.10 + '@vitest/utils': 4.1.10 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@4.1.9': {} + '@vitest/spy@4.1.10': {} - '@vitest/utils@4.1.9': + '@vitest/utils@4.1.10': dependencies: - '@vitest/pretty-format': 4.1.9 + '@vitest/pretty-format': 4.1.10 convert-source-map: 2.0.0 - tinyrainbow: 3.1.0 + tinyrainbow: 3.1.1 '@volar/language-core@2.4.28': dependencies: @@ -3666,111 +3561,107 @@ snapshots: path-browserify: 1.0.1 vscode-uri: 3.1.0 - '@vue/compiler-core@3.5.39': + '@vue/compiler-core@3.5.40': dependencies: '@babel/parser': 7.29.7 - '@vue/shared': 3.5.39 + '@vue/shared': 3.5.40 entities: 7.0.1 estree-walker: 2.0.2 source-map-js: 1.2.1 - '@vue/compiler-dom@3.5.39': + '@vue/compiler-dom@3.5.40': dependencies: - '@vue/compiler-core': 3.5.39 - '@vue/shared': 3.5.39 + '@vue/compiler-core': 3.5.40 + '@vue/shared': 3.5.40 - '@vue/compiler-sfc@3.5.39': + '@vue/compiler-sfc@3.5.40': dependencies: '@babel/parser': 7.29.7 - '@vue/compiler-core': 3.5.39 - '@vue/compiler-dom': 3.5.39 - '@vue/compiler-ssr': 3.5.39 - '@vue/shared': 3.5.39 + '@vue/compiler-core': 3.5.40 + '@vue/compiler-dom': 3.5.40 + '@vue/compiler-ssr': 3.5.40 + '@vue/shared': 3.5.40 estree-walker: 2.0.2 magic-string: 0.30.21 - postcss: 8.5.15 + postcss: 8.5.25 source-map-js: 1.2.1 - '@vue/compiler-ssr@3.5.39': + '@vue/compiler-ssr@3.5.40': dependencies: - '@vue/compiler-dom': 3.5.39 - '@vue/shared': 3.5.39 + '@vue/compiler-dom': 3.5.40 + '@vue/shared': 3.5.40 - '@vue/devtools-api@8.1.4': + '@vue/devtools-api@8.2.1': dependencies: - '@vue/devtools-kit': 8.1.4 + '@vue/devtools-kit': 8.2.1 - '@vue/devtools-kit@8.1.4': + '@vue/devtools-kit@8.2.1': dependencies: - '@vue/devtools-shared': 8.1.4 + '@vue/devtools-shared': 8.2.1 birpc: 2.9.0 hookable: 5.5.3 perfect-debounce: 2.1.0 - '@vue/devtools-shared@8.1.4': {} + '@vue/devtools-shared@8.2.1': {} - '@vue/language-core@3.3.5': + '@vue/language-core@3.3.9': dependencies: '@volar/language-core': 2.4.28 - '@vue/compiler-dom': 3.5.39 - '@vue/shared': 3.5.39 + '@vue/compiler-dom': 3.5.40 + '@vue/shared': 3.5.40 alien-signals: 3.2.1 muggle-string: 0.4.1 path-browserify: 1.0.1 - picomatch: 4.0.4 + picomatch: 4.0.5 - '@vue/reactivity@3.5.39': + '@vue/reactivity@3.5.40': dependencies: - '@vue/shared': 3.5.39 + '@vue/shared': 3.5.40 - '@vue/runtime-core@3.5.39': + '@vue/runtime-core@3.5.40': dependencies: - '@vue/reactivity': 3.5.39 - '@vue/shared': 3.5.39 + '@vue/reactivity': 3.5.40 + '@vue/shared': 3.5.40 - '@vue/runtime-dom@3.5.39': + '@vue/runtime-dom@3.5.40': dependencies: - '@vue/reactivity': 3.5.39 - '@vue/runtime-core': 3.5.39 - '@vue/shared': 3.5.39 + '@vue/reactivity': 3.5.40 + '@vue/runtime-core': 3.5.40 + '@vue/shared': 3.5.40 csstype: 3.2.3 - '@vue/server-renderer@3.5.39(vue@3.5.39(typescript@5.9.3))': + '@vue/server-renderer@3.5.40': dependencies: - '@vue/compiler-ssr': 3.5.39 - '@vue/shared': 3.5.39 - vue: 3.5.39(typescript@5.9.3) + '@vue/compiler-ssr': 3.5.40 + '@vue/runtime-dom': 3.5.40 + '@vue/shared': 3.5.40 - '@vue/shared@3.5.39': {} + '@vue/shared@3.5.40': {} - '@vueuse/core@14.3.0(vue@3.5.39(typescript@5.9.3))': + '@vueuse/core@14.4.0(vue@3.5.40(typescript@5.9.3))': dependencies: '@types/web-bluetooth': 0.0.21 - '@vueuse/metadata': 14.3.0 - '@vueuse/shared': 14.3.0(vue@3.5.39(typescript@5.9.3)) - vue: 3.5.39(typescript@5.9.3) + '@vueuse/metadata': 14.4.0 + '@vueuse/shared': 14.4.0(vue@3.5.40(typescript@5.9.3)) + vue: 3.5.40(typescript@5.9.3) - '@vueuse/integrations@14.3.0(axios@1.18.1)(focus-trap@8.2.2)(vue@3.5.39(typescript@5.9.3))': + '@vueuse/integrations@14.4.0(axios@1.19.0(debug@4.4.3))(focus-trap@8.2.2)(vue@3.5.40(typescript@5.9.3))': dependencies: - '@vueuse/core': 14.3.0(vue@3.5.39(typescript@5.9.3)) - '@vueuse/shared': 14.3.0(vue@3.5.39(typescript@5.9.3)) - vue: 3.5.39(typescript@5.9.3) + '@vueuse/core': 14.4.0(vue@3.5.40(typescript@5.9.3)) + '@vueuse/shared': 14.4.0(vue@3.5.40(typescript@5.9.3)) + vue: 3.5.40(typescript@5.9.3) optionalDependencies: - axios: 1.18.1 + axios: 1.19.0(debug@4.4.3) focus-trap: 8.2.2 - '@vueuse/metadata@14.3.0': {} + '@vueuse/metadata@14.4.0': {} - '@vueuse/shared@14.3.0(vue@3.5.39(typescript@5.9.3))': + '@vueuse/shared@14.4.0(vue@3.5.40(typescript@5.9.3))': dependencies: - vue: 3.5.39(typescript@5.9.3) + vue: 3.5.40(typescript@5.9.3) '@xmldom/xmldom@0.9.10': {} - abort-controller@3.0.0: - dependencies: - event-target-shim: 5.0.1 - agent-base@6.0.2: dependencies: debug: 4.4.3 @@ -3781,10 +3672,6 @@ snapshots: ansi-colors@4.1.3: {} - ansi-escapes@7.3.0: - dependencies: - environment: 1.1.0 - ansi-regex@5.0.1: {} ansi-regex@6.2.2: {} @@ -3793,8 +3680,6 @@ snapshots: dependencies: color-convert: 2.0.1 - ansi-styles@6.2.3: {} - arg@5.0.2: {} argparse@1.0.10: @@ -3803,15 +3688,15 @@ snapshots: argparse@2.0.1: {} - array-ify@1.0.0: {} + argue-cli@3.1.0: {} assertion-error@2.0.1: {} asynckit@0.4.0: {} - axios@1.18.1: + axios@1.19.0(debug@4.4.3): dependencies: - follow-redirects: 1.16.0 + follow-redirects: 1.16.0(debug@4.4.3) form-data: 4.0.6 https-proxy-agent: 5.0.1 proxy-from-env: 2.1.0 @@ -3823,13 +3708,11 @@ snapshots: balanced-match@4.0.4: {} - base64-js@1.5.1: {} - birpc@2.9.0: {} boolbase@1.0.0: {} - brace-expansion@5.0.6: + brace-expansion@5.0.9: dependencies: balanced-match: 4.0.4 @@ -3837,11 +3720,6 @@ snapshots: dependencies: fill-range: 7.1.1 - buffer@6.0.3: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - bundle-name@4.1.0: dependencies: run-applescript: 7.1.0 @@ -3891,11 +3769,6 @@ snapshots: cli-spinners@3.4.0: {} - cli-truncate@5.2.0: - dependencies: - slice-ansi: 8.0.0 - string-width: 8.2.1 - cliui@8.0.1: dependencies: string-width: 4.2.3 @@ -3908,8 +3781,6 @@ snapshots: color-name@1.1.4: {} - colorette@2.0.20: {} - combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 @@ -3918,51 +3789,43 @@ snapshots: commander@13.1.0: {} - commander@14.0.3: {} - commander@6.2.1: {} commondir@1.0.1: {} - compare-func@2.0.0: - dependencies: - array-ify: 1.0.0 - dot-prop: 5.3.0 - - conventional-changelog-angular@8.3.1: + conventional-changelog-angular@9.2.1: dependencies: - compare-func: 2.0.0 + '@conventional-changelog/template': 1.2.1 - conventional-changelog-preset-loader@5.0.0: {} + conventional-changelog-preset-loader@6.0.1: {} - conventional-changelog-writer@8.4.0: + conventional-changelog-writer@9.2.0: dependencies: - '@simple-libs/stream-utils': 1.2.0 - conventional-commits-filter: 5.0.0 - handlebars: 4.7.9 - meow: 13.2.0 + '@conventional-changelog/template': 1.2.1 + '@simple-libs/stream-utils': 2.0.0 + argue-cli: 3.1.0 + conventional-commits-filter: 6.0.1 semver: 7.8.5 - conventional-changelog@7.2.1(conventional-commits-filter@5.0.0): + conventional-changelog@8.1.0(conventional-commits-filter@6.0.1): dependencies: - '@conventional-changelog/git-client': 2.7.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0) - '@simple-libs/hosted-git-info': 1.0.2 - '@types/normalize-package-data': 2.4.4 - conventional-changelog-preset-loader: 5.0.0 - conventional-changelog-writer: 8.4.0 - conventional-commits-parser: 6.4.0 + '@conventional-changelog/git-client': 3.1.0(conventional-commits-filter@6.0.1)(conventional-commits-parser@7.1.1) + '@simple-libs/hosted-git-info': 2.0.0 + '@simple-libs/normalize-package-data': 1.0.0 + argue-cli: 3.1.0 + conventional-changelog-preset-loader: 6.0.1 + conventional-changelog-writer: 9.2.0 + conventional-commits-parser: 7.1.1 fd-package-json: 2.0.0 - meow: 13.2.0 - normalize-package-data: 7.0.1 transitivePeerDependencies: - conventional-commits-filter - conventional-commits-filter@5.0.0: {} + conventional-commits-filter@6.0.1: {} - conventional-commits-parser@6.4.0: + conventional-commits-parser@7.1.1: dependencies: - '@simple-libs/stream-utils': 1.2.0 - meow: 13.2.0 + '@simple-libs/stream-utils': 2.0.0 + argue-cli: 3.1.0 convert-source-map@2.0.0: {} @@ -4041,39 +3904,27 @@ snapshots: domelementtype: 2.3.0 domhandler: 4.3.1 - dot-prop@5.3.0: - dependencies: - is-obj: 2.0.0 - dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 es-errors: 1.3.0 gopd: 1.2.0 - eastasianwidth@0.2.0: {} - - emoji-regex@10.6.0: {} - emoji-regex@8.0.0: {} - emoji-regex@9.2.2: {} - entities@2.2.0: {} entities@4.5.0: {} entities@7.0.1: {} - environment@1.1.0: {} - es-define-property@1.0.1: {} es-errors@1.3.0: {} es-module-lexer@1.7.0: {} - es-module-lexer@2.3.0: {} + es-module-lexer@2.3.1: {} es-object-atoms@1.1.2: dependencies: @@ -4131,12 +3982,6 @@ snapshots: dependencies: '@types/estree': 1.0.9 - event-target-shim@5.0.1: {} - - eventemitter3@5.0.4: {} - - events@3.3.0: {} - expect-type@1.4.0: {} extend-shallow@2.0.1: @@ -4175,15 +4020,18 @@ snapshots: dependencies: walk-up-path: 4.0.0 - fdir@6.5.0(picomatch@4.0.4): + fdir@6.5.0(picomatch@4.0.5): optionalDependencies: - picomatch: 4.0.4 + picomatch: 4.0.5 - file-type@18.7.0: + file-type@21.3.4: dependencies: - readable-web-to-node-stream: 3.0.4 - strtok3: 7.1.1 - token-types: 5.0.1 + '@tokenizer/inflate': 0.4.1 + strtok3: 10.3.5 + token-types: 6.1.2 + uint8array-extras: 1.5.0 + transitivePeerDependencies: + - supports-color fill-range@7.1.1: dependencies: @@ -4195,7 +4043,9 @@ snapshots: dependencies: tabbable: 6.5.0 - follow-redirects@1.16.0: {} + follow-redirects@1.16.0(debug@4.4.3): + optionalDependencies: + debug: 4.4.3 form-data@4.0.6: dependencies: @@ -4236,8 +4086,6 @@ snapshots: dunder-proto: 1.0.1 es-object-atoms: 1.1.2 - get-stdin@9.0.0: {} - get-tsconfig@4.14.0: dependencies: resolve-pkg-maps: 1.0.0 @@ -4255,15 +4103,6 @@ snapshots: section-matter: 1.0.0 strip-bom-string: 1.0.0 - handlebars@4.7.9: - dependencies: - minimist: 1.2.8 - neo-async: 2.6.2 - source-map: 0.6.1 - wordwrap: 1.0.0 - optionalDependencies: - uglify-js: 3.19.3 - has-symbols@1.1.0: {} has-tostringtag@1.0.2: @@ -4276,7 +4115,7 @@ snapshots: hast-util-to-html@9.0.5: dependencies: - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 '@types/unist': 3.0.3 ccount: 2.0.1 comma-separated-tokens: 2.0.3 @@ -4290,14 +4129,10 @@ snapshots: hast-util-whitespace@3.0.0: dependencies: - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 hookable@5.5.3: {} - hosted-git-info@8.1.0: - dependencies: - lru-cache: 10.4.3 - html-void-elements@3.0.0: {} htmlparser2@5.0.1: @@ -4323,6 +4158,8 @@ snapshots: ieee754@1.2.1: {} + image-size@2.0.2: {} + import-meta-resolve@4.2.0: {} is-core-module@2.16.2: @@ -4337,14 +4174,12 @@ snapshots: is-fullwidth-code-point@3.0.0: {} - is-fullwidth-code-point@5.1.0: - dependencies: - get-east-asian-width: 1.6.0 - is-glob@4.0.3: dependencies: is-extglob: 2.1.1 + is-in-ssh@1.0.0: {} + is-inside-container@1.0.0: dependencies: is-docker: 3.0.0 @@ -4355,8 +4190,6 @@ snapshots: is-number@7.0.0: {} - is-obj@2.0.0: {} - is-plain-obj@4.1.0: {} is-reference@1.2.1: @@ -4393,6 +4226,10 @@ snapshots: argparse: 1.0.10 esprima: 4.0.1 + js-yaml@4.3.0: + dependencies: + argparse: 2.0.1 + juice@8.1.0: dependencies: cheerio: 1.0.0-rc.10 @@ -4405,79 +4242,67 @@ snapshots: kind-of@6.0.3: {} - kleur@3.0.3: {} - - lightningcss-android-arm64@1.32.0: + lightningcss-android-arm64@1.33.0: optional: true - lightningcss-darwin-arm64@1.32.0: + lightningcss-darwin-arm64@1.33.0: optional: true - lightningcss-darwin-x64@1.32.0: + lightningcss-darwin-x64@1.33.0: optional: true - lightningcss-freebsd-x64@1.32.0: + lightningcss-freebsd-x64@1.33.0: optional: true - lightningcss-linux-arm-gnueabihf@1.32.0: + lightningcss-linux-arm-gnueabihf@1.33.0: optional: true - lightningcss-linux-arm64-gnu@1.32.0: + lightningcss-linux-arm64-gnu@1.33.0: optional: true - lightningcss-linux-arm64-musl@1.32.0: + lightningcss-linux-arm64-musl@1.33.0: optional: true - lightningcss-linux-x64-gnu@1.32.0: + lightningcss-linux-x64-gnu@1.33.0: optional: true - lightningcss-linux-x64-musl@1.32.0: + lightningcss-linux-x64-musl@1.33.0: optional: true - lightningcss-win32-arm64-msvc@1.32.0: + lightningcss-win32-arm64-msvc@1.33.0: optional: true - lightningcss-win32-x64-msvc@1.32.0: + lightningcss-win32-x64-msvc@1.33.0: optional: true - lightningcss@1.32.0: + lightningcss@1.33.0: dependencies: detect-libc: 2.1.2 optionalDependencies: - lightningcss-android-arm64: 1.32.0 - lightningcss-darwin-arm64: 1.32.0 - lightningcss-darwin-x64: 1.32.0 - lightningcss-freebsd-x64: 1.32.0 - lightningcss-linux-arm-gnueabihf: 1.32.0 - lightningcss-linux-arm64-gnu: 1.32.0 - lightningcss-linux-arm64-musl: 1.32.0 - lightningcss-linux-x64-gnu: 1.32.0 - lightningcss-linux-x64-musl: 1.32.0 - lightningcss-win32-arm64-msvc: 1.32.0 - lightningcss-win32-x64-msvc: 1.32.0 - - linkify-it@5.0.1: + lightningcss-android-arm64: 1.33.0 + lightningcss-darwin-arm64: 1.33.0 + lightningcss-darwin-x64: 1.33.0 + lightningcss-freebsd-x64: 1.33.0 + lightningcss-linux-arm-gnueabihf: 1.33.0 + lightningcss-linux-arm64-gnu: 1.33.0 + lightningcss-linux-arm64-musl: 1.33.0 + lightningcss-linux-x64-gnu: 1.33.0 + lightningcss-linux-x64-musl: 1.33.0 + lightningcss-win32-arm64-msvc: 1.33.0 + lightningcss-win32-x64-msvc: 1.33.0 + + linkify-it@5.0.2: dependencies: uc.micro: 2.1.0 - lint-staged@16.4.0: + lint-staged@17.3.0: dependencies: - commander: 14.0.3 - listr2: 9.0.5 - picomatch: 4.0.4 + picomatch: 4.0.5 string-argv: 0.3.2 tinyexec: 1.2.4 + optionalDependencies: yaml: 2.9.0 - listr2@9.0.5: - dependencies: - cli-truncate: 5.2.0 - colorette: 2.0.20 - eventemitter3: 5.0.4 - log-update: 6.1.0 - rfdc: 1.4.1 - wrap-ansi: 9.0.2 - lodash._reinterpolate@3.0.0: {} lodash.template@4.18.1: @@ -4494,21 +4319,11 @@ snapshots: log-symbols@7.0.1: dependencies: is-unicode-supported: 2.1.0 - yoctocolors: 2.1.2 - - log-update@6.1.0: - dependencies: - ansi-escapes: 7.3.0 - cli-cursor: 5.0.0 - slice-ansi: 7.1.2 - strip-ansi: 7.2.0 - wrap-ansi: 9.0.2 + yoctocolors: 2.2.0 longest-streak@3.1.0: {} - lru-cache@10.4.3: {} - - lru-cache@11.5.1: {} + lru-cache@11.5.2: {} magic-string@0.30.21: dependencies: @@ -4516,31 +4331,18 @@ snapshots: mark.js@8.11.1: {} - markdown-it-anchor@9.2.0(patch_hash=cdc28e7c329be30688ad192126ba505446611fbe526ad51483e4b1287aa35cf9)(@types/markdown-it@14.1.2)(markdown-it@14.2.0): - dependencies: - '@types/markdown-it': 14.1.2 - markdown-it: 14.2.0 - markdown-it-async@2.2.0: dependencies: '@types/markdown-it': 14.1.2 - markdown-it: 14.2.0 + markdown-it: 14.3.0 - markdown-it-attrs@4.3.1(patch_hash=12883b753541724964b5246a739df34c4b76db10415bbb63c35dce408cfe977e)(markdown-it@14.2.0): - dependencies: - markdown-it: 14.2.0 - - markdown-it-cjk-friendly@2.0.2(@types/markdown-it@14.1.2)(markdown-it@14.2.0): + markdown-it-cjk-friendly@2.0.2(@types/markdown-it@14.1.2)(markdown-it@14.3.0): dependencies: get-east-asian-width: 1.6.0 - markdown-it: 14.2.0 + markdown-it: 14.3.0 optionalDependencies: '@types/markdown-it': 14.1.2 - markdown-it-container@4.0.0: {} - - markdown-it-emoji@3.0.0: {} - markdown-it-mathjax3@4.3.2: dependencies: juice: 8.1.0 @@ -4548,12 +4350,12 @@ snapshots: transitivePeerDependencies: - encoding - markdown-it@14.2.0: + markdown-it@14.3.0: dependencies: argparse: 2.0.1 entities: 4.5.0 - linkify-it: 5.0.1 - mdurl: 2.0.0 + linkify-it: 5.0.2 + mdurl: 2.1.0 punycode.js: 2.3.1 uc.micro: 2.1.0 @@ -4603,9 +4405,9 @@ snapshots: mdast-util-to-hast@13.2.1: dependencies: - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 '@types/mdast': 4.0.4 - '@ungap/structured-clone': 1.3.2 + '@ungap/structured-clone': 1.3.3 devlop: 1.1.0 micromark-util-sanitize-uri: 2.0.1 trim-lines: 3.0.1 @@ -4629,13 +4431,11 @@ snapshots: dependencies: '@types/mdast': 4.0.4 - mdurl@2.0.0: {} + mdurl@2.1.0: {} mensch@0.3.4: {} - meow@12.1.1: {} - - meow@13.2.0: {} + meow@14.1.0: {} merge2@1.4.1: {} @@ -4800,9 +4600,9 @@ snapshots: mimic-function@5.0.1: {} - minimatch@10.2.5: + minimatch@10.2.6: dependencies: - brace-expansion: 5.0.6 + brace-expansion: 5.0.9 minimist@1.2.8: {} @@ -4816,27 +4616,19 @@ snapshots: muggle-string@0.4.1: {} - nanoid@3.3.15: {} - - nanoid@5.1.16: {} + nanoid@3.3.16: {} - neo-async@2.6.2: {} + nanoid@6.0.0: {} node-fetch@2.7.0: dependencies: whatwg-url: 5.0.0 - normalize-package-data@7.0.1: - dependencies: - hosted-git-info: 8.1.0 - semver: 7.8.5 - validate-npm-package-license: 3.0.4 - nth-check@2.1.1: dependencies: boolbase: 1.0.0 - obug@2.1.3: {} + obug@2.1.4: {} onetime@7.0.0: dependencies: @@ -4850,20 +4642,23 @@ snapshots: regex: 6.1.0 regex-recursion: 6.0.2 - open-cli@8.0.0: + open-cli@9.0.0: dependencies: - file-type: 18.7.0 - get-stdin: 9.0.0 - meow: 12.1.1 - open: 10.2.0 + file-type: 21.3.4 + meow: 14.1.0 + open: 11.0.0 tempy: 3.2.0 + transitivePeerDependencies: + - supports-color - open@10.2.0: + open@11.0.0: dependencies: default-browser: 5.5.0 define-lazy-prop: 3.0.0 + is-in-ssh: 1.0.0 is-inside-container: 1.0.0 - wsl-utils: 0.1.0 + powershell-utils: 0.1.0 + wsl-utils: 0.3.1 ora@9.4.1: dependencies: @@ -4874,15 +4669,15 @@ snapshots: is-unicode-supported: 2.1.0 log-symbols: 7.0.1 stdin-discarder: 0.3.2 - string-width: 5.1.2 + string-width: 8.2.2 - p-map@7.0.4: {} + p-map@7.0.6: {} package-directory@8.2.0: dependencies: find-up-simple: 1.0.1 - package-manager-detector@1.6.0: {} + package-manager-detector@1.8.0: {} parse5-htmlparser2-tree-adapter@6.0.1: dependencies: @@ -4900,30 +4695,28 @@ snapshots: pathe@2.0.3: {} - peek-readable@5.4.2: {} - perfect-debounce@2.1.0: {} picocolors@1.1.1: {} picomatch@2.3.2: {} - picomatch@4.0.4: {} + picomatch@4.0.5: {} - playwright-chromium@1.61.1: + playwright-chromium@1.62.1: dependencies: - playwright-core: 1.61.1 + playwright-core: 1.62.1 - playwright-core@1.61.1: {} + playwright-core@1.62.1: {} polka@1.0.0-next.28: dependencies: '@polka/url': 1.0.0-next.29 trouter: 4.0.0 - postcss-rtlcss@6.0.0(postcss@8.5.16): + postcss-rtlcss@6.0.0(postcss@8.5.25): dependencies: - postcss: 8.5.16 + postcss: 8.5.25 rtlcss: 4.3.0 postcss-selector-parser@7.1.4: @@ -4931,28 +4724,17 @@ snapshots: cssesc: 3.0.0 util-deprecate: 1.0.2 - postcss@8.5.15: - dependencies: - nanoid: 3.3.15 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - postcss@8.5.16: + postcss@8.5.25: dependencies: - nanoid: 3.3.15 + nanoid: 3.3.16 picocolors: 1.1.1 source-map-js: 1.2.1 - prettier@3.9.0: {} + powershell-utils@0.1.0: {} - pretty-bytes@7.1.0: {} + prettier@3.9.6: {} - process@0.11.10: {} - - prompts@2.4.2: - dependencies: - kleur: 3.0.3 - sisteransi: 1.0.5 + pretty-bytes@7.1.1: {} property-information@7.2.0: {} @@ -4964,18 +4746,6 @@ snapshots: queue-microtask@1.2.3: {} - 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: - readable-stream: 4.7.0 - readdirp@5.0.0: {} regex-recursion@6.0.2: @@ -5041,84 +4811,82 @@ snapshots: reusify@1.1.0: {} - rfdc@1.4.1: {} - - rolldown@1.1.4: + rolldown@1.2.1: dependencies: - '@oxc-project/types': 0.138.0 + '@oxc-project/types': 0.142.0 '@rolldown/pluginutils': 1.0.1 optionalDependencies: - '@rolldown/binding-android-arm64': 1.1.4 - '@rolldown/binding-darwin-arm64': 1.1.4 - '@rolldown/binding-darwin-x64': 1.1.4 - '@rolldown/binding-freebsd-x64': 1.1.4 - '@rolldown/binding-linux-arm-gnueabihf': 1.1.4 - '@rolldown/binding-linux-arm64-gnu': 1.1.4 - '@rolldown/binding-linux-arm64-musl': 1.1.4 - '@rolldown/binding-linux-ppc64-gnu': 1.1.4 - '@rolldown/binding-linux-s390x-gnu': 1.1.4 - '@rolldown/binding-linux-x64-gnu': 1.1.4 - '@rolldown/binding-linux-x64-musl': 1.1.4 - '@rolldown/binding-openharmony-arm64': 1.1.4 - '@rolldown/binding-wasm32-wasi': 1.1.4 - '@rolldown/binding-win32-arm64-msvc': 1.1.4 - '@rolldown/binding-win32-x64-msvc': 1.1.4 - - rollup-plugin-dts@6.1.1(rollup@4.62.2)(typescript@5.9.3): + '@rolldown/binding-android-arm64': 1.2.1 + '@rolldown/binding-darwin-arm64': 1.2.1 + '@rolldown/binding-darwin-x64': 1.2.1 + '@rolldown/binding-freebsd-x64': 1.2.1 + '@rolldown/binding-linux-arm-gnueabihf': 1.2.1 + '@rolldown/binding-linux-arm64-gnu': 1.2.1 + '@rolldown/binding-linux-arm64-musl': 1.2.1 + '@rolldown/binding-linux-ppc64-gnu': 1.2.1 + '@rolldown/binding-linux-s390x-gnu': 1.2.1 + '@rolldown/binding-linux-x64-gnu': 1.2.1 + '@rolldown/binding-linux-x64-musl': 1.2.1 + '@rolldown/binding-openharmony-arm64': 1.2.1 + '@rolldown/binding-wasm32-wasi': 1.2.1 + '@rolldown/binding-win32-arm64-msvc': 1.2.1 + '@rolldown/binding-win32-x64-msvc': 1.2.1 + + rollup-plugin-dts@6.1.1(rollup@4.62.3)(typescript@5.9.3): dependencies: magic-string: 0.30.21 - rollup: 4.62.2 + rollup: 4.62.3 typescript: 5.9.3 optionalDependencies: '@babel/code-frame': 7.29.7 - rollup-plugin-esbuild@6.2.1(esbuild@0.27.7)(rollup@4.62.2): + rollup-plugin-esbuild@6.2.1(esbuild@0.27.7)(rollup@4.62.3): dependencies: debug: 4.4.3 es-module-lexer: 1.7.0 esbuild: 0.27.7 get-tsconfig: 4.14.0 - rollup: 4.62.2 + rollup: 4.62.3 unplugin-utils: 0.2.5 transitivePeerDependencies: - supports-color - rollup@4.62.2: + rollup@4.62.3: dependencies: '@types/estree': 1.0.9 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.62.2 - '@rollup/rollup-android-arm64': 4.62.2 - '@rollup/rollup-darwin-arm64': 4.62.2 - '@rollup/rollup-darwin-x64': 4.62.2 - '@rollup/rollup-freebsd-arm64': 4.62.2 - '@rollup/rollup-freebsd-x64': 4.62.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.62.2 - '@rollup/rollup-linux-arm-musleabihf': 4.62.2 - '@rollup/rollup-linux-arm64-gnu': 4.62.2 - '@rollup/rollup-linux-arm64-musl': 4.62.2 - '@rollup/rollup-linux-loong64-gnu': 4.62.2 - '@rollup/rollup-linux-loong64-musl': 4.62.2 - '@rollup/rollup-linux-ppc64-gnu': 4.62.2 - '@rollup/rollup-linux-ppc64-musl': 4.62.2 - '@rollup/rollup-linux-riscv64-gnu': 4.62.2 - '@rollup/rollup-linux-riscv64-musl': 4.62.2 - '@rollup/rollup-linux-s390x-gnu': 4.62.2 - '@rollup/rollup-linux-x64-gnu': 4.62.2 - '@rollup/rollup-linux-x64-musl': 4.62.2 - '@rollup/rollup-openbsd-x64': 4.62.2 - '@rollup/rollup-openharmony-arm64': 4.62.2 - '@rollup/rollup-win32-arm64-msvc': 4.62.2 - '@rollup/rollup-win32-ia32-msvc': 4.62.2 - '@rollup/rollup-win32-x64-gnu': 4.62.2 - '@rollup/rollup-win32-x64-msvc': 4.62.2 + '@rollup/rollup-android-arm-eabi': 4.62.3 + '@rollup/rollup-android-arm64': 4.62.3 + '@rollup/rollup-darwin-arm64': 4.62.3 + '@rollup/rollup-darwin-x64': 4.62.3 + '@rollup/rollup-freebsd-arm64': 4.62.3 + '@rollup/rollup-freebsd-x64': 4.62.3 + '@rollup/rollup-linux-arm-gnueabihf': 4.62.3 + '@rollup/rollup-linux-arm-musleabihf': 4.62.3 + '@rollup/rollup-linux-arm64-gnu': 4.62.3 + '@rollup/rollup-linux-arm64-musl': 4.62.3 + '@rollup/rollup-linux-loong64-gnu': 4.62.3 + '@rollup/rollup-linux-loong64-musl': 4.62.3 + '@rollup/rollup-linux-ppc64-gnu': 4.62.3 + '@rollup/rollup-linux-ppc64-musl': 4.62.3 + '@rollup/rollup-linux-riscv64-gnu': 4.62.3 + '@rollup/rollup-linux-riscv64-musl': 4.62.3 + '@rollup/rollup-linux-s390x-gnu': 4.62.3 + '@rollup/rollup-linux-x64-gnu': 4.62.3 + '@rollup/rollup-linux-x64-musl': 4.62.3 + '@rollup/rollup-openbsd-x64': 4.62.3 + '@rollup/rollup-openharmony-arm64': 4.62.3 + '@rollup/rollup-win32-arm64-msvc': 4.62.3 + '@rollup/rollup-win32-ia32-msvc': 4.62.3 + '@rollup/rollup-win32-x64-gnu': 4.62.3 + '@rollup/rollup-win32-x64-msvc': 4.62.3 fsevents: 2.3.3 rtlcss@4.3.0: dependencies: escalade: 3.2.0 picocolors: 1.1.1 - postcss: 8.5.15 + postcss: 8.5.25 strip-json-comments: 3.1.1 run-applescript@7.1.0: {} @@ -5131,9 +4899,7 @@ snapshots: dependencies: tslib: 2.8.1 - safe-buffer@5.2.1: {} - - sax@1.6.0: {} + sax@1.6.1: {} section-matter@1.0.0: dependencies: @@ -5148,16 +4914,16 @@ snapshots: shebang-regex@3.0.0: {} - shiki@4.3.0: + shiki@4.4.1: dependencies: - '@shikijs/core': 4.3.0 - '@shikijs/engine-javascript': 4.3.0 - '@shikijs/engine-oniguruma': 4.3.0 - '@shikijs/langs': 4.3.0 - '@shikijs/themes': 4.3.0 - '@shikijs/types': 4.3.0 + '@shikijs/core': 4.4.1 + '@shikijs/engine-javascript': 4.4.1 + '@shikijs/engine-oniguruma': 4.4.1 + '@shikijs/langs': 4.4.1 + '@shikijs/themes': 4.4.1 + '@shikijs/types': 4.4.1 '@shikijs/vscode-textmate': 10.0.2 - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 siginfo@2.0.0: {} @@ -5185,43 +4951,17 @@ snapshots: sitemap@9.0.1: dependencies: - '@types/node': 24.13.2 + '@types/node': 24.13.3 '@types/sax': 1.2.7 arg: 5.0.2 - sax: 1.6.0 - - slice-ansi@7.1.2: - dependencies: - ansi-styles: 6.2.3 - is-fullwidth-code-point: 5.1.0 - - slice-ansi@8.0.0: - dependencies: - ansi-styles: 6.2.3 - is-fullwidth-code-point: 5.1.0 + sax: 1.6.1 slick@1.12.2: {} source-map-js@1.2.1: {} - 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.23 - - spdx-exceptions@2.5.0: {} - - spdx-expression-parse@3.0.1: - dependencies: - spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.23 - - spdx-license-ids@3.0.23: {} - speech-rule-engine@4.1.4: dependencies: '@xmldom/xmldom': 0.9.10 @@ -5232,7 +4972,7 @@ snapshots: stackback@0.0.2: {} - std-env@4.1.0: {} + std-env@4.2.0: {} stdin-discarder@0.3.2: {} @@ -5244,27 +4984,11 @@ snapshots: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - string-width@5.1.2: - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.2.0 - - string-width@7.2.0: + string-width@8.2.2: dependencies: - emoji-regex: 10.6.0 get-east-asian-width: 1.6.0 strip-ansi: 7.2.0 - string-width@8.2.1: - dependencies: - get-east-asian-width: 1.6.0 - strip-ansi: 7.2.0 - - string_decoder@1.3.0: - dependencies: - safe-buffer: 5.2.1 - stringify-entities@4.0.4: dependencies: character-entities-html4: 2.1.0 @@ -5282,10 +5006,9 @@ snapshots: strip-json-comments@3.1.1: {} - strtok3@7.1.1: + strtok3@10.3.5: dependencies: '@tokenizer/token': 0.3.0 - peek-readable: 5.4.2 supports-preserve-symlinks-flag@1.0.0: {} @@ -5306,21 +5029,22 @@ snapshots: tinyglobby@0.2.17: dependencies: - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 - tinyrainbow@3.1.0: {} + tinyrainbow@3.1.1: {} to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - token-types@5.0.1: + token-types@6.1.2: dependencies: + '@borewit/text-codec': 0.2.2 '@tokenizer/token': 0.3.0 ieee754: 1.2.1 - tokenx@1.3.0: {} + tokenx@1.6.0: {} totalist@3.0.1: {} @@ -5344,14 +5068,13 @@ snapshots: uc.micro@2.1.0: {} - uglify-js@3.19.3: - optional: true + uint8array-extras@1.5.0: {} ultramatter@0.0.4: {} undici-types@7.18.2: {} - undici-types@7.24.6: {} + undici-types@8.3.0: {} unified@11.0.5: dependencies: @@ -5399,17 +5122,12 @@ snapshots: unplugin-utils@0.2.5: dependencies: pathe: 2.0.3 - picomatch: 4.0.4 + picomatch: 4.0.5 util-deprecate@1.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 - vfile-message@4.0.3: dependencies: '@types/unist': 3.0.3 @@ -5420,95 +5138,95 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite@8.1.3(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0): + vite@8.2.0(@types/node@26.1.2)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0): dependencies: - lightningcss: 1.32.0 - picomatch: 4.0.4 - postcss: 8.5.16 - rolldown: 1.1.4 + lightningcss: 1.33.0 + picomatch: 4.0.5 + postcss: 8.5.25 + rolldown: 1.2.1 tinyglobby: 0.2.17 optionalDependencies: - '@types/node': 25.9.4 + '@types/node': 26.1.2 esbuild: 0.27.7 fsevents: 2.3.3 jiti: 1.21.7 yaml: 2.9.0 - vitepress-plugin-group-icons@1.7.5(vite@8.1.3(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0)): + vitepress-plugin-group-icons@1.7.6(vite@8.2.0(@types/node@26.1.2)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0)): dependencies: '@iconify-json/logos': 1.2.11 - '@iconify-json/vscode-icons': 1.2.62 - '@iconify/utils': 3.1.3 + '@iconify-json/vscode-icons': 1.2.67 + '@iconify/utils': 3.1.4 optionalDependencies: - vite: 8.1.3(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0) + vite: 8.2.0(@types/node@26.1.2)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0) - vitepress-plugin-llms@1.13.2: + vitepress-plugin-llms@1.13.4: dependencies: - gray-matter: 4.0.3 - markdown-it: 14.2.0 + '@11ty/gray-matter': 2.1.0 + markdown-it: 14.3.0 markdown-title: 1.0.2 mdast-util-from-markdown: 2.0.3 millify: 6.1.0 - minimatch: 10.2.5 + minimatch: 10.2.6 path-to-regexp: 6.3.0 picocolors: 1.1.1 - pretty-bytes: 7.1.0 + pretty-bytes: 7.1.1 remark: 15.0.1 remark-frontmatter: 5.0.0 - tokenx: 1.3.0 + tokenx: 1.6.0 unist-util-remove: 4.0.0 unist-util-visit: 5.1.0 transitivePeerDependencies: - supports-color - vitest@4.1.9(@types/node@25.9.4)(vite@8.1.3(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0)): + vitest@4.1.10(@types/node@26.1.2)(vite@8.2.0(@types/node@26.1.2)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0)): dependencies: - '@vitest/expect': 4.1.9 - '@vitest/mocker': 4.1.9(vite@8.1.3(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0)) - '@vitest/pretty-format': 4.1.9 - '@vitest/runner': 4.1.9 - '@vitest/snapshot': 4.1.9 - '@vitest/spy': 4.1.9 - '@vitest/utils': 4.1.9 - es-module-lexer: 2.3.0 + '@vitest/expect': 4.1.10 + '@vitest/mocker': 4.1.10(vite@8.2.0(@types/node@26.1.2)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0)) + '@vitest/pretty-format': 4.1.10 + '@vitest/runner': 4.1.10 + '@vitest/snapshot': 4.1.10 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 + es-module-lexer: 2.3.1 expect-type: 1.4.0 magic-string: 0.30.21 - obug: 2.1.3 + obug: 2.1.4 pathe: 2.0.3 - picomatch: 4.0.4 - std-env: 4.1.0 + picomatch: 4.0.5 + std-env: 4.2.0 tinybench: 2.9.0 tinyexec: 1.2.4 tinyglobby: 0.2.17 - tinyrainbow: 3.1.0 - vite: 8.1.3(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0) + tinyrainbow: 3.1.1 + vite: 8.2.0(@types/node@26.1.2)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 25.9.4 + '@types/node': 26.1.2 transitivePeerDependencies: - msw vscode-uri@3.1.0: {} - vue-tsc@3.3.5(typescript@5.9.3): + vue-tsc@3.3.9(typescript@5.9.3): dependencies: '@volar/typescript': 2.4.28 - '@vue/language-core': 3.3.5 + '@vue/language-core': 3.3.9 typescript: 5.9.3 - vue@3.5.39(typescript@5.9.3): + vue@3.5.40(typescript@5.9.3): dependencies: - '@vue/compiler-dom': 3.5.39 - '@vue/compiler-sfc': 3.5.39 - '@vue/runtime-dom': 3.5.39 - '@vue/server-renderer': 3.5.39(vue@3.5.39(typescript@5.9.3)) - '@vue/shared': 3.5.39 + '@vue/compiler-dom': 3.5.40 + '@vue/compiler-sfc': 3.5.40 + '@vue/runtime-dom': 3.5.40 + '@vue/server-renderer': 3.5.40 + '@vue/shared': 3.5.40 optionalDependencies: typescript: 5.9.3 - wait-on@9.0.10: + wait-on@9.1.0(debug@4.4.3): dependencies: - axios: 1.18.1 + axios: 1.19.0(debug@4.4.3) joi: 18.2.3 lodash: 4.18.1 minimist: 1.2.8 @@ -5548,27 +5266,21 @@ snapshots: wicked-good-xpath@1.3.0: {} - wordwrap@1.0.0: {} - wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - wrap-ansi@9.0.2: - dependencies: - ansi-styles: 6.2.3 - string-width: 7.2.0 - strip-ansi: 7.2.0 - - wsl-utils@0.1.0: + wsl-utils@0.3.1: dependencies: is-wsl: 3.1.1 + powershell-utils: 0.1.0 y18n@5.0.8: {} - yaml@2.9.0: {} + yaml@2.9.0: + optional: true yargs-parser@21.1.1: {} @@ -5582,7 +5294,7 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 - yoctocolors@2.1.2: {} + yoctocolors@2.2.0: {} zod@3.25.76: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index aefb59fe..057dece6 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -2,22 +2,20 @@ packages: - docs - __tests__/* +allowBuilds: + esbuild: true + playwright-chromium: true + simple-git-hooks: true + autoInstallPeers: false ignoreWorkspaceRootCheck: true -onlyBuiltDependencies: - - esbuild - - playwright-chromium - - simple-git-hooks - -overrides: - ora>string-width: ^5 - -patchedDependencies: - '@types/markdown-it-attrs': patches/@types__markdown-it-attrs@4.1.3.patch - '@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 - markdown-it-attrs@4.3.1: patches/markdown-it-attrs@4.3.1.patch +minimumReleaseAge: 1440 +minimumReleaseAgeExclude: + - '@mdit/*' + - '@vueuse/*' shellEmulator: true + +strictPeerDependencies: true diff --git a/rollup.config.ts b/rollup.config.ts index 23c9d41f..7f040f6f 100644 --- a/rollup.config.ts +++ b/rollup.config.ts @@ -5,6 +5,7 @@ import { nodeResolve } from '@rollup/plugin-node-resolve' import replace from '@rollup/plugin-replace' import { rm } from 'node:fs/promises' import { builtinModules, createRequire } from 'node:module' +import { fileURLToPath } from 'node:url' import { type RollupOptions, defineConfig } from 'rollup' import dts from 'rollup-plugin-dts' import esbuild from 'rollup-plugin-esbuild' @@ -53,11 +54,27 @@ const esmBuild: RollupOptions = { } } -const typesExternal = [ - ...external, - /\/vitepress\/(?!(dist|node_modules|vitepress)\/).*\.d\.ts$/, - /^markdown-it(?:\/|$)/ -] +// keep .d.ts files under the repo root (e.g. types/*) external so module +// augmentations in the bundle still target the same files users reference. +// compared on normalized resolved paths so this works regardless of the +// checkout location, path separators, or drive-letter casing. +const normalizePath = (id: string): string => { + const normalized = id.replaceAll('\\', '/') + return process.platform === 'win32' ? normalized.toLowerCase() : normalized +} + +const root = normalizePath(fileURLToPath(new URL('.', import.meta.url))) + +const typesExternal = (id: string): boolean => { + if (external.includes(id) || /^markdown-it(?:\/|$)/.test(id)) return true + const normalized = normalizePath(id) + return ( + normalized.endsWith('.d.ts') && + normalized.startsWith(root) && + !normalized.startsWith(`${root}dist/`) && + !normalized.startsWith(`${root}node_modules/`) + ) +} const dtsNode = dts({ respectExternal: true, diff --git a/scripts/fontSubsets.json b/scripts/fontSubsets.json new file mode 100644 index 00000000..1890fae9 --- /dev/null +++ b/scripts/fontSubsets.json @@ -0,0 +1,11 @@ +{ + "cyrillic-ext": "U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F", + "cyrillic": "U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116", + "greek-ext": "U+1F00-1FFF", + "greek": "U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF", + "vietnamese": "U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB", + "latin-ext": "U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF", + "latin": "U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+21A9,U+2212,U+2215,U+2318,U+FEFF,U+FFFD", + "symbols": "U+02CD,U+02D8-02D9,U+02DB,U+0302,U+0306-0307,U+030A,U+030C,U+030F,U+0313,U+0315,U+031B,U+0326-0328,U+032C,U+0337-0338,U+0342-0343,U+0346-036F,U+0E3F,U+1DC0-1DF5,U+1DFC-1DFF,U+2070-2071,U+2074-208E,U+2090-209C,U+20DB-20DE,U+20E8,U+20F0,U+2100-2101,U+2103,U+2105-2106,U+2109,U+2117,U+211E-2121,U+2126,U+212A-212B,U+212E,U+2132,U+213B,U+214D,U+2150-217F,U+2183-2186,U+2189,U+2190,U+2192,U+2194-2199,U+21AA,U+21B0-21B1,U+21B3-21B5,U+21BA-21BB,U+21D0,U+21D2,U+21D4,U+21DE-21DF,U+21E4-21E5,U+21E7,U+21EA,U+2202,U+2205-2206,U+220F,U+2211,U+221A,U+221E,U+222B,U+2236,U+2248,U+2260,U+2264-2265,U+2295-2298,U+2303-2305,U+2325-2327,U+232B,U+2380,U+2387,U+238B,U+23CE-23CF,U+2423,U+2460-2468,U+24B6-24CF,U+24EA,U+25A0-25A2,U+25AA,U+25B2-25B3,U+25B6-25B7,U+25BA-25BD,U+25C0-25C1,U+25C4-25C7,U+25CA-25CB,U+25CF,U+25E6,U+25EF,U+2600,U+2605-2606,U+263C,U+2661,U+2665,U+266A-266B,U+26A0,U+2713,U+2717,U+2756,U+2764,U+2780-2788,U+27EF,U+27F5-27FA,U+2913,U+2A38,U+2B06,U+2B12-2B13,U+2B1C,U+2B24,U+2E18,U+A92E,U+1F12F-1F149,U+1F16A-1F16B,U+1F850,U+1F852", + "cjkExclusions": "U+007E,U+00B7,U+02C4,U+02C7,U+02C9-02CB,U+02CD,U+02D0,U+02D8-02D9,U+02DB,U+02DD,U+02DF,U+2013-2015,U+2018-2019,U+201C-201D,U+2026,U+203B,U+2074,U+207F,U+2081-2084,U+2103,U+2105,U+2109,U+2121,U+2126,U+212B,U+2153-2154,U+215B-215E,U+2160-216B,U+2170-2179,U+2189,U+2190,U+2192,U+2194-2199,U+21D2,U+21D4,U+21E7,U+2202,U+220F,U+2211,U+221A,U+221E,U+222B,U+2236,U+2248,U+2260,U+2264-2265,U+2295,U+2460-2468,U+24B6-24CF,U+25A0-25A1,U+25B2-25B3,U+25B6-25B7,U+25BC-25BD,U+25C0-25C1,U+25C6-25C7,U+25CB,U+25CF,U+25EF,U+2605-2606,U+2661,U+2665,U+266A,U+2B1C,U+1F130-1F149" +} diff --git a/scripts/genWebTypes.ts b/scripts/genWebTypes.ts new file mode 100644 index 00000000..ce372f4e --- /dev/null +++ b/scripts/genWebTypes.ts @@ -0,0 +1,78 @@ +import { mkdirSync, readFileSync, writeFileSync } from 'node:fs' + +const { version } = JSON.parse(readFileSync('package.json', 'utf-8')) + +const webTypes = { + $schema: 'http://json.schemastore.org/web-types', + framework: 'vue', + name: 'vitepress', + version, + 'js-types-syntax': 'typescript', + 'description-markup': 'markdown', + contributions: { + html: { + 'vue-components': [ + { + name: 'Content', + source: { symbol: 'Content' }, + description: + 'Displays the rendered markdown contents. Useful when creating your own theme.', + 'doc-url': 'https://vitepress.dev/reference/runtime-api#content', + props: [ + { + name: 'as', + description: + 'The content wrapper. Accepts an HTML tag name, a component name, or a component reference.', + type: ['string', 'object'], + default: 'div' + } + ] + }, + { + name: 'ClientOnly', + source: { symbol: 'ClientOnly' }, + description: + 'Renders its slot only at client side. Useful for wrapping components that are not SSR-friendly.', + 'doc-url': 'https://vitepress.dev/reference/runtime-api#clientonly', + slots: [ + { + name: 'default', + description: 'Content to render once the client app is mounted.' + } + ] + }, + { + name: 'Badge', + source: { module: 'vitepress/theme', symbol: 'VPBadge' }, + description: + "Adds a status label to headers, such as a section's type or supported version. Available when using the default theme.", + 'doc-url': 'https://vitepress.dev/reference/default-theme-badge', + props: [ + { + name: 'type', + description: 'The badge color type.', + type: "'info' | 'tip' | 'warning' | 'danger'", + default: 'tip' + }, + { + name: 'text', + description: + 'The text displayed inside the badge. Ignored when the default slot is passed.', + type: 'string' + } + ], + slots: [ + { + name: 'default', + description: + 'Content displayed inside the badge. Takes precedence over the `text` prop.' + } + ] + } + ] + } + } +} + +mkdirSync('dist', { recursive: true }) +writeFileSync('dist/web-types.json', JSON.stringify(webTypes, null, 2) + '\n') diff --git a/scripts/release.ts b/scripts/release.ts index 2d4d1505..1e44e490 100644 --- a/scripts/release.ts +++ b/scripts/release.ts @@ -1,11 +1,11 @@ import { spawn } from 'cross-spawn' import type { SpawnOptions } from 'node:child_process' +import { once } from 'node:events' import fs from 'node:fs' import { createRequire } from 'node:module' import { resolve } from 'node:path' import { fileURLToPath } from 'node:url' -import c from 'picocolors' -import prompts from 'prompts' +import * as prompts from '@clack/prompts' import semver from 'semver' const { version: currentVersion } = createRequire(import.meta.url)( @@ -19,25 +19,21 @@ const tags = ['latest', 'next'] as const const dir = fileURLToPath(new URL('.', import.meta.url)) const inc = (i: semver.ReleaseType) => _inc(currentVersion, i) -const run = (bin: string, args: string[], opts: SpawnOptions = {}) => - new Promise((resolve, reject) => { - const child = spawn(bin, args, { - stdio: 'inherit', - ...opts - }) - - child.on('error', reject) - child.on('close', (code, signal) => { - if (code === 0) { - resolve() - } else if (signal) { - reject(new Error(`${bin} exited with signal ${signal}`)) - } else { - reject(new Error(`${bin} exited with code ${code}`)) - } - }) - }) -const step = (msg: string) => console.log(c.cyan(msg)) +const run = async (bin: string, args: string[], opts: SpawnOptions = {}) => { + const child = spawn(bin, args, { stdio: 'inherit', ...opts }) + const [code, signal] = (await once(child, 'close')) as [ + number | null, + NodeJS.Signals | null + ] + if (code !== 0) { + throw new Error( + signal + ? `${bin} exited with signal ${signal}` + : `${bin} exited with code ${code}` + ) + } +} +const cancel = () => prompts.cancel('Operation cancelled') async function main() { let targetVersion: string @@ -46,22 +42,19 @@ async function main() { .map((i) => `${i} (${inc(i)})`) .concat(['custom']) - const { release } = await prompts({ - type: 'select', - name: 'release', + const release = await prompts.select({ message: 'Select release type', - choices: versions.map((title, value) => ({ title, value })) + options: versions.map((label, value) => ({ label, value })) }) + if (prompts.isCancel(release)) return cancel() if (release === 3) { - targetVersion = ( - await prompts({ - type: 'text', - name: 'version', - message: 'Input custom version', - initial: currentVersion - }) - ).version + const customVersion = await prompts.text({ + message: 'Input custom version', + initialValue: currentVersion + }) + if (prompts.isCancel(customVersion)) return cancel() + targetVersion = customVersion } else { targetVersion = versions[release].match(/\((.*)\)/)![1] } @@ -70,39 +63,35 @@ async function main() { throw new Error(`Invalid target version: ${targetVersion}`) } - const { tag } = await prompts({ - type: 'select', - name: 'tag', + const tag = await prompts.select({ message: 'Select tag type', - choices: tags.map((title, value) => ({ title, value })) + options: tags.map((label, value) => ({ label, value })) }) + if (prompts.isCancel(tag)) return cancel() - const { yes: tagOk } = await prompts({ - type: 'confirm', - name: 'yes', + const tagOk = await prompts.confirm({ message: `Releasing v${targetVersion} on ${tags[tag]}. Confirm?` }) + if (prompts.isCancel(tagOk)) return cancel() if (!tagOk) { return } // Update the package version. - step('\nUpdating the package version...') + prompts.log.step('Updating the package version...') updatePackage(targetVersion) // Build the package. - step('\nBuilding the package...') + prompts.log.step('Building the package...') await run('pnpm', ['build']) // Generate the changelog. - step('\nGenerating the changelog...') + prompts.log.step('Generating the changelog...') await run('pnpm', ['changelog']) await run('pnpm', ['prettier', '--write', 'CHANGELOG.md']) - const { yes: changelogOk } = await prompts({ - type: 'confirm', - name: 'yes', + const changelogOk = await prompts.confirm({ message: `Changelog generated. Does it look good?` }) @@ -111,13 +100,13 @@ async function main() { } // Commit changes to the Git and create a tag. - step('\nCommitting changes...') + prompts.log.step('Committing changes...') await run('git', ['add', 'CHANGELOG.md', 'package.json']) await run('git', ['commit', '-m', `release: v${targetVersion}`]) await run('git', ['tag', `v${targetVersion}`]) // Publish the package. - step('\nPublishing the package...') + prompts.log.step('Publishing the package...') await run('pnpm', [ 'publish', '--tag', @@ -127,7 +116,7 @@ async function main() { ]) // Push to GitHub. - step('\nPushing to GitHub...') + prompts.log.step('Pushing to GitHub...') await run('git', ['push', 'origin', `refs/tags/v${targetVersion}`]) await run('git', ['push']) } diff --git a/scripts/subsetFonts.py b/scripts/subsetFonts.py new file mode 100755 index 00000000..422b6b33 --- /dev/null +++ b/scripts/subsetFonts.py @@ -0,0 +1,247 @@ +#!/usr/bin/env -S uv run --script +# /// script +# requires-python = ">=3.11" +# dependencies = ["fonttools>=4.63", "brotli"] +# /// +"""Regenerate the default theme's Inter webfont subsets. + +Reads the subset definitions from scripts/fontSubsets.json, downloads the +pinned Inter release (cached in node_modules/.cache/inter), verifies that +every non-PUA codepoint of the full font is covered by some subset, writes +the woff2 files into src/client/theme-default/fonts, and regenerates the +@font-face declarations in the theme's fonts.css. + +Usage: scripts/subsetFonts.py +""" + +import io +import json +import sys +import urllib.request +import zipfile +from pathlib import Path + +from fontTools import subset +from fontTools.ttLib import TTFont + +INTER_VERSION = "4.1" + +ROOT = Path(__file__).resolve().parent.parent +SUBSETS_JSON = ROOT / "scripts" / "fontSubsets.json" +FONTS_DIR = ROOT / "src" / "client" / "theme-default" / "fonts" +FONTS_CSS = ROOT / "src" / "client" / "theme-default" / "styles" / "fonts.css" +CACHE_DIR = ROOT / "node_modules" / ".cache" / "inter" + +STYLES = { + "italic": ("InterVariable-Italic.ttf", "italic"), + "roman": ("InterVariable.ttf", "normal"), +} + +# Inter maps its internal alternate glyphs into the Private Use Area. These +# are intentionally not shipped: they are not real text, and declaring PUA +# unicode-ranges would let Inter shadow icon fonts that live there. +PUA = range(0xE000, 0xF8FF + 1) + +BASE_VAR = """\ +:root { + --vp-font-family-base: + 'Inter', -apple-system, BlinkMacSystemFont, sans-serif, 'Apple Color Emoji', + 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; +} +""" + +# The 'Inter Core' faces leave the `cjkExclusions` characters uncovered so that +# they fall through to the next family in the stack, which therefore must be +# an explicit CJK font: a Latin system font (or `sans-serif`) would claim most +# of the excluded punctuation before the language-aware system fallback ever +# got a chance to pick the right CJK font. The names below cover the defaults +# of macOS / Windows / Linux (fonts-noto-cjk); families that are not installed +# are simply skipped, and sites can splice a CJK webfont between 'Inter Core' +# and the system families. Bare zh means Hans per BCP 47 likely subtags, and +# with no Traditional Chinese rule it also covers zh-Hant/zh-TW/zh-HK/zh-MO +# pages. If Hant handling is ever requested, add after the zh rule (same +# specificity, so the later rule wins; the region tags must be enumerated +# because `:lang(zh-Hant)` cannot match e.g. `lang="zh-TW"`): +# [lang]:where(:lang(zh-Hant), :lang(zh-TW), :lang(zh-HK), :lang(zh-MO)) { +# --vp-font-family-base: +# 'Inter Core', 'PingFang TC', 'Microsoft JhengHei', 'Noto Sans CJK TC', +# ...; +# } +# (Hong Kong variants also exist: 'PingFang HK' / 'Noto Sans CJK HK'.) +CJK_BASE_VAR = """\ +[lang]:where(:lang(zh)) { + --vp-font-family-base: + 'Inter Core', 'PingFang SC', 'Microsoft YaHei', 'Noto Sans CJK SC', + -apple-system, BlinkMacSystemFont, sans-serif, 'Apple Color Emoji', + 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; +} + +[lang]:where(:lang(ja)) { + --vp-font-family-base: + 'Inter Core', 'Hiragino Sans', 'Meiryo', 'Yu Gothic', 'Noto Sans CJK JP', + -apple-system, BlinkMacSystemFont, sans-serif, 'Apple Color Emoji', + 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; +} + +[lang]:where(:lang(ko)) { + --vp-font-family-base: + 'Inter Core', 'Apple SD Gothic Neo', 'Malgun Gothic', 'Noto Sans CJK KR', + -apple-system, BlinkMacSystemFont, sans-serif, 'Apple Color Emoji', + 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; +} +""" + +# used instead of everything else in this file when `useWebFonts` is enabled +# (only the content between the markers survives) - see +# src/node/plugins/webFontsPlugin.ts. There is no 'Inter Core' on Google Fonts, +# so CJK documents use the regular Inter there. +WEBFONT_IMPORT = f"""\ +/* webfont-marker-begin */ +@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap'); + +{BASE_VAR}\ +/* webfont-marker-end */ +""" + +# The `cjkExclusions` key of the json lists characters that have both a +# Western (proportional) and an East Asian (em-square) form with no +# encoding-level distinction - mostly East Asian Ambiguous punctuation and +# symbols (UAX #11). The generated 'Inter Core' faces reuse the same font files +# but leave these out of their unicode-ranges so that CJK fonts render them +# in CJK documents. References: +# https://www.unicode.org/L2/L2014/14006-sv-western-vs-cjk.pdf +# https://www.unicode.org/L2/L2018/18013-svs-proposal.pdf +# https://www.unicode.org/L2/L2018/18073-svs-proposal.pdf +# https://www.unicode.org/L2/L2023/23212r-quotes-svs-proposal.pdf +# https://github.com/w3c/clreq/blob/gh-pages/local.css +# & U+2015 (used like U+2014 in Japanese), U+203B (Japanese reference mark), +# U+007E (zh's request; both forms are fine in ja because it is unused there) +CJK_COMMENT = """\ +/* 'Inter Core' reuses the files above, but leaves out characters that should + be rendered by CJK fonts in CJK documents - see scripts/subsetFonts.py */ +""" + + +def parse_ranges(value: str) -> set[int]: + cps: set[int] = set() + for part in value.split(","): + lo, _, hi = part.strip().removeprefix("U+").partition("-") + cps.update(range(int(lo, 16), int(hi or lo, 16) + 1)) + return cps + + +def format_ranges(cps: set[int]) -> str: + ranges: list[tuple[int, int]] = [] + start = prev = -2 + for cp in sorted(cps): + if cp != prev + 1: + if start >= 0: + ranges.append((start, prev)) + start = cp + prev = cp + ranges.append((start, prev)) + return ", ".join( + f"U+{lo:04X}" if lo == hi else f"U+{lo:04X}-{hi:04X}" for lo, hi in ranges + ) + + +def download_release() -> Path: + release_dir = CACHE_DIR / f"Inter-{INTER_VERSION}" + zip_path = CACHE_DIR / f"Inter-{INTER_VERSION}.zip" + if not zip_path.exists(): + url = f"https://github.com/rsms/inter/releases/download/v{INTER_VERSION}/Inter-{INTER_VERSION}.zip" + print(f"downloading {url}") + CACHE_DIR.mkdir(parents=True, exist_ok=True) + with urllib.request.urlopen(url) as res: + zip_path.write_bytes(res.read()) + with zipfile.ZipFile(zip_path) as zf: + for file, _ in STYLES.values(): + if not (release_dir / file).exists(): + zf.extract(file, release_dir) + return release_dir + + +def check_coverage(release: Path, subsets: dict[str, str]) -> None: + covered = set().union(*(parse_ranges(v) for v in subsets.values())) + ok = True + for file, _ in STYLES.values(): + cmap = set(TTFont(release / file).getBestCmap()) + missing = sorted(cp for cp in cmap - covered if cp not in PUA) + if missing: + ok = False + print(f"{file}: {len(missing)} codepoints not covered by any subset:") + print(" " + ", ".join(f"U+{cp:04X}" for cp in missing)) + if not ok: + sys.exit("add the missing codepoints to a subset in scripts/fontSubsets.json") + + +def build_subsets(release: Path, subsets: dict[str, str]) -> None: + for style, (file, _) in STYLES.items(): + for name, value in subsets.items(): + options = subset.Options() + options.flavor = "woff2" + options.layout_features = [*options.layout_features, "pnum", "tnum"] + font = subset.load_font(release / file, options) + subsetter = subset.Subsetter(options) + subsetter.populate(unicodes=parse_ranges(value)) + subsetter.subset(font) + buf = io.BytesIO() + subset.save_font(font, buf, options) + out = FONTS_DIR / f"inter-{style}-{name}.woff2" + changed = not out.exists() or out.read_bytes() != buf.getvalue() + if changed: + out.write_bytes(buf.getvalue()) + print( + f"{out.name:36} {font['maxp'].numGlyphs:4} glyphs " + f"{buf.tell() / 1024:6.1f} KB{'' if changed else ' (unchanged)'}" + ) + + +def face(family: str, css_style: str, file: str, ranges: str) -> str: + return ( + "@font-face {\n" + f" font-family: {family};\n" + f" font-style: {css_style};\n" + " font-weight: 100 900;\n" + " font-display: swap;\n" + f" src: url('../fonts/{file}') format('woff2');\n" + f" unicode-range: {ranges};\n" + "}\n" + ) + + +def write_css(subsets: dict[str, str], cjk_exclusions: set[int]) -> None: + inter = [] + cjk = [] + for style, (_, css_style) in STYLES.items(): + for name, value in subsets.items(): + file = f"inter-{style}-{name}.woff2" + inter.append(face("Inter", css_style, file, value.replace(",", ", "))) + cjk_cps = parse_ranges(value) - cjk_exclusions + if cjk_cps: + cjk.append( + face("'Inter Core'", css_style, file, format_ranges(cjk_cps)) + ) + + FONTS_CSS.write_text( + f"{WEBFONT_IMPORT}\n" + "/* Generated by scripts/subsetFonts.py from scripts/fontSubsets.json */\n\n" + + "\n".join(inter) + + f"\n{CJK_COMMENT}\n" + + "\n".join(cjk) + + f"\n{BASE_VAR}\n{CJK_BASE_VAR}" + ) + + +def main() -> None: + subsets: dict[str, str] = json.loads(SUBSETS_JSON.read_text()) + cjk_exclusions = parse_ranges(subsets.pop("cjkExclusions")) + release = download_release() + check_coverage(release, subsets) + build_subsets(release, subsets) + write_css(subsets, cjk_exclusions) + print(f"\nwrote {len(subsets) * len(STYLES)} subsets and {FONTS_CSS.relative_to(ROOT)}") + + +if __name__ == "__main__": + main() diff --git a/src/client/app/components/Content.ts b/src/client/app/components/Content.ts index 12456451..d21ed2aa 100644 --- a/src/client/app/components/Content.ts +++ b/src/client/app/components/Content.ts @@ -10,8 +10,8 @@ export const Content = defineComponent({ as: { type: [Object, String], default: 'div' } }, setup(props) { - const route = useRoute() const { frontmatter, site } = useData() + const route = useRoute() watch(frontmatter, runCbs, { deep: true, flush: 'post' }) return () => h( diff --git a/src/client/app/composables/head.ts b/src/client/app/composables/head.ts index 13fb9bb0..2b63d5cf 100644 --- a/src/client/app/composables/head.ts +++ b/src/client/app/composables/head.ts @@ -3,9 +3,9 @@ import { createTitle, mergeHead, type HeadConfig, + type Route, type SiteData } from '../../shared' -import type { Route } from '../router' export function useUpdateHead(route: Route, siteDataByRouteRef: Ref) { let isFirstUpdate = true diff --git a/src/client/app/data.ts b/src/client/app/data.ts index 89297dba..7af33182 100644 --- a/src/client/app/data.ts +++ b/src/client/app/data.ts @@ -6,19 +6,17 @@ import { readonly, ref, shallowRef, - watch, type InjectionKey, type Ref } from 'vue' import { APPEARANCE_KEY, createTitle, - inBrowser, resolveSiteDataByRoute, + type Route, type SiteData, type VitePressData } from '../shared' -import type { Route } from './router' export const dataSymbol: InjectionKey = Symbol() export type { VitePressData } from '../shared' @@ -31,7 +29,11 @@ export const siteDataRef: Ref = shallowRef( // per-app data export function initData(route: Route): VitePressData { const site = computed(() => - resolveSiteDataByRoute(siteDataRef.value, route.data.relativePath) + resolveSiteDataByRoute( + siteDataRef.value, + route.data.relativePath, + route.data.filePath + ) ) const appearance = site.value.appearance // fine with reactivity being lost here, config change triggers a restart @@ -48,21 +50,6 @@ export function initData(route: Route): VitePressData { }) : 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), @@ -76,8 +63,7 @@ export function initData(route: Route): VitePressData { description: computed( () => route.data.description || site.value.description ), - isDark, - hash: computed(() => hashRef.value) + isDark } } diff --git a/src/client/app/router.ts b/src/client/app/router.ts index 5d3d86f1..818f46fb 100644 --- a/src/client/app/router.ts +++ b/src/client/app/router.ts @@ -1,18 +1,10 @@ import type { Component, InjectionKey } from 'vue' import { inject, markRaw, nextTick, reactive, readonly } from 'vue' -import type { Awaitable, PageData, PageDataPayload } from '../shared' +import type { Awaitable, PageData, PageDataPayload, Route } from '../shared' import { notFoundPageData, treatAsHtml } from '../shared' import { siteDataRef } from './data' import { inBrowser, withBase } from './utils' -export interface Route { - path: string - hash: string - query: string - data: PageData - component: Component | null -} - export interface Router { /** * Current route. diff --git a/src/client/app/utils.ts b/src/client/app/utils.ts index d63c5ee3..89e778ab 100644 --- a/src/client/app/utils.ts +++ b/src/client/app/utils.ts @@ -18,7 +18,7 @@ export function joinPath(base: string, path: string) { } /** - * Append base to internal (non-relative) urls + * Prepend base to internal (non-relative) urls */ export function withBase(path: string) { return EXTERNAL_URL_RE.test(path) || !path.startsWith('/') diff --git a/src/client/index.ts b/src/client/index.ts index 47074c43..80322bd7 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -2,15 +2,20 @@ // so the user can do `import { useRoute, useData } from 'vitepress'` // generic types -export type { Route, Router } from './app/router' -export type { VitePressData } from './shared' +export type { Router } from './app/router' +export type { Route, VitePressData } from './shared' // theme types export type { EnhanceAppContext, Theme } from './app/theme' // shared types +import type { PageData } from '../../types/shared' export type { HeadConfig, Header, PageData, SiteData } from '../../types/shared' +// components +import { ClientOnly } from './app/components/ClientOnly' +import { Content } from './app/components/Content' + // composables export { dataSymbol, useData } from './app/data' export { useRoute, useRouter } from './app/router' @@ -25,4 +30,16 @@ export { } from './app/utils' // components -export { Content } from './app/components/Content' +export { ClientOnly, Content } + +declare module 'vue' { + interface GlobalComponents { + ClientOnly: typeof ClientOnly + Content: typeof Content + } + + interface ComponentCustomProperties { + $frontmatter: PageData['frontmatter'] + $params: PageData['params'] + } +} diff --git a/src/client/theme-default/components/VPCarbonAds.vue b/src/client/theme-default/components/VPCarbonAds.vue index b8fc77a2..ca034ccb 100644 --- a/src/client/theme-default/components/VPCarbonAds.vue +++ b/src/client/theme-default/components/VPCarbonAds.vue @@ -1,10 +1,10 @@ diff --git a/src/client/theme-default/components/VPNavBarExtra.vue b/src/client/theme-default/components/VPNavBarExtra.vue index 7201623b..b234997d 100644 --- a/src/client/theme-default/components/VPNavBarExtra.vue +++ b/src/client/theme-default/components/VPNavBarExtra.vue @@ -8,7 +8,9 @@ import VPSocialLinks from './VPSocialLinks.vue' import VPSwitchAppearance from './VPSwitchAppearance.vue' const { site, theme } = useData() -const { localeLinks, currentLang } = useLangs({ correspondingLink: true }) +const { localeLinks, currentLang } = useLangs({ + linkToCorrespondingPage: true +}) const hasExtraContent = computed( () => @@ -24,13 +26,13 @@ const hasExtraContent = computed( class="VPNavBarExtra" label="extra navigation" > -
      -

      {{ currentLang.label }}

      +
    • {{ currentLang.label }}
    • - -
      +

    • +
    Main Navigation - +
      +
    • + + + +
    • +
    @@ -32,9 +34,13 @@ const { theme } = useData() display: none; } +.list { + display: flex; +} + @media (min-width: 768px) { .VPNavBarMenu { - display: flex; + display: block; } } diff --git a/src/client/theme-default/components/VPNavBarMenuGroup.vue b/src/client/theme-default/components/VPNavBarMenuGroup.vue index 4d014a49..61004f3f 100644 --- a/src/client/theme-default/components/VPNavBarMenuGroup.vue +++ b/src/client/theme-default/components/VPNavBarMenuGroup.vue @@ -1,19 +1,24 @@ diff --git a/src/client/theme-default/components/VPNavScreenMenuGroupLink.vue b/src/client/theme-default/components/VPNavScreenMenuGroupLink.vue index 9a884e01..53932dff 100644 --- a/src/client/theme-default/components/VPNavScreenMenuGroupLink.vue +++ b/src/client/theme-default/components/VPNavScreenMenuGroupLink.vue @@ -1,8 +1,8 @@ diff --git a/src/client/theme-default/components/VPNavScreenMenuGroupSection.vue b/src/client/theme-default/components/VPNavScreenMenuGroupSection.vue index a7e2cd38..e094a707 100644 --- a/src/client/theme-default/components/VPNavScreenMenuGroupSection.vue +++ b/src/client/theme-default/components/VPNavScreenMenuGroupSection.vue @@ -11,7 +11,11 @@ defineProps<{ diff --git a/src/client/theme-default/components/VPNavScreenMenuLink.vue b/src/client/theme-default/components/VPNavScreenMenuLink.vue index 9684cf78..c6b6bacf 100644 --- a/src/client/theme-default/components/VPNavScreenMenuLink.vue +++ b/src/client/theme-default/components/VPNavScreenMenuLink.vue @@ -1,8 +1,8 @@ diff --git a/src/client/theme-default/components/VPNavScreenTranslations.vue b/src/client/theme-default/components/VPNavScreenTranslations.vue index 108ac60c..c81b33ce 100644 --- a/src/client/theme-default/components/VPNavScreenTranslations.vue +++ b/src/client/theme-default/components/VPNavScreenTranslations.vue @@ -3,7 +3,9 @@ import { ref } from 'vue' import { useLangs } from '../composables/langs' import VPLink from './VPLink.vue' -const { localeLinks, currentLang } = useLangs({ correspondingLink: true }) +const { localeLinks, currentLang } = useLangs({ + linkToCorrespondingPage: true +}) const isOpen = ref(false) function toggle() { @@ -33,6 +35,7 @@ function toggle() { :hreflang="locale.lang" rel="alternate" :dir="locale.dir" + data-allow-mismatch="attribute" > {{ locale.text }} diff --git a/src/client/theme-default/components/VPSidebarItem.vue b/src/client/theme-default/components/VPSidebarItem.vue index d71d1062..e4c63f2b 100644 --- a/src/client/theme-default/components/VPSidebarItem.vue +++ b/src/client/theme-default/components/VPSidebarItem.vue @@ -94,16 +94,16 @@ function onCaretClick() {
    -
    - -
    + + diff --git a/src/client/theme-default/components/VPSocialLinks.vue b/src/client/theme-default/components/VPSocialLinks.vue index 062f7f62..f30b86c9 100644 --- a/src/client/theme-default/components/VPSocialLinks.vue +++ b/src/client/theme-default/components/VPSocialLinks.vue @@ -11,17 +11,17 @@ withDefaults(defineProps<{ diff --git a/src/client/theme-default/components/VPSponsorsGrid.vue b/src/client/theme-default/components/VPSponsorsGrid.vue index 65dbe81b..370e5af0 100644 --- a/src/client/theme-default/components/VPSponsorsGrid.vue +++ b/src/client/theme-default/components/VPSponsorsGrid.vue @@ -22,8 +22,8 @@ useSponsorsGrid({ el, size: props.size }) diff --git a/src/client/theme-default/components/VPTeamMembers.vue b/src/client/theme-default/components/VPTeamMembers.vue index 0337eb5a..6b83e4a6 100644 --- a/src/client/theme-default/components/VPTeamMembers.vue +++ b/src/client/theme-default/components/VPTeamMembers.vue @@ -17,11 +17,11 @@ const classes = computed(() => [props.size, `count-${props.members.length}`]) @@ -63,4 +63,15 @@ const classes = computed(() => [props.size, `count-${props.members.length}`]) margin: 0 auto; max-width: 1152px; } + +/* Reset styles from vp-doc if used in markdown */ +.vp-doc .VPTeamMembers .container { + list-style: none; + margin: 0 auto; + padding: 0; +} +.vp-doc .VPTeamMembers .item { + margin: 0; + padding: 0; +} diff --git a/src/client/theme-default/composables/flyout.ts b/src/client/theme-default/composables/flyout.ts index 9b10a704..5f80e93f 100644 --- a/src/client/theme-default/composables/flyout.ts +++ b/src/client/theme-default/composables/flyout.ts @@ -1,5 +1,5 @@ +import { inBrowser } from 'vitepress' import { onUnmounted, readonly, type Ref, ref, watch } from 'vue' -import { inBrowser } from '../../shared' interface UseFlyoutOptions { el: Ref diff --git a/src/client/theme-default/composables/langs.ts b/src/client/theme-default/composables/langs.ts index 9c10a1e9..64ca65ce 100644 --- a/src/client/theme-default/composables/langs.ts +++ b/src/client/theme-default/composables/langs.ts @@ -1,12 +1,24 @@ -import { computed } from 'vue' import type { DefaultTheme } from 'vitepress/theme' -import type { VitePressData } from '../../app/data' +import { computed } from 'vue' +import { useRoute } from '../../app/router' +import type { Route, VitePressData } from '../../shared' import { ensureStartingSlash } from '../support/utils' import { useData } from './data' -export function useLangs({ correspondingLink = false } = {}) { +export function useLangs({ + linkToCorrespondingPage = false +}: { + /** + * Link each entry of the translations menu to the current page's + * equivalent in that locale (resolved by `resolveLocaleLink`) instead of + * that locale's home page. + */ + linkToCorrespondingPage?: boolean +} = {}) { const data = useData() + const route = useRoute() const { site, localeIndex } = data + const currentLang = computed(() => ({ label: site.value.locales[localeIndex.value]?.label, link: @@ -20,58 +32,83 @@ export function useLangs({ correspondingLink = false } = {}) { ? [] : { text: value.label, - link: resolveLocaleLink( - data, - key, - value.link || (key === 'root' ? '/' : `/${key}/`), - currentLang.value.link, - correspondingLink - ), + link: resolveLocaleLink(data, route, { + targetLocale: key, + targetLocaleLink: + value.link || (key === 'root' ? '/' : `/${key}/`), + currentLocaleLink: currentLang.value.link, + linkToCorrespondingPage + }), lang: value.lang, dir: value.dir } ) ) - return { localeLinks, currentLang } + return { currentLang, localeLinks } } +/** + * Resolves the link used for switching from the current page to + * `targetLocale`. Without `linkToCorrespondingPage`, this is simply the home + * of the target locale. With it, the current page's path is rewritten into + * the target locale (honoring `cleanUrls`) — unless + * `themeConfig.i18nRouting` is `false` (the locale home is used instead) or + * a function (which then fully controls the resolution). + * + * The current query and hash are carried over, except when a custom + * `i18nRouting` function is used. + */ export function resolveLocaleLink( data: VitePressData, - targetLocale: string, - targetLink: string, - currentLink: string, - correspondingLink: boolean + route: Route, + { + targetLocale, + targetLocaleLink, + currentLocaleLink, + linkToCorrespondingPage + }: { + /** Key of the target locale in `site.locales`, e.g. `'fr'` or `'root'`. */ + targetLocale: string + /** Home link of the target locale, e.g. `'/fr/'`. */ + targetLocaleLink: string + /** Home link of the locale the current page is in, e.g. `'/'`. */ + currentLocaleLink: string + /** Link to the current page's equivalent instead of the locale home. */ + linkToCorrespondingPage: boolean + } ) { - const { site, page, theme, hash } = data + const { site, theme } = data const i18nRouting = theme.value.i18nRouting - if (correspondingLink && typeof i18nRouting === 'function') { - return i18nRouting(data, hash.value, targetLocale) + if (linkToCorrespondingPage && typeof i18nRouting === 'function') { + return i18nRouting(data, route, targetLocale) } return ( normalizeLink( - targetLink, - i18nRouting !== false && correspondingLink, - page.value.relativePath.slice(currentLink.length - 1), + targetLocaleLink, + i18nRouting !== false && linkToCorrespondingPage, + route.data.relativePath.slice(currentLocaleLink.length - 1), !site.value.cleanUrls - ) + hash.value + ) + + route.query + + route.hash ) } function normalizeLink( - link: string, - addPath: boolean, - path: string, - addExt: boolean + localeLink: string, + appendPagePath: boolean, + pagePath: string, + addHtmlExt: boolean ) { - return addPath - ? link.replace(/\/$/, '') + + return appendPagePath + ? localeLink.replace(/\/$/, '') + ensureStartingSlash( - path + pagePath .replace(/(^|\/)index\.md$/, '$1') - .replace(/\.md$/, addExt ? '.html' : '') + .replace(/\.md$/, addHtmlExt ? '.html' : '') ) - : link + : localeLink } diff --git a/src/client/theme-default/composables/layout.ts b/src/client/theme-default/composables/layout.ts index 37943eec..d6efb7ec 100644 --- a/src/client/theme-default/composables/layout.ts +++ b/src/client/theme-default/composables/layout.ts @@ -74,7 +74,7 @@ interface RegisterWatchersOptions { } export function registerWatchers({ closeSidebar }: RegisterWatchersOptions) { - const { frontmatter, page, theme } = useData() + const { theme, page, frontmatter } = useData() watch( () => [page.value.relativePath, theme.value.sidebar] as const, diff --git a/src/client/theme-default/composables/outline.ts b/src/client/theme-default/composables/outline.ts index bc03203f..067b2b1a 100644 --- a/src/client/theme-default/composables/outline.ts +++ b/src/client/theme-default/composables/outline.ts @@ -13,7 +13,6 @@ export function resolveTitle(theme: DefaultTheme.Config): string { (typeof theme.outline === 'object' && !Array.isArray(theme.outline) && theme.outline.label) || - theme.outlineTitle || 'On this page' ) } @@ -100,7 +99,6 @@ export function useActiveAnchor( onUnmounted(() => { window.removeEventListener('scroll', onScroll) - container.value.removeEventListener('click', onClick) }) function onClick(e: MouseEvent) { diff --git a/src/client/theme-default/composables/prev-next.ts b/src/client/theme-default/composables/prev-next.ts index d04db435..258d9856 100644 --- a/src/client/theme-default/composables/prev-next.ts +++ b/src/client/theme-default/composables/prev-next.ts @@ -1,20 +1,24 @@ import { computed } from 'vue' -import { isActive } from '../../shared' +import { isActive, normalize } from '../../shared' import { getFlatSideBarLinks, getSidebar } from '../support/sidebar' +import { uniqBy } from '../support/utils' import { useData } from './data' export function usePrevNext() { - const { page, theme, frontmatter } = useData() + const { theme, page, frontmatter } = useData() - return computed(() => { + return computed<{ + prev?: { text?: string; link?: string; target?: string; rel?: string } + next?: { text?: string; link?: string; target?: string; rel?: string } + }>(() => { const sidebar = getSidebar(theme.value.sidebar, page.value.relativePath) const links = getFlatSideBarLinks(sidebar) // ignore inner-page links with hashes - const candidates = uniqBy(links, (link) => link.link.replace(/[?#].*$/, '')) + const candidates = uniqBy(links, (link) => normalize(link.link)) const index = candidates.findIndex((link) => { - return isActive(page.value.relativePath, link.link) + return isActive(page.value.relativePath, '', link.link, false, true) }) const hidePrev = @@ -74,17 +78,6 @@ export function usePrevNext() { ? frontmatter.value.next.rel : undefined) ?? candidates[index + 1]?.rel } - } as { - prev?: { text?: string; link?: string; target?: string; rel?: string } - next?: { text?: string; link?: string; target?: string; rel?: string } } }) } - -function uniqBy(array: T[], keyFn: (item: T) => any): T[] { - const seen = new Set() - return array.filter((item) => { - const k = keyFn(item) - return seen.has(k) ? false : seen.add(k) - }) -} diff --git a/src/client/theme-default/composables/sidebar.ts b/src/client/theme-default/composables/sidebar.ts index b693cc89..1b9df6bd 100644 --- a/src/client/theme-default/composables/sidebar.ts +++ b/src/client/theme-default/composables/sidebar.ts @@ -1,17 +1,17 @@ +import { useRoute } from 'vitepress' import type { DefaultTheme } from 'vitepress/theme' import { computed, + nextTick, onMounted, onUnmounted, ref, watch, watchEffect, - watchPostEffect, type ComputedRef } from 'vue' import { isActive } from '../../shared' import { hasActiveLink as containsActiveLink } from '../support/sidebar' -import { useData } from './data' const isOpen = ref(false) @@ -68,7 +68,7 @@ export function useSidebarControl() { export function useSidebarItemControl( item: ComputedRef ) { - const { page, hash } = useData() + const route = useRoute() const collapsed = ref(false) @@ -81,22 +81,39 @@ export function useSidebarItemControl( }) const isActiveLink = ref(false) - const updateIsActiveLink = () => { - isActiveLink.value = isActive(page.value.relativePath, item.value.link) - } - - watch([page, item, hash], updateIsActiveLink) - onMounted(updateIsActiveLink) - - const hasActiveLink = computed(() => { + const hasActiveLink = ref(false) + + function updateActiveLink(): void { + if (item.value.link) { + isActiveLink.value = isActive( + route.data.relativePath, + route.hash, + item.value.link + ) + } else { + isActiveLink.value = false + } if (isActiveLink.value) { - return true + hasActiveLink.value = true + nextTick(() => (collapsed.value = false)) + return + } + if (!item.value.items) { + hasActiveLink.value = false + return + } + hasActiveLink.value = containsActiveLink( + route.data.relativePath, + route.hash, + item.value.items + ) + if (hasActiveLink.value) { + nextTick(() => (collapsed.value = false)) } + } - return item.value.items - ? containsActiveLink(page.value.relativePath, item.value.items) - : false - }) + watch([item, route], updateActiveLink) + onMounted(updateActiveLink) const hasChildren = computed(() => { return !!(item.value.items && item.value.items.length) @@ -106,11 +123,7 @@ export function useSidebarItemControl( collapsed.value = !!(collapsible.value && item.value.collapsed) }) - watchPostEffect(() => { - ;(isActiveLink.value || hasActiveLink.value) && (collapsed.value = false) - }) - - function toggle() { + function toggle(): void { if (collapsible.value) { collapsed.value = !collapsed.value } @@ -120,8 +133,8 @@ export function useSidebarItemControl( collapsed, collapsible, isLink, - isActiveLink, - hasActiveLink, + isActiveLink: isActiveLink as ComputedRef, + hasActiveLink: hasActiveLink as ComputedRef, hasChildren, toggle } diff --git a/src/client/theme-default/fonts/inter-italic-latin.woff2 b/src/client/theme-default/fonts/inter-italic-latin.woff2 index fdc2aa22..94a1ae94 100644 Binary files a/src/client/theme-default/fonts/inter-italic-latin.woff2 and b/src/client/theme-default/fonts/inter-italic-latin.woff2 differ diff --git a/src/client/theme-default/fonts/inter-italic-symbols.woff2 b/src/client/theme-default/fonts/inter-italic-symbols.woff2 new file mode 100644 index 00000000..d8425105 Binary files /dev/null and b/src/client/theme-default/fonts/inter-italic-symbols.woff2 differ diff --git a/src/client/theme-default/fonts/inter-roman-latin.woff2 b/src/client/theme-default/fonts/inter-roman-latin.woff2 index 18a8987f..c428d326 100644 Binary files a/src/client/theme-default/fonts/inter-roman-latin.woff2 and b/src/client/theme-default/fonts/inter-roman-latin.woff2 differ diff --git a/src/client/theme-default/fonts/inter-roman-symbols.woff2 b/src/client/theme-default/fonts/inter-roman-symbols.woff2 new file mode 100644 index 00000000..ba86b3dc Binary files /dev/null and b/src/client/theme-default/fonts/inter-roman-symbols.woff2 differ diff --git a/src/client/theme-default/index.ts b/src/client/theme-default/index.ts index fe52cd65..ff26e67f 100644 --- a/src/client/theme-default/index.ts +++ b/src/client/theme-default/index.ts @@ -1,3 +1,4 @@ +import './without-fonts' import './styles/fonts.css' export * from './without-fonts' diff --git a/src/client/theme-default/styles/base.css b/src/client/theme-default/styles/base.css index a9215ae8..52a3c664 100644 --- a/src/client/theme-default/styles/base.css +++ b/src/client/theme-default/styles/base.css @@ -1,56 +1,41 @@ @layer __vitepress_base { - @media (prefers-reduced-motion: reduce) { - *, - ::before, - ::after { - animation-delay: -1ms !important; - animation-duration: 1ms !important; - animation-iteration-count: 1 !important; - background-attachment: initial !important; - scroll-behavior: auto !important; - transition-duration: 0s !important; - transition-delay: 0s !important; - } - } + /* #region Tailwind Preflight */ + + /* Based on https://github.com/tailwindlabs/tailwindcss/blob/e48c5e80473c25fe5a27fe267fbaf4f6512424a3/packages/tailwindcss/preflight.css, + with the `--theme()` references replaced by vitepress variables, and `bolder` replaced by `600` */ *, + ::after, ::before, - ::after { + ::backdrop, + ::file-selector-button { box-sizing: border-box; + margin: 0; + padding: 0; + border: 0 solid; } - html { - line-height: 1.4; - font-size: 16px; + html, + :host { + line-height: 1.5; -webkit-text-size-adjust: 100%; scrollbar-gutter: stable; + tab-size: 4; + font-family: var(--vp-font-family-base); + font-feature-settings: normal; + font-variation-settings: normal; + -webkit-tap-highlight-color: transparent; } - html.dark { - color-scheme: dark; - } - - body { - margin: 0; - width: 100%; - min-width: 320px; - min-height: 100vh; - line-height: 24px; - font-family: var(--vp-font-family-base); - font-size: 16px; - font-weight: 400; - color: var(--vp-c-text-1); - background-color: var(--vp-c-bg); - font-synthesis: style; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - text-autospace: normal; - text-spacing-trim: normal; + hr { + height: 0; + color: inherit; + border-top-width: 1px; } - main { - display: block; + abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; } h1, @@ -59,70 +44,73 @@ h4, h5, h6 { - margin: 0; - line-height: 24px; - font-size: 16px; - font-weight: 400; + font-size: inherit; + font-weight: inherit; } - p { - margin: 0; + a { + color: inherit; + -webkit-text-decoration: inherit; + text-decoration: inherit; } - strong, - b { + b, + strong { font-weight: 600; } - /** - * Avoid 300ms click delay on touch devices that support the `touch-action` - * CSS property. - * - * In particular, unlike most other browsers, IE11+Edge on Windows 10 on - * touch devices and IE Mobile 10-11 DON'T remove the click delay when - * `` is present. - * However, they DO support removing the click delay via - * `touch-action: manipulation`. - * - * See: - * - http://v4-alpha.getbootstrap.com/content/reboot/#click-delay-optimization-for-touch - * - http://caniuse.com/#feat=css-touch-action - * - http://patrickhlauke.github.io/touch/tests/results/#suppressing-300ms-delay - */ - a, - area, - button, - [role='button'], - input, - label, - select, - summary, - textarea { - touch-action: manipulation; + code, + kbd, + samp, + pre { + font-family: var(--vp-font-family-mono); + font-feature-settings: normal; + font-variation-settings: normal; + font-size: 1em; } - a { - color: inherit; - text-decoration: inherit; + small { + font-size: 80%; } - ol, - ul { - list-style: none; - margin: 0; - padding: 0; + sub, + sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; } - blockquote { - margin: 0; + sub { + bottom: -0.25em; } - pre, - code, - kbd, - samp { - font-family: var(--vp-font-family-mono); - text-autospace: no-autospace; + sup { + top: -0.5em; + } + + table { + text-indent: 0; + border-color: inherit; + border-collapse: collapse; + } + + :-moz-focusring:where(:not(iframe)) { + outline: auto; + } + + progress { + vertical-align: baseline; + } + + summary { + display: list-item; + } + + ol, + ul, + menu { + list-style: none; } img, @@ -136,10 +124,6 @@ display: block; } - figure { - margin: 0; - } - img, video { max-width: 100%; @@ -148,87 +132,171 @@ button, input, - optgroup, select, - textarea { - border: 0; - padding: 0; - line-height: inherit; + optgroup, + textarea, + ::file-selector-button { + font: inherit; + font-feature-settings: inherit; + font-variation-settings: inherit; + letter-spacing: inherit; color: inherit; + border-radius: 0; + background-color: transparent; + opacity: 1; } - button { + :where(select:is([multiple], [size])) optgroup { + font-weight: 600; + } + + :where(select:is([multiple], [size])) optgroup option { + padding-inline-start: 20px; + } + + ::file-selector-button { + margin-inline-end: 4px; + } + + ::placeholder { + opacity: 1; + } + + @supports (not (-webkit-appearance: -apple-pay-button)) or + (contain-intrinsic-size: 1px) { + ::placeholder { + color: color-mix(in oklab, currentcolor 50%, transparent); + } + } + + textarea { + resize: vertical; + } + + ::-webkit-search-decoration { + -webkit-appearance: none; + } + + ::-webkit-date-and-time-value { + min-height: 1lh; + text-align: inherit; + } + + ::-webkit-datetime-edit { + display: inline-flex; + } + + ::-webkit-datetime-edit-fields-wrapper { padding: 0; - font-family: inherit; - background-color: transparent; - background-image: none; } - button:enabled, - [role='button']:enabled { - cursor: pointer; + ::-webkit-datetime-edit, + ::-webkit-datetime-edit-year-field, + ::-webkit-datetime-edit-month-field, + ::-webkit-datetime-edit-day-field, + ::-webkit-datetime-edit-hour-field, + ::-webkit-datetime-edit-minute-field, + ::-webkit-datetime-edit-second-field, + ::-webkit-datetime-edit-millisecond-field, + ::-webkit-datetime-edit-meridiem-field { + padding-block: 0; } - button:focus, - button:focus-visible { - outline: 1px dotted; - outline: 4px auto -webkit-focus-ring-color; + ::-webkit-calendar-picker-indicator { + line-height: 1; } - button:focus:not(:focus-visible) { - outline: none !important; + :-moz-ui-invalid { + box-shadow: none; } - input:focus, - textarea:focus, - select:focus { - outline: none; + button, + input:where([type='button'], [type='reset'], [type='submit']), + ::file-selector-button { + appearance: button; } - table { - border-collapse: collapse; + ::-webkit-inner-spin-button, + ::-webkit-outer-spin-button { + height: auto; } - input { - background-color: transparent; + [hidden]:where(:not([hidden='until-found'])) { + display: none !important; } - input:-ms-input-placeholder, - textarea:-ms-input-placeholder { - color: var(--vp-c-text-3); + /* #endregion */ + + /* #region VitePress Overrides */ + + /* https://web.dev/articles/prefers-reduced-motion#bonus_forcing_reduced_motion_on_all_websites */ + @media (prefers-reduced-motion: reduce) { + *, + ::before, + ::after { + animation-delay: -1ms !important; + animation-duration: 1ms !important; + animation-iteration-count: 1 !important; + background-attachment: initial !important; + scroll-behavior: auto !important; + transition-duration: 0s !important; + transition-delay: 0s !important; + } } - input::-ms-input-placeholder, - textarea::-ms-input-placeholder { - color: var(--vp-c-text-3); + :root { + /* FIXME: pins rem-sized bits while the theme is px-based - remove when + moving to relative units (#570) */ + font-size: 16px; + + &:is(.dark) { + color-scheme: dark; + } + &:not(.dark) { + color-scheme: light; + } } - input::placeholder, - textarea::placeholder { - color: var(--vp-c-text-3); + body { + /* FIXME: unlike html's unitless 1.5, this is inherited as-is by elements + with other font sizes - make unitless with #570 */ + line-height: 24px; + color: var(--vp-c-text-1); + background-color: var(--vp-c-bg); + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-autospace: normal; + text-spacing-trim: normal; } - input::-webkit-outer-spin-button, - input::-webkit-inner-spin-button { - -webkit-appearance: none; - margin: 0; + pre, + code, + kbd, + samp { + text-autospace: no-autospace; } - input[type='number'] { - -moz-appearance: textfield; + button:enabled, + [role='button']:enabled { + cursor: pointer; } - textarea { - resize: vertical; + button:focus, + input:focus, + textarea:focus, + select:focus { + outline: none; } - select { - -webkit-appearance: none; + button:focus-visible { + outline: 1px dotted; + outline: 4px auto -webkit-focus-ring-color; } - fieldset { - margin: 0; - padding: 0; + input::placeholder, + textarea::placeholder { + color: var(--vp-c-text-3); } h1, @@ -242,22 +310,6 @@ overflow-wrap: break-word; } - sub, - sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; - } - - sub { - bottom: -0.25em; - } - - sup { - top: -0.5em; - } - vite-error-overlay { z-index: 9999; } @@ -270,4 +322,6 @@ display: inline-block; margin: auto; } + + /* #endregion */ } diff --git a/src/client/theme-default/styles/components/custom-block.css b/src/client/theme-default/styles/components/custom-block.css index a960381c..f3445a81 100644 --- a/src/client/theme-default/styles/components/custom-block.css +++ b/src/client/theme-default/styles/components/custom-block.css @@ -1,12 +1,17 @@ .custom-block { border: 1px solid transparent; border-radius: 8px; - padding: 16px 16px 8px; + padding: 8px 16px; line-height: 24px; font-size: var(--vp-custom-block-font-size); color: var(--vp-c-text-2); } +/* containers rendered with `{no-title}` keep the reduced padding */ +.custom-block:has(> .custom-block-title, > summary) { + padding-top: 16px; +} + .custom-block.info { border-color: var(--vp-custom-block-info-border); color: var(--vp-custom-block-info-text); diff --git a/src/client/theme-default/styles/components/vp-doc.css b/src/client/theme-default/styles/components/vp-doc.css index 904427fc..6250685e 100644 --- a/src/client/theme-default/styles/components/vp-doc.css +++ b/src/client/theme-default/styles/components/vp-doc.css @@ -1,3 +1,28 @@ +/** + * Anchors + * -------------------------------------------------------------------------- */ + +.vp-doc [id] { + scroll-margin-top: calc( + 47px + var(--vp-layout-top-height, 0px) + + var(--vp-extra-scroll-margin, 24px) + ); + + @media (min-width: 960px) { + scroll-margin-top: calc( + var(--vp-nav-height) + 47px + var(--vp-layout-top-height, 0px) + + var(--vp-extra-scroll-margin, 24px) + ); + } + + @media (min-width: 1280px) { + scroll-margin-top: calc( + var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + + var(--vp-extra-scroll-margin, 24px) + ); + } +} + /** * Headings * -------------------------------------------------------------------------- */ @@ -11,9 +36,6 @@ position: relative; font-weight: 600; outline: none; - scroll-margin-top: calc( - var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 24px - ); } .vp-doc h1 { @@ -29,6 +51,8 @@ letter-spacing: -0.02em; line-height: 32px; font-size: 24px; + /* since it already has a top padding of 24px, we don't need extra scroll margin */ + --vp-extra-scroll-margin: 0px; } .vp-doc h3 { @@ -163,6 +187,37 @@ margin: 8px 0 0; } +.vp-doc li > p:first-child { + margin-top: 0; +} + +.vp-doc li > p:last-child { + margin-bottom: 0; +} + +.vp-doc li.task-list-item { + list-style: none; +} + +.vp-doc .task-list-item-checkbox { + margin: 0 4px 2px -1.25rem; + vertical-align: middle; + accent-color: var(--vp-c-brand-1); +} + +/** + * Footnotes + * -------------------------------------------------------------------------- */ + +.vp-doc .footnote-ref a, +.vp-doc .footnote-backref { + text-decoration: none; +} + +.vp-doc .footnotes { + font-size: 14px; +} + /** * Table * -------------------------------------------------------------------------- */ @@ -508,7 +563,7 @@ color: var(--vp-code-copy-code-active-text); background-color: var(--vp-code-copy-code-hover-bg); white-space: nowrap; - content: var(--vp-code-copy-copied-text-content); + content: attr(data-copied); } .vp-doc [class*='language-'] > span.lang { @@ -576,6 +631,8 @@ -webkit-mask-size: 11px 11px; mask-size: 11px 11px; /*rtl:raw:transform: scaleX(-1);*/ + vertical-align: bottom; + font-size: 10px; } .vp-external-link-icon::after { diff --git a/src/client/theme-default/styles/components/vp-sponsor.css b/src/client/theme-default/styles/components/vp-sponsor.css index 9e677ab9..79de6b73 100644 --- a/src/client/theme-default/styles/components/vp-sponsor.css +++ b/src/client/theme-default/styles/components/vp-sponsor.css @@ -153,3 +153,11 @@ .dark .vp-sponsor-grid-image { filter: grayscale(1) invert(1); } + +/* Reset styles from vp-doc if used in markdown */ +.vp-doc .vp-sponsor-grid, +.vp-doc .vp-sponsor-grid-item { + list-style: none; + margin: 0; + padding: 0; +} diff --git a/src/client/theme-default/styles/fonts.css b/src/client/theme-default/styles/fonts.css index 03b72458..ed6d01df 100644 --- a/src/client/theme-default/styles/fonts.css +++ b/src/client/theme-default/styles/fonts.css @@ -1,15 +1,94 @@ /* webfont-marker-begin */ @import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap'); + +:root { + --vp-font-family-base: + 'Inter', -apple-system, BlinkMacSystemFont, sans-serif, 'Apple Color Emoji', + 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; +} /* webfont-marker-end */ +/* Generated by scripts/subsetFonts.py from scripts/fontSubsets.json */ + +@font-face { + font-family: Inter; + font-style: italic; + font-weight: 100 900; + font-display: swap; + src: url('../fonts/inter-italic-cyrillic-ext.woff2') format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} + +@font-face { + font-family: Inter; + font-style: italic; + font-weight: 100 900; + font-display: swap; + src: url('../fonts/inter-italic-cyrillic.woff2') format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} + +@font-face { + font-family: Inter; + font-style: italic; + font-weight: 100 900; + font-display: swap; + src: url('../fonts/inter-italic-greek-ext.woff2') format('woff2'); + unicode-range: U+1F00-1FFF; +} + +@font-face { + font-family: Inter; + font-style: italic; + font-weight: 100 900; + font-display: swap; + src: url('../fonts/inter-italic-greek.woff2') format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} + +@font-face { + font-family: Inter; + font-style: italic; + font-weight: 100 900; + font-display: swap; + src: url('../fonts/inter-italic-vietnamese.woff2') format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} + +@font-face { + font-family: Inter; + font-style: italic; + font-weight: 100 900; + font-display: swap; + src: url('../fonts/inter-italic-latin-ext.woff2') format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} + +@font-face { + font-family: Inter; + font-style: italic; + font-weight: 100 900; + font-display: swap; + src: url('../fonts/inter-italic-latin.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+21A9, U+2212, U+2215, U+2318, U+FEFF, U+FFFD; +} + +@font-face { + font-family: Inter; + font-style: italic; + font-weight: 100 900; + font-display: swap; + src: url('../fonts/inter-italic-symbols.woff2') format('woff2'); + unicode-range: U+02CD, U+02D8-02D9, U+02DB, U+0302, U+0306-0307, U+030A, U+030C, U+030F, U+0313, U+0315, U+031B, U+0326-0328, U+032C, U+0337-0338, U+0342-0343, U+0346-036F, U+0E3F, U+1DC0-1DF5, U+1DFC-1DFF, U+2070-2071, U+2074-208E, U+2090-209C, U+20DB-20DE, U+20E8, U+20F0, U+2100-2101, U+2103, U+2105-2106, U+2109, U+2117, U+211E-2121, U+2126, U+212A-212B, U+212E, U+2132, U+213B, U+214D, U+2150-217F, U+2183-2186, U+2189, U+2190, U+2192, U+2194-2199, U+21AA, U+21B0-21B1, U+21B3-21B5, U+21BA-21BB, U+21D0, U+21D2, U+21D4, U+21DE-21DF, U+21E4-21E5, U+21E7, U+21EA, U+2202, U+2205-2206, U+220F, U+2211, U+221A, U+221E, U+222B, U+2236, U+2248, U+2260, U+2264-2265, U+2295-2298, U+2303-2305, U+2325-2327, U+232B, U+2380, U+2387, U+238B, U+23CE-23CF, U+2423, U+2460-2468, U+24B6-24CF, U+24EA, U+25A0-25A2, U+25AA, U+25B2-25B3, U+25B6-25B7, U+25BA-25BD, U+25C0-25C1, U+25C4-25C7, U+25CA-25CB, U+25CF, U+25E6, U+25EF, U+2600, U+2605-2606, U+263C, U+2661, U+2665, U+266A-266B, U+26A0, U+2713, U+2717, U+2756, U+2764, U+2780-2788, U+27EF, U+27F5-27FA, U+2913, U+2A38, U+2B06, U+2B12-2B13, U+2B1C, U+2B24, U+2E18, U+A92E, U+1F12F-1F149, U+1F16A-1F16B, U+1F850, U+1F852; +} + @font-face { font-family: Inter; font-style: normal; font-weight: 100 900; font-display: swap; src: url('../fonts/inter-roman-cyrillic-ext.woff2') format('woff2'); - unicode-range: - U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @font-face { @@ -36,8 +115,7 @@ font-weight: 100 900; font-display: swap; src: url('../fonts/inter-roman-greek.woff2') format('woff2'); - unicode-range: - U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; } @font-face { @@ -46,10 +124,7 @@ font-weight: 100 900; font-display: swap; src: url('../fonts/inter-roman-vietnamese.woff2') format('woff2'); - unicode-range: - U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, - U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, - U+1EA0-1EF9, U+20AB; + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; } @font-face { @@ -58,10 +133,7 @@ font-weight: 100 900; font-display: swap; src: url('../fonts/inter-roman-latin-ext.woff2') format('woff2'); - unicode-range: - U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, - U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, - U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; } @font-face { @@ -70,24 +142,32 @@ font-weight: 100 900; font-display: swap; src: url('../fonts/inter-roman-latin.woff2') format('woff2'); - unicode-range: - U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, - U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, - U+2215, U+FEFF, U+FFFD; + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+21A9, U+2212, U+2215, U+2318, U+FEFF, U+FFFD; } @font-face { font-family: Inter; + font-style: normal; + font-weight: 100 900; + font-display: swap; + src: url('../fonts/inter-roman-symbols.woff2') format('woff2'); + unicode-range: U+02CD, U+02D8-02D9, U+02DB, U+0302, U+0306-0307, U+030A, U+030C, U+030F, U+0313, U+0315, U+031B, U+0326-0328, U+032C, U+0337-0338, U+0342-0343, U+0346-036F, U+0E3F, U+1DC0-1DF5, U+1DFC-1DFF, U+2070-2071, U+2074-208E, U+2090-209C, U+20DB-20DE, U+20E8, U+20F0, U+2100-2101, U+2103, U+2105-2106, U+2109, U+2117, U+211E-2121, U+2126, U+212A-212B, U+212E, U+2132, U+213B, U+214D, U+2150-217F, U+2183-2186, U+2189, U+2190, U+2192, U+2194-2199, U+21AA, U+21B0-21B1, U+21B3-21B5, U+21BA-21BB, U+21D0, U+21D2, U+21D4, U+21DE-21DF, U+21E4-21E5, U+21E7, U+21EA, U+2202, U+2205-2206, U+220F, U+2211, U+221A, U+221E, U+222B, U+2236, U+2248, U+2260, U+2264-2265, U+2295-2298, U+2303-2305, U+2325-2327, U+232B, U+2380, U+2387, U+238B, U+23CE-23CF, U+2423, U+2460-2468, U+24B6-24CF, U+24EA, U+25A0-25A2, U+25AA, U+25B2-25B3, U+25B6-25B7, U+25BA-25BD, U+25C0-25C1, U+25C4-25C7, U+25CA-25CB, U+25CF, U+25E6, U+25EF, U+2600, U+2605-2606, U+263C, U+2661, U+2665, U+266A-266B, U+26A0, U+2713, U+2717, U+2756, U+2764, U+2780-2788, U+27EF, U+27F5-27FA, U+2913, U+2A38, U+2B06, U+2B12-2B13, U+2B1C, U+2B24, U+2E18, U+A92E, U+1F12F-1F149, U+1F16A-1F16B, U+1F850, U+1F852; +} + +/* 'Inter Core' reuses the files above, but leaves out characters that should + be rendered by CJK fonts in CJK documents - see scripts/subsetFonts.py */ + +@font-face { + font-family: 'Inter Core'; font-style: italic; font-weight: 100 900; font-display: swap; src: url('../fonts/inter-italic-cyrillic-ext.woff2') format('woff2'); - unicode-range: - U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @font-face { - font-family: Inter; + font-family: 'Inter Core'; font-style: italic; font-weight: 100 900; font-display: swap; @@ -96,7 +176,7 @@ } @font-face { - font-family: Inter; + font-family: 'Inter Core'; font-style: italic; font-weight: 100 900; font-display: swap; @@ -105,79 +185,61 @@ } @font-face { - font-family: Inter; + font-family: 'Inter Core'; font-style: italic; font-weight: 100 900; font-display: swap; src: url('../fonts/inter-italic-greek.woff2') format('woff2'); - unicode-range: - U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; } @font-face { - font-family: Inter; + font-family: 'Inter Core'; font-style: italic; font-weight: 100 900; font-display: swap; src: url('../fonts/inter-italic-vietnamese.woff2') format('woff2'); - unicode-range: - U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, - U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, - U+1EA0-1EF9, U+20AB; + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; } @font-face { - font-family: Inter; + font-family: 'Inter Core'; font-style: italic; font-weight: 100 900; font-display: swap; src: url('../fonts/inter-italic-latin-ext.woff2') format('woff2'); - unicode-range: - U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, - U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, - U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; + unicode-range: U+0100-02BA, U+02BD-02C3, U+02C5, U+02C8, U+02CC, U+02CE-02CF, U+02D1-02D7, U+02DE, U+02E0-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; } @font-face { - font-family: Inter; + font-family: 'Inter Core'; font-style: italic; font-weight: 100 900; font-display: swap; src: url('../fonts/inter-italic-latin.woff2') format('woff2'); - unicode-range: - U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, - U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, - U+2215, U+FEFF, U+FFFD; + unicode-range: U+0000-007D, U+007F-00B6, U+00B8-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-2012, U+2016-2017, U+201A-201B, U+201E-2025, U+2027-203A, U+203C-206F, U+20AC, U+2122, U+2191, U+2193, U+21A9, U+2212, U+2215, U+2318, U+FEFF, U+FFFD; } -/* -Some code points in Inter are not compatible with CJK languages. - -https://www.unicode.org/L2/L2014/14006-sv-western-vs-cjk.pdf -https://www.unicode.org/L2/L2018/18013-svs-proposal.pdf -https://www.unicode.org/L2/L2018/18073-svs-proposal.pdf -https://www.unicode.org/L2/L2023/23212r-quotes-svs-proposal.pdf - -https://github.com/w3c/clreq/blob/f837ffe4a5501e72c17bd02961ce1b440916624f/local.css#L4 -& U+2015 (similar to U+2014 in Japanese) - -All CJK languages: U+00B7, U+2013, U+2014, U+2015, U+2018, U+2019, U+201C, U+201D, U+2026, U+2E3A -zh's request: U+007E (Both are fine in ja because unused there) -zh's request but decision postponed: U+002F (Both are fine in ja; include it into Inter for the time being) -*/ +@font-face { + font-family: 'Inter Core'; + font-style: italic; + font-weight: 100 900; + font-display: swap; + src: url('../fonts/inter-italic-symbols.woff2') format('woff2'); + unicode-range: U+0302, U+0306-0307, U+030A, U+030C, U+030F, U+0313, U+0315, U+031B, U+0326-0328, U+032C, U+0337-0338, U+0342-0343, U+0346-036F, U+0E3F, U+1DC0-1DF5, U+1DFC-1DFF, U+2070-2071, U+2075-207E, U+2080, U+2085-208E, U+2090-209C, U+20DB-20DE, U+20E8, U+20F0, U+2100-2101, U+2106, U+2117, U+211E-2120, U+212A, U+212E, U+2132, U+213B, U+214D, U+2150-2152, U+2155-215A, U+215F, U+216C-216F, U+217A-217F, U+2183-2186, U+21AA, U+21B0-21B1, U+21B3-21B5, U+21BA-21BB, U+21D0, U+21DE-21DF, U+21E4-21E5, U+21EA, U+2205-2206, U+2296-2298, U+2303-2305, U+2325-2327, U+232B, U+2380, U+2387, U+238B, U+23CE-23CF, U+2423, U+24EA, U+25A2, U+25AA, U+25BA-25BB, U+25C4-25C5, U+25CA, U+25E6, U+2600, U+263C, U+266B, U+26A0, U+2713, U+2717, U+2756, U+2764, U+2780-2788, U+27EF, U+27F5-27FA, U+2913, U+2A38, U+2B06, U+2B12-2B13, U+2B24, U+2E18, U+A92E, U+1F12F, U+1F16A-1F16B, U+1F850, U+1F852; +} @font-face { - font-family: Inter4CJK; + font-family: 'Inter Core'; font-style: normal; font-weight: 100 900; font-display: swap; src: url('../fonts/inter-roman-cyrillic-ext.woff2') format('woff2'); - unicode-range: - U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @font-face { - font-family: Inter4CJK; + font-family: 'Inter Core'; font-style: normal; font-weight: 100 900; font-display: swap; @@ -186,7 +248,7 @@ zh's request but decision postponed: U+002F (Both are fine in ja; include it int } @font-face { - font-family: Inter4CJK; + font-family: 'Inter Core'; font-style: normal; font-weight: 100 900; font-display: swap; @@ -195,125 +257,73 @@ zh's request but decision postponed: U+002F (Both are fine in ja; include it int } @font-face { - font-family: Inter4CJK; + font-family: 'Inter Core'; font-style: normal; font-weight: 100 900; font-display: swap; src: url('../fonts/inter-roman-greek.woff2') format('woff2'); - unicode-range: - U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; } @font-face { - font-family: Inter4CJK; + font-family: 'Inter Core'; font-style: normal; font-weight: 100 900; font-display: swap; src: url('../fonts/inter-roman-vietnamese.woff2') format('woff2'); - unicode-range: - U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, - U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, - U+1EA0-1EF9, U+20AB; + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; } @font-face { - font-family: Inter4CJK; + font-family: 'Inter Core'; font-style: normal; font-weight: 100 900; font-display: swap; src: url('../fonts/inter-roman-latin-ext.woff2') format('woff2'); - unicode-range: - U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, - U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; + unicode-range: U+0100-02BA, U+02BD-02C3, U+02C5, U+02C8, U+02CC, U+02CE-02CF, U+02D1-02D7, U+02DE, U+02E0-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; } -/* Exclude some ambiguous CJK characters. */ @font-face { - font-family: Inter4CJK; + font-family: 'Inter Core'; font-style: normal; font-weight: 100 900; font-display: swap; src: url('../fonts/inter-roman-latin.woff2') format('woff2'); - unicode-range: - U+0000-007D, U+007F-00B6, U+00B8-00FF, U+0131, U+0152-0153, U+02BB-02BC, - U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-2012, U+2016-2017, - U+201A-201B, U+201E-2025, U+2027-206F, U+2074, U+20AC, U+2122, U+2191, - U+2193, U+2212, U+2215, U+FEFF, U+FFFD; -} - -@font-face { - font-family: Inter4CJK; - font-style: italic; - font-weight: 100 900; - font-display: swap; - src: url('../fonts/inter-italic-cyrillic-ext.woff2') format('woff2'); - unicode-range: - U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; -} - -@font-face { - font-family: Inter4CJK; - font-style: italic; - font-weight: 100 900; - font-display: swap; - src: url('../fonts/inter-italic-cyrillic.woff2') format('woff2'); - unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; + unicode-range: U+0000-007D, U+007F-00B6, U+00B8-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-2012, U+2016-2017, U+201A-201B, U+201E-2025, U+2027-203A, U+203C-206F, U+20AC, U+2122, U+2191, U+2193, U+21A9, U+2212, U+2215, U+2318, U+FEFF, U+FFFD; } @font-face { - font-family: Inter4CJK; - font-style: italic; + font-family: 'Inter Core'; + font-style: normal; font-weight: 100 900; font-display: swap; - src: url('../fonts/inter-italic-greek-ext.woff2') format('woff2'); - unicode-range: U+1F00-1FFF; + src: url('../fonts/inter-roman-symbols.woff2') format('woff2'); + unicode-range: U+0302, U+0306-0307, U+030A, U+030C, U+030F, U+0313, U+0315, U+031B, U+0326-0328, U+032C, U+0337-0338, U+0342-0343, U+0346-036F, U+0E3F, U+1DC0-1DF5, U+1DFC-1DFF, U+2070-2071, U+2075-207E, U+2080, U+2085-208E, U+2090-209C, U+20DB-20DE, U+20E8, U+20F0, U+2100-2101, U+2106, U+2117, U+211E-2120, U+212A, U+212E, U+2132, U+213B, U+214D, U+2150-2152, U+2155-215A, U+215F, U+216C-216F, U+217A-217F, U+2183-2186, U+21AA, U+21B0-21B1, U+21B3-21B5, U+21BA-21BB, U+21D0, U+21DE-21DF, U+21E4-21E5, U+21EA, U+2205-2206, U+2296-2298, U+2303-2305, U+2325-2327, U+232B, U+2380, U+2387, U+238B, U+23CE-23CF, U+2423, U+24EA, U+25A2, U+25AA, U+25BA-25BB, U+25C4-25C5, U+25CA, U+25E6, U+2600, U+263C, U+266B, U+26A0, U+2713, U+2717, U+2756, U+2764, U+2780-2788, U+27EF, U+27F5-27FA, U+2913, U+2A38, U+2B06, U+2B12-2B13, U+2B24, U+2E18, U+A92E, U+1F12F, U+1F16A-1F16B, U+1F850, U+1F852; } -@font-face { - font-family: Inter4CJK; - font-style: italic; - font-weight: 100 900; - font-display: swap; - src: url('../fonts/inter-italic-greek.woff2') format('woff2'); - unicode-range: - U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +:root { + --vp-font-family-base: + 'Inter', -apple-system, BlinkMacSystemFont, sans-serif, 'Apple Color Emoji', + 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; } -@font-face { - font-family: Inter4CJK; - font-style: italic; - font-weight: 100 900; - font-display: swap; - src: url('../fonts/inter-italic-vietnamese.woff2') format('woff2'); - unicode-range: - U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, - U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, - U+1EA0-1EF9, U+20AB; +[lang]:where(:lang(zh)) { + --vp-font-family-base: + 'Inter Core', 'PingFang SC', 'Microsoft YaHei', 'Noto Sans CJK SC', + -apple-system, BlinkMacSystemFont, sans-serif, 'Apple Color Emoji', + 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; } -@font-face { - font-family: Inter4CJK; - font-style: italic; - font-weight: 100 900; - font-display: swap; - src: url('../fonts/inter-italic-latin-ext.woff2') format('woff2'); - unicode-range: - U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, - U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +[lang]:where(:lang(ja)) { + --vp-font-family-base: + 'Inter Core', 'Hiragino Sans', 'Meiryo', 'Yu Gothic', 'Noto Sans CJK JP', + -apple-system, BlinkMacSystemFont, sans-serif, 'Apple Color Emoji', + 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; } -/* Exclude some ambiguous CJK characters. */ -@font-face { - font-family: Inter4CJK; - font-style: italic; - font-weight: 100 900; - font-display: swap; - src: url('../fonts/inter-italic-latin.woff2') format('woff2'); - unicode-range: - U+0000-007D, U+007F-00B6, U+00B8-00FF, U+0131, U+0152-0153, U+02BB-02BC, - U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-2012, U+2016-2017, - U+201A-201B, U+201E-2025, U+2027-206F, U+2074, U+20AC, U+2122, U+2191, - U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +[lang]:where(:lang(ko)) { + --vp-font-family-base: + 'Inter Core', 'Apple SD Gothic Neo', 'Malgun Gothic', 'Noto Sans CJK KR', + -apple-system, BlinkMacSystemFont, sans-serif, 'Apple Color Emoji', + 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; } - -/* Generate the subsetted fonts using: `pyftsubset .woff2 --unicodes="" --layout-features+=pnum,tnum --flavor=woff2 --output-file="inter-