diff --git a/.github/contributing.md b/.github/contributing.md index 5738cbc2..c2f14f4a 100644 --- a/.github/contributing.md +++ b/.github/contributing.md @@ -19,7 +19,7 @@ Hi! We're really excited that you are interested in contributing to VitePress. B - It's OK to have multiple small commits as you work on the PR - GitHub can automatically squash them before merging. -- Commit messages must follow the [commit message convention](./commit-convention.md) so that changelogs can be automatically generated. +- Commit messages must follow the [commit message convention](/.github/commit-convention.md) so that changelogs can be automatically generated. ## Development Setup diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a89cc38c..aa97e0f7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,7 +18,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - node_version: [20, 22, 24, latest] + node_version: [22, 24, 26] include: - os: windows-latest node_version: 24 diff --git a/CHANGELOG.md b/CHANGELOG.md index b3c1b636..3240a3db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,46 @@ +## [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 + +- **build:** apply `base` to links with download attribute ([#5186](https://github.com/vuejs/vitepress/issues/5186)) ([01987c4](https://github.com/vuejs/vitepress/commit/01987c4c0838478a8fda81f427775f28476c5557)) +- **build:** normalize rewrite drive letters ([#5245](https://github.com/vuejs/vitepress/issues/5245)) ([5c50b99](https://github.com/vuejs/vitepress/commit/5c50b99724815a6fb3d2311e801dcad4aeb9b412)) +- **build:** show dead link line numbers ([#5230](https://github.com/vuejs/vitepress/issues/5230)) ([c37bde6](https://github.com/vuejs/vitepress/commit/c37bde6308fb9f202e224f5eb38c0fac35468ea6)) +- compose markdown config when extending configs ([#5236](https://github.com/vuejs/vitepress/issues/5236)) ([04f4fba](https://github.com/vuejs/vitepress/commit/04f4fbadbdc05c75dbf3564c21404540d570d43b)) +- delete undefined values while merging sidepanel props ([cc30b10](https://github.com/vuejs/vitepress/commit/cc30b10b60beb862f85915055dc97651703bf250)) +- disable pluginTimings and invalidAnnotation for now ([9315fc1](https://github.com/vuejs/vitepress/commit/9315fc182229f13ee793dc44107947b2fe6ab50e)) +- don't invalidate framework chunk when a new asset is added ([c0e2e18](https://github.com/vuejs/vitepress/commit/c0e2e1809464c48435a22a0aa9468ff5e562791d)) +- escape description in head ([d96bf1d](https://github.com/vuejs/vitepress/commit/d96bf1dc616599609d8a24af7183aee6a7b9ae07)) +- index rewritten local search pages by locale ([#5241](https://github.com/vuejs/vitepress/issues/5241)) ([80cf265](https://github.com/vuejs/vitepress/commit/80cf2650aa5fa4b49093509f60766cc5b28c19bc)) +- keep translation links in the current tab ([#5158](https://github.com/vuejs/vitepress/issues/5158)) ([202ee70](https://github.com/vuejs/vitepress/commit/202ee7026054ac5c721bbdbf196426628b0c9b18)) +- normalize `/index` to `/` ([856858d](https://github.com/vuejs/vitepress/commit/856858d26a78f2e19e2c8ee23c2e85a95dbfdd29)), closes [#5165](https://github.com/vuejs/vitepress/issues/5165) +- preserve Agent Studio DocSearch options ([#5254](https://github.com/vuejs/vitepress/issues/5254)) ([f29ffdb](https://github.com/vuejs/vitepress/commit/f29ffdbb33022eb41327fec836f9cfbc16bf01d8)) +- preserve external sidebar links with base ([#5243](https://github.com/vuejs/vitepress/issues/5243)) ([ddf178a](https://github.com/vuejs/vitepress/commit/ddf178a170967527bafe7c9b262fb66aa10ec9de)) +- prevent DocSearch SVG clipping in WebKit ([#5240](https://github.com/vuejs/vitepress/issues/5240)) ([a357e5e](https://github.com/vuejs/vitepress/commit/a357e5ef67ed266861877eb08da753b2141a784f)) +- strip frontmatter before heading includes ([#5246](https://github.com/vuejs/vitepress/issues/5246)) ([e68fade](https://github.com/vuejs/vitepress/commit/e68fade75d2259b10695e85277f5483a084e3ae7)) +- **theme:** avatars misaligned in team member cards ([6730fb8](https://github.com/vuejs/vitepress/commit/6730fb84620c852b516de59f6f7c39c4f04f0e37)), closes [#5160](https://github.com/vuejs/vitepress/issues/5160) +- **theme:** correct mixed LTR/RTL text rendering in code blocks ([73f7b0b](https://github.com/vuejs/vitepress/commit/73f7b0b984853758d41e897dd43e5e93a1066266)) +- **theme:** keep external link icon inline ([#5232](https://github.com/vuejs/vitepress/issues/5232)) ([756a88c](https://github.com/vuejs/vitepress/commit/756a88cfa2f8f71400362327d2255cb8b5ccacfa)) +- **theme:** prevent `sub` and `sup` elements from affecting line height ([19357f9](https://github.com/vuejs/vitepress/commit/19357f9d337472572a500b8d2af8ef97932bfdda)), closes [#5173](https://github.com/vuejs/vitepress/issues/5173) +- use resolveDynamicComponent instead of resolveComponent ([9da1e3e](https://github.com/vuejs/vitepress/commit/9da1e3e70f41b7b8cb81f791307c778d65854f7a)) + +### Features + +- add macOS local search navigation shortcuts ([#5237](https://github.com/vuejs/vitepress/issues/5237)) ([e635e9e](https://github.com/vuejs/vitepress/commit/e635e9e5ea2876a293954970c6a00d6e09cb50a5)) +- add support for `format` option in Carbon options ([#5188](https://github.com/vuejs/vitepress/issues/5188)) ([6ee01bf](https://github.com/vuejs/vitepress/commit/6ee01bf30534cbf7847fe8c94fbf23efd9637f68)) +- allow custom i18n routing ([#5239](https://github.com/vuejs/vitepress/issues/5239)) ([eef5742](https://github.com/vuejs/vitepress/commit/eef57427f4861939ff27f07d71587e68118064e2)) +- allow VPContent to use custom components ([#5176](https://github.com/vuejs/vitepress/issues/5176)) ([c0b38d5](https://github.com/vuejs/vitepress/commit/c0b38d52c270e4efb59effa8ab7207535c48ec05)) +- **markdown:** expose Shiki color replacements in markdown options ([#5153](https://github.com/vuejs/vitepress/issues/5153)) ([fccc617](https://github.com/vuejs/vitepress/commit/fccc6171024f1b0087dd963dbe5a6236081b5d3d)) +- migrate to vite 8 ([228eef1](https://github.com/vuejs/vitepress/commit/228eef187ae33d1676a79e466d289c0e6e9ab321)) +- show local search loading state ([#5252](https://github.com/vuejs/vitepress/issues/5252)) ([7e2273a](https://github.com/vuejs/vitepress/commit/7e2273a3e470da2777c2510b51262e85879f2ee9)) +- support scroll-margin / scroll-padding ([6cce766](https://github.com/vuejs/vitepress/commit/6cce76685da39f8b5c75da047f847f82f70b9c4e)) +- support social link target option ([#5242](https://github.com/vuejs/vitepress/issues/5242)) ([d0159c8](https://github.com/vuejs/vitepress/commit/d0159c8a850cbd2a010a3d44bdeb97c3db651d0e)) + +### BREAKING CHANGES + +- VitePress now uses Vite 8. If you are using Vite plugins in your config, please check the [Vite 8 migration guide](https://vite.dev/guide/migration) for any breaking changes that may affect you. +- Node 20 support is dropped. v22 or higher is needed. +- `scrollOffset` from config is removed. Users wanting to customize scroll offset should customize `scroll-margin-top` via CSS instead. `smoothScroll` support from `router.go` is also removed as it didn't work as expected for most users. Users wanting smooth scrolling should set `scroll-behavior: smooth` in CSS, ideally inside a `@media (prefers-reduced-motion: no-preference)` block. + ## [2.0.0-alpha.17](https://github.com/vuejs/vitepress/compare/v2.0.0-alpha.16...v2.0.0-alpha.17) (2026-03-19) ### Bug Fixes diff --git a/__tests__/e2e/.vitepress/config.ts b/__tests__/e2e/.vitepress/config.ts index 121761e7..441eda1c 100644 --- a/__tests__/e2e/.vitepress/config.ts +++ b/__tests__/e2e/.vitepress/config.ts @@ -162,6 +162,14 @@ export default defineConfig({ themeConfig: { nav, sidebar, + socialLinks: [ + { + icon: 'github', + link: '/home', + ariaLabel: 'Home social link', + target: '_self' + } + ], search: { provider: 'local', options: { diff --git a/__tests__/e2e/data-loading/data.test.ts b/__tests__/e2e/data-loading/data.test.ts index 21cfa061..4a4e87a8 100644 --- a/__tests__/e2e/data-loading/data.test.ts +++ b/__tests__/e2e/data-loading/data.test.ts @@ -1,4 +1,4 @@ -import fs from 'node:fs/promises' +import { writeFile, unlink } from 'node:fs/promises' import { fileURLToPath } from 'node:url' describe('static data file support in vite 3', () => { @@ -48,20 +48,20 @@ describe('static data file support in vite 3', () => { const b = fileURLToPath(new URL('./data/b.json', import.meta.url)) try { - await fs.writeFile(a, JSON.stringify({ a: false }, null, 2) + '\n') + await writeFile(a, JSON.stringify({ a: false }, null, 2) + '\n') await page.waitForFunction( () => document.querySelector('pre#basic')?.textContent === JSON.stringify([{ a: false }, { b: true }], null, 2) ) } finally { - await fs.writeFile(a, JSON.stringify({ a: true }, null, 2) + '\n') + await writeFile(a, JSON.stringify({ a: true }, null, 2) + '\n') } let err = true try { - await fs.unlink(b) + await unlink(b) await page.waitForFunction( () => document.querySelector('pre#basic')?.textContent === @@ -70,19 +70,19 @@ describe('static data file support in vite 3', () => { err = false } finally { if (err) { - await fs.writeFile(b, JSON.stringify({ b: true }, null, 2) + '\n') + await writeFile(b, JSON.stringify({ b: true }, null, 2) + '\n') } } try { - await fs.writeFile(b, JSON.stringify({ b: false }, null, 2) + '\n') + await writeFile(b, JSON.stringify({ b: false }, null, 2) + '\n') await page.waitForFunction( () => document.querySelector('pre#basic')?.textContent === JSON.stringify([{ a: true }, { b: false }], null, 2) ) } finally { - await fs.writeFile(b, JSON.stringify({ b: true }, null, 2) + '\n') + await writeFile(b, JSON.stringify({ b: true }, null, 2) + '\n') } }) diff --git a/__tests__/e2e/home.test.ts b/__tests__/e2e/home.test.ts index 76868361..b6bd6ff9 100644 --- a/__tests__/e2e/home.test.ts +++ b/__tests__/e2e/home.test.ts @@ -32,4 +32,13 @@ describe('render correct content', async () => { const outlineLinksCount = await outlineLinksLocator.count() expect(outlineLinksCount).toEqual(4) }) + + test('social link target override', async () => { + const socialLink = page.locator( + '.VPNavBarSocialLinks a[aria-label="Home social link"]' + ) + + expect(await socialLink.getAttribute('href')).toBe('/home') + expect(await socialLink.getAttribute('target')).toBe('_self') + }) }) diff --git a/__tests__/e2e/local-search/local-search.test.ts b/__tests__/e2e/local-search/local-search.test.ts index 613a9e94..07ec1926 100644 --- a/__tests__/e2e/local-search/local-search.test.ts +++ b/__tests__/e2e/local-search/local-search.test.ts @@ -3,15 +3,69 @@ describe('local search', () => { await goto('/') }) + test.runIf(!process.env.VITE_TEST_BUILD)( + 'shows progress while loading search index', + async () => { + const indexRoute = /@localSearchIndexroot/ + let delayedIndex = false + + await page.route(indexRoute, async (route) => { + delayedIndex = true + await new Promise((resolve) => setTimeout(resolve, 800)) + await route.continue() + }) + + try { + await page.locator('.VPNavBarSearchButton').click() + + const loading = page.locator('.search-loading') + const results = page.locator('.results') + + await page.waitForFunction(() => + document + .querySelector('.search-loading') + ?.classList.contains('active') + ) + + expect(delayedIndex).toBe(true) + expect(await loading.getAttribute('role')).toBe('status') + expect(await loading.getAttribute('aria-label')).toBe( + 'Loading search results' + ) + expect(await results.getAttribute('aria-busy')).toBe('true') + + await page.waitForFunction( + () => + !document + .querySelector('.search-loading') + ?.classList.contains('active') + ) + + expect(await results.getAttribute('aria-busy')).toBe('false') + } finally { + await page.unroute(indexRoute) + } + } + ) + test('exclude content from search results', async () => { await page.locator('.VPNavBarSearchButton').click() const input = await page.waitForSelector('input#localsearch-input') await input.type('local') - await page.waitForSelector('ul#localsearch-list', { state: 'visible' }) - const searchResults = page.locator('#localsearch-list') + await page.waitForFunction(() => { + const options = [ + ...document.querySelectorAll('#localsearch-list li[role=option]') + ] + + return ( + options.length === 1 && + options[0].textContent?.includes('Local search included') + ) + }) + expect(await searchResults.locator('li[role=option]').count()).toBe(1) expect( diff --git a/__tests__/init/init.test.ts b/__tests__/init/init.test.ts index 7766b060..0066f43d 100644 --- a/__tests__/init/init.test.ts +++ b/__tests__/init/init.test.ts @@ -1,6 +1,6 @@ -import fs from 'fs-extra' import getPort from 'get-port' import { nanoid } from 'nanoid' +import { rm } from 'node:fs/promises' import path from 'node:path' import { fileURLToPath, URL } from 'node:url' import { chromium } from 'playwright-chromium' @@ -33,12 +33,12 @@ const variations = themes.flatMap((theme) => afterAll(async () => { await page.close() await browser.close() - await fs.remove(tempDir) + await rm(tempDir, { recursive: true, force: true }) }) test.each(variations)('init %s', async (_, { theme, useTs }) => { const root = getTempRoot() - await fs.remove(root) + await rm(root, { recursive: true, force: true }) scaffold({ root, theme, useTs, injectNpmScripts: false }) const port = await getPort() diff --git a/__tests__/unit/client/theme-default/composables/langs.test.ts b/__tests__/unit/client/theme-default/composables/langs.test.ts index 565a4a23..dc91bbe7 100644 --- a/__tests__/unit/client/theme-default/composables/langs.test.ts +++ b/__tests__/unit/client/theme-default/composables/langs.test.ts @@ -1,7 +1,7 @@ -import { ref } from 'vue' +import { resolveLocaleLink } from 'client/theme-default/composables/langs' import type { VitePressData } from 'vitepress' import type { DefaultTheme } from 'vitepress/theme' -import { resolveLocaleLink } from 'client/theme-default/composables/langs' +import { ref } from 'vue' function createData( themeConfig: DefaultTheme.Config, diff --git a/__tests__/unit/client/theme-default/support/docsearch.test.ts b/__tests__/unit/client/theme-default/support/docsearch.test.ts index 4da8f113..78c5ee68 100644 --- a/__tests__/unit/client/theme-default/support/docsearch.test.ts +++ b/__tests__/unit/client/theme-default/support/docsearch.test.ts @@ -1,5 +1,6 @@ import { buildAskAiConfig, + buildSidePanelProps, hasAskAi, hasKeywordSearch, mergeLangFacetFilters, @@ -192,5 +193,110 @@ describe('client/theme-default/support/docsearch', () => { ) expect(result.searchParameters?.facetFilters).toEqual(['lang:en']) }) + + test('preserves Agent Studio search parameters by index', () => { + const result = buildAskAiConfig( + { + assistantId: 'assistant123', + agentStudio: true, + searchParameters: { + index: { + distinct: false + } + } + } as any, + { + appId: 'app', + apiKey: 'key', + indexName: 'index', + searchParameters: { + facetFilters: ['tag:docs'] + } + } as any, + 'en' + ) + + expect(result.searchParameters).toEqual({ + index: { + distinct: false + } + }) + expect(result.searchParameters).not.toHaveProperty('facetFilters') + }) + + test('does not add legacy facet filters to Agent Studio config', () => { + const result = buildAskAiConfig( + { + assistantId: 'assistant123', + agentStudio: true + } as any, + { + appId: 'app', + apiKey: 'key', + indexName: 'index', + searchParameters: { + facetFilters: ['tag:docs'] + } + } as any, + 'en' + ) + + expect(result.searchParameters).toBeUndefined() + }) + }) + + describe('buildSidePanelProps', () => { + test('passes resolved Ask AI options to the side panel', () => { + const result = buildSidePanelProps( + { + assistantId: 'assistant123', + agentStudio: true, + searchParameters: { + index: { + facetFilters: ['lang:en'] + } + }, + suggestedQuestions: true, + useStagingEnv: true, + sidePanel: { + button: { + variant: 'inline' + }, + panel: { + width: 420, + suggestedQuestions: true + } + } + } as any, + { + appId: 'app', + apiKey: 'key', + indexName: 'index' + } as any + ) + + expect(result).toEqual({ + container: '#vp-docsearch-sidepanel', + appId: 'app', + apiKey: 'key', + indexName: 'index', + assistantId: 'assistant123', + agentStudio: true, + searchParameters: { + index: { + facetFilters: ['lang:en'] + } + }, + suggestedQuestions: true, + useStagingEnv: true, + button: { + variant: 'inline' + }, + panel: { + width: 420, + suggestedQuestions: true + } + }) + }) }) }) diff --git a/__tests__/unit/client/theme-default/support/sidebar.test.ts b/__tests__/unit/client/theme-default/support/sidebar.test.ts index f33dcbd9..7232757c 100644 --- a/__tests__/unit/client/theme-default/support/sidebar.test.ts +++ b/__tests__/unit/client/theme-default/support/sidebar.test.ts @@ -1,4 +1,8 @@ -import { getSidebar, hasActiveLink } from 'client/theme-default/support/sidebar' +import { + getFlatSideBarLinks, + getSidebar, + hasActiveLink +} from 'client/theme-default/support/sidebar' describe('client/theme-default/support/sidebar', () => { describe('getSidebar', () => { @@ -103,6 +107,75 @@ describe('client/theme-default/support/sidebar', () => { ) }) }) + + test('applies base only to internal links', () => { + expect( + getSidebar( + { + '/en/': { + base: '/en/', + items: [ + { + text: 'Guide', + items: [ + { text: 'Intro', link: 'intro' }, + { text: 'Root', link: '/root' }, + { text: 'External', link: 'https://example.com/' } + ] + } + ] + } + }, + '/en/intro' + ) + ).toStrictEqual([ + { + text: 'Guide', + items: [ + { text: 'Intro', link: '/en/intro' }, + { text: 'Root', link: '/en/root' }, + { text: 'External', link: 'https://example.com/' } + ] + } + ]) + }) + }) + + describe('getFlatSideBarLinks', () => { + test('flattens nested items and preserves link metadata', () => { + const sidebar = [ + { + text: 'Group', + items: [ + { text: 'Intro', link: '/intro' }, + { + text: 'External', + link: 'https://example.com/', + target: '_self', + rel: 'noopener', + docFooterText: 'Go external' + } + ] + } + ] + + expect(getFlatSideBarLinks(sidebar)).toStrictEqual([ + { + text: 'Intro', + link: '/intro', + docFooterText: undefined, + rel: undefined, + target: undefined + }, + { + text: 'External', + link: 'https://example.com/', + docFooterText: 'Go external', + rel: 'noopener', + target: '_self' + } + ]) + }) }) describe('hasActiveLink', () => { diff --git a/__tests__/unit/node/config.test.ts b/__tests__/unit/node/config.test.ts index 9837879c..22f7d034 100644 --- a/__tests__/unit/node/config.test.ts +++ b/__tests__/unit/node/config.test.ts @@ -1,5 +1,5 @@ -import { mergeConfig } from 'node/config' import type { MarkdownItAsync } from 'markdown-it-async' +import { mergeConfig } from 'node/config' describe('node/config', () => { test('merges markdown config hooks from extended configs', async () => { diff --git a/__tests__/unit/node/markdownToVue.test.ts b/__tests__/unit/node/markdownToVue.test.ts index 2a139b1b..232496df 100644 --- a/__tests__/unit/node/markdownToVue.test.ts +++ b/__tests__/unit/node/markdownToVue.test.ts @@ -1,8 +1,8 @@ +import { resolveConfig } from 'node/config' +import { createMarkdownToVueRenderFn } from 'node/markdownToVue' import { mkdtemp, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import path from 'node:path' -import { resolveConfig } from 'node/config' -import { createMarkdownToVueRenderFn } from 'node/markdownToVue' describe('node/markdownToVue', () => { let root: string | undefined @@ -66,4 +66,94 @@ describe('node/markdownToVue', () => { line: 8 }) }) + + test('selects included heading sections after frontmatter', async () => { + root = await mkdtemp(path.join(tmpdir(), 'vitepress-include-')) + + const file = path.join(root, 'index.md') + const source = path.join(root, 'source.md') + await writeFile( + source, + [ + '---', + 'description: Source description', + '---', + '# Intro', + '', + 'intro text', + '', + '## Shared', + '', + 'shared before target', + '', + '## Target', + '', + 'target text', + '', + '### Child', + '', + 'child text', + '', + '## Shared', + '', + 'shared after target', + '' + ].join('\n') + ) + const src = '' + await writeFile(file, src) + + const siteConfig = await resolveConfig(root, 'build', 'production') + const render = await createMarkdownToVueRenderFn( + siteConfig.srcDir, + { cache: false }, + '/', + false, + false, + siteConfig + ) + + const result = await render(src, file, 'public') + + expect(result.vueSrc).toContain('

target text

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

child text

') + expect(result.vueSrc).not.toContain('Source description') + expect(result.vueSrc).not.toContain('intro text') + expect(result.vueSrc).not.toContain('shared before target') + expect(result.vueSrc).not.toContain('shared after target') + }) + + test('applies rewrites with mismatched Windows drive letter case', async () => { + root = await mkdtemp(path.join(tmpdir(), 'vitepress-rewrite-')) + + const file = path.join(root, 'index.md') + await writeFile(file, '# Home\n') + + const siteConfig = await resolveConfig(root, 'build', 'production') + siteConfig.srcDir = 'c:/site/docs' + siteConfig.pages = ['en/index.md'] + siteConfig.rewrites = { + map: { 'en/index.md': 'index.md' }, + inv: { 'index.md': 'en/index.md' } + } + ;(siteConfig as any).__dirty = true + + const render = await createMarkdownToVueRenderFn( + siteConfig.srcDir, + { cache: false }, + '/', + false, + false, + siteConfig + ) + + const result = await render( + '# Home\n', + 'C:/site/docs/en/index.md', + 'public' + ) + + 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 new file mode 100644 index 00000000..c972795c --- /dev/null +++ b/__tests__/unit/node/plugins/localSearchPlugin.test.ts @@ -0,0 +1,102 @@ +import MiniSearch from 'minisearch' +import { resolveConfig } from 'node/config' +import { localSearchPlugin } from 'node/plugins/localSearchPlugin' +import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import path from 'node:path' + +describe('node/plugins/localSearchPlugin', () => { + let root: string | undefined + let nodeEnv: string | undefined + + beforeEach(() => { + nodeEnv = process.env.NODE_ENV + process.env.NODE_ENV = 'production' + }) + + afterEach(async () => { + if (nodeEnv === undefined) { + delete process.env.NODE_ENV + } else { + process.env.NODE_ENV = nodeEnv + } + + if (root) { + await rm(root, { recursive: true, force: true }) + root = undefined + } + }) + + test('indexes rewritten pages by rewritten locale path', 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'), + '# English home\n\nrootonlytoken\n' + ) + await writeFile( + path.join(root, 'zh.md'), + '# Chinese home\n\nlocaleonlytoken\n' + ) + await writeFile( + path.join(configDir, 'config.ts'), + [ + 'export default {', + ' rewrites: {', + " 'index.md': 'guide.md',", + " 'zh.md': 'zh/guide.md'", + ' },', + ' locales: {', + " root: { label: 'English', lang: 'en' },", + " zh: { label: 'Chinese', lang: 'zh' }", + ' },', + ' themeConfig: {', + " search: { provider: 'local' }", + ' }', + '}' + ].join('\n') + ) + + const siteConfig = await resolveConfig(root, 'build', 'production') + const plugin = await localSearchPlugin(siteConfig) + + const indexModule = (await plugin.load?.call( + {} as never, + '/@localSearchIndex' + )) as string + + expect(indexModule).toContain( + '"root": () => import(\'@localSearchIndexroot\')' + ) + expect(indexModule).toContain('"zh": () => import(\'@localSearchIndexzh\')') + + const rootIndex = loadIndex( + (await plugin.load?.call({} as never, '/@localSearchIndexroot')) as string + ) + const zhIndex = loadIndex( + (await plugin.load?.call({} as never, '/@localSearchIndexzh')) as string + ) + + expect(rootIndex.search('rootonlytoken')).toMatchObject([ + { id: '/guide.html#english-home' } + ]) + expect(rootIndex.search('localeonlytoken')).toEqual([]) + + expect(zhIndex.search('localeonlytoken')).toMatchObject([ + { id: '/zh/guide.html#chinese-home' } + ]) + expect(zhIndex.search('rootonlytoken')).toEqual([]) + }) +}) + +function loadIndex(serializedModule: string) { + const serializedIndex = JSON.parse( + serializedModule.slice('export default '.length) + ) + return MiniSearch.loadJSON(serializedIndex, { + fields: ['title', 'titles', 'text'], + storeFields: ['title', 'titles'] + }) +} diff --git a/docs/config.ts b/docs/config.ts index 8620d955..8f38b2b4 100644 --- a/docs/config.ts +++ b/docs/config.ts @@ -1,4 +1,4 @@ -import { createRequire } from 'module' +import { createRequire } from 'node:module' import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' const require = createRequire(import.meta.url) diff --git a/docs/en/guide/custom-theme.md b/docs/en/guide/custom-theme.md index c0ce8597..8de4c7ab 100644 --- a/docs/en/guide/custom-theme.md +++ b/docs/en/guide/custom-theme.md @@ -67,6 +67,24 @@ export default { } ``` +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] +export default { + enhanceApp({ router }) { + router.onBeforeRouteChange = (to) => { + console.log('navigating to', to) + } + + router.onAfterRouteChange = (to) => { + console.log('navigated to', to) + } + } +} +``` + +Return `false` from `onBeforeRouteChange` or `onBeforePageLoad` to cancel navigation. + The default export is the only contract for a custom theme, and only the `Layout` property is required. So technically, a VitePress theme can be as simple as a single Vue component. Inside your layout component, it works just like a normal Vite + Vue 3 application. Do note the theme also needs to be [SSR-compatible](./ssr-compat). diff --git a/docs/en/guide/getting-started.md b/docs/en/guide/getting-started.md index 0dd62926..31e45695 100644 --- a/docs/en/guide/getting-started.md +++ b/docs/en/guide/getting-started.md @@ -12,7 +12,7 @@ You can try VitePress directly in your browser on [StackBlitz](https://vitepress ### Prerequisites -- [Node.js](https://nodejs.org/) version 20 or higher. +- [Node.js](https://nodejs.org/) version 22 or higher. - Terminal for accessing VitePress via its command line interface (CLI). - Text Editor with [Markdown](https://en.wikipedia.org/wiki/Markdown) syntax support. - [VSCode](https://code.visualstudio.com/) is recommended, along with the [official Vue extension](https://marketplace.visualstudio.com/items?itemName=Vue.volar). diff --git a/docs/en/guide/routing.md b/docs/en/guide/routing.md index 2631c632..c858ec13 100644 --- a/docs/en/guide/routing.md +++ b/docs/en/guide/routing.md @@ -329,7 +329,7 @@ The paths loader module is run in Node.js and only executed during build time. Y Generating paths from local files: ```js -import fs from 'fs' +import fs from 'node:fs' export default { paths() { diff --git a/docs/en/reference/default-theme-config.md b/docs/en/reference/default-theme-config.md index b515cb45..cc4ffd0e 100644 --- a/docs/en/reference/default-theme-config.md +++ b/docs/en/reference/default-theme-config.md @@ -253,6 +253,7 @@ export default { // You can add any icon from simple-icons (https://simpleicons.org/): { icon: 'github', link: 'https://github.com/vuejs/vitepress' }, { icon: 'twitter', link: '...' }, + { icon: 'discord', link: '/community', target: '_self' }, // You can also add custom icons by passing SVG as string: { icon: { @@ -272,6 +273,7 @@ interface SocialLink { icon: string | { svg: string } link: string ariaLabel?: string + target?: string } ``` diff --git a/docs/en/reference/default-theme-search.md b/docs/en/reference/default-theme-search.md index a3138294..3c3fc41b 100644 --- a/docs/en/reference/default-theme-search.md +++ b/docs/en/reference/default-theme-search.md @@ -291,6 +291,12 @@ export default defineConfig({ }) ``` +Use `askAi.sidePanel.panel.suggestedQuestions` for side panel suggested +questions. Algolia's standalone Ask AI examples also mention +`askAi.suggestedQuestions`, but that top-level option is not enough for +VitePress side panel mode and does not make the integrated keyword-search +modal display suggested questions on first open. + If you need to disable the keyboard shortcut, use the `keyboardShortcuts` option at the sidepanel root level: ```ts diff --git a/docs/en/reference/runtime-api.md b/docs/en/reference/runtime-api.md index b39e4dcd..a202b270 100644 --- a/docs/en/reference/runtime-api.md +++ b/docs/en/reference/runtime-api.md @@ -124,6 +124,18 @@ interface Router { } ``` +Assign route-change handlers on the router instance: + +```ts +const router = useRouter() + +router.onBeforeRouteChange = (to) => { + console.log('navigating to', to) +} +``` + +For custom themes, the same router is available from [`enhanceApp`](../guide/custom-theme#theme-interface). + ## `withBase` - **Type**: `(path: string) => string` diff --git a/docs/es/config.ts b/docs/es/config.ts index fee38361..382ad71b 100644 --- a/docs/es/config.ts +++ b/docs/es/config.ts @@ -1,4 +1,4 @@ -import { createRequire } from 'module' +import { createRequire } from 'node:module' import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' const require = createRequire(import.meta.url) diff --git a/docs/es/guide/getting-started.md b/docs/es/guide/getting-started.md index ce36352a..10408445 100644 --- a/docs/es/guide/getting-started.md +++ b/docs/es/guide/getting-started.md @@ -12,7 +12,7 @@ Puede experimentar VitePress directamente en su navegador en [StackBlitz](https: ### Prerrequisitos {#prerequisites} -- [Node.js](https://nodejs.org/) versión 20 o superior. +- [Node.js](https://nodejs.org/) versión 22 o superior. - Terminal para acessar VitePress a través de su interfaz de linea de comando (CLI). - Editor de texto con soporte a sintaxis [Markdown](https://en.wikipedia.org/wiki/Markdown). - [VSCode](https://code.visualstudio.com/) es recomendado, junto con la [extensión oficial Vue](https://marketplace.visualstudio.com/items?itemName=Vue.volar). diff --git a/docs/es/guide/routing.md b/docs/es/guide/routing.md index e3c42162..e4d2894b 100644 --- a/docs/es/guide/routing.md +++ b/docs/es/guide/routing.md @@ -290,7 +290,7 @@ El módulo de carga de paths es ejecutado en Node.js y apenas durante el momento Generando paths a partir de archivos locales: ```js -import fs from 'fs' +import fs from 'node:fs' export default { paths() { diff --git a/docs/fa/config.ts b/docs/fa/config.ts index 4cb8c245..c3b34727 100644 --- a/docs/fa/config.ts +++ b/docs/fa/config.ts @@ -1,4 +1,4 @@ -import { createRequire } from 'module' +import { createRequire } from 'node:module' import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' const require = createRequire(import.meta.url) diff --git a/docs/fa/guide/getting-started.md b/docs/fa/guide/getting-started.md index 33af8299..d9d7d660 100644 --- a/docs/fa/guide/getting-started.md +++ b/docs/fa/guide/getting-started.md @@ -12,7 +12,7 @@ description: نصب و راه‌اندازی ویت‌پرس. یاد بگیری ### پیش‌نیازها {#prerequisites} -- [Node.js](https://nodejs.org/) نسخه 20 یا بالاتر. +- [Node.js](https://nodejs.org/) نسخه 22 یا بالاتر. - ترمینال برای دسترسی به ویت‌پرس از طریق رابط خط فرمان (CLI). - ویرایشگر متنی با پشتیبانی از [Markdown](https://en.wikipedia.org/wiki/Markdown). - [VSCode](https://code.visualstudio.com/) به همراه [افزونه رسمی Vue](https://marketplace.visualstudio.com/items?itemName=Vue.volar). diff --git a/docs/fa/guide/routing.md b/docs/fa/guide/routing.md index f159a876..b8c3a99b 100644 --- a/docs/fa/guide/routing.md +++ b/docs/fa/guide/routing.md @@ -295,7 +295,7 @@ export default { تولید مسیرها از فایل‌های محلی: ```js -import fs from 'fs' +import fs from 'node:fs' export default { paths() { diff --git a/docs/ja/config.ts b/docs/ja/config.ts index 0631ca82..bc92b006 100644 --- a/docs/ja/config.ts +++ b/docs/ja/config.ts @@ -1,4 +1,4 @@ -import { createRequire } from 'module' +import { createRequire } from 'node:module' import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' const require = createRequire(import.meta.url) diff --git a/docs/ja/guide/getting-started.md b/docs/ja/guide/getting-started.md index 5b9a8e2a..5e164aa1 100644 --- a/docs/ja/guide/getting-started.md +++ b/docs/ja/guide/getting-started.md @@ -12,7 +12,7 @@ description: VitePressのインストール、セットアップ、開発サー ### 前提条件 {#prerequisites} -- [Node.js](https://nodejs.org/) バージョン 20 以上 +- [Node.js](https://nodejs.org/) バージョン 22 以上 - VitePress をコマンドラインインターフェース (CLI) で操作するためのターミナル - [Markdown](https://en.wikipedia.org/wiki/Markdown) 構文に対応したテキストエディタ - 推奨: [VSCode](https://code.visualstudio.com/) と [公式 Vue 拡張](https://marketplace.visualstudio.com/items?itemName=Vue.volar) diff --git a/docs/ja/guide/routing.md b/docs/ja/guide/routing.md index f624bee0..a77e6062 100644 --- a/docs/ja/guide/routing.md +++ b/docs/ja/guide/routing.md @@ -304,7 +304,7 @@ export default { ローカルファイルから生成する例: ```js -import fs from 'fs' +import fs from 'node:fs' export default { paths() { diff --git a/docs/ko/config.ts b/docs/ko/config.ts index 4a076036..7a275cd3 100644 --- a/docs/ko/config.ts +++ b/docs/ko/config.ts @@ -1,4 +1,4 @@ -import { createRequire } from 'module' +import { createRequire } from 'node:module' import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' const require = createRequire(import.meta.url) diff --git a/docs/ko/guide/getting-started.md b/docs/ko/guide/getting-started.md index 5e28c2d8..ca6e743b 100644 --- a/docs/ko/guide/getting-started.md +++ b/docs/ko/guide/getting-started.md @@ -12,7 +12,7 @@ description: VitePress를 시작하세요. 문서 사이트를 설치하고, 스 ### 사전 준비 사항 {#prerequisites} -- [Node.js](https://nodejs.org/) 버전 20 이상. +- [Node.js](https://nodejs.org/) 버전 22 이상. - VitePress를 명령줄 인터페이스(CLI)를 통해 접근하기 위한 터미널. - [마크다운](https://en.wikipedia.org/wiki/Markdown) 문법 지원이 있는 텍스트 에디터. - [VSCode](https://code.visualstudio.com/)와 [공식 Vue 확장 프로그램](https://marketplace.visualstudio.com/items?itemName=Vue.volar) 사용을 권장합니다. diff --git a/docs/ko/guide/routing.md b/docs/ko/guide/routing.md index b0a8e23e..35c7621e 100644 --- a/docs/ko/guide/routing.md +++ b/docs/ko/guide/routing.md @@ -291,7 +291,7 @@ export default { 로컬 파일에서 경로 생성: ```js -import fs from 'fs' +import fs from 'node:fs' export default { paths() { diff --git a/docs/pt/config.ts b/docs/pt/config.ts index 5f71d84f..193eb2f4 100644 --- a/docs/pt/config.ts +++ b/docs/pt/config.ts @@ -1,4 +1,4 @@ -import { createRequire } from 'module' +import { createRequire } from 'node:module' import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' const require = createRequire(import.meta.url) diff --git a/docs/pt/guide/getting-started.md b/docs/pt/guide/getting-started.md index 182a3738..056626ff 100644 --- a/docs/pt/guide/getting-started.md +++ b/docs/pt/guide/getting-started.md @@ -12,7 +12,7 @@ Você pode experimentar VitePress diretamente no seu navegador em [StackBlitz](h ### Pré-requisitos {#prerequisites} -- [Node.js](https://nodejs.org/) na versão 20 ou superior. +- [Node.js](https://nodejs.org/) na versão 22 ou superior. - Terminal para acessar VitePress através da sua interface de linha de comando (CLI). - Editor de texto com suporte a sintaxe [Markdown](https://en.wikipedia.org/wiki/Markdown). - [VSCode](https://code.visualstudio.com/) é recomendado, junto com a [extensão oficial Vue](https://marketplace.visualstudio.com/items?itemName=Vue.volar). diff --git a/docs/pt/guide/routing.md b/docs/pt/guide/routing.md index 996f75bb..eb97ff01 100644 --- a/docs/pt/guide/routing.md +++ b/docs/pt/guide/routing.md @@ -290,7 +290,7 @@ O módulo de carregamento de caminhos é executado no Node.js e apenas durante o Gerando caminhos a partir de arquivos locais: ```js -import fs from 'fs' +import fs from 'node:fs' export default { paths() { diff --git a/docs/ru/config.ts b/docs/ru/config.ts index 515cffba..86f8452a 100644 --- a/docs/ru/config.ts +++ b/docs/ru/config.ts @@ -1,4 +1,4 @@ -import { createRequire } from 'module' +import { createRequire } from 'node:module' import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' const require = createRequire(import.meta.url) @@ -189,7 +189,7 @@ function searchOptions(): Partial { clearButtonAriaLabel: 'Очистить запрос', closeButtonText: 'Закрыть', closeButtonAriaLabel: 'Закрыть', - placeholderText: 'Поиск по документации или задайте вопрос Ask AI', + placeholderText: 'Искать в документации или задать вопрос Ask AI', placeholderTextAskAi: 'Задайте другой вопрос...', placeholderTextAskAiStreaming: 'Отвечаю...', searchInputLabel: 'Поиск', diff --git a/docs/ru/guide/cms.md b/docs/ru/guide/cms.md index c55040c0..b3d12dee 100644 --- a/docs/ru/guide/cms.md +++ b/docs/ru/guide/cms.md @@ -1,5 +1,5 @@ --- -description: Подключите VitePress к безголовой CMS с помощью динамических маршрутов и загрузчиков данных. +description: Подключите VitePress к CMS без встроенного интерфейса с помощью динамических маршрутов и загрузчиков данных. outline: deep --- diff --git a/docs/ru/guide/custom-theme.md b/docs/ru/guide/custom-theme.md index fdbd1caf..3cb62035 100644 --- a/docs/ru/guide/custom-theme.md +++ b/docs/ru/guide/custom-theme.md @@ -67,6 +67,24 @@ export default { } ``` +Значение `router` представляет собой тот же экземпляр маршрутизатора VitePress, который возвращает [`useRouter()`](../reference/runtime-api#userouter). Чтобы отслеживать изменения маршрутов, назначьте обработчики для маршрутизатора: + +```ts [.vitepress/theme/index.ts] +export default { + enhanceApp({ router }) { + router.onBeforeRouteChange = (to) => { + console.log('navigating to', to) + } + + router.onAfterRouteChange = (to) => { + console.log('navigated to', to) + } + } +} +``` + +Верните `false` из `onBeforeRouteChange` или `onBeforePageLoad`, чтобы отменить переход. + Экспорт по умолчанию является единственным контрактом для пользовательской темы, и только свойство `Layout` является обязательным. Таким образом, технически тема VitePress может быть простой, как один компонент Vue. Внутри компонент макета работает так же, как и обычное приложение Vite + Vue 3. Обратите внимание, что тема также должна быть [SSR-совместимой](./ssr-compat). @@ -156,7 +174,7 @@ const { page, frontmatter } = useData() ## Распространение пользовательской темы {#distributing-a-custom-theme} -Самый простой способ распространить пользовательскую тему — предоставить её в виде [репозитория шаблонов на GitHub](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-template-repository). +Самый простой способ распространить пользовательскую тему — предоставить её в виде [репозитория шаблонов на GitHub](https://docs.github.com/ru/repositories/creating-and-managing-repositories/creating-a-template-repository). Если вы хотите распространить тему в виде пакета npm, выполните следующие действия: diff --git a/docs/ru/guide/deploy.md b/docs/ru/guide/deploy.md index f92761e5..56cc8a0a 100644 --- a/docs/ru/guide/deploy.md +++ b/docs/ru/guide/deploy.md @@ -166,6 +166,13 @@ Cache-Control: max-age=31536000,immutable with: node-version: 24 cache: npm # или pnpm / yarn + - name: Cache VitePress + uses: actions/cache@v4 + with: + path: docs/.vitepress/cache + key: ${{ runner.os }}-vitepress-${{ hashFiles('docs/**', 'package-lock.json', 'pnpm-lock.yaml', 'yarn.lock', 'bun.lockb') }} + restore-keys: | + ${{ runner.os }}-vitepress- - name: Setup Pages uses: actions/configure-pages@v4 - name: Install dependencies diff --git a/docs/ru/guide/getting-started.md b/docs/ru/guide/getting-started.md index b2b81aac..e88ddc00 100644 --- a/docs/ru/guide/getting-started.md +++ b/docs/ru/guide/getting-started.md @@ -12,7 +12,7 @@ description: Начните работу с VitePress. Узнайте, как у ### Требования {#prerequisites} -- [Node.js](https://nodejs.org/) версии 20 или выше. +- [Node.js](https://nodejs.org/) версии 22 или выше. - Терминал для доступа к VitePress через интерфейс командной строки (CLI). - Текстовый редактор с поддержкой синтаксиса [Markdown](https://ru.wikipedia.org/wiki/Markdown). - Рекомендуется использовать [VSCode](https://code.visualstudio.com/), а также [официальное расширение Vue](https://marketplace.visualstudio.com/items?itemName=Vue.volar). @@ -37,6 +37,10 @@ $ yarn add -D vitepress@next vue $ bun add -D vitepress@next ``` +```sh [deno] +$ deno add -D vitepress@next +``` + ::: ::: tip ПРИМЕЧАНИЕ diff --git a/docs/ru/guide/routing.md b/docs/ru/guide/routing.md index d7971f77..37e48109 100644 --- a/docs/ru/guide/routing.md +++ b/docs/ru/guide/routing.md @@ -329,7 +329,7 @@ export default { Генерация путей из локальных файлов: ```js -import fs from 'fs' +import fs from 'node:fs' export default { paths() { diff --git a/docs/ru/reference/default-theme-config.md b/docs/ru/reference/default-theme-config.md index 99689bd1..796b5bb4 100644 --- a/docs/ru/reference/default-theme-config.md +++ b/docs/ru/reference/default-theme-config.md @@ -25,10 +25,28 @@ export default { ## i18nRouting -- Тип: `boolean` +- Тип: `boolean | ((data: VitePressData, hash: string, targetLocale: string) => string)` При смене локали на `ru` URL изменится с `/foo` (или `/en/foo/`) на `/ru/foo`. Вы можете отключить это поведение, установив для параметра `themeConfig.i18nRouting` значение `false`. +Установите для `themeConfig.i18nRouting` функцию, чтобы настроить ссылки для переключения локали. Эта функция получает текущие данные VitePress, текущий хеш и ключ целевой локали, а затем возвращает ссылку для перехода на неё. + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + i18nRouting(data, hash, targetLocale) { + const target = data.site.value.locales[targetLocale] + const targetLink = + target.link || (targetLocale === 'root' ? '/' : `/${targetLocale}/`) + + return `${targetLink}${data.page.value.relativePath.replace(/\.md$/, '')}${hash}` + } + } +}) +``` + ## logo - Тип: `ThemeableImage` @@ -235,6 +253,7 @@ export default { // Можно добавить любую иконку из simple-icons (https://simpleicons.org/): { icon: 'github', link: 'https://github.com/vuejs/vitepress' }, { icon: 'twitter', link: '...' }, + { icon: 'discord', link: '/community', target: '_self' }, // Можно добавить пользовательские иконки, передав SVG в виде строки: { icon: { @@ -254,6 +273,7 @@ interface SocialLink { icon: string | { svg: string } link: string ariaLabel?: string + target?: string } ``` diff --git a/docs/ru/reference/default-theme-search.md b/docs/ru/reference/default-theme-search.md index 838e7cea..efead057 100644 --- a/docs/ru/reference/default-theme-search.md +++ b/docs/ru/reference/default-theme-search.md @@ -276,7 +276,6 @@ export default defineConfig({ askAi: { assistantId: 'XXXYYY', sidePanel: { - // Отражает API @docsearch/sidepanel-js SidepanelProps panel: { variant: 'floating', // или 'inline' side: 'right', @@ -292,6 +291,8 @@ export default defineConfig({ }) ``` +Используйте `askAi.sidePanel.panel.suggestedQuestions` для настройки рекомендуемых вопросов в боковой панели. В примерах автономного Ask AI от Algolia также упоминается `askAi.suggestedQuestions`, однако одного этого параметра верхнего уровня недостаточно для режима боковой панели VitePress, и он не позволяет встроенному модальному окну поиска по ключевым словам отображать рекомендуемые вопросы при первом открытии. + Если вам нужно отключить сочетание клавиш, используйте опцию `keyboardShortcuts` боковой панели: ```ts diff --git a/docs/ru/reference/runtime-api.md b/docs/ru/reference/runtime-api.md index efbaae88..5157bd67 100644 --- a/docs/ru/reference/runtime-api.md +++ b/docs/ru/reference/runtime-api.md @@ -62,6 +62,8 @@ interface PageData { } ``` +`page.headers` заполняется только в том случае, если включён параметр [markdown.headers](./site-config#markdown). Без него это свойство остаётся пустым массивом. Оглавление в теме по умолчанию получает заголовки из уже отрендеренного содержимого страницы, поэтому оно может отображаться, даже если `page.headers` пуст. + **Пример:** ```vue @@ -122,6 +124,18 @@ interface Router { } ``` +Назначьте обработчики изменения маршрутов для экземпляра маршрутизатора: + +```ts +const router = useRouter() + +router.onBeforeRouteChange = (to) => { + console.log('переход к', to) +} +``` + +В пользовательских темах этот же экземпляр маршрутизатора доступен через [`enhanceApp`](../guide/custom-theme#theme-interface). + ## `withBase` {#withbase} - **Тип**: `(path: string) => string` diff --git a/docs/ru/reference/site-config.md b/docs/ru/reference/site-config.md index d8c0d255..b04a3bdd 100644 --- a/docs/ru/reference/site-config.md +++ b/docs/ru/reference/site-config.md @@ -134,13 +134,43 @@ export default defineConfigWithTheme({ Вы можете настроить базовый экземпляр [Markdown-It](https://github.com/markdown-it/markdown-it) с помощью опции [markdown](#markdown) в конфигурации VitePress. +### Переопределение на уровне страницы {#page-level-overrides} + +Некоторые настройки можно переопределить для отдельных страниц с помощью метаданных. + +Подробности см. в разделе [Конфигурация метаданных](./frontmatter-config). + +### Переопределение на уровне директории {#directory-level-overrides} + +Некоторые параметры конфигурации можно переопределить на уровне директории, что позволяет всем страницам в этой директории использовать общие настройки без необходимости повторять их в блоке метаданных каждой страницы. + +Для этого добавьте файл с именем `config.ts` (или `.js`, `.mjs` или `.mts`) в соответствующую директорию. Этот файл должен экспортировать объект конфигурации с помощью `export default`, аналогично основному файлу конфигурации. + +Вложенные директории наследуют настройки от родительской директории, при этом переопределения конфигурации объединяются соответствующим образом. + +Вспомогательную функцию `defineAdditionalConfig` можно использовать для получения подсказок TypeScript по доступным параметрам, однако, как и в случае с `defineConfig`, её использование необязательно. + +Например, для сайта с несколькими языками может потребоваться разное значение `description` для каждого языка. Мы можем добавить файл `es/config.ts` со следующим содержимым: + +```ts +import { defineAdditionalConfig } from 'vitepress' + +export default defineAdditionalConfig({ + description: 'Generador de Sitios Estáticos desarrollado con Vite y Vue.' +}) +``` + +Этот `description` затем будет использоваться для всех страниц в директории `es`. + +В качестве альтернативы, при использовании встроенных возможностей i18n настройки для директории локали можно переопределить через параметр `locales` в основном файле конфигурации. Подробности см. в разделе [Интернационализация](../guide/i18n). + ## Метаданные сайта {#site-metadata} ### title {#title} - Тип: `string` - По умолчанию: `VitePress` -- Можно переопределить для каждой страницы с помощью [метаданных](./frontmatter-config#title) +- Можно переопределить для каждой страницы с помощью [метаданных](./frontmatter-config#title) или на [уровне директории](#directory-level-overrides) Название для сайта. При использовании темы по умолчанию оно будет отображаться в панели навигации. @@ -161,7 +191,7 @@ export default { ### titleTemplate {##titletemplate} - Тип: `string | boolean` -- Можно переопределить для каждой страницы с помощью [метаданных](./frontmatter-config#titletemplate) +- Можно переопределить для каждой страницы с помощью [метаданных](./frontmatter-config#titletemplate) или на [уровне директории](#directory-level-overrides) Позволяет настраивать суффикс заголовка каждой страницы или весь заголовок. Например: @@ -194,7 +224,7 @@ export default { - Тип: `string` - По умолчанию: `A VitePress site` -- Можно переопределить для каждой страницы с помощью [метаданных](./frontmatter-config#description) +- Можно переопределить для каждой страницы с помощью [метаданных](./frontmatter-config#description) или на [уровне директории](#directory-level-overrides) Описание для сайта. Это будет отображаться как тег `` в HTML-странице. @@ -208,7 +238,7 @@ export default { - Тип: `HeadConfig[]` - По умолчанию: `[]` -- Можно добавлять на страницу через [метаданные](./frontmatter-config#head) +- Можно добавлять на страницу через [метаданные](./frontmatter-config#head) или на [уровне директории](#directory-level-overrides) Дополнительные элементы для отображения в теге `` в HTML-странице. Добавленные пользователем теги выводятся перед закрывающим тегом `head`, после тегов VitePress. @@ -320,6 +350,7 @@ export default { - Тип: `string` - По умолчанию: `en-US` +- Может быть переопределено [на уровне директории](#directory-level-overrides) Атрибут lang для сайта. Будет выглядеть как тег `` в HTML-странице. @@ -530,6 +561,8 @@ export default { Проверьте [объявление типа и jsdocs](https://github.com/vuejs/vitepress/blob/main/src/node/markdown/markdown.ts) на наличие всех доступных опций. +Установите `markdown.headers` в значение `true` или передайте параметры [`@mdit-vue/plugin-headers`](https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-headers), чтобы собирать заголовки в [`useData().page.headers`](./runtime-api#usedata). Этот параметр отключён по умолчанию. + ### vite {#vite} - Тип: `import('vite').UserConfig` @@ -607,7 +640,7 @@ interface SSGContext { - Тип: `(context: TransformContext) => Awaitable` -`transformHead` — это хук сборки для преобразования заголовка перед генерацией каждой страницы. Это позволит вам добавить в конфигурацию VitePress записи, которые не могут быть добавлены статически. Вам нужно только вернуть дополнительные записи, они будут автоматически объединены с существующими. +`transformHead` — это хук сборки для добавления дополнительных тегов в `` каждой страницы. Он позволяет добавлять элементы в head, которые невозможно статически добавить в конфигурацию VitePress. Вам нужно только вернуть дополнительные элементы — они будут автоматически объединены с уже существующими. ::: warning ПРЕДУПРЕЖДЕНИЕ Не мутируйте ничего внутри `context`. @@ -635,44 +668,38 @@ interface TransformContext { } ``` -Обратите внимание, что этот хук вызывается только при статической генерации сайта. Он не вызывается во время разработки. Если вам нужно добавить динамические записи в голову во время разработки, вместо этого вы можете использовать хук [`transformPageData`](#transformpagedata): +Этот хук вызывается только при выполнении сборки и не вызывается в режиме разработки. -```ts -export default { - transformPageData(pageData) { - pageData.frontmatter.head ??= [] - pageData.frontmatter.head.push([ - 'meta', - { - name: 'og:title', - content: - pageData.frontmatter.layout === 'home' - ? `VitePress` - : `${pageData.title} | VitePress` - } - ]) - } -} -``` +Дополнительные теги будут добавлены в статические HTML-файлы, созданные во время сборки. Они не будут обновляться при навигации на стороне клиента. -#### Пример: Добавление канонического URL-адреса `` {#example-adding-a-canonical-url-link} +Во многих случаях более подходящим решением будет использование хука [`transformPageData`](#transformpagedata). Этот хук также применяется как при клиентской навигации, так и в режиме разработки. Однако если генерация тегов head требует значительных вычислительных ресурсов, `transformHead` позволяет избежать этих затрат во время разработки. + +#### Пример: добавление мета-тега `og:image` {#example-adding-og-image-meta} ```ts export default { - transformPageData(pageData) { - const canonicalUrl = `https://example.com/${pageData.relativePath}` - .replace(/index\.md$/, '') - .replace(/\.md$/, '.html') + async transformHead(context) { + if (context.page === '404.md') { + return + } - pageData.frontmatter.head ??= [] - pageData.frontmatter.head.push([ - 'link', - { rel: 'canonical', href: canonicalUrl } - ]) + // Детали реализации `generatePageImage` зависят от ваших требований. + // Здесь мы предполагаем, что она создаёт подходящее изображение + // для каждой страницы и возвращает URL изображения. + const imageUrl = await generatePageImage(context) + + return [[ + 'meta', + { name: 'og:image', content: imageUrl } + ]] } } ``` +Здесь мы предполагаем, что URL изображения является динамическим и требует много времени для генерации. Использование `transformHead` позволяет избежать этих затрат во время разработки. + +Для более простых случаев может быть достаточно использовать параметр [`head`](./frontmatter-config#head) в метаданных или [`transformPageData`](#transformpagedata). + ### transformHtml {#transformhtml} - Тип: `(code: string, id: string, context: TransformContext) => Awaitable` @@ -721,3 +748,39 @@ interface TransformPageContext { siteConfig: SiteConfig } ``` + +#### Пример: добавление `` {#example-adding-a-meta-name-og-title} + +```ts +export default { + transformPageData(pageData) { + const title = pageData.frontmatter.layout === 'home' + ? 'VitePress' + : `${pageData.title} | VitePress` + + pageData.frontmatter.head ??= [] + pageData.frontmatter.head.push([ + 'meta', + { name: 'og:title', content: title } + ]) + } +} +``` + +#### Пример: добавление `` с каноническим URL {#example-adding-a-canonical-url-link} + +```ts +export default { + transformPageData(pageData) { + const canonicalUrl = `https://example.com/${pageData.relativePath}` + .replace(/index\.md$/, '') + .replace(/\.md$/, '.html') + + pageData.frontmatter.head ??= [] + pageData.frontmatter.head.push([ + 'link', + { rel: 'canonical', href: canonicalUrl } + ]) + } +} +``` diff --git a/docs/zh/config.ts b/docs/zh/config.ts index 91687c54..9769c1a9 100644 --- a/docs/zh/config.ts +++ b/docs/zh/config.ts @@ -1,4 +1,4 @@ -import { createRequire } from 'module' +import { createRequire } from 'node:module' import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' const require = createRequire(import.meta.url) @@ -209,7 +209,7 @@ function searchOptions(): Partial { closeText: '关闭', backToSearchText: '返回搜索', closeKeyAriaLabel: 'Esc 键', - poweredByText: '由…提供支持' + poweredByText: '搜索提供' }, errorScreen: { titleText: '无法获取结果', @@ -301,7 +301,7 @@ function searchOptions(): Partial { '我会搜索你的文档,快速帮你找到设置指南、功能细节和故障排除提示。' }, logo: { - poweredByText: '由…提供支持' + poweredByText: '搜索提供' } } } diff --git a/docs/zh/guide/getting-started.md b/docs/zh/guide/getting-started.md index 03af7b1e..847c117a 100644 --- a/docs/zh/guide/getting-started.md +++ b/docs/zh/guide/getting-started.md @@ -12,7 +12,7 @@ description: 快速上手 VitePress。了解如何安装、创建项目结构并 ### 前置准备 {#prerequisites} -- [Node.js](https://nodejs.org/) 20 及以上版本。 +- [Node.js](https://nodejs.org/) 22 及以上版本。 - 通过命令行界面 (CLI) 访问 VitePress 的终端。 - 支持 [Markdown](https://en.wikipedia.org/wiki/Markdown) 语法的编辑器。 - 推荐 [VSCode](https://code.visualstudio.com/) 及其[官方 Vue 扩展](https://marketplace.visualstudio.com/items?itemName=Vue.volar)。 diff --git a/docs/zh/guide/routing.md b/docs/zh/guide/routing.md index db652f97..06fa2eba 100644 --- a/docs/zh/guide/routing.md +++ b/docs/zh/guide/routing.md @@ -291,7 +291,7 @@ export default { 从本地文件生成路径: ```js -import fs from 'fs' +import fs from 'node:fs' export default { paths() { diff --git a/package.json b/package.json index e04e627c..99fd0c10 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vitepress", - "version": "2.0.0-alpha.17", + "version": "2.0.0-alpha.18", "description": "Vite & Vue powered static site generator", "keywords": [ "vite", @@ -56,11 +56,11 @@ "dev:start": "pnpm --stream '/^dev:(client|node|watch)$/'", "dev:client": "tsc --sourcemap -w --preserveWatchOutput -p src/client", "dev:node": "DEV=true pnpm build:node -w", - "dev:shared": "node scripts/copyShared", - "dev:watch": "node scripts/watchAndCopy", + "dev:shared": "node scripts/copyShared.ts", + "dev:watch": "node scripts/watchAndCopy.ts", "build": "pnpm build:prepare && pnpm build:client && pnpm build:node", - "build:prepare": "pnpm clean && node scripts/copyShared", - "build:client": "vue-tsc --noEmit -p src/client && tsc -p src/client && node scripts/copyClient", + "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:unit": "vitest run -r __tests__/unit", @@ -87,7 +87,7 @@ "format:fail": "prettier --experimental-cli --check .", "check": "pnpm format:fail && pnpm build && pnpm test", "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s", - "release": "node scripts/release.js" + "release": "node scripts/release.ts" }, "simple-git-hooks": { "pre-commit": "pnpm lint-staged" @@ -113,7 +113,7 @@ "mark.js": "8.11.1", "minisearch": "^7.2.0", "shiki": "^4.3.0", - "vite": "^7.3.6", + "vite": "^8.1.3", "vue": "^3.5.39" }, "devDependencies": { @@ -135,7 +135,6 @@ "@rollup/plugin-node-resolve": "^16.0.3", "@rollup/plugin-replace": "^6.0.3", "@types/cross-spawn": "^6.0.6", - "@types/fs-extra": "^11.0.4", "@types/lodash.template": "^4.5.3", "@types/mark.js": "^8.11.12", "@types/markdown-it-attrs": "^4.1.3", @@ -145,12 +144,12 @@ "@types/node": "^25.9.4", "@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", "cross-spawn": "^7.0.6", "esbuild": "^0.27.7", - "fs-extra": "^11.3.5", "get-port": "^7.2.0", "gray-matter": "^4.0.3", "lint-staged": "^16.4.0", @@ -168,7 +167,6 @@ "nanoid": "^5.1.16", "obug": "^2.1.3", "ora": "^9.4.1", - "oxc-minify": "^0.98.0", "p-map": "^7.0.4", "package-directory": "^8.2.0", "path-to-regexp": "^6.3.0", @@ -190,13 +188,12 @@ "sitemap": "^9.0.1", "tinyglobby": "^0.2.17", "typescript": "^5.9.3", - "vitest": "4.0.0-beta.4", + "vitest": "^4.1.9", "vue-tsc": "^3.3.5", "wait-on": "^9.0.10" }, "peerDependencies": { "markdown-it-mathjax3": "^4", - "oxc-minify": "*", "postcss": "^8" }, "peerDependenciesMeta": { @@ -205,9 +202,6 @@ }, "postcss": { "optional": true - }, - "oxc-minify": { - "optional": true } }, "packageManager": "pnpm@10.33.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ea730e46..6775cb74 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,7 +6,6 @@ settings: overrides: ora>string-width: ^5 - vite: npm:rolldown-vite@latest patchedDependencies: '@types/markdown-it-attrs': @@ -52,7 +51,7 @@ importers: version: 14.1.2 '@vitejs/plugin-vue': specifier: ^6.0.7 - version: 6.0.7(rolldown-vite@7.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@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)) + 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)) '@vue/devtools-api': specifier: ^8.1.4 version: 8.1.4 @@ -78,8 +77,8 @@ importers: specifier: ^4.3.0 version: 4.3.0 vite: - specifier: npm:rolldown-vite@latest - version: rolldown-vite@7.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0) + 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) vue: specifier: ^3.5.39 version: 3.5.39(typescript@5.9.3) @@ -138,9 +137,6 @@ importers: '@types/cross-spawn': specifier: ^6.0.6 version: 6.0.6 - '@types/fs-extra': - specifier: ^11.0.4 - version: 11.0.4 '@types/lodash.template': specifier: ^4.5.3 version: 4.5.3 @@ -168,6 +164,9 @@ importers: '@types/prompts': specifier: ^2.4.9 version: 2.4.9 + '@types/semver': + specifier: ^7.7.1 + version: 7.7.1 chokidar: specifier: ^5.0.0 version: 5.0.0 @@ -183,9 +182,6 @@ importers: esbuild: specifier: ^0.27.7 version: 0.27.7 - fs-extra: - specifier: ^11.3.5 - version: 11.3.5 get-port: specifier: ^7.2.0 version: 7.2.0 @@ -237,9 +233,6 @@ importers: ora: specifier: ^9.4.1 version: 9.4.1 - oxc-minify: - specifier: ^0.98.0 - version: 0.98.0(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) p-map: specifier: ^7.0.4 version: 7.0.4 @@ -304,8 +297,8 @@ importers: specifier: ^5.9.3 version: 5.9.3 vitest: - specifier: 4.0.0-beta.4 - version: 4.0.0-beta.4(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/debug@4.1.13)(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0) + 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)) vue-tsc: specifier: ^3.3.5 version: 3.3.5(typescript@5.9.3) @@ -338,13 +331,13 @@ importers: version: 8.0.0 postcss-rtlcss: specifier: ^6.0.0 - version: 6.0.0(postcss@8.5.15) + version: 6.0.0(postcss@8.5.16) vitepress: specifier: workspace:* version: link:.. vitepress-plugin-group-icons: specifier: ^1.7.5 - version: 1.7.5(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0) + 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)) vitepress-plugin-llms: specifier: ^1.13.2 version: 1.13.2 @@ -671,199 +664,111 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@oxc-minify/binding-android-arm64@0.98.0': - resolution: {integrity: sha512-fQ9zAfwQvQE+FboIU7dgeDTOBGNQhV8xafXlyhay3jFjOcjqnvokWE1pcJSIRnhaVxahTXzMYvYJzizqWvluhQ==} + '@oxc-project/types@0.138.0': + resolution: {integrity: sha512-1a7ZKmrRTCoN1XMZ4L0PyyqrMnrNlLyPuOkdSX2MZg7IiIGRUyurNhAm73ptDOraoBcIordsIGKNPKUzy3ZmfA==} + + '@polka/compression@1.0.0-next.28': + resolution: {integrity: sha512-aDmrBhgHJtxE+jy145WfhW9WmTAFmES/dNnn1LAs8UnnkFgBUj4T8I4ScQ9+rOkpDZStvnVP5iqhN3tvt7O1NA==} + engines: {node: '>=6'} + + '@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==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@oxc-minify/binding-darwin-arm64@0.98.0': - resolution: {integrity: sha512-0cwHg1aHGbf8FtR69luAD9Fd7WJr2HyDO12aUC5mQCPdOmfMPFQYYlaziZhyt3gVcgzSq+988GQtDGtcJNU2ow==} + '@rolldown/binding-darwin-arm64@1.1.4': + resolution: {integrity: sha512-aUi+HBvmYb7j8krl1+qJgkG8C17fO79gk3c+jPw4S8glRFc1DTija9S3EyaTSQUm5GJXYKDAsugBEhFHH2vYiQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@oxc-minify/binding-darwin-x64@0.98.0': - resolution: {integrity: sha512-kftNK3NyfzPMSJduFU1B0ntVnMlr4zOjzVztJHyalelSi86UpItSCNu+GH9sYGc6WE2qd6r8gXokQqd0Vi4QQQ==} + '@rolldown/binding-darwin-x64@1.1.4': + resolution: {integrity: sha512-F7hHC3gwY11+vByKPRWqwGbeXWVgKmL+pTGCinaEhdihzBV2aQ0fvZOch9cXYUOKuKKq429HeYXOqQLc7wFCEg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@oxc-minify/binding-freebsd-x64@0.98.0': - resolution: {integrity: sha512-rf3KZNYs4Wk4eQgyT2rjaYXs3/UBgCeM+13iNiUl0sbgMT2OuP63Wb7A/ICbaPaCcoA9cXJA1Y84SPM2vPTkCQ==} + '@rolldown/binding-freebsd-x64@1.1.4': + resolution: {integrity: sha512-sI5yw+7s92SK6odiEhD5lKCBlWcpjHS5qyqpVQbZAJ0fIzEUXrmbl3DH2ybR3PZogulNJF+COLtmA8hUfvkCCQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@oxc-minify/binding-linux-arm-gnueabihf@0.98.0': - resolution: {integrity: sha512-Dtw9jkzssB2JbZ4Q9lZCfrl9r8r2Q60QABNQaIcpDILDoD4yk3GivOhjSuf3vQCYRlvHjPUmLmazZxaNuRK/Jg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm] - os: [linux] - - '@oxc-minify/binding-linux-arm-musleabihf@0.98.0': - resolution: {integrity: sha512-gKgjKnHQLvEZqIPvp2D4AxFjtHDwEmNoNcfg6WePhkzNO7ud8M3F1x60GMKn6Nb/8CX2Y67GVISs+xivzYPo1A==} + '@rolldown/binding-linux-arm-gnueabihf@1.1.4': + resolution: {integrity: sha512-mCi0OKgEieFircrtVYmQAFGszRtMnZ6fpZAXrxanXAu7lqZcsK1E1RAaZNG0uKAnxox3B1f4EyQNnoyMfN1vAA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxc-minify/binding-linux-arm64-gnu@0.98.0': - resolution: {integrity: sha512-0TYQjHk/bzxo/Q0oF0BVM2bs4mIoTS7ee+m+r1B6QxMdmENMq1Q1EKgiGnwvhIu07srJJdJBYJoScaXbssmExA==} + '@rolldown/binding-linux-arm64-gnu@1.1.4': + resolution: {integrity: sha512-B9Ial3Kv5sh0SHnB1g/QWcUQCEvCF6QKGAl4zXypYj65mVI+B4AhFBwPtSN7pDrJeIx8Z7zdy4ntx+wQABom7w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@oxc-minify/binding-linux-arm64-musl@0.98.0': - resolution: {integrity: sha512-TOGEzv2tr/lGttB6MIYExXdkMxWDVUqxFcu4AQ25e/Jk0kq5IVyDNmLfKzUin5r/1nmOJEpuBeS3xq0VPmtU7A==} + '@rolldown/binding-linux-arm64-musl@1.1.4': + resolution: {integrity: sha512-lZVym0PuHE1KZ22gmFTC15lAkrg9iTszR617oYRB/iPY1A56ywoJzVKOJBKaot5RiikCObmur6pogpse3gRcng==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@oxc-minify/binding-linux-riscv64-gnu@0.98.0': - resolution: {integrity: sha512-zTyb36zh3s2ZDwRP3c5VEs2aS+CECXmpmgEWds+1bawELuueozsr455lqDE1qNcIMUS/AxeX9DCE4vM+LHYHfw==} + '@rolldown/binding-linux-ppc64-gnu@1.1.4': + resolution: {integrity: sha512-t2DNiLJWNTbnEHyUzTumldML6ET4/g16467LZoDDJ3tSxGvguL5/NyC2lCsNKuyRycg9XeDQF5SSv+TNOhQEXg==} engines: {node: ^20.19.0 || >=22.12.0} - cpu: [riscv64] + cpu: [ppc64] os: [linux] libc: [glibc] - '@oxc-minify/binding-linux-s390x-gnu@0.98.0': - resolution: {integrity: sha512-UafNlOq0Uy/PmfkMuSWSpBAW+55QlGny1ysLMK1D6l2xC8SjFTheWHVjQVChHhgKFZxT1NypV/cbTQyh06mAYA==} + '@rolldown/binding-linux-s390x-gnu@1.1.4': + resolution: {integrity: sha512-0WIRnL1Uw4BvTZRLQt+PVgo6ZKTJadlC2btP+/EOXv2f/DWbY0rEgl+y834mIVwP1FkTlWVTrGGJXf12lru7EQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@oxc-minify/binding-linux-x64-gnu@0.98.0': - resolution: {integrity: sha512-P/9krmxwtLbxdT339jEm4XUHUFMN4lzjqqvGwBug6NxPvN1sppSl06CNXzHQ6H7/oSftZIyAmsOaLWknhm30uw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@oxc-minify/binding-linux-x64-musl@0.98.0': - resolution: {integrity: sha512-XpbZ15Lm3eFg8+VLAKgTmu+9VVMb7B2Cz6LOGd0EqMwPYaC+I84O8RM55/vU1fSH58BZByOnjeVWf4RPOSz7UA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - libc: [musl] - - '@oxc-minify/binding-wasm32-wasi@0.98.0': - resolution: {integrity: sha512-VVNRbDWHZ7+Viv14Vy1y2yutOzLdivtVKKtcSt+xFSoS2wDhkn0KtRMnNTBVUnxjYqkwrDaDfcqhez5jA5bAUA==} - engines: {node: '>=14.0.0'} - cpu: [wasm32] - - '@oxc-minify/binding-win32-arm64-msvc@0.98.0': - resolution: {integrity: sha512-i0hcvKlWa8CcBDo8BGjKSkmWOPWcdvQXNwpYjMeuTIyzUEhstDC35us9pmhqOwnBDgIJfSPcjFMGA32W8VbKWw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [win32] - - '@oxc-minify/binding-win32-x64-msvc@0.98.0': - resolution: {integrity: sha512-ts2pD2yf+92hiJYEitsq0XmidmZCyEmKWTDCoGezBZtNmEXovnKOUjQq6bruJrUnxxCBKDo8+S74g4wMziO2Ww==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [win32] - - '@oxc-project/runtime@0.101.0': - resolution: {integrity: sha512-t3qpfVZIqSiLQ5Kqt/MC4Ge/WCOGrrcagAdzTcDaggupjiGxUx4nJF2v6wUCXWSzWHn5Ns7XLv13fCJEwCOERQ==} - engines: {node: ^20.19.0 || >=22.12.0} - - '@oxc-project/types@0.101.0': - resolution: {integrity: sha512-nuFhqlUzJX+gVIPPfuE6xurd4lST3mdcWOhyK/rZO0B9XWMKm79SuszIQEnSMmmDhq1DC8WWVYGVd+6F93o1gQ==} - - '@polka/compression@1.0.0-next.28': - resolution: {integrity: sha512-aDmrBhgHJtxE+jy145WfhW9WmTAFmES/dNnn1LAs8UnnkFgBUj4T8I4ScQ9+rOkpDZStvnVP5iqhN3tvt7O1NA==} - engines: {node: '>=6'} - - '@polka/url@1.0.0-next.29': - resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} - - '@rolldown/binding-android-arm64@1.0.0-beta.53': - resolution: {integrity: sha512-Ok9V8o7o6YfSdTTYA/uHH30r3YtOxLD6G3wih/U9DO0ucBBFq8WPt/DslU53OgfteLRHITZny9N/qCUxMf9kjQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [android] - - '@rolldown/binding-darwin-arm64@1.0.0-beta.53': - resolution: {integrity: sha512-yIsKqMz0CtRnVa6x3Pa+mzTihr4Ty+Z6HfPbZ7RVbk1Uxnco4+CUn7Qbm/5SBol1JD/7nvY8rphAgyAi7Lj6Vg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [darwin] - - '@rolldown/binding-darwin-x64@1.0.0-beta.53': - resolution: {integrity: sha512-GTXe+mxsCGUnJOFMhfGWmefP7Q9TpYUseHvhAhr21nCTgdS8jPsvirb0tJwM3lN0/u/cg7bpFNa16fQrjKrCjQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [darwin] - - '@rolldown/binding-freebsd-x64@1.0.0-beta.53': - resolution: {integrity: sha512-9Tmp7bBvKqyDkMcL4e089pH3RsjD3SUungjmqWtyhNOxoQMh0fSmINTyYV8KXtE+JkxYMPWvnEt+/mfpVCkk8w==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [freebsd] - - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.53': - resolution: {integrity: sha512-a1y5fiB0iovuzdbjUxa7+Zcvgv+mTmlGGC4XydVIsyl48eoxgaYkA3l9079hyTyhECsPq+mbr0gVQsFU11OJAQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm] - os: [linux] - - '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.53': - resolution: {integrity: sha512-bpIGX+ov9PhJYV+wHNXl9rzq4F0QvILiURn0y0oepbQx+7stmQsKA0DhPGwmhfvF856wq+gbM8L92SAa/CBcLg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@rolldown/binding-linux-arm64-musl@1.0.0-beta.53': - resolution: {integrity: sha512-bGe5EBB8FVjHBR1mOLOPEFg1Lp3//7geqWkU5NIhxe+yH0W8FVrQ6WRYOap4SUTKdklD/dC4qPLREkMMQ855FA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@rolldown/binding-linux-x64-gnu@1.0.0-beta.53': - resolution: {integrity: sha512-qL+63WKVQs1CMvFedlPt0U9PiEKJOAL/bsHMKUDS6Vp2Q+YAv/QLPu8rcvkfIMvQ0FPU2WL0aX4eWwF6e/GAnA==} + '@rolldown/binding-linux-x64-gnu@1.1.4': + resolution: {integrity: sha512-JWtGshGfX+oENAKonoNkqEJX+7hC8yfhi9GUyPX1VX4mdh1y5r+ZiJLR5XzAB0aoP6s/PcILsGjKq8O0mm24bw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-musl@1.0.0-beta.53': - resolution: {integrity: sha512-VGl9JIGjoJh3H8Mb+7xnVqODajBmrdOOb9lxWXdcmxyI+zjB2sux69br0hZJDTyLJfvBoYm439zPACYbCjGRmw==} + '@rolldown/binding-linux-x64-musl@1.1.4': + resolution: {integrity: sha512-rT6yQcxUuXs4CnbofqwHRRV0iem349rLMYpTjkgQGLjrY4ado/eDzwPZPTCgTOlF6Nkp8NEv70yLMTn6qkWxsQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@rolldown/binding-openharmony-arm64@1.0.0-beta.53': - resolution: {integrity: sha512-B4iIserJXuSnNzA5xBLFUIjTfhNy7d9sq4FUMQY3GhQWGVhS2RWWzzDnkSU6MUt7/aHUrep0CdQfXUJI9D3W7A==} + '@rolldown/binding-openharmony-arm64@1.1.4': + resolution: {integrity: sha512-KXMGoboq5cyaCQjDA4GLuRiOwBQ0EyFnJoVViLeZ45/3rFItRODEr+NdsBcVpll40hhNArlm/speWGRvj08LzA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.0.0-beta.53': - resolution: {integrity: sha512-BUjAEgpABEJXilGq/BPh7jeU3WAJ5o15c1ZEgHaDWSz3LB881LQZnbNJHmUiM4d1JQWMYYyR1Y490IBHi2FPJg==} - engines: {node: '>=14.0.0'} + '@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-win32-arm64-msvc@1.0.0-beta.53': - resolution: {integrity: sha512-s27uU7tpCWSjHBnxyVXHt3rMrQdJq5MHNv3BzsewCIroIw3DJFjMH1dzCPPMUFxnh1r52Nf9IJ/eWp6LDoyGcw==} + '@rolldown/binding-win32-arm64-msvc@1.1.4': + resolution: {integrity: sha512-PnWBtw3TV5KOg69HQQDR0mnQuyCmSGR2pAB4DC1rPF808fgKeTUMj2EOEyKATpgiuxuR5APQmiDO7PDgEjTFSA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.0.0-beta.53': - resolution: {integrity: sha512-cjWL/USPJ1g0en2htb4ssMjIycc36RvdQAx1WlXnS6DpULswiUTVXPDesTifSKYSyvx24E0YqQkEm0K/M2Z/AA==} + '@rolldown/binding-win32-x64-msvc@1.1.4': + resolution: {integrity: sha512-M1lpniBePobTfsa7Ks9a199e1akxsXn+GYBUKsEzv3YFzOm1HJAMNwKI3qr0Zq+mxwx9gOZoTdP1yXRYsZUocQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@rolldown/pluginutils@1.0.0-beta.53': - resolution: {integrity: sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==} - '@rolldown/pluginutils@1.0.1': resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} @@ -1136,18 +1041,12 @@ packages: '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} - '@types/fs-extra@11.0.4': - resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} - '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} '@types/jquery@4.0.1': resolution: {integrity: sha512-9a59A/tycXgYuPABcp6/3spSShn0NT2UOM4EfHvMumjYi4lJWTsK5SZWjhx3yRm9IHGCeWXdV2YfNsrWrft/CA==} - '@types/jsonfile@6.1.4': - resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} - '@types/linkify-it@5.0.0': resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} @@ -1205,6 +1104,9 @@ packages: '@types/sax@1.2.7': resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==} + '@types/semver@7.7.1': + resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} + '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} @@ -1221,37 +1123,34 @@ packages: vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 vue: ^3.2.25 - '@vitest/expect@4.0.0-beta.4': - resolution: {integrity: sha512-yvFhDLYmfmTPSF0NS2i7dbHKO6u+agYML82W/7lBNpHgBxPU8hLw87JDpaR1BQbd+gGy9ThAp85a+PGscy1QHw==} + '@vitest/expect@4.1.9': + resolution: {integrity: sha512-vl/rYsUKcBr3SnQn166+XR5ZQcgMx3DQhFWdfli/cWpLnLUmbxZvyrJZotLFUryib+LtArYMSTJ5RbQ57ZqrlA==} - '@vitest/mocker@4.0.0-beta.4': - resolution: {integrity: sha512-A4Dn3bSGUgrttz3XZq7ckU7uFav6/U0smCnvvsiRUzoA+J7Rqvp9hvGCR4tylS3gbaaUA+lUw/0dy08IynyWZg==} + '@vitest/mocker@4.1.9': + resolution: {integrity: sha512-EVkXzBjrPGM+cK8/ANWgBrkUCfJfb38/EfTSO8h7pWvKkyPkpWxvR7BkD2MyItMF62C97zAEoqdpUixwR/e+Rw==} peerDependencies: msw: ^2.4.9 - vite: ^6.0.0 || ^7.0.0-0 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: msw: optional: true vite: optional: true - '@vitest/pretty-format@4.0.0-beta.4': - resolution: {integrity: sha512-BW9Y/t5tGLFi1DgNzs9R4EDqh3MVGiPFBTPGZLK+Y7jBUOFINmLTYTVz1iDnSFLwTOpHxAQfERyOmcu429OQog==} - '@vitest/pretty-format@4.1.9': resolution: {integrity: sha512-s0iufns3iIFitdgm+YR7g1whCAaGtXz459VS9/PqyKDEEFgYIhsHOQmXgIgDuYCt7DeQmiZT0Qe2OA2p4ZPu5A==} - '@vitest/runner@4.0.0-beta.4': - resolution: {integrity: sha512-27ptMzYl0dNvN6o1jmKDsEX0gR3IwulSgPwJVvoKSQntUFUqMeQh0jbNtdZj60li49Rxbh/rdSE25D/7ABJAJg==} + '@vitest/runner@4.1.9': + resolution: {integrity: sha512-KXLMDtc7oe70+3mJfGrPUWPesswH+3sTxAMAMl8DG7I8IUQT4XW718dY5ID3vPUcmlu27CcKfY4P3h3I29SLJg==} - '@vitest/snapshot@4.0.0-beta.4': - resolution: {integrity: sha512-nqSjaWSlIxVc3C+wj6MTucacaveKEtDhrm4WS1u2udhgy304/pvEpcWQfWLFsASfF0ThPmoo/nADTm8KcSkr0g==} + '@vitest/snapshot@4.1.9': + resolution: {integrity: sha512-Jc7RKGNBo8Z28WYIm0Niej4xdSPByRf6mU58VpHQkd6Zh05rlnA+twjbK5HyeIGHxrzsc3mJgS43uM0CZKzaIA==} - '@vitest/spy@4.0.0-beta.4': - resolution: {integrity: sha512-RRcQBXXz2IS5EFGip+BmlV45by8yDSCWgH0+QbEebxF9SFChmbzDTKix7Mb4iGo17h7El2g6568Yk6VWwd9Gjw==} + '@vitest/spy@4.1.9': + resolution: {integrity: sha512-fHpsS6mIi+PiEW+vcRVOMkX1oSaPKne3VOclSFICPcGOmfKgXPU5iAah+wcNcj2xPrCCmfq99IDGf+EojhhvhA==} - '@vitest/utils@4.0.0-beta.4': - resolution: {integrity: sha512-AYAKmvweKomQ71BSmM4uuLdj7Lwb7go2tNLoNijObvmwwandidbcNoJzr2MZNm406RtUq+ZN9JsEYhID7uTgNw==} + '@vitest/utils@4.1.9': + resolution: {integrity: sha512-A51o8ymO5PpqlWNnBP9ZHPXDIpuMtTLlGSjN7la4US+LJzoUMyhwjA5QXlm39JexgwHKW4Xjs8Z2d3dLCXOeuA==} '@volar/language-core@2.4.28': resolution: {integrity: sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==} @@ -1450,10 +1349,6 @@ packages: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} - cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} @@ -1461,8 +1356,8 @@ packages: ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} - chai@5.3.3: - resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} chalk@5.6.2: @@ -1478,10 +1373,6 @@ packages: character-entities@2.0.2: resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} - check-error@2.1.3: - resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} - engines: {node: '>= 16'} - cheerio-select@1.6.0: resolution: {integrity: sha512-eq0GdBvxVFbqWgmCm7M3XGs1I8oLy/nExUnh6oLqmBditPO9AqQJrkslDpMun/hZ0yyTs8L0m85OHp4ho6Qm9g==} @@ -1571,6 +1462,9 @@ packages: engines: {node: '>=18'} hasBin: true + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -1606,10 +1500,6 @@ packages: decode-named-character-reference@1.3.0: resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} - deep-eql@5.0.2: - resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} - engines: {node: '>=6'} - deepmerge@4.3.1: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} @@ -1704,6 +1594,9 @@ 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-object-atoms@1.1.2: resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} engines: {node: '>= 0.4'} @@ -1829,10 +1722,6 @@ packages: resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} engines: {node: '>=0.4.x'} - fs-extra@11.3.5: - resolution: {integrity: sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==} - engines: {node: '>=14.14'} - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -1876,9 +1765,6 @@ packages: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - gray-matter@4.0.3: resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} engines: {node: '>=6.0'} @@ -2014,16 +1900,10 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-tokens@9.0.1: - resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} - js-yaml@3.15.0: resolution: {integrity: sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog==} hasBin: true - jsonfile@6.2.1: - resolution: {integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==} - juice@8.1.0: resolution: {integrity: sha512-FLzurJrx5Iv1e7CfBSZH68dC04EEvXvvVvPYB7Vx1WAuhCp1ZPIMtqxc+WTWxVkpTIC2Ach/GAv0rQbtGf6YMA==} engines: {node: '>=10.0.0'} @@ -2147,9 +2027,6 @@ packages: longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} - loupe@3.2.1: - resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} - lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} @@ -2422,10 +2299,6 @@ packages: resolution: {integrity: sha512-6VlU9MLXbjVQD04AZCMX28hVtA5bUoadvUqO76MUCVA0ilwJbMiHsITRPfyVm6p/BC0Av/BXMujx39WCe1LEqw==} engines: {node: '>=20'} - oxc-minify@0.98.0: - resolution: {integrity: sha512-4/Hv1NgOTtb893cxkmJM7YF+mLzqODHOvkCoPLRsnXm5rVXDa2tc1kMQn4b6JYAUh+TvRfH8rqJxFAJDeRt0Zg==} - engines: {node: ^20.19.0 || >=22.12.0} - p-map@7.0.4: resolution: {integrity: sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==} engines: {node: '>=18'} @@ -2459,10 +2332,6 @@ packages: pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - pathval@2.0.1: - resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} - engines: {node: '>= 14.16'} - peek-readable@5.4.2: resolution: {integrity: sha512-peBp3qZyuS6cNIJ2akRNG1uo1WJ1d0wTxg/fxMdZ0BqCVhx242bSFHM9eNqflfJVS9SsgkzgT/1UgnsurBOTMg==} engines: {node: '>=14.16'} @@ -2509,6 +2378,10 @@ packages: resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} engines: {node: ^10 || ^12 || >=14} + postcss@8.5.16: + resolution: {integrity: sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==} + engines: {node: ^10 || ^12 || >=14} + prettier@3.9.0: resolution: {integrity: sha512-LjIqSIC5VYLzs9WedVmJ2ljNAGnU+DteIClbahu4L/DBeWjZ6iT/k1lAYyu9JUh+1xINxWadaPw/Pl63y/agAw==} engines: {node: '>=14'} @@ -2604,49 +2477,8 @@ packages: rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - rolldown-vite@7.3.1: - resolution: {integrity: sha512-LYzdNAjRHhF2yA4JUQm/QyARyi216N2rpJ0lJZb8E9FU2y5v6Vk+xq/U4XBOxMefpWixT5H3TslmAHm1rqIq2w==} - engines: {node: ^20.19.0 || >=22.12.0} - deprecated: Use this package to migrate from Vite 7 to Vite 8. For the most recent updates, migrate to Vite 8 once you're ready. - hasBin: true - peerDependencies: - '@types/node': ^20.19.0 || >=22.12.0 - esbuild: ^0.27.0 - jiti: '>=1.21.0' - less: ^4.0.0 - sass: ^1.70.0 - sass-embedded: ^1.70.0 - stylus: '>=0.54.8' - sugarss: ^5.0.0 - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - peerDependenciesMeta: - '@types/node': - optional: true - esbuild: - optional: true - jiti: - optional: true - less: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true - - rolldown@1.0.0-beta.53: - resolution: {integrity: sha512-Qd9c2p0XKZdgT5AYd+KgAMggJ8ZmCs3JnS9PTMWkyUfteKlfmKtxJbWTHkVakxwXs1Ub7jrRYVeFeF7N0sQxyw==} + rolldown@1.1.4: + resolution: {integrity: sha512-IjZYiLxZwpnhwhdBH2ugdTGVSdhCQUmLxLoqyjiL0JxYjyRst+5a0P3xfrTxJ5F638j4Mvvw5FAX5XE6eHpXbA==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -2782,8 +2614,8 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - std-env@3.10.0: - resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + std-env@4.1.0: + resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} stdin-discarder@0.3.2: resolution: {integrity: sha512-eCPu1qRxPVkl5605OTWF8Wz40b4Mf45NY5LQmVPQ599knfs5QhASUm9GbJ5BDMDOXgrnh0wyEdvzmL//YMlw0A==} @@ -2831,9 +2663,6 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - strip-literal@3.1.0: - resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} - strtok3@7.1.1: resolution: {integrity: sha512-mKX8HA/cdBqMKUr0MMZAFssCkIGoZeSCMXgnt79yKxNFguMLVFgRe6wB+fsL0NmoHDbeyZXczy7vEPSoo3rkzg==} engines: {node: '>=16'} @@ -2856,9 +2685,6 @@ packages: tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - tinyexec@0.3.2: - resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} - tinyexec@1.2.4: resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} engines: {node: '>=18'} @@ -2867,22 +2693,10 @@ packages: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} - tinypool@1.1.1: - resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} - engines: {node: ^18.0.0 || >=20.0.0} - - tinyrainbow@2.0.0: - resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} - engines: {node: '>=14.0.0'} - tinyrainbow@3.1.0: resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} engines: {node: '>=14.0.0'} - tinyspy@4.0.4: - resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} - engines: {node: '>=14.0.0'} - to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -2969,10 +2783,6 @@ packages: unist-util-visit@5.1.0: resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} - universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - unplugin-utils@0.2.5: resolution: {integrity: sha512-gwXJnPRewT4rT7sBi/IvxKTjsms7jX7QIDLOClApuZwR49SXbrB1z2NLUZ+vDHyqCj/n58OzRRqaW+B8OZi8vg==} engines: {node: '>=18.12.0'} @@ -2993,38 +2803,94 @@ packages: vfile@6.0.3: resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} - vite-node@4.0.0-beta.4: - resolution: {integrity: sha512-J8rg/GLeInlEVEFlOw/49lBdQSGH8o9zOhmXhmiWTGhEi/vtRkdOiTlzNl5HO+J2mHkF032piFX1o+cqsvt/LQ==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + vite@8.1.3: + resolution: {integrity: sha512-Ds+gBRbj0lwRO2Y5hwnUBdxSwlAve9LeRyU4sNnAr0ewW0gWF0n5bgXgUzbgZ49MV9BVUAQUFYVcDUcilUExMA==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.3.0 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true vitepress-plugin-group-icons@1.7.5: resolution: {integrity: sha512-QzcroUuIiVKyXpmEiiHVbfRTQIy9Zbwxpk5JC/zavO8mavitwumz2RZWlwTchMCCHducYyPptkYvXvdnNUWkog==} + peerDependencies: + vite: '>=3' + peerDependenciesMeta: + vite: + optional: true vitepress-plugin-llms@1.13.2: resolution: {integrity: sha512-2O4s0I5pjEZzgnoWgBPCZCyhah9FH5uQB6lGADazMoyF1URJshtG04ZnmX+cbmQmniN3T5JzdJO9B4q8JHDKOQ==} engines: {node: '>=18'} - vitest@4.0.0-beta.4: - resolution: {integrity: sha512-LWwBGvfWUinm0ATarVmXuzhGvL8HyydanPwQLAY21fvrUhXHyP04UvMYF5t+3TcXQdXPIP5AiVm09J+AbIwKhg==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + vitest@4.1.9: + resolution: {integrity: sha512-nE3/LEyc0z87uHYLZebqCUOaJr2hdtuPp7BQ4BosVFnfltxgAvMG08NyrSGlPpOUWvR27c5flSmYFTNr78L9GQ==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' - '@types/debug': ^4.1.12 - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 4.0.0-beta.4 - '@vitest/ui': 4.0.0-beta.4 + '@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 happy-dom: '*' jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: '@edge-runtime/vm': optional: true - '@types/debug': + '@opentelemetry/api': optional: true '@types/node': optional: true - '@vitest/browser': + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': optional: true '@vitest/ui': optional: true @@ -3401,110 +3267,61 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@oxc-minify/binding-android-arm64@0.98.0': - optional: true - - '@oxc-minify/binding-darwin-arm64@0.98.0': - optional: true - - '@oxc-minify/binding-darwin-x64@0.98.0': - optional: true - - '@oxc-minify/binding-freebsd-x64@0.98.0': - optional: true - - '@oxc-minify/binding-linux-arm-gnueabihf@0.98.0': - optional: true - - '@oxc-minify/binding-linux-arm-musleabihf@0.98.0': - optional: true - - '@oxc-minify/binding-linux-arm64-gnu@0.98.0': - optional: true - - '@oxc-minify/binding-linux-arm64-musl@0.98.0': - optional: true - - '@oxc-minify/binding-linux-riscv64-gnu@0.98.0': - optional: true - - '@oxc-minify/binding-linux-s390x-gnu@0.98.0': - optional: true + '@oxc-project/types@0.138.0': {} - '@oxc-minify/binding-linux-x64-gnu@0.98.0': - optional: true - - '@oxc-minify/binding-linux-x64-musl@0.98.0': - optional: true + '@polka/compression@1.0.0-next.28': {} - '@oxc-minify/binding-wasm32-wasi@0.98.0(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': - dependencies: - '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' - optional: true + '@polka/url@1.0.0-next.29': {} - '@oxc-minify/binding-win32-arm64-msvc@0.98.0': + '@rolldown/binding-android-arm64@1.1.4': optional: true - '@oxc-minify/binding-win32-x64-msvc@0.98.0': + '@rolldown/binding-darwin-arm64@1.1.4': optional: true - '@oxc-project/runtime@0.101.0': {} - - '@oxc-project/types@0.101.0': {} - - '@polka/compression@1.0.0-next.28': {} - - '@polka/url@1.0.0-next.29': {} - - '@rolldown/binding-android-arm64@1.0.0-beta.53': + '@rolldown/binding-darwin-x64@1.1.4': optional: true - '@rolldown/binding-darwin-arm64@1.0.0-beta.53': + '@rolldown/binding-freebsd-x64@1.1.4': optional: true - '@rolldown/binding-darwin-x64@1.0.0-beta.53': + '@rolldown/binding-linux-arm-gnueabihf@1.1.4': optional: true - '@rolldown/binding-freebsd-x64@1.0.0-beta.53': + '@rolldown/binding-linux-arm64-gnu@1.1.4': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.53': + '@rolldown/binding-linux-arm64-musl@1.1.4': optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.53': + '@rolldown/binding-linux-ppc64-gnu@1.1.4': optional: true - '@rolldown/binding-linux-arm64-musl@1.0.0-beta.53': + '@rolldown/binding-linux-s390x-gnu@1.1.4': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0-beta.53': + '@rolldown/binding-linux-x64-gnu@1.1.4': optional: true - '@rolldown/binding-linux-x64-musl@1.0.0-beta.53': + '@rolldown/binding-linux-x64-musl@1.1.4': optional: true - '@rolldown/binding-openharmony-arm64@1.0.0-beta.53': + '@rolldown/binding-openharmony-arm64@1.1.4': optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-beta.53(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + '@rolldown/binding-wasm32-wasi@1.1.4': 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) - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.53': + '@rolldown/binding-win32-arm64-msvc@1.1.4': optional: true - '@rolldown/binding-win32-x64-msvc@1.0.0-beta.53': + '@rolldown/binding-win32-x64-msvc@1.1.4': optional: true - '@rolldown/pluginutils@1.0.0-beta.53': {} - '@rolldown/pluginutils@1.0.1': {} '@rollup/plugin-alias@6.0.0(rollup@4.62.2)': @@ -3714,21 +3531,12 @@ snapshots: '@types/estree@1.0.9': {} - '@types/fs-extra@11.0.4': - dependencies: - '@types/jsonfile': 6.1.4 - '@types/node': 25.9.4 - '@types/hast@3.0.4': dependencies: '@types/unist': 3.0.3 '@types/jquery@4.0.1': {} - '@types/jsonfile@6.1.4': - dependencies: - '@types/node': 25.9.4 - '@types/linkify-it@5.0.0': {} '@types/lodash.template@4.5.3': @@ -3791,63 +3599,60 @@ snapshots: dependencies: '@types/node': 25.9.4 + '@types/semver@7.7.1': {} + '@types/unist@3.0.3': {} '@types/web-bluetooth@0.0.21': {} '@ungap/structured-clone@1.3.2': {} - '@vitejs/plugin-vue@6.0.7(rolldown-vite@7.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@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.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))': dependencies: '@rolldown/pluginutils': 1.0.1 - vite: rolldown-vite@7.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0) + 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) - '@vitest/expect@4.0.0-beta.4': + '@vitest/expect@4.1.9': dependencies: + '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@vitest/spy': 4.0.0-beta.4 - '@vitest/utils': 4.0.0-beta.4 - chai: 5.3.3 - tinyrainbow: 2.0.0 + '@vitest/spy': 4.1.9 + '@vitest/utils': 4.1.9 + chai: 6.2.2 + tinyrainbow: 3.1.0 - '@vitest/mocker@4.0.0-beta.4(rolldown-vite@7.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0))': + '@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))': dependencies: - '@vitest/spy': 4.0.0-beta.4 + '@vitest/spy': 4.1.9 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: rolldown-vite@7.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0) - - '@vitest/pretty-format@4.0.0-beta.4': - dependencies: - tinyrainbow: 2.0.0 + 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': dependencies: tinyrainbow: 3.1.0 - '@vitest/runner@4.0.0-beta.4': + '@vitest/runner@4.1.9': dependencies: - '@vitest/utils': 4.0.0-beta.4 + '@vitest/utils': 4.1.9 pathe: 2.0.3 - strip-literal: 3.1.0 - '@vitest/snapshot@4.0.0-beta.4': + '@vitest/snapshot@4.1.9': dependencies: - '@vitest/pretty-format': 4.0.0-beta.4 + '@vitest/pretty-format': 4.1.9 + '@vitest/utils': 4.1.9 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@4.0.0-beta.4': - dependencies: - tinyspy: 4.0.4 + '@vitest/spy@4.1.9': {} - '@vitest/utils@4.0.0-beta.4': + '@vitest/utils@4.1.9': dependencies: - '@vitest/pretty-format': 4.0.0-beta.4 - loupe: 3.2.1 - tinyrainbow: 2.0.0 + '@vitest/pretty-format': 4.1.9 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 '@volar/language-core@2.4.28': dependencies: @@ -4041,8 +3846,6 @@ snapshots: dependencies: run-applescript: 7.1.0 - cac@6.7.14: {} - call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 @@ -4050,13 +3853,7 @@ snapshots: ccount@2.0.1: {} - chai@5.3.3: - dependencies: - assertion-error: 2.0.1 - check-error: 2.1.3 - deep-eql: 5.0.2 - loupe: 3.2.1 - pathval: 2.0.1 + chai@6.2.2: {} chalk@5.6.2: {} @@ -4066,8 +3863,6 @@ snapshots: character-entities@2.0.2: {} - check-error@2.1.3: {} - cheerio-select@1.6.0: dependencies: css-select: 4.3.0 @@ -4169,6 +3964,8 @@ snapshots: '@simple-libs/stream-utils': 1.2.0 meow: 13.2.0 + convert-source-map@2.0.0: {} + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -4201,8 +3998,6 @@ snapshots: dependencies: character-entities: 2.0.2 - deep-eql@5.0.2: {} - deepmerge@4.3.1: {} default-browser-id@5.0.1: {} @@ -4278,6 +4073,8 @@ snapshots: es-module-lexer@1.7.0: {} + es-module-lexer@2.3.0: {} + es-object-atoms@1.1.2: dependencies: es-errors: 1.3.0 @@ -4410,12 +4207,6 @@ snapshots: format@0.2.2: {} - fs-extra@11.3.5: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.2.1 - universalify: 2.0.1 - fsevents@2.3.3: optional: true @@ -4457,8 +4248,6 @@ snapshots: gopd@1.2.0: {} - graceful-fs@4.2.11: {} - gray-matter@4.0.3: dependencies: js-yaml: 3.15.0 @@ -4599,19 +4388,11 @@ snapshots: js-tokens@4.0.0: optional: true - js-tokens@9.0.1: {} - js-yaml@3.15.0: dependencies: argparse: 1.0.10 esprima: 4.0.1 - jsonfile@6.2.1: - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - juice@8.1.0: dependencies: cheerio: 1.0.0-rc.10 @@ -4725,8 +4506,6 @@ snapshots: longest-streak@3.1.0: {} - loupe@3.2.1: {} - lru-cache@10.4.3: {} lru-cache@11.5.1: {} @@ -5097,27 +4876,6 @@ snapshots: stdin-discarder: 0.3.2 string-width: 5.1.2 - oxc-minify@0.98.0(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1): - optionalDependencies: - '@oxc-minify/binding-android-arm64': 0.98.0 - '@oxc-minify/binding-darwin-arm64': 0.98.0 - '@oxc-minify/binding-darwin-x64': 0.98.0 - '@oxc-minify/binding-freebsd-x64': 0.98.0 - '@oxc-minify/binding-linux-arm-gnueabihf': 0.98.0 - '@oxc-minify/binding-linux-arm-musleabihf': 0.98.0 - '@oxc-minify/binding-linux-arm64-gnu': 0.98.0 - '@oxc-minify/binding-linux-arm64-musl': 0.98.0 - '@oxc-minify/binding-linux-riscv64-gnu': 0.98.0 - '@oxc-minify/binding-linux-s390x-gnu': 0.98.0 - '@oxc-minify/binding-linux-x64-gnu': 0.98.0 - '@oxc-minify/binding-linux-x64-musl': 0.98.0 - '@oxc-minify/binding-wasm32-wasi': 0.98.0(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) - '@oxc-minify/binding-win32-arm64-msvc': 0.98.0 - '@oxc-minify/binding-win32-x64-msvc': 0.98.0 - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' - p-map@7.0.4: {} package-directory@8.2.0: @@ -5142,8 +4900,6 @@ snapshots: pathe@2.0.3: {} - pathval@2.0.1: {} - peek-readable@5.4.2: {} perfect-debounce@2.1.0: {} @@ -5165,9 +4921,9 @@ snapshots: '@polka/url': 1.0.0-next.29 trouter: 4.0.0 - postcss-rtlcss@6.0.0(postcss@8.5.15): + postcss-rtlcss@6.0.0(postcss@8.5.16): dependencies: - postcss: 8.5.15 + postcss: 8.5.16 rtlcss: 4.3.0 postcss-selector-parser@7.1.4: @@ -5181,6 +4937,12 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + postcss@8.5.16: + dependencies: + nanoid: 3.3.15 + picocolors: 1.1.1 + source-map-js: 1.2.1 + prettier@3.9.0: {} pretty-bytes@7.1.0: {} @@ -5281,46 +5043,26 @@ snapshots: rfdc@1.4.1: {} - rolldown-vite@7.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0): + rolldown@1.1.4: dependencies: - '@oxc-project/runtime': 0.101.0 - fdir: 6.5.0(picomatch@4.0.4) - lightningcss: 1.32.0 - picomatch: 4.0.4 - postcss: 8.5.15 - rolldown: 1.0.0-beta.53(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) - tinyglobby: 0.2.17 - optionalDependencies: - '@types/node': 25.9.4 - esbuild: 0.27.7 - fsevents: 2.3.3 - jiti: 1.21.7 - yaml: 2.9.0 - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' - - rolldown@1.0.0-beta.53(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1): - dependencies: - '@oxc-project/types': 0.101.0 - '@rolldown/pluginutils': 1.0.0-beta.53 + '@oxc-project/types': 0.138.0 + '@rolldown/pluginutils': 1.0.1 optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.0-beta.53 - '@rolldown/binding-darwin-arm64': 1.0.0-beta.53 - '@rolldown/binding-darwin-x64': 1.0.0-beta.53 - '@rolldown/binding-freebsd-x64': 1.0.0-beta.53 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.53 - '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.53 - '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.53 - '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.53 - '@rolldown/binding-linux-x64-musl': 1.0.0-beta.53 - '@rolldown/binding-openharmony-arm64': 1.0.0-beta.53 - '@rolldown/binding-wasm32-wasi': 1.0.0-beta.53(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) - '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.53 - '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.53 - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' + '@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): dependencies: @@ -5490,7 +5232,7 @@ snapshots: stackback@0.0.2: {} - std-env@3.10.0: {} + std-env@4.1.0: {} stdin-discarder@0.3.2: {} @@ -5540,10 +5282,6 @@ snapshots: strip-json-comments@3.1.1: {} - strip-literal@3.1.0: - dependencies: - js-tokens: 9.0.1 - strtok3@7.1.1: dependencies: '@tokenizer/token': 0.3.0 @@ -5564,8 +5302,6 @@ snapshots: tinybench@2.9.0: {} - tinyexec@0.3.2: {} - tinyexec@1.2.4: {} tinyglobby@0.2.17: @@ -5573,14 +5309,8 @@ snapshots: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 - tinypool@1.1.1: {} - - tinyrainbow@2.0.0: {} - tinyrainbow@3.1.0: {} - tinyspy@4.0.4: {} - to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -5666,8 +5396,6 @@ snapshots: unist-util-is: 6.0.1 unist-util-visit-parents: 6.0.2 - universalify@2.0.1: {} - unplugin-utils@0.2.5: dependencies: pathe: 2.0.3 @@ -5692,49 +5420,27 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite-node@4.0.0-beta.4(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0): + vite@8.1.3(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0): dependencies: - cac: 6.7.14 - debug: 4.4.3 - es-module-lexer: 1.7.0 - pathe: 2.0.3 - vite: rolldown-vite@7.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0) - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' - - '@types/node' - - esbuild - - jiti - - less - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml + lightningcss: 1.32.0 + picomatch: 4.0.4 + postcss: 8.5.16 + rolldown: 1.1.4 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 25.9.4 + esbuild: 0.27.7 + fsevents: 2.3.3 + jiti: 1.21.7 + yaml: 2.9.0 - vitepress-plugin-group-icons@1.7.5(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@25.9.4)(esbuild@0.27.7)(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)): dependencies: '@iconify-json/logos': 1.2.11 '@iconify-json/vscode-icons': 1.2.62 '@iconify/utils': 3.1.3 - vite: rolldown-vite@7.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0) - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' - - '@types/node' - - esbuild - - jiti - - less - - sass - - sass-embedded - - stylus - - sugarss - - terser - - tsx - - yaml + optionalDependencies: + vite: 8.1.3(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0) vitepress-plugin-llms@1.13.2: dependencies: @@ -5755,49 +5461,32 @@ snapshots: transitivePeerDependencies: - supports-color - vitest@4.0.0-beta.4(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/debug@4.1.13)(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0): + 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)): dependencies: - '@types/chai': 5.2.3 - '@vitest/expect': 4.0.0-beta.4 - '@vitest/mocker': 4.0.0-beta.4(rolldown-vite@7.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0)) + '@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.0.0-beta.4 - '@vitest/snapshot': 4.0.0-beta.4 - '@vitest/spy': 4.0.0-beta.4 - '@vitest/utils': 4.0.0-beta.4 - chai: 5.3.3 - debug: 4.4.3 + '@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 expect-type: 1.4.0 magic-string: 0.30.21 + obug: 2.1.3 pathe: 2.0.3 picomatch: 4.0.4 - std-env: 3.10.0 + std-env: 4.1.0 tinybench: 2.9.0 - tinyexec: 0.3.2 + tinyexec: 1.2.4 tinyglobby: 0.2.17 - tinypool: 1.1.1 - tinyrainbow: 2.0.0 - vite: rolldown-vite@7.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0) - vite-node: 4.0.0-beta.4(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@25.9.4)(esbuild@0.27.7)(jiti@1.21.7)(yaml@2.9.0) + 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) why-is-node-running: 2.3.0 optionalDependencies: - '@types/debug': 4.1.13 '@types/node': 25.9.4 transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' - - esbuild - - jiti - - less - msw - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml vscode-uri@3.1.0: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index b116e4ab..aefb59fe 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -13,7 +13,6 @@ onlyBuiltDependencies: overrides: ora>string-width: ^5 - vite: npm:rolldown-vite@latest patchedDependencies: '@types/markdown-it-attrs': patches/@types__markdown-it-attrs@4.1.3.patch diff --git a/rollup.config.ts b/rollup.config.ts index 7f02b1b8..23c9d41f 100644 --- a/rollup.config.ts +++ b/rollup.config.ts @@ -3,7 +3,7 @@ import commonjs from '@rollup/plugin-commonjs' import json from '@rollup/plugin-json' import { nodeResolve } from '@rollup/plugin-node-resolve' import replace from '@rollup/plugin-replace' -import * as fs from 'node:fs/promises' +import { rm } from 'node:fs/promises' import { builtinModules, createRequire } from 'node:module' import { type RollupOptions, defineConfig } from 'rollup' import dts from 'rollup-plugin-dts' @@ -33,7 +33,7 @@ const plugins = [ }), commonjs(), nodeResolve({ preferBuiltins: false }), - esbuild({ target: 'node20' }), + esbuild({ target: 'node22' }), json() ] @@ -88,7 +88,7 @@ const clientTypes: RollupOptions = { name: 'cleanup', async closeBundle() { if (PROD) { - await fs.rm('dist/client-types', { recursive: true }) + await rm('dist/client-types', { recursive: true }) } } } diff --git a/scripts/copyClient.js b/scripts/copyClient.ts similarity index 65% rename from scripts/copyClient.js rename to scripts/copyClient.ts index 465be10c..7257748e 100644 --- a/scripts/copyClient.js +++ b/scripts/copyClient.ts @@ -1,11 +1,11 @@ -import { copy } from 'fs-extra' +import { cp } from 'node:fs/promises' import { globSync } from 'tinyglobby' -function toDest(file) { +function toDest(file: string) { return file.replace(/^src\//, 'dist/') } globSync(['src/client/**']).forEach((file) => { if (/(\.ts|tsconfig\.json)$/.test(file)) return - copy(file, toDest(file)) + cp(file, toDest(file)) }) diff --git a/scripts/copyShared.js b/scripts/copyShared.js deleted file mode 100644 index af73c48e..00000000 --- a/scripts/copyShared.js +++ /dev/null @@ -1,9 +0,0 @@ -import { copy } from 'fs-extra' -import { globSync } from 'tinyglobby' - -globSync(['src/shared/**/*.ts']).forEach(async (file) => { - await Promise.all([ - copy(file, file.replace(/^src\/shared\//, 'src/node/')), - copy(file, file.replace(/^src\/shared\//, 'src/client/')) - ]) -}) diff --git a/scripts/copyShared.ts b/scripts/copyShared.ts new file mode 100644 index 00000000..c9512bd1 --- /dev/null +++ b/scripts/copyShared.ts @@ -0,0 +1,9 @@ +import { cp } from 'node:fs/promises' +import { globSync } from 'tinyglobby' + +globSync(['src/shared/**/*.ts']).forEach(async (file) => { + await Promise.all([ + cp(file, file.replace(/^src\/shared\//, 'src/node/')), + cp(file, file.replace(/^src\/shared\//, 'src/client/')) + ]) +}) diff --git a/scripts/release.js b/scripts/release.ts similarity index 77% rename from scripts/release.js rename to scripts/release.ts index b35c9019..2d4d1505 100644 --- a/scripts/release.js +++ b/scripts/release.ts @@ -1,8 +1,9 @@ -import { spawn } from 'node:child_process' -import { readFileSync, writeFileSync } from 'node:fs' +import { spawn } from 'cross-spawn' +import type { SpawnOptions } from 'node:child_process' +import fs from 'node:fs' +import { createRequire } from 'node:module' import { resolve } from 'node:path' import { fileURLToPath } from 'node:url' -import { createRequire } from 'node:module' import c from 'picocolors' import prompts from 'prompts' import semver from 'semver' @@ -12,17 +13,16 @@ const { version: currentVersion } = createRequire(import.meta.url)( ) const { inc: _inc, valid } = semver -const versionIncrements = ['patch', 'minor', 'major'] +const versionIncrements = ['patch', 'minor', 'major'] as const -const tags = ['latest', 'next'] +const tags = ['latest', 'next'] as const const dir = fileURLToPath(new URL('.', import.meta.url)) -const inc = (i) => _inc(currentVersion, i) -const run = (bin, args, opts = {}) => - new Promise((resolve, reject) => { +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', - shell: process.platform === 'win32', ...opts }) @@ -37,10 +37,10 @@ const run = (bin, args, opts = {}) => } }) }) -const step = (msg) => console.log(c.cyan(msg)) +const step = (msg: string) => console.log(c.cyan(msg)) async function main() { - let targetVersion + let targetVersion: string const versions = versionIncrements .map((i) => `${i} (${inc(i)})`) @@ -50,7 +50,7 @@ async function main() { type: 'select', name: 'release', message: 'Select release type', - choices: versions + choices: versions.map((title, value) => ({ title, value })) }) if (release === 3) { @@ -63,7 +63,7 @@ async function main() { }) ).version } else { - targetVersion = versions[release].match(/\((.*)\)/)[1] + targetVersion = versions[release].match(/\((.*)\)/)![1] } if (!valid(targetVersion)) { @@ -74,7 +74,7 @@ async function main() { type: 'select', name: 'tag', message: 'Select tag type', - choices: tags + choices: tags.map((title, value) => ({ title, value })) }) const { yes: tagOk } = await prompts({ @@ -132,13 +132,13 @@ async function main() { await run('git', ['push']) } -function updatePackage(version) { +function updatePackage(version: string) { const pkgPath = resolve(resolve(dir, '..'), 'package.json') - const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) + const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) pkg.version = version - writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n') + fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n') } main().catch((err) => console.error(err)) diff --git a/scripts/watchAndCopy.js b/scripts/watchAndCopy.js deleted file mode 100644 index c66085f8..00000000 --- a/scripts/watchAndCopy.js +++ /dev/null @@ -1,36 +0,0 @@ -import { watch } from 'chokidar' -import { copy, remove } from 'fs-extra' -import { normalizePath } from 'vite' - -function toClientAndNode(method, file) { - file = normalizePath(file) - if (method === 'copy') { - copy(file, file.replace(/^src\/shared\//, 'src/node/')) - copy(file, file.replace(/^src\/shared\//, 'src/client/')) - } else if (method === 'remove') { - remove(file.replace(/^src\/shared\//, 'src/node/')) - remove(file.replace(/^src\/shared\//, 'src/client/')) - } -} - -function toDist(file) { - return normalizePath(file).replace(/^src\//, 'dist/') -} - -// copy shared files to the client and node directory whenever they change. -watch('src/shared', { - ignored: (path, stats) => stats?.isFile() && !path.endsWith('.ts') -}) - .on('change', (file) => toClientAndNode('copy', file)) - .on('add', (file) => toClientAndNode('copy', file)) - .on('unlink', (file) => toClientAndNode('remove', file)) - -// copy non ts files, such as an html or css, to the dist directory whenever -// they change. -watch('src/client', { - ignored: (path, stats) => - stats?.isFile() && (path.endsWith('.ts') || path.endsWith('tsconfig.json')) -}) - .on('change', (file) => copy(file, toDist(file))) - .on('add', (file) => copy(file, toDist(file))) - .on('unlink', (file) => remove(toDist(file))) diff --git a/scripts/watchAndCopy.ts b/scripts/watchAndCopy.ts new file mode 100644 index 00000000..8f4b6679 --- /dev/null +++ b/scripts/watchAndCopy.ts @@ -0,0 +1,37 @@ +import { watch } from 'chokidar' +import { cp, rm } from 'node:fs/promises' +import { normalizePath } from 'vite' + +function toClientAndNode(method: 'copy' | 'remove', file: string) { + file = normalizePath(file) + if (method === 'copy') { + cp(file, file.replace(/^src\/shared\//, 'src/node/')) + cp(file, file.replace(/^src\/shared\//, 'src/client/')) + } else if (method === 'remove') { + rm(file.replace(/^src\/shared\//, 'src/node/'), { force: true }) + rm(file.replace(/^src\/shared\//, 'src/client/'), { force: true }) + } +} + +function toDist(file: string) { + return normalizePath(file).replace(/^src\//, 'dist/') +} + +// copy shared files to the client and node directory whenever they change. +watch('src/shared', { + ignored: (path, stats) => !!stats?.isFile() && !path.endsWith('.ts') +}) + .on('change', (file) => toClientAndNode('copy', file)) + .on('add', (file) => toClientAndNode('copy', file)) + .on('unlink', (file) => toClientAndNode('remove', file)) + +// copy non ts files, such as an html or css, to the dist directory whenever +// they change. +watch('src/client', { + ignored: (path, stats) => + !!stats?.isFile() && + (path.endsWith('.ts') || path.endsWith('tsconfig.json')) +}) + .on('change', (file) => cp(file, toDist(file))) + .on('add', (file) => cp(file, toDist(file))) + .on('unlink', (file) => rm(toDist(file), { force: true })) diff --git a/src/client/index.ts b/src/client/index.ts index 6112e866..47074c43 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -2,8 +2,8 @@ // so the user can do `import { useRoute, useData } from 'vitepress'` // generic types -export type { VitePressData } from './shared' export type { Route, Router } from './app/router' +export type { VitePressData } from './shared' // theme types export type { EnhanceAppContext, Theme } from './app/theme' diff --git a/src/client/theme-default/components/VPAlgoliaSearchBox.vue b/src/client/theme-default/components/VPAlgoliaSearchBox.vue index 26df2b7c..3d56c670 100644 --- a/src/client/theme-default/components/VPAlgoliaSearchBox.vue +++ b/src/client/theme-default/components/VPAlgoliaSearchBox.vue @@ -1,12 +1,16 @@ diff --git a/src/client/theme-default/components/VPDocAsideCarbonAds.vue b/src/client/theme-default/components/VPDocAsideCarbonAds.vue index d10598dd..a04d4f67 100644 --- a/src/client/theme-default/components/VPDocAsideCarbonAds.vue +++ b/src/client/theme-default/components/VPDocAsideCarbonAds.vue @@ -1,6 +1,6 @@ diff --git a/src/client/theme-default/components/VPLink.vue b/src/client/theme-default/components/VPLink.vue index f087a88c..36977697 100644 --- a/src/client/theme-default/components/VPLink.vue +++ b/src/client/theme-default/components/VPLink.vue @@ -2,14 +2,16 @@ import { computed } from 'vue' import { isLinkExternal, normalizeLink } from '../support/utils' -const props = defineProps<{ +const props = withDefaults(defineProps<{ tag?: string href?: string noIcon?: boolean external?: boolean target?: string rel?: string -}>() +}>(), { + external: undefined, +}) const tag = computed(() => props.tag ?? (props.href ? 'a' : 'span')) const isExternal = computed(() => diff --git a/src/client/theme-default/components/VPLocalSearchBox.vue b/src/client/theme-default/components/VPLocalSearchBox.vue index 5b592149..28a46a2f 100644 --- a/src/client/theme-default/components/VPLocalSearchBox.vue +++ b/src/client/theme-default/components/VPLocalSearchBox.vue @@ -67,25 +67,34 @@ const { activate } = useFocusTrap(el, { escapeDeactivates: true }) const { localeIndex, theme } = vitePressData -const searchIndex = computedAsync(async () => - markRaw( - MiniSearch.loadJSON( - (await searchIndexData.value[localeIndex.value]?.())?.default, - { - fields: ['title', 'titles', 'text'], - storeFields: ['title', 'titles'], - searchOptions: { - fuzzy: 0.2, - prefix: true, - boost: { title: 4, text: 2, titles: 1 }, +const isSearchIndexLoading = ref(false) +const isSearching = ref(false) +const showSearchSpinner = computed(() => { + return isSearchIndexLoading.value || isSearching.value +}) + +const searchIndex = computedAsync( + async () => + markRaw( + MiniSearch.loadJSON( + (await searchIndexData.value[localeIndex.value]?.())?.default, + { + fields: ['title', 'titles', 'text'], + storeFields: ['title', 'titles'], + searchOptions: { + fuzzy: 0.2, + prefix: true, + boost: { title: 4, text: 2, titles: 1 }, + ...(theme.value.search?.provider === 'local' && + theme.value.search.options?.miniSearch?.searchOptions) + }, ...(theme.value.search?.provider === 'local' && - theme.value.search.options?.miniSearch?.searchOptions) - }, - ...(theme.value.search?.provider === 'local' && - theme.value.search.options?.miniSearch?.options) - } - ) - ) + theme.value.search.options?.miniSearch?.options) + } + ) + ), + undefined, + isSearchIndexLoading ) const disableQueryPersistence = computed(() => { @@ -145,9 +154,15 @@ watchDebounced( let canceled = false onCleanup(() => { canceled = true + isSearching.value = false }) - if (!index) return + if (!index) { + results.value = [] + return + } + + isSearching.value = true // Search results.value = index @@ -232,6 +247,7 @@ watchDebounced( } // FIXME: without this whole page scrolls to the bottom resultsEl.value?.firstElementChild?.scrollIntoView({ block: 'start' }) + isSearching.value = false }, { debounce: 200, immediate: true } ) @@ -487,6 +503,14 @@ function onMouseMove(e: MouseEvent) { type="search" />
+ +