diff --git a/.eslintignore b/.eslintignore
deleted file mode 100644
index 744240c870..0000000000
--- a/.eslintignore
+++ /dev/null
@@ -1,7 +0,0 @@
-!.vuepress/
-!.*.js
-.cache/
-.temp/
-node_modules/
-lib/
-dist/
diff --git a/.eslintrc.cjs b/.eslintrc.cjs
deleted file mode 100644
index 7f763acda8..0000000000
--- a/.eslintrc.cjs
+++ /dev/null
@@ -1,26 +0,0 @@
-module.exports = {
- root: true,
- extends: 'vuepress',
- overrides: [
- {
- files: ['*.ts', '*.vue', '*.cts'],
- extends: 'vuepress-typescript',
- parserOptions: {
- project: ['tsconfig.json'],
- },
- rules: {
- '@typescript-eslint/no-explicit-any': 'off',
- '@typescript-eslint/no-non-null-assertion': 'off',
- 'vue/multi-word-component-names': 'off',
- },
- },
- {
- files: ['**/tests/**/*.ts', 'e2e/**/*.ts', 'tsup.config.ts'],
- rules: {
- '@typescript-eslint/explicit-function-return-type': 'off',
- 'import/no-extraneous-dependencies': 'off',
- 'vue/one-component-per-file': 'off',
- },
- },
- ],
-}
diff --git a/commitlint.config.ts b/commitlint.config.ts
index 6ee3b18b7a..859187f3de 100644
--- a/commitlint.config.ts
+++ b/commitlint.config.ts
@@ -6,12 +6,13 @@ const getSubDirectories = (dir: string): string[] =>
fs
.readdirSync(dir)
.filter((item) => fs.statSync(path.join(dir, item)).isDirectory())
-const packages = getSubDirectories(path.resolve(__dirname, 'packages'))
+
+const PACKAGES = getSubDirectories(path.resolve(__dirname, 'packages'))
export default {
extends: ['@commitlint/config-conventional'],
rules: {
- 'scope-enum': [2, 'always', [...packages, 'e2e']],
+ 'scope-enum': [2, 'always', [...PACKAGES, 'e2e']],
'footer-max-line-length': [0],
},
} satisfies UserConfig
diff --git a/e2e/docs/.vuepress/plugins/foo/fooPlugin.ts b/e2e/docs/.vuepress/plugins/foo/fooPlugin.ts
index 93ef0c8cff..ac2c07663f 100644
--- a/e2e/docs/.vuepress/plugins/foo/fooPlugin.ts
+++ b/e2e/docs/.vuepress/plugins/foo/fooPlugin.ts
@@ -1,11 +1,8 @@
import { getDirname, path } from 'vuepress/utils'
-const __dirname = getDirname(import.meta.url)
+const DIRNAME = getDirname(import.meta.url)
export const fooPlugin = {
name: 'test-plugin',
- clientConfigFile: path.resolve(
- __dirname,
- './nonDefaultExportClientConfig.js',
- ),
+ clientConfigFile: path.resolve(DIRNAME, './nonDefaultExportClientConfig.js'),
}
diff --git a/e2e/docs/.vuepress/theme/client/config.ts b/e2e/docs/.vuepress/theme/client/config.ts
index 8d35748afe..c263a6f6e7 100644
--- a/e2e/docs/.vuepress/theme/client/config.ts
+++ b/e2e/docs/.vuepress/theme/client/config.ts
@@ -8,7 +8,7 @@ import NotFound from './layouts/NotFound.vue'
import './styles/index.scss'
export default defineClientConfig({
- enhance({ app, router }) {
+ enhance() {
// ...
},
@@ -16,12 +16,14 @@ export default defineClientConfig({
// ...
},
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment -- vue sfc type info is not available in eslint scope */
layouts: {
CssModulesLayout,
CustomLayout,
Layout,
NotFound,
},
+ /* eslint-enable @typescript-eslint/no-unsafe-assignment */
rootComponents: [RootComponentFromTheme],
})
diff --git a/e2e/docs/.vuepress/theme/client/layouts/Layout.vue b/e2e/docs/.vuepress/theme/client/layouts/Layout.vue
index 4c4d2d83d2..07519db48d 100644
--- a/e2e/docs/.vuepress/theme/client/layouts/Layout.vue
+++ b/e2e/docs/.vuepress/theme/client/layouts/Layout.vue
@@ -21,4 +21,6 @@ const siteData = useSiteData()
-
+
diff --git a/e2e/docs/.vuepress/theme/node/e2eTheme.ts b/e2e/docs/.vuepress/theme/node/e2eTheme.ts
index 7c2a5f2e6c..7d2f5d1288 100644
--- a/e2e/docs/.vuepress/theme/node/e2eTheme.ts
+++ b/e2e/docs/.vuepress/theme/node/e2eTheme.ts
@@ -1,26 +1,24 @@
-import type { Page, Theme } from 'vuepress/core'
+import type { Theme } from 'vuepress/core'
import { getDirname, path } from 'vuepress/utils'
-const __dirname = getDirname(import.meta.url)
+const DIRNAME = getDirname(import.meta.url)
-export const e2eTheme = (): Theme => {
- return {
- name: '@vuepress/theme-e2e',
+export const e2eTheme = (): Theme => ({
+ name: '@vuepress/theme-e2e',
- alias: {
- // ...
- },
+ alias: {
+ // ...
+ },
- define: {
- // ...
- },
+ define: {
+ // ...
+ },
- clientConfigFile: path.resolve(__dirname, '../client/config.ts'),
+ clientConfigFile: path.resolve(DIRNAME, '../client/config.ts'),
- extendsPage: (page: Page) => {
- // ...
- },
+ extendsPage: () => {
+ // ...
+ },
- plugins: [],
- }
-}
+ plugins: [],
+})
diff --git a/e2e/modules/conditional-exports/types.d.ts b/e2e/modules/conditional-exports/types.d.ts
index 657d2a74ff..a1d1d5f6c2 100644
--- a/e2e/modules/conditional-exports/types.d.ts
+++ b/e2e/modules/conditional-exports/types.d.ts
@@ -1,2 +1,2 @@
-declare const str: string
-export default str
+declare const STR: string
+export default STR
diff --git a/e2e/playwright.config.ts b/e2e/playwright.config.ts
index 13ff0ad7f3..8bfcec75b8 100644
--- a/e2e/playwright.config.ts
+++ b/e2e/playwright.config.ts
@@ -1,16 +1,16 @@
import { defineConfig, devices } from '@playwright/test'
-import { BASE, BUNDLER, isCI, isDev } from './utils/env'
+import { BASE, BUNDLER, IS_CI, IS_DEV } from './utils/env'
-const commandPart1 = isDev ? 'docs:dev' : 'docs:build'
-const commandPart2 = BUNDLER === 'vite' ? '' : `-${BUNDLER}`
-const commandPart3 = isDev ? '' : ' && pnpm docs:serve'
+const COMMAND_PART1 = IS_DEV ? 'docs:dev' : 'docs:build'
+const COMMAND_PART2 = BUNDLER === 'vite' ? '' : `-${BUNDLER}`
+const COMMAND_PART3 = IS_DEV ? '' : ' && pnpm docs:serve'
export default defineConfig({
testDir: 'tests',
- forbidOnly: isCI,
- reporter: isCI ? 'github' : 'line',
- retries: isCI ? 2 : 0,
- workers: isDev ? 1 : undefined,
+ forbidOnly: IS_CI,
+ reporter: IS_CI ? 'github' : 'line',
+ retries: IS_CI ? 2 : 0,
+ workers: IS_DEV ? 1 : undefined,
projects: [
{
name: 'chromium',
@@ -22,8 +22,8 @@ export default defineConfig({
trace: 'on-first-retry',
},
webServer: {
- command: `pnpm docs:clean && pnpm ${commandPart1}${commandPart2}${commandPart3}`,
+ command: `pnpm docs:clean && pnpm ${COMMAND_PART1}${COMMAND_PART2}${COMMAND_PART3}`,
url: 'http://127.0.0.1:9080',
- reuseExistingServer: !isCI,
+ reuseExistingServer: !IS_CI,
},
})
diff --git a/e2e/tests/hmr.spec.ts b/e2e/tests/hmr.spec.ts
index 37336026ca..f1040d9c02 100644
--- a/e2e/tests/hmr.spec.ts
+++ b/e2e/tests/hmr.spec.ts
@@ -1,5 +1,5 @@
import { expect, test } from '@playwright/test'
-import { isDev } from '../utils/env'
+import { IS_DEV } from '../utils/env'
import { readSourceMarkdown, writeSourceMarkdown } from '../utils/source'
const hmrUpdateTitle = async (): Promise => {
@@ -33,7 +33,7 @@ const hmrRestore = async (): Promise => {
)
}
-if (isDev) {
+if (IS_DEV) {
test.beforeEach(async () => {
await hmrRestore()
})
diff --git a/e2e/tests/imports/conditional-exports.spec.ts b/e2e/tests/imports/conditional-exports.spec.ts
index daec6fc941..6f43cb25b8 100644
--- a/e2e/tests/imports/conditional-exports.spec.ts
+++ b/e2e/tests/imports/conditional-exports.spec.ts
@@ -8,8 +8,8 @@ test('should load different files correctly', async ({ page }) => {
if (COMMAND === 'build') {
expect(
- await page.evaluate(() =>
- fetch('./conditional-exports.html').then((res) => res.text()),
+ await page.evaluate(async () =>
+ fetch('./conditional-exports.html').then(async (res) => res.text()),
),
).toContain('node-mjs
')
}
diff --git a/e2e/tests/router/navigate-by-link.spec.ts b/e2e/tests/router/navigate-by-link.spec.ts
index 4b7560a732..7c6f974992 100644
--- a/e2e/tests/router/navigate-by-link.spec.ts
+++ b/e2e/tests/router/navigate-by-link.spec.ts
@@ -8,7 +8,7 @@ test.beforeEach(async ({ page }) => {
test.describe('markdown links', () => {
test('should navigate to home correctly', async ({ page }) => {
await page.locator('#markdown-links + ul > li > a').nth(0).click()
- await expect(page).toHaveURL(`${BASE}`)
+ await expect(page).toHaveURL(BASE)
await expect(page.locator('#home-h2')).toHaveText('Home H2')
})
@@ -46,7 +46,7 @@ test.describe('markdown links', () => {
test.describe('html links', () => {
test('should navigate to home correctly', async ({ page }) => {
await page.locator('#html-links + p > a').nth(0).click()
- await expect(page).toHaveURL(`${BASE}`)
+ await expect(page).toHaveURL(BASE)
await expect(page.locator('#home-h2')).toHaveText('Home H2')
})
diff --git a/e2e/tests/router/navigate-by-router.spec.ts b/e2e/tests/router/navigate-by-router.spec.ts
index 327c53be57..b847a839a2 100644
--- a/e2e/tests/router/navigate-by-router.spec.ts
+++ b/e2e/tests/router/navigate-by-router.spec.ts
@@ -7,7 +7,7 @@ test.beforeEach(async ({ page }) => {
test('should navigate to home correctly', async ({ page }) => {
await page.locator('#home').click()
- await expect(page).toHaveURL(`${BASE}`)
+ await expect(page).toHaveURL(BASE)
await expect(page.locator('#home-h2')).toHaveText('Home H2')
})
diff --git a/e2e/tests/router/resolve-route-query-hash.spec.ts b/e2e/tests/router/resolve-route-query-hash.spec.ts
index d7554c6425..1afa86d501 100644
--- a/e2e/tests/router/resolve-route-query-hash.spec.ts
+++ b/e2e/tests/router/resolve-route-query-hash.spec.ts
@@ -1,6 +1,6 @@
import { expect, test } from '@playwright/test'
-const testCases = [
+const TEST_CASES = [
{
path: '/?query=1',
notFound: false,
@@ -28,8 +28,11 @@ test('should resolve routes when including both the query and hash', async ({
for (const [index, li] of listItemsLocator.entries()) {
const textContent = await li.textContent()
- const resolvedRoute = JSON.parse(/: (\{.*\})\s*$/.exec(textContent!)![1])
- expect(resolvedRoute.path).toEqual(testCases[index].path)
- expect(resolvedRoute.notFound).toEqual(testCases[index].notFound)
+ const resolvedRoute = JSON.parse(
+ /: (\{.*\})\s*$/.exec(textContent!)![1],
+ ) as { path: string; notFound: boolean }
+
+ expect(resolvedRoute.path).toEqual(TEST_CASES[index].path)
+ expect(resolvedRoute.notFound).toEqual(TEST_CASES[index].notFound)
}
})
diff --git a/e2e/tests/router/resolve-route.spec.ts b/e2e/tests/router/resolve-route.spec.ts
index 10cf9799c1..bad4350843 100644
--- a/e2e/tests/router/resolve-route.spec.ts
+++ b/e2e/tests/router/resolve-route.spec.ts
@@ -1,6 +1,6 @@
import { expect, test } from '@playwright/test'
-const testCases = [
+const TEST_CASES = [
{
selector: '#index',
expected: {
@@ -54,13 +54,19 @@ const testCases = [
test('should resolve routes correctly', async ({ page }) => {
await page.goto('router/resolve-route.html')
- for (const { selector, expected } of testCases) {
+ for (const { selector, expected } of TEST_CASES) {
const listItemsLocator = await page
.locator(`.e2e-theme-content ${selector} + ul > li`)
.all()
for (const li of listItemsLocator) {
const textContent = await li.textContent()
- const resolvedRoute = JSON.parse(/: (\{.*\})\s*$/.exec(textContent!)![1])
+ const resolvedRoute = JSON.parse(
+ /: (\{.*\})\s*$/.exec(textContent!)![1],
+ ) as {
+ path: string
+ meta: Record
+ notFound: boolean
+ }
expect(resolvedRoute.path).toEqual(expected.path)
expect(resolvedRoute.meta).toStrictEqual(expected.meta)
expect(resolvedRoute.notFound).toEqual(expected.notFound)
diff --git a/e2e/utils/env.ts b/e2e/utils/env.ts
index c1999dd3e2..17781ce31e 100644
--- a/e2e/utils/env.ts
+++ b/e2e/utils/env.ts
@@ -2,6 +2,6 @@ export const BASE = process.env.E2E_BASE ?? '/'
export const BUNDLER = process.env.E2E_BUNDLER ?? 'vite'
export const COMMAND = process.env.E2E_COMMAND ?? 'dev'
-export const isDev = COMMAND === 'dev'
-export const isProd = COMMAND === 'build'
-export const isCI = !!process.env.CI
+export const IS_DEV = COMMAND === 'dev'
+export const IS_PROD = COMMAND === 'build'
+export const IS_CI = !!process.env.CI
diff --git a/e2e/utils/source.ts b/e2e/utils/source.ts
index 1db8f57011..6f07073446 100644
--- a/e2e/utils/source.ts
+++ b/e2e/utils/source.ts
@@ -1,17 +1,14 @@
import { fs, getDirname, path } from 'vuepress/utils'
-const __dirname = getDirname(import.meta.url)
+const DIRNAME = getDirname(import.meta.url)
const resolveSourceMarkdownPath = (...args: string[]): string =>
- path.resolve(__dirname, '../docs', ...args)
+ path.resolve(DIRNAME, '../docs', ...args)
-export const readSourceMarkdown = async (filePath: string): Promise => {
- return fs.readFile(resolveSourceMarkdownPath(filePath), 'utf-8')
-}
+export const readSourceMarkdown = async (filePath: string): Promise =>
+ fs.readFile(resolveSourceMarkdownPath(filePath), 'utf-8')
export const writeSourceMarkdown = async (
filePath: string,
content: string,
-): Promise => {
- return fs.writeFile(resolveSourceMarkdownPath(filePath), content)
-}
+): Promise => fs.writeFile(resolveSourceMarkdownPath(filePath), content)
diff --git a/eslint.config.js b/eslint.config.js
new file mode 100644
index 0000000000..955989f874
--- /dev/null
+++ b/eslint.config.js
@@ -0,0 +1,41 @@
+import fs from 'node:fs'
+import path from 'node:path'
+import { fileURLToPath } from 'node:url'
+import { vuepress } from 'eslint-config-vuepress'
+
+const ROOT = path.resolve(fileURLToPath(import.meta.url), '..')
+const E2E_DIR = path.resolve(ROOT, 'e2e')
+const PACKAGES_DIRS = fs
+ .readdirSync(path.resolve(ROOT, 'packages'))
+ .map((item) => `./packages/${item}`)
+
+export default vuepress(
+ {
+ imports: {
+ packageDir: [ROOT, E2E_DIR, ...PACKAGES_DIRS],
+ },
+ typescript: {
+ overrides: {
+ '@typescript-eslint/no-dynamic-delete': 'off',
+ '@typescript-eslint/no-non-null-assertion': 'off',
+ 'no-underscore-dangle': [
+ 'warn',
+ { allow: ['_context', '_pageChunk', '_registeredComponents'] },
+ ],
+ },
+ },
+ vue: {
+ overrides: {
+ 'no-useless-assignment': 'off', // TODO: false positive in vue sfc
+ },
+ },
+ },
+ {
+ files: ['**/tests/**'],
+ rules: {
+ 'import/no-unresolved': 'off',
+ 'no-console': 'off',
+ 'prefer-template': 'off',
+ },
+ },
+)
diff --git a/package.json b/package.json
index c5fd77e1f4..81672f1251 100644
--- a/package.json
+++ b/package.json
@@ -8,8 +8,8 @@
"check-types": "vue-tsc --noEmit",
"clean": "pnpm --parallel --stream clean",
"format": "prettier --write .",
- "lint": "eslint --ext .cjs,.js,.ts,.vue . && prettier --check .",
- "lint:fix": "eslint --fix --ext .cjs,.js,.ts,.vue . && prettier --write .",
+ "lint": "eslint . && prettier --check .",
+ "lint:fix": "eslint --fix . && prettier --write .",
"prepare": "husky",
"release": "pnpm release:check && pnpm release:version && pnpm release:publish",
"release:changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
@@ -39,16 +39,15 @@
"@vitest/coverage-istanbul": "^2.0.5",
"bumpp": "^9.5.1",
"conventional-changelog-cli": "^5.0.0",
- "eslint": "^8.57.0",
- "eslint-config-vuepress": "^4.10.1",
- "eslint-config-vuepress-typescript": "^4.10.1",
+ "eslint": "^9.9.0",
+ "eslint-config-vuepress": "^5.1.2",
"husky": "^9.1.4",
"lint-staged": "^15.2.9",
"prettier": "^3.3.3",
- "prettier-config-vuepress": "^4.4.0",
+ "prettier-config-vuepress": "^5.0.0",
"rimraf": "^6.0.1",
"sort-package-json": "^2.10.0",
- "tsconfig-vuepress": "^4.5.0",
+ "tsconfig-vuepress": "^5.0.0",
"tsup": "^8.2.4",
"typescript": "^5.5.4",
"vite": "~5.4.0",
diff --git a/packages/bundler-vite/package.json b/packages/bundler-vite/package.json
index ae4be4aabf..9862ee3c25 100644
--- a/packages/bundler-vite/package.json
+++ b/packages/bundler-vite/package.json
@@ -49,6 +49,9 @@
"vue": "^3.4.37",
"vue-router": "^4.4.3"
},
+ "devDependencies": {
+ "@types/connect-history-api-fallback": "^1.5.4"
+ },
"publishConfig": {
"access": "public"
},
diff --git a/packages/bundler-vite/src/build/build.ts b/packages/bundler-vite/src/build/build.ts
index 4b90aa5137..33466ea6b0 100644
--- a/packages/bundler-vite/src/build/build.ts
+++ b/packages/bundler-vite/src/build/build.ts
@@ -22,13 +22,13 @@ export const build = async (
let serverOutput!: RollupOutput
await withSpinner('Compiling with vite')(async () => {
// create vite config
- const clientConfig = await resolveViteConfig({
+ const clientConfig = resolveViteConfig({
app,
options,
isBuild: true,
isServer: false,
})
- const serverConfig = await resolveViteConfig({
+ const serverConfig = resolveViteConfig({
app,
options,
isBuild: true,
diff --git a/packages/bundler-vite/src/build/renderPage.ts b/packages/bundler-vite/src/build/renderPage.ts
index 6e8af6ed88..a0af5b2374 100644
--- a/packages/bundler-vite/src/build/renderPage.ts
+++ b/packages/bundler-vite/src/build/renderPage.ts
@@ -1,8 +1,9 @@
import type { App, Page } from '@vuepress/core'
+import type { VuepressSSRContext } from '@vuepress/shared'
import { fs, renderHead } from '@vuepress/utils'
import type { OutputAsset, OutputChunk, RollupOutput } from 'rollup'
-import { ssrContextKey } from 'vue'
import type { App as VueApp } from 'vue'
+import { ssrContextKey } from 'vue'
import type { SSRContext } from 'vue/server-renderer'
import type { Router } from 'vue-router'
import { renderPagePrefetchLinks } from './renderPagePrefetchLinks.js'
@@ -38,7 +39,7 @@ export const renderPage = async ({
// create vue ssr context with default values
delete vueApp._context.provides[ssrContextKey]
- const ssrContext: SSRContext = {
+ const ssrContext: VuepressSSRContext = {
lang: 'en',
head: [],
}
diff --git a/packages/bundler-vite/src/build/renderPagePrefetchLinks.ts b/packages/bundler-vite/src/build/renderPagePrefetchLinks.ts
index a0bd189560..e4a81b24df 100644
--- a/packages/bundler-vite/src/build/renderPagePrefetchLinks.ts
+++ b/packages/bundler-vite/src/build/renderPagePrefetchLinks.ts
@@ -14,7 +14,7 @@ export const renderPagePrefetchLinks = ({
pageChunkFiles: string[]
}): string => {
// shouldPrefetch option
- const shouldPrefetch = app.options.shouldPrefetch
+ const { shouldPrefetch } = app.options
// do not render prefetch links
if (shouldPrefetch === false) {
diff --git a/packages/bundler-vite/src/build/renderPagePreloadLinks.ts b/packages/bundler-vite/src/build/renderPagePreloadLinks.ts
index 8e198ec445..3f035d699e 100644
--- a/packages/bundler-vite/src/build/renderPagePreloadLinks.ts
+++ b/packages/bundler-vite/src/build/renderPagePreloadLinks.ts
@@ -14,7 +14,7 @@ export const renderPagePreloadLinks = ({
pageChunkFiles: string[]
}): string => {
// shouldPreload option
- const shouldPreload = app.options.shouldPreload
+ const { shouldPreload } = app.options
// do not render preload links
if (shouldPreload === false) {
diff --git a/packages/bundler-vite/src/dev.ts b/packages/bundler-vite/src/dev.ts
index da2c69bb4f..c389d08131 100644
--- a/packages/bundler-vite/src/dev.ts
+++ b/packages/bundler-vite/src/dev.ts
@@ -14,7 +14,7 @@ export const dev = async (
// plugin hook: extendsBundlerOptions
await app.pluginApi.hooks.extendsBundlerOptions.process(options, app)
- const viteConfig = await resolveViteConfig({
+ const viteConfig = resolveViteConfig({
app,
options,
isBuild: false,
@@ -24,8 +24,8 @@ export const dev = async (
const server = await createServer(viteConfig)
await server.listen()
- const viteVersion = fs.readJsonSync(
- require.resolve('vite/package.json'),
+ const viteVersion = (
+ fs.readJsonSync(require.resolve('vite/package.json')) as { version: string }
).version
server.config.logger.info(
colors.cyan(`\n vite v${viteVersion}`) +
diff --git a/packages/bundler-vite/src/plugins/vuepressMainPlugin.ts b/packages/bundler-vite/src/plugins/vuepressMainPlugin.ts
index 05a53d3b0d..da2ce652fe 100644
--- a/packages/bundler-vite/src/plugins/vuepressMainPlugin.ts
+++ b/packages/bundler-vite/src/plugins/vuepressMainPlugin.ts
@@ -6,6 +6,92 @@ import type { AcceptedPlugin } from 'postcss'
import postcssrc from 'postcss-load-config'
import type { AliasOptions, Connect, Plugin, UserConfig } from 'vite'
+/**
+ * Resolve vite config `resolve.alias`
+ */
+const resolveAlias = async ({
+ app,
+ isServer,
+}: {
+ app: App
+ isServer: boolean
+}): Promise => {
+ const alias: AliasOptions = {
+ '@internal': app.dir.temp('internal'),
+ '@temp': app.dir.temp(),
+ '@source': app.dir.source(),
+ }
+
+ // plugin hook: alias
+ const aliasResult = await app.pluginApi.hooks.alias.process(app, isServer)
+
+ aliasResult.forEach((aliasObject) => {
+ Object.entries(aliasObject).forEach(([key, value]) => {
+ alias[key] = value as string
+ })
+ })
+
+ return [
+ ...Object.keys(alias).map((item) => ({
+ find: item,
+ replacement: alias[item],
+ })),
+ ...(isServer
+ ? []
+ : [
+ {
+ find: /^vue$/,
+ replacement: 'vue/dist/vue.runtime.esm-bundler.js',
+ },
+ {
+ find: /^vue-router$/,
+ replacement: 'vue-router/dist/vue-router.esm-bundler.js',
+ },
+ ]),
+ ]
+}
+
+/**
+ * Resolve vite config `define`
+ */
+const resolveDefine = async ({
+ app,
+ isBuild,
+ isServer,
+}: {
+ app: App
+ isBuild: boolean
+ isServer: boolean
+}): Promise => {
+ const define: UserConfig['define'] = {
+ __VUEPRESS_VERSION__: JSON.stringify(app.version),
+ __VUEPRESS_BASE__: JSON.stringify(app.options.base),
+ __VUEPRESS_DEV__: JSON.stringify(!isBuild),
+ __VUEPRESS_SSR__: JSON.stringify(isServer),
+ // @see http://link.vuejs.org/feature-flags
+ // enable options API by default
+ __VUE_OPTIONS_API__: JSON.stringify(true),
+ __VUE_PROD_DEVTOOLS__: JSON.stringify(app.env.isDebug),
+ __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: JSON.stringify(app.env.isDebug),
+ }
+
+ // override vite built-in define config in debug mode
+ if (app.env.isDebug) {
+ define['process.env.NODE_ENV'] = JSON.stringify('development')
+ }
+
+ // plugin hook: define
+ const defineResult = await app.pluginApi.hooks.define.process(app, isServer)
+
+ defineResult.forEach((defineObject) => {
+ Object.entries(defineObject).forEach(([key, value]) => {
+ define[key] = JSON.stringify(value)
+ })
+ })
+
+ return define
+}
+
/**
* The main plugin to compat vuepress with vite
*/
@@ -56,7 +142,7 @@ import 'vuepress/client-app'
try {
const postcssConfigResult = await postcssrc()
postcssPlugins = postcssConfigResult.plugins
- } catch (error) {
+ } catch {
postcssPlugins = [autoprefixer]
}
@@ -92,7 +178,11 @@ import 'vuepress/client-app'
cssCodeSplit: false,
rollupOptions: {
input: app.dir.client(
- fs.readJsonSync(app.dir.client('package.json')).exports['./app'],
+ (
+ fs.readJsonSync(app.dir.client('package.json')) as {
+ exports: { './app': string }
+ }
+ ).exports['./app'],
),
output: {
sanitizeFileName,
@@ -144,89 +234,3 @@ import 'vuepress/client-app'
}
},
})
-
-/**
- * Resolve vite config `resolve.alias`
- */
-const resolveAlias = async ({
- app,
- isServer,
-}: {
- app: App
- isServer: boolean
-}): Promise => {
- const alias: AliasOptions = {
- '@internal': app.dir.temp('internal'),
- '@temp': app.dir.temp(),
- '@source': app.dir.source(),
- }
-
- // plugin hook: alias
- const aliasResult = await app.pluginApi.hooks.alias.process(app, isServer)
-
- aliasResult.forEach((aliasObject) =>
- Object.entries(aliasObject).forEach(([key, value]) => {
- alias[key] = value
- }),
- )
-
- return [
- ...Object.keys(alias).map((item) => ({
- find: item,
- replacement: alias[item],
- })),
- ...(isServer
- ? []
- : [
- {
- find: /^vue$/,
- replacement: 'vue/dist/vue.runtime.esm-bundler.js',
- },
- {
- find: /^vue-router$/,
- replacement: 'vue-router/dist/vue-router.esm-bundler.js',
- },
- ]),
- ]
-}
-
-/**
- * Resolve vite config `define`
- */
-const resolveDefine = async ({
- app,
- isBuild,
- isServer,
-}: {
- app: App
- isBuild: boolean
- isServer: boolean
-}): Promise => {
- const define: UserConfig['define'] = {
- __VUEPRESS_VERSION__: JSON.stringify(app.version),
- __VUEPRESS_BASE__: JSON.stringify(app.options.base),
- __VUEPRESS_DEV__: JSON.stringify(!isBuild),
- __VUEPRESS_SSR__: JSON.stringify(isServer),
- // @see http://link.vuejs.org/feature-flags
- // enable options API by default
- __VUE_OPTIONS_API__: JSON.stringify(true),
- __VUE_PROD_DEVTOOLS__: JSON.stringify(app.env.isDebug),
- __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: JSON.stringify(app.env.isDebug),
- }
-
- // override vite built-in define config in debug mode
- if (app.env.isDebug) {
- define['process.env.NODE_ENV'] = JSON.stringify('development')
- }
-
- // plugin hook: define
- const defineResult = await app.pluginApi.hooks.define.process(app, isServer)
-
- defineResult.forEach((defineObject) =>
- Object.entries(defineObject).forEach(([key, value]) => {
- define[key] = JSON.stringify(value)
- }),
- )
-
- return define
-}
diff --git a/packages/bundler-vite/src/plugins/vuepressVuePlugin.ts b/packages/bundler-vite/src/plugins/vuepressVuePlugin.ts
index 35d72951de..96b11b514a 100644
--- a/packages/bundler-vite/src/plugins/vuepressVuePlugin.ts
+++ b/packages/bundler-vite/src/plugins/vuepressVuePlugin.ts
@@ -3,19 +3,6 @@ import type { Plugin } from 'vite'
import type { AssetURLOptions, AssetURLTagConfig } from 'vue/compiler-sfc'
import type { ViteBundlerOptions } from '../types.js'
-/**
- * Wrapper of official vue plugin
- */
-export const vuepressVuePlugin = (options: ViteBundlerOptions): Plugin => {
- return vuePlugin({
- ...options.vuePluginOptions,
- template: {
- ...options.vuePluginOptions?.template,
- transformAssetUrls: resolveTransformAssetUrls(options),
- },
- })
-}
-
/**
* Determine if the given `transformAssetUrls` option is `AssetURLTagConfig`
*/
@@ -56,3 +43,15 @@ const resolveTransformAssetUrls = (
...userTransformAssetUrls,
}
}
+
+/**
+ * Wrapper of official vue plugin
+ */
+export const vuepressVuePlugin = (options: ViteBundlerOptions): Plugin =>
+ vuePlugin({
+ ...options.vuePluginOptions,
+ template: {
+ ...options.vuePluginOptions?.template,
+ transformAssetUrls: resolveTransformAssetUrls(options),
+ },
+ })
diff --git a/packages/bundler-vite/src/resolveViteConfig.ts b/packages/bundler-vite/src/resolveViteConfig.ts
index ee18480c1e..2c381386c7 100644
--- a/packages/bundler-vite/src/resolveViteConfig.ts
+++ b/packages/bundler-vite/src/resolveViteConfig.ts
@@ -8,7 +8,7 @@ import {
} from './plugins/index.js'
import type { ViteBundlerOptions } from './types.js'
-export const resolveViteConfig = async ({
+export const resolveViteConfig = ({
app,
options,
isBuild,
@@ -18,8 +18,8 @@ export const resolveViteConfig = async ({
options: ViteBundlerOptions
isBuild: boolean
isServer: boolean
-}): Promise => {
- return mergeConfig(
+}): InlineConfig =>
+ mergeConfig(
{
clearScreen: false,
configFile: false,
@@ -36,4 +36,3 @@ export const resolveViteConfig = async ({
// some vite options would not take effect inside a plugin, so we still need to merge them here in addition to userConfigPlugin
options.viteOptions ?? {},
)
-}
diff --git a/packages/bundler-vite/src/types.ts b/packages/bundler-vite/src/types.ts
index c6f968edf1..dde557c177 100644
--- a/packages/bundler-vite/src/types.ts
+++ b/packages/bundler-vite/src/types.ts
@@ -1,10 +1,11 @@
import type { Options as VuePluginOptions } from '@vitejs/plugin-vue'
+import type { BundlerOptions } from '@vuepress/core'
import type { InlineConfig } from 'vite'
/**
* Options for bundler-vite
*/
-export interface ViteBundlerOptions {
+export interface ViteBundlerOptions extends BundlerOptions {
viteOptions?: InlineConfig
vuePluginOptions?: VuePluginOptions
}
diff --git a/packages/bundler-vite/src/viteBundler.ts b/packages/bundler-vite/src/viteBundler.ts
index d8e85898a1..6764c4aea1 100644
--- a/packages/bundler-vite/src/viteBundler.ts
+++ b/packages/bundler-vite/src/viteBundler.ts
@@ -5,6 +5,6 @@ import type { ViteBundlerOptions } from './types.js'
export const viteBundler = (options: ViteBundlerOptions = {}): Bundler => ({
name: '@vuepress/bundler-vite',
- dev: (app) => dev(options, app),
- build: (app) => build(options, app),
+ dev: async (app) => dev(options, app),
+ build: async (app) => build(options, app),
})
diff --git a/packages/bundler-webpack/src/build/build.ts b/packages/bundler-webpack/src/build/build.ts
index c6ead7feab..72ddb08331 100644
--- a/packages/bundler-webpack/src/build/build.ts
+++ b/packages/bundler-webpack/src/build/build.ts
@@ -5,13 +5,14 @@ import {
debug,
fs,
importFileDefault,
+ logger,
withSpinner,
} from '@vuepress/utils'
import webpack from 'webpack'
import { resolveWebpackConfig } from '../resolveWebpackConfig.js'
import type { WebpackBundlerOptions } from '../types.js'
import {
- clientManifestFilename,
+ CLIENT_MANIFEST_FILENAME,
createClientConfig,
} from './createClientConfig.js'
import { createServerConfig } from './createServerConfig.js'
@@ -50,14 +51,14 @@ export const build = async (
if (err) {
reject(err)
} else if (stats?.hasErrors()) {
- stats.toJson().errors?.forEach((err) => {
- console.error(err)
+ stats.toJson().errors?.forEach((item) => {
+ logger.error(item)
})
reject(new Error('Failed to compile with errors'))
} else {
if (stats?.hasWarnings()) {
stats.toJson().warnings?.forEach((warning) => {
- console.warn(warning)
+ logger.warn(warning)
})
}
resolve()
@@ -70,8 +71,10 @@ export const build = async (
// render pages
await withSpinner(`Rendering ${app.pages.length} pages`)(async (spinner) => {
// load the client manifest file
- const clientManifestPath = app.dir.temp(clientManifestFilename)
- const clientManifest: ClientManifest = await fs.readJson(clientManifestPath)
+ const clientManifestPath = app.dir.temp(CLIENT_MANIFEST_FILENAME)
+ const clientManifest = (await fs.readJson(
+ clientManifestPath,
+ )) as ClientManifest
// resolve client files meta
const { initialFilesMeta, asyncFilesMeta, moduleFilesMetaMap } =
diff --git a/packages/bundler-webpack/src/build/createClientConfig.ts b/packages/bundler-webpack/src/build/createClientConfig.ts
index b64ea26770..e61f048c77 100644
--- a/packages/bundler-webpack/src/build/createClientConfig.ts
+++ b/packages/bundler-webpack/src/build/createClientConfig.ts
@@ -15,7 +15,7 @@ const require = createRequire(import.meta.url)
/**
* Filename of the client manifest file that generated by client plugin
*/
-export const clientManifestFilename = '.server/client-manifest.json'
+export const CLIENT_MANIFEST_FILENAME = '.server/client-manifest.json'
export const createClientConfig = async (
app: App,
@@ -39,7 +39,7 @@ export const createClientConfig = async (
// vuepress client plugin, handle client assets info for ssr
config
.plugin('vuepress-client')
- .use(createClientPlugin(app.dir.temp(clientManifestFilename)))
+ .use(createClientPlugin(app.dir.temp(CLIENT_MANIFEST_FILENAME)))
// copy files from public dir to dest dir
if (fs.pathExistsSync(app.dir.public())) {
@@ -66,7 +66,7 @@ export const createClientConfig = async (
styles: {
idHint: 'styles',
// necessary to ensure async chunks are also extracted
- test: (m: CssModule) => /css\/mini-extract/.test(m.type),
+ test: (m: CssModule) => m.type.includes('css/mini-extract'),
chunks: 'all',
enforce: true,
reuseExistingChunk: true,
diff --git a/packages/bundler-webpack/src/build/renderPage.ts b/packages/bundler-webpack/src/build/renderPage.ts
index ac7deb7378..009841dffb 100644
--- a/packages/bundler-webpack/src/build/renderPage.ts
+++ b/packages/bundler-webpack/src/build/renderPage.ts
@@ -1,8 +1,8 @@
import type { App, Page } from '@vuepress/core'
import type { VuepressSSRContext } from '@vuepress/shared'
import { fs, renderHead } from '@vuepress/utils'
-import { ssrContextKey } from 'vue'
import type { App as VueApp } from 'vue'
+import { ssrContextKey } from 'vue'
import type { SSRContext } from 'vue/server-renderer'
import type { Router } from 'vue-router'
import { renderPagePrefetchLinks } from './renderPagePrefetchLinks.js'
diff --git a/packages/bundler-webpack/src/build/renderPagePrefetchLinks.ts b/packages/bundler-webpack/src/build/renderPagePrefetchLinks.ts
index aeb60089cf..875013c598 100644
--- a/packages/bundler-webpack/src/build/renderPagePrefetchLinks.ts
+++ b/packages/bundler-webpack/src/build/renderPagePrefetchLinks.ts
@@ -14,7 +14,7 @@ export const renderPagePrefetchLinks = ({
pageClientFilesMeta: FileMeta[]
}): string => {
// shouldPrefetch option
- const shouldPrefetch = app.options.shouldPrefetch
+ const { shouldPrefetch } = app.options
// do not render prefetch links
if (shouldPrefetch === false) {
diff --git a/packages/bundler-webpack/src/build/renderPagePreloadLinks.ts b/packages/bundler-webpack/src/build/renderPagePreloadLinks.ts
index 3321fbabd1..5dbec08f0c 100644
--- a/packages/bundler-webpack/src/build/renderPagePreloadLinks.ts
+++ b/packages/bundler-webpack/src/build/renderPagePreloadLinks.ts
@@ -14,7 +14,7 @@ export const renderPagePreloadLinks = ({
pageClientFilesMeta: FileMeta[]
}): string => {
// shouldPreload option
- const shouldPreload = app.options.shouldPreload
+ const { shouldPreload } = app.options
// do not render preload links
if (shouldPreload === false) {
diff --git a/packages/bundler-webpack/src/build/resolveClientManifestMeta.ts b/packages/bundler-webpack/src/build/resolveClientManifestMeta.ts
index 38f4dfe625..837c4b1efb 100644
--- a/packages/bundler-webpack/src/build/resolveClientManifestMeta.ts
+++ b/packages/bundler-webpack/src/build/resolveClientManifestMeta.ts
@@ -27,17 +27,15 @@ export const resolveClientManifestMeta = ({
// module to files meta map
const moduleFilesMetaMap = Object.fromEntries(
- Object.entries(modules).map(([moduleRequest, assetFilesIndex]) => {
- return [
- moduleRequest,
- assetFilesIndex
- .map((fileIndex) => allFilesMeta[fileIndex])
- .filter(
- ({ file, type }) =>
- async.includes(file) || (type !== 'style' && type !== 'script'),
- ),
- ]
- }),
+ Object.entries(modules).map(([moduleRequest, assetFilesIndex]) => [
+ moduleRequest,
+ assetFilesIndex
+ .map((fileIndex) => allFilesMeta[fileIndex])
+ .filter(
+ ({ file, type }) =>
+ async.includes(file) || (type !== 'style' && type !== 'script'),
+ ),
+ ]),
)
return {
diff --git a/packages/bundler-webpack/src/build/resolvePageClientFilesMeta.ts b/packages/bundler-webpack/src/build/resolvePageClientFilesMeta.ts
index 05d19a47de..17a3c57963 100644
--- a/packages/bundler-webpack/src/build/resolvePageClientFilesMeta.ts
+++ b/packages/bundler-webpack/src/build/resolvePageClientFilesMeta.ts
@@ -12,6 +12,7 @@ export const resolvePageClientFilesMeta = ({
}): FileMeta[] => {
const files = new Set()
moduleRequests.forEach((request) => {
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- unsafe indexed access
moduleFilesMetaMap[request]?.forEach((file) => files.add(file))
})
return Array.from(files)
diff --git a/packages/bundler-webpack/src/build/ssr/createClientPlugin.ts b/packages/bundler-webpack/src/build/ssr/createClientPlugin.ts
index 25a778f6ae..39d50f7164 100644
--- a/packages/bundler-webpack/src/build/ssr/createClientPlugin.ts
+++ b/packages/bundler-webpack/src/build/ssr/createClientPlugin.ts
@@ -50,7 +50,7 @@ export const createClientPlugin = (
// get asset modules
const assetModules = modules.filter(
- (m): m is StatsModule & Required> =>
+ (m): m is Required> & StatsModule =>
Boolean(m.assets?.length),
)
@@ -81,10 +81,10 @@ export const createClientPlugin = (
const files = [...chunk.files.map(fileToIndex)]
// find all asset modules associated with the same chunk
- assetModules.forEach((m) => {
- if (m.chunks?.some((id) => id === cid)) {
+ assetModules.forEach((item) => {
+ if (item.chunks?.some((id) => id === cid)) {
// get asset files
- files.push(...m.assets.map(fileToIndex))
+ files.push(...item.assets.map(fileToIndex))
}
})
diff --git a/packages/bundler-webpack/src/build/types.ts b/packages/bundler-webpack/src/build/types.ts
index 5cf926c25c..112392f4cf 100644
--- a/packages/bundler-webpack/src/build/types.ts
+++ b/packages/bundler-webpack/src/build/types.ts
@@ -21,7 +21,7 @@ export interface FileMeta {
/**
* Client file meta type, mainly used for
*/
-export type FileMetaType = 'script' | 'style' | 'image' | 'font' | ''
+export type FileMetaType = '' | 'font' | 'image' | 'script' | 'style'
/**
* A "module request" to "client files meta" key-value map
diff --git a/packages/bundler-webpack/src/config/createBaseConfig.ts b/packages/bundler-webpack/src/config/createBaseConfig.ts
index b6d8bec3b0..0b6e0accc3 100644
--- a/packages/bundler-webpack/src/config/createBaseConfig.ts
+++ b/packages/bundler-webpack/src/config/createBaseConfig.ts
@@ -52,7 +52,7 @@ export const createBaseConfig = async ({
/**
* module
*/
- handleModule({ app, options, config, isBuild, isServer })
+ handleModule({ options, config, isBuild, isServer })
/**
* plugins
diff --git a/packages/bundler-webpack/src/config/handleEntry.ts b/packages/bundler-webpack/src/config/handleEntry.ts
index 1c2c592b7d..0600895275 100644
--- a/packages/bundler-webpack/src/config/handleEntry.ts
+++ b/packages/bundler-webpack/src/config/handleEntry.ts
@@ -13,11 +13,13 @@ export const handleEntry = ({
config: Config
}): void => {
// set client app as entry point
- config
- .entry('app')
- .add(
- app.dir.client(
- fs.readJsonSync(app.dir.client('package.json')).exports['./app'],
- ),
- )
+ config.entry('app').add(
+ app.dir.client(
+ (
+ fs.readJsonSync(app.dir.client('package.json')) as {
+ exports: { './app': string }
+ }
+ ).exports['./app'],
+ ),
+ )
}
diff --git a/packages/bundler-webpack/src/config/handleModule.ts b/packages/bundler-webpack/src/config/handleModule.ts
index fe857c7f11..be33ca6a73 100644
--- a/packages/bundler-webpack/src/config/handleModule.ts
+++ b/packages/bundler-webpack/src/config/handleModule.ts
@@ -1,4 +1,3 @@
-import type { App } from '@vuepress/core'
import type Config from 'webpack-5-chain'
import type { WebpackBundlerOptions } from '../types.js'
import { handleModuleAssets } from './handleModuleAssets.js'
@@ -12,13 +11,11 @@ import { handleModuleVue } from './handleModuleVue.js'
* Set webpack module
*/
export const handleModule = ({
- app,
options,
config,
isBuild,
isServer,
}: {
- app: App
options: WebpackBundlerOptions
config: Config
isBuild: boolean
@@ -30,19 +27,19 @@ export const handleModule = ({
)
// vue files
- handleModuleVue({ app, options, config, isServer })
+ handleModuleVue({ options, config, isServer })
// pug files, for templates
handleModulePug({ config })
// images & media & fonts
- handleModuleAssets({ app, config })
+ handleModuleAssets({ config })
// js files
handleModuleJs({ options, config, isBuild, isServer })
// ts files
- handleModuleTs({ app, config })
+ handleModuleTs({ config })
// styles files
handleModuleStyles({ options, config, isBuild, isServer })
diff --git a/packages/bundler-webpack/src/config/handleModuleAssets.ts b/packages/bundler-webpack/src/config/handleModuleAssets.ts
index 0ccd291938..03f66337ae 100644
--- a/packages/bundler-webpack/src/config/handleModuleAssets.ts
+++ b/packages/bundler-webpack/src/config/handleModuleAssets.ts
@@ -1,16 +1,9 @@
-import type { App } from '@vuepress/core'
import type Config from 'webpack-5-chain'
/**
* Set webpack config to handle assets files
*/
-export const handleModuleAssets = ({
- app,
- config,
-}: {
- app: App
- config: Config
-}): void => {
+export const handleModuleAssets = ({ config }: { config: Config }): void => {
// images
config.module
.rule('images')
diff --git a/packages/bundler-webpack/src/config/handleModuleJs.ts b/packages/bundler-webpack/src/config/handleModuleJs.ts
index d0e3efb386..89a51d698d 100644
--- a/packages/bundler-webpack/src/config/handleModuleJs.ts
+++ b/packages/bundler-webpack/src/config/handleModuleJs.ts
@@ -45,7 +45,7 @@ export const handleModuleJs = ({
return false
}
// don't transpile node_modules
- return /node_modules/.test(filePath)
+ return filePath.includes('node_modules')
})
.end()
// use esbuild-loader
diff --git a/packages/bundler-webpack/src/config/handleModuleStyles.ts b/packages/bundler-webpack/src/config/handleModuleStyles.ts
index 45b5bede25..6a99b02206 100644
--- a/packages/bundler-webpack/src/config/handleModuleStyles.ts
+++ b/packages/bundler-webpack/src/config/handleModuleStyles.ts
@@ -3,10 +3,7 @@ import autoprefixer from 'autoprefixer'
import MiniCssExtractPlugin from 'mini-css-extract-plugin'
import type Config from 'webpack-5-chain'
import type {
- LessLoaderOptions,
- SassLoaderOptions,
StylePreprocessorLoaderOptions,
- StylusLoaderOptions,
WebpackBundlerOptions,
} from '../types.js'
@@ -26,9 +23,7 @@ export const handleModuleStyles = ({
isBuild: boolean
isServer: boolean
}): void => {
- const handleStyle = <
- T extends StylePreprocessorLoaderOptions = StylePreprocessorLoaderOptions,
- >({
+ const handleStyle = ({
lang,
test,
loaderName,
@@ -37,7 +32,7 @@ export const handleModuleStyles = ({
lang: string
test: RegExp
loaderName?: string
- loaderOptions?: T
+ loaderOptions?: StylePreprocessorLoaderOptions
}): void => {
const rule = config.module.rule(lang).test(test)
@@ -94,28 +89,28 @@ export const handleModuleStyles = ({
test: /\.p(ost)?css$/,
})
- handleStyle({
+ handleStyle({
lang: 'scss',
test: /\.scss$/,
loaderName: 'sass-loader',
loaderOptions: options.scss,
})
- handleStyle({
+ handleStyle({
lang: 'sass',
test: /\.sass$/,
loaderName: 'sass-loader',
loaderOptions: options.sass,
})
- handleStyle({
+ handleStyle({
lang: 'less',
test: /\.less$/,
loaderName: 'less-loader',
loaderOptions: options.less,
})
- handleStyle({
+ handleStyle({
lang: 'stylus',
test: /\.styl(us)?$/,
loaderName: 'stylus-loader',
diff --git a/packages/bundler-webpack/src/config/handleModuleTs.ts b/packages/bundler-webpack/src/config/handleModuleTs.ts
index 74e045a372..db254558d5 100644
--- a/packages/bundler-webpack/src/config/handleModuleTs.ts
+++ b/packages/bundler-webpack/src/config/handleModuleTs.ts
@@ -1,5 +1,4 @@
import { createRequire } from 'node:module'
-import type { App } from '@vuepress/core'
import type Config from 'webpack-5-chain'
import { resolveEsbuildJsxOptions } from './resolveEsbuildJsxOptions.js'
@@ -8,13 +7,7 @@ const require = createRequire(import.meta.url)
/**
* Set webpack module to handle ts files
*/
-export const handleModuleTs = ({
- app,
- config,
-}: {
- app: App
- config: Config
-}): void => {
+export const handleModuleTs = ({ config }: { config: Config }): void => {
config.module
.rule('ts')
.test(/\.tsx?/)
diff --git a/packages/bundler-webpack/src/config/handleModuleVue.ts b/packages/bundler-webpack/src/config/handleModuleVue.ts
index ecfdbc7069..335159cc1b 100644
--- a/packages/bundler-webpack/src/config/handleModuleVue.ts
+++ b/packages/bundler-webpack/src/config/handleModuleVue.ts
@@ -1,7 +1,6 @@
import { createRequire } from 'node:module'
-import type { App } from '@vuepress/core'
-import { VueLoaderPlugin } from 'vue-loader'
import type { VueLoaderOptions } from 'vue-loader'
+import { VueLoaderPlugin } from 'vue-loader'
import type Config from 'webpack-5-chain'
import type { WebpackBundlerOptions } from '../types.js'
@@ -11,12 +10,10 @@ const require = createRequire(import.meta.url)
* Set webpack module to handle vue files
*/
export const handleModuleVue = ({
- app,
options,
config,
isServer,
}: {
- app: App
options: WebpackBundlerOptions
config: Config
isServer: boolean
diff --git a/packages/bundler-webpack/src/config/handleOtherOptions.ts b/packages/bundler-webpack/src/config/handleOtherOptions.ts
index ef8e1d8816..57c9b67392 100644
--- a/packages/bundler-webpack/src/config/handleOtherOptions.ts
+++ b/packages/bundler-webpack/src/config/handleOtherOptions.ts
@@ -35,9 +35,13 @@ export const handleOtherOptions = ({
isServer,
'version': app.version,
// dependencies
- 'esbuild-loader': require('esbuild-loader/package.json').version,
- 'vue-loader': require('vue-loader/package.json').version,
- 'webpack': require('webpack/package.json').version,
+ 'esbuild-loader': (
+ require('esbuild-loader/package.json') as { version: string }
+ ).version,
+ 'vue-loader': (require('vue-loader/package.json') as { version: string })
+ .version,
+ 'webpack': (require('webpack/package.json') as { version: string })
+ .version,
}),
})
}
diff --git a/packages/bundler-webpack/src/config/handlePluginDefine.ts b/packages/bundler-webpack/src/config/handlePluginDefine.ts
index d118844d48..8fdf06b1ac 100644
--- a/packages/bundler-webpack/src/config/handlePluginDefine.ts
+++ b/packages/bundler-webpack/src/config/handlePluginDefine.ts
@@ -36,12 +36,14 @@ export const handlePluginDefine = async ({
// tap the arguments of DefinePlugin
config.plugin('define').tap(([options]) => {
- defineResult.forEach((defineObject) =>
+ defineResult.forEach((defineObject) => {
Object.entries(defineObject).forEach(([key, value]) => {
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
options[key] = JSON.stringify(value)
- }),
- )
+ })
+ })
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
return [options]
})
}
diff --git a/packages/bundler-webpack/src/config/handleResolve.ts b/packages/bundler-webpack/src/config/handleResolve.ts
index 6081614be2..b20704b52a 100644
--- a/packages/bundler-webpack/src/config/handleResolve.ts
+++ b/packages/bundler-webpack/src/config/handleResolve.ts
@@ -44,9 +44,9 @@ export const handleResolve = async ({
const aliasResult = await app.pluginApi.hooks.alias.process(app, isServer)
// set aliases
- aliasResult.forEach((aliasObject) =>
+ aliasResult.forEach((aliasObject) => {
Object.entries(aliasObject).forEach(([key, value]) => {
- config.resolve.alias.set(key, value)
- }),
- )
+ config.resolve.alias.set(key, value as string)
+ })
+ })
}
diff --git a/packages/bundler-webpack/src/dev/createDevServerConfig.ts b/packages/bundler-webpack/src/dev/createDevServerConfig.ts
index de6ce8c7c1..742e7ae82c 100644
--- a/packages/bundler-webpack/src/dev/createDevServerConfig.ts
+++ b/packages/bundler-webpack/src/dev/createDevServerConfig.ts
@@ -5,10 +5,10 @@ import type WebpackDevServer from 'webpack-dev-server'
import type { WebpackBundlerOptions } from '../types.js'
import { trailingSlashMiddleware } from './trailingSlashMiddleware.js'
-export const createDevServerConfig = async (
+export const createDevServerConfig = (
app: App,
options: WebpackBundlerOptions,
-): Promise => ({
+): WebpackDevServer.Configuration => ({
allowedHosts: 'all',
compress: true,
devMiddleware: {
diff --git a/packages/bundler-webpack/src/dev/dev.ts b/packages/bundler-webpack/src/dev/dev.ts
index 96b5f5428e..c96a31c530 100644
--- a/packages/bundler-webpack/src/dev/dev.ts
+++ b/packages/bundler-webpack/src/dev/dev.ts
@@ -29,7 +29,7 @@ export const dev = async (
const compiler = webpack(webpackConfig)
// create webpack-dev-server
- const serverConfig = await createDevServerConfig(app, options)
+ const serverConfig = createDevServerConfig(app, options)
const server = new WebpackDevServer(serverConfig, compiler)
const [, close] = await Promise.all([
@@ -56,7 +56,7 @@ export const dev = async (
if (hasFinished) return
hasFinished = true
- spinner.succeed(`Compilation finished in ${endTime! - startTime!}ms`)
+ spinner.succeed(`Compilation finished in ${endTime - startTime}ms`)
// replace `0.0.0.0` with `localhost` as `0.0.0.0` is not available on windows
const url = `http://${
@@ -67,7 +67,7 @@ export const dev = async (
)
// resolve the close function
- resolve((): Promise => server.stop())
+ resolve(async (): Promise => server.stop())
})
// stop spinner and reject error if the first compilation is failed
diff --git a/packages/bundler-webpack/src/dev/trailingSlashMiddleware.ts b/packages/bundler-webpack/src/dev/trailingSlashMiddleware.ts
index 17133dd16a..34d34e0717 100644
--- a/packages/bundler-webpack/src/dev/trailingSlashMiddleware.ts
+++ b/packages/bundler-webpack/src/dev/trailingSlashMiddleware.ts
@@ -15,7 +15,8 @@ export const trailingSlashMiddleware: RequestHandler = (req, res, next) => {
// if the path already has trailing slash
req.path.endsWith('/')
) {
- return next()
+ next()
+ return
}
// add trailing slash and retain query
diff --git a/packages/bundler-webpack/src/types.ts b/packages/bundler-webpack/src/types.ts
index 9ce835dba1..162d8aa238 100644
--- a/packages/bundler-webpack/src/types.ts
+++ b/packages/bundler-webpack/src/types.ts
@@ -1,3 +1,4 @@
+import type { BundlerOptions } from '@vuepress/core'
import type { VueLoaderOptions } from 'vue-loader'
import type {
LoaderContext,
@@ -16,7 +17,7 @@ export type {
/**
* Options for bundler-webpack
*/
-export interface WebpackBundlerOptions {
+export interface WebpackBundlerOptions extends BundlerOptions {
/**
* use webpack-merge to set webpack config
*/
@@ -84,7 +85,7 @@ export interface StylePreprocessorLoaderOptions {
| string
| ((
content: string,
- loaderContext: LoaderContext>,
+ loaderContext: LoaderContext>,
) => string)
sourceMap?: boolean
webpackImporter?: boolean
@@ -94,7 +95,7 @@ export interface StylePreprocessorLoaderOptions {
* Common type for style pre-processor options
*/
export type StylePreprocessorOptions<
- T extends Record = Record,
+ T extends Record = Record,
> = T | ((loaderContext: LoaderContext) => TextDecodeOptions)
/**
@@ -105,7 +106,7 @@ export type StylePreprocessorOptions<
export interface PostcssLoaderOptions
extends Pick {
execute?: boolean
- implementation?: ((...args: any) => any) | string
+ implementation?: string | ((...args: unknown[]) => unknown)
postcssOptions?: StylePreprocessorOptions
}
@@ -115,7 +116,7 @@ export interface PostcssLoaderOptions
* @see https://github.com/webpack-contrib/stylus-loader#options
*/
export interface StylusLoaderOptions extends StylePreprocessorLoaderOptions {
- implementation?: ((...args: any) => any) | string
+ implementation?: string | ((...args: unknown[]) => unknown)
stylusOptions?: StylePreprocessorOptions
}
@@ -125,8 +126,8 @@ export interface StylusLoaderOptions extends StylePreprocessorLoaderOptions {
* @see https://github.com/webpack-contrib/sass-loader#options
*/
export interface SassLoaderOptions extends StylePreprocessorLoaderOptions {
- api?: 'legacy' | 'modern' | 'modern-compiler'
- implementation?: Record | string
+ api?: 'legacy' | 'modern-compiler' | 'modern'
+ implementation?: Record | string
sassOptions?: StylePreprocessorOptions
warnRuleAsWarning?: boolean
}
@@ -137,7 +138,7 @@ export interface SassLoaderOptions extends StylePreprocessorLoaderOptions {
* @see https://github.com/webpack-contrib/less-loader#options
*/
export interface LessLoaderOptions extends StylePreprocessorLoaderOptions {
- implementation?: Record | string
+ implementation?: Record | string
lessLogAsWarnOrErr?: boolean
lessOptions?: StylePreprocessorOptions
}
diff --git a/packages/bundler-webpack/src/webpackBundler.ts b/packages/bundler-webpack/src/webpackBundler.ts
index 6a219eea14..1cfb1f9ba2 100644
--- a/packages/bundler-webpack/src/webpackBundler.ts
+++ b/packages/bundler-webpack/src/webpackBundler.ts
@@ -7,6 +7,6 @@ export const webpackBundler = (
options: WebpackBundlerOptions = {},
): Bundler => ({
name: '@vuepress/bundler-webpack',
- dev: (app) => dev(options, app),
- build: (app) => build(options, app),
+ dev: async (app) => dev(options, app),
+ build: async (app) => build(options, app),
})
diff --git a/packages/cli/src/cli.ts b/packages/cli/src/cli.ts
index 4561cd04e2..1ec277bd8f 100644
--- a/packages/cli/src/cli.ts
+++ b/packages/cli/src/cli.ts
@@ -1,7 +1,7 @@
import { createRequire } from 'node:module'
import process from 'node:process'
import type { AppConfig } from '@vuepress/core'
-import { colors } from '@vuepress/utils'
+import { colors, logger } from '@vuepress/utils'
import { cac } from 'cac'
import { createBuild, createDev, info } from './commands/index.js'
@@ -15,8 +15,10 @@ export const cli = (defaultAppConfig: Partial = {}): void => {
const program = cac('vuepress')
// display core version and cli version
- const versionCli = require('../package.json').version
- const versionCore = require('@vuepress/core/package.json').version
+ const versionCli = (require('../package.json') as { version: string }).version
+ const versionCore = (
+ require('@vuepress/core/package.json') as { version: string }
+ ).version
program.version(`core@${versionCore} vuepress/cli@${versionCli}`)
// display help message
@@ -59,8 +61,8 @@ export const cli = (defaultAppConfig: Partial = {}): void => {
// run command or fallback to help messages
if (program.matchedCommand) {
- program.runMatchedCommand().catch((err) => {
- console.error(colors.red(err.stack))
+ ;(program.runMatchedCommand() as Promise).catch((err: unknown) => {
+ logger.error(err instanceof Error ? colors.red(err.stack) : err)
process.exit(1)
})
} else {
diff --git a/packages/cli/src/commands/build/createBuild.ts b/packages/cli/src/commands/build/createBuild.ts
index 5828bdc5c8..ad001bd536 100644
--- a/packages/cli/src/commands/build/createBuild.ts
+++ b/packages/cli/src/commands/build/createBuild.ts
@@ -1,6 +1,6 @@
import process from 'node:process'
-import { createBuildApp } from '@vuepress/core'
import type { AppConfig } from '@vuepress/core'
+import { createBuildApp } from '@vuepress/core'
import { debug, formatMs, fs, logger, withSpinner } from '@vuepress/utils'
import {
loadUserConfig,
@@ -53,13 +53,13 @@ export const createBuild =
// clean temp and cache
if (commandOptions.cleanTemp === true) {
- await withSpinner('Cleaning temp')(() => {
- return fs.remove(app.dir.temp())
+ await withSpinner('Cleaning temp')(async () => {
+ await fs.remove(app.dir.temp())
})
}
if (commandOptions.cleanCache === true) {
- await withSpinner('Cleaning cache')(() => {
- return fs.remove(app.dir.cache())
+ await withSpinner('Cleaning cache')(async () => {
+ await fs.remove(app.dir.cache())
})
}
diff --git a/packages/cli/src/commands/dev/createDev.ts b/packages/cli/src/commands/dev/createDev.ts
index d34a7b7f82..b340e00a82 100644
--- a/packages/cli/src/commands/dev/createDev.ts
+++ b/packages/cli/src/commands/dev/createDev.ts
@@ -1,6 +1,6 @@
import process from 'node:process'
-import { createDevApp } from '@vuepress/core'
import type { AppConfig } from '@vuepress/core'
+import { createDevApp } from '@vuepress/core'
import { debug, fs, logger, withSpinner } from '@vuepress/utils'
import type { FSWatcher } from 'chokidar'
import {
@@ -57,14 +57,12 @@ export const createDev = (defaultAppConfig: Partial): DevCommand => {
// clean temp and cache
if (commandOptions.cleanTemp === true) {
- await withSpinner('Cleaning temp')(() => {
- return fs.remove(app.dir.temp())
- })
+ await withSpinner('Cleaning temp')(async () => fs.remove(app.dir.temp()))
}
if (commandOptions.cleanCache === true) {
- await withSpinner('Cleaning cache')(() => {
- return fs.remove(app.dir.cache())
- })
+ await withSpinner('Cleaning cache')(async () =>
+ fs.remove(app.dir.cache()),
+ )
}
// initialize and prepare
@@ -88,7 +86,7 @@ export const createDev = (defaultAppConfig: Partial): DevCommand => {
const restart = async (): Promise => {
await Promise.all([
// close all watchers
- ...watchers.map((item) => item.close()),
+ ...watchers.map(async (item) => item.close()),
// close current dev server
close(),
])
diff --git a/packages/cli/src/commands/dev/handlePageAdd.ts b/packages/cli/src/commands/dev/handlePageAdd.ts
index 8f4b367975..bcf5415a97 100644
--- a/packages/cli/src/commands/dev/handlePageAdd.ts
+++ b/packages/cli/src/commands/dev/handlePageAdd.ts
@@ -1,10 +1,10 @@
+import type { App, Page } from '@vuepress/core'
import {
createPage,
preparePageChunk,
preparePageComponent,
prepareRoutes,
} from '@vuepress/core'
-import type { App, Page } from '@vuepress/core'
/**
* Event handler for page add event
diff --git a/packages/cli/src/commands/dev/handlePageChange.ts b/packages/cli/src/commands/dev/handlePageChange.ts
index 6eeff179aa..c2255096f0 100644
--- a/packages/cli/src/commands/dev/handlePageChange.ts
+++ b/packages/cli/src/commands/dev/handlePageChange.ts
@@ -1,10 +1,10 @@
+import type { App, Page } from '@vuepress/core'
import {
createPage,
preparePageChunk,
preparePageComponent,
prepareRoutes,
} from '@vuepress/core'
-import type { App, Page } from '@vuepress/core'
/**
* Event handler for page change event
diff --git a/packages/cli/src/commands/dev/handlePageUnlink.ts b/packages/cli/src/commands/dev/handlePageUnlink.ts
index 1260480292..ad4d01a2c4 100644
--- a/packages/cli/src/commands/dev/handlePageUnlink.ts
+++ b/packages/cli/src/commands/dev/handlePageUnlink.ts
@@ -1,5 +1,5 @@
-import { prepareRoutes } from '@vuepress/core'
import type { App, Page } from '@vuepress/core'
+import { prepareRoutes } from '@vuepress/core'
/**
* Event handler for page unlink event
diff --git a/packages/cli/src/commands/dev/watchPageFiles.ts b/packages/cli/src/commands/dev/watchPageFiles.ts
index 48dcee2060..d9b884a2ee 100644
--- a/packages/cli/src/commands/dev/watchPageFiles.ts
+++ b/packages/cli/src/commands/dev/watchPageFiles.ts
@@ -1,7 +1,8 @@
+/* eslint-disable @typescript-eslint/no-misused-promises */
import type { App, Page } from '@vuepress/core'
import { colors, logger } from '@vuepress/utils'
-import chokidar from 'chokidar'
import type { FSWatcher } from 'chokidar'
+import chokidar from 'chokidar'
import { handlePageAdd } from './handlePageAdd.js'
import { handlePageChange } from './handlePageChange.js'
import { handlePageUnlink } from './handlePageUnlink.js'
@@ -27,7 +28,6 @@ export const watchPageFiles = (app: App): FSWatcher[] => {
}
const depsListener = async (dep: string): Promise => {
const pagePaths = depsHelper.get(dep)
- if (!pagePaths) return
for (const filePathRelative of pagePaths) {
logger.info(
`dependency of page ${colors.magenta(filePathRelative)} is modified`,
@@ -38,7 +38,9 @@ export const watchPageFiles = (app: App): FSWatcher[] => {
depsWatcher.on('add', depsListener)
depsWatcher.on('change', depsListener)
depsWatcher.on('unlink', depsListener)
- app.pages.forEach((page) => addDeps(page))
+ app.pages.forEach((page) => {
+ addDeps(page)
+ })
// watch page files
const pagesWatcher = chokidar.watch(app.options.pagePatterns, {
diff --git a/packages/cli/src/commands/dev/watchUserConfigFile.ts b/packages/cli/src/commands/dev/watchUserConfigFile.ts
index 6b89ac9e89..fa11200698 100644
--- a/packages/cli/src/commands/dev/watchUserConfigFile.ts
+++ b/packages/cli/src/commands/dev/watchUserConfigFile.ts
@@ -1,7 +1,7 @@
import process from 'node:process'
import { colors, logger } from '@vuepress/utils'
-import chokidar from 'chokidar'
import type { FSWatcher } from 'chokidar'
+import chokidar from 'chokidar'
export const watchUserConfigFile = ({
userConfigPath,
@@ -20,7 +20,7 @@ export const watchUserConfigFile = ({
})
configWatcher.on('change', (configFile) => {
logger.info(`config ${colors.magenta(configFile)} is modified`)
- restart()
+ void restart()
})
const depsWatcher = chokidar.watch(userConfigDependencies, {
@@ -29,7 +29,7 @@ export const watchUserConfigFile = ({
})
depsWatcher.on('change', (depFile) => {
logger.info(`config dependency ${colors.magenta(depFile)} is modified`)
- restart()
+ void restart()
})
return [configWatcher, depsWatcher]
diff --git a/packages/cli/src/commands/info.ts b/packages/cli/src/commands/info.ts
index 3b09851a3b..ee2906e4b3 100644
--- a/packages/cli/src/commands/info.ts
+++ b/packages/cli/src/commands/info.ts
@@ -1,4 +1,4 @@
-import { ora } from '@vuepress/utils'
+import { logger, ora } from '@vuepress/utils'
import envinfo from 'envinfo'
export const info = async (): Promise => {
@@ -33,5 +33,5 @@ export const info = async (): Promise => {
)
spinner.stop()
- console.info(result)
+ logger.info(result)
}
diff --git a/packages/cli/src/config/loadUserConfig.ts b/packages/cli/src/config/loadUserConfig.ts
index ff796865fa..5f42bbf1a5 100644
--- a/packages/cli/src/config/loadUserConfig.ts
+++ b/packages/cli/src/config/loadUserConfig.ts
@@ -42,10 +42,10 @@ export const loadUserConfig = async (
plugins: [
{
name: 'externalize-deps',
- setup(build) {
- build.onResolve({ filter: /.*/ }, ({ path: id }) => {
+ setup(pluginBuild) {
+ pluginBuild.onResolve({ filter: /.*/ }, ({ path: id }) => {
// externalize bare imports
- if (id[0] !== '.' && !path.isAbsolute(id)) {
+ if (!id.startsWith('.') && !path.isAbsolute(id)) {
return {
external: true,
}
@@ -56,8 +56,8 @@ export const loadUserConfig = async (
},
{
name: 'inject-file-scope-variables',
- setup(build) {
- build.onLoad({ filter: /\.[cm]?[jt]s$/ }, async (args) => {
+ setup(pluginBuild) {
+ pluginBuild.onLoad({ filter: /\.[cm]?[jt]s$/ }, async (args) => {
const contents = await fs.readFile(args.path, 'utf8')
const injectValues =
`const ${dirnameVarName} = ${JSON.stringify(
@@ -92,6 +92,6 @@ export const loadUserConfig = async (
}
return {
userConfig,
- userConfigDependencies: Object.keys(result.metafile?.inputs ?? {}),
+ userConfigDependencies: Object.keys(result.metafile.inputs),
}
}
diff --git a/packages/cli/src/config/resolveAppConfig.ts b/packages/cli/src/config/resolveAppConfig.ts
index ba52cde94e..0c8263cbdb 100644
--- a/packages/cli/src/config/resolveAppConfig.ts
+++ b/packages/cli/src/config/resolveAppConfig.ts
@@ -25,7 +25,12 @@ export const resolveAppConfig = ({
...userConfig,
// allow cli options to override config file
...cliAppConfig,
- } as AppConfig
+ }
+
+ if (appConfig.source === undefined) {
+ logger.error(`The ${colors.magenta('source')} option is missing.`)
+ return null
+ }
if (appConfig.bundler === undefined || appConfig.theme === undefined) {
logger.error(
@@ -57,5 +62,5 @@ export const resolveAppConfig = ({
delete appConfig.dest
}
- return appConfig
+ return appConfig as AppConfig
}
diff --git a/packages/cli/src/config/types.ts b/packages/cli/src/config/types.ts
index 570c825dcc..ec2da48e4a 100644
--- a/packages/cli/src/config/types.ts
+++ b/packages/cli/src/config/types.ts
@@ -5,6 +5,5 @@ import type { AppConfig, PluginObject } from '@vuepress/core'
*
* It will be transformed to `AppConfig` by cli
*/
-export type UserConfig = Partial &
- // user config can be used as a plugin
- Omit
+export type UserConfig = Omit &
+ Partial
diff --git a/packages/cli/tests/config/loadUserConfig.spec.ts b/packages/cli/tests/config/loadUserConfig.spec.ts
index 74ccbd1c3b..3327d9bd05 100644
--- a/packages/cli/tests/config/loadUserConfig.spec.ts
+++ b/packages/cli/tests/config/loadUserConfig.spec.ts
@@ -2,7 +2,7 @@ import { path } from '@vuepress/utils'
import { describe, expect, it } from 'vitest'
import { loadUserConfig } from '../../src/index.js'
-const tsCases: [string, any][] = [
+const TS_CASES: [string, unknown][] = [
[
path.resolve(__dirname, '../__fixtures__/config/ts/.vuepress/config.ts'),
{
@@ -17,7 +17,7 @@ const tsCases: [string, any][] = [
],
]
-const jsCases: [string, any][] = [
+const JS_CASES: [string, unknown][] = [
[
path.resolve(__dirname, '../__fixtures__/config/js/.vuepress/config.js'),
{
@@ -32,7 +32,7 @@ const jsCases: [string, any][] = [
],
]
-const mjsCases: [string, any][] = [
+const MJS_CASES: [string, unknown][] = [
[
path.resolve(__dirname, '../__fixtures__/config/mjs/.vuepress/config.mjs'),
{
@@ -49,7 +49,7 @@ const mjsCases: [string, any][] = [
describe('cli > config > loadUserConfig', () => {
describe('should load ts config file correctly', () => {
- tsCases.forEach(([source, expected]) => {
+ TS_CASES.forEach(([source, expected]) => {
it(JSON.stringify(source), async () => {
const { userConfig } = await loadUserConfig(source)
expect(userConfig).toEqual(expected)
@@ -58,7 +58,7 @@ describe('cli > config > loadUserConfig', () => {
})
describe('should load js config file correctly', () => {
- jsCases.forEach(([source, expected]) => {
+ JS_CASES.forEach(([source, expected]) => {
it(JSON.stringify(source), async () => {
const { userConfig } = await loadUserConfig(source)
expect(userConfig).toEqual(expected)
@@ -67,7 +67,7 @@ describe('cli > config > loadUserConfig', () => {
})
describe('should load mjs config file correctly', () => {
- mjsCases.forEach(([source, expected]) => {
+ MJS_CASES.forEach(([source, expected]) => {
it(JSON.stringify(source), async () => {
const { userConfig } = await loadUserConfig(source)
expect(userConfig).toEqual(expected)
diff --git a/packages/cli/tests/config/resolveUserConfigConventionalPath.spec.ts b/packages/cli/tests/config/resolveUserConfigConventionalPath.spec.ts
index f74b1f1d20..808ac4ec19 100644
--- a/packages/cli/tests/config/resolveUserConfigConventionalPath.spec.ts
+++ b/packages/cli/tests/config/resolveUserConfigConventionalPath.spec.ts
@@ -5,7 +5,7 @@ import { resolveUserConfigConventionalPath } from '../../src/index.js'
const resolveFixtures = (str: string): string =>
path.resolve(__dirname, '../__fixtures__/config/convention', str)
-const testCases: [string, string][] = [
+const TEST_CASES: [string, string][] = [
[resolveFixtures('case1'), 'vuepress.config.ts'],
[resolveFixtures('case2'), '.vuepress/config.ts'],
[resolveFixtures('case3'), 'vuepress.config.js'],
@@ -16,7 +16,7 @@ const testCases: [string, string][] = [
describe('cli > config > resolveUserConfigConventionalPath', () => {
describe('should resolve conventional config file correctly', () => {
- testCases.forEach(([source, expected]) => {
+ TEST_CASES.forEach(([source, expected]) => {
it(expected, () => {
const configFile = resolveUserConfigConventionalPath(source, source)
expect(configFile).toEqual(path.resolve(source, expected))
diff --git a/packages/client/src/app.ts b/packages/client/src/app.ts
index 4c85269963..dfab9f56d2 100644
--- a/packages/client/src/app.ts
+++ b/packages/client/src/app.ts
@@ -29,15 +29,16 @@ export const createVueApp: CreateVueAppFunction = async () => {
}
// get all root components
- const rootComponents = clientConfigs.flatMap(({ rootComponents = [] }) =>
- rootComponents.map((component) => h(component)),
+ const clientRootComponents = clientConfigs.flatMap(
+ ({ rootComponents = [] }) =>
+ rootComponents.map((component) => h(component)),
)
// get page layout
const pageLayout = usePageLayout()
// render layout and root components
- return () => [h(pageLayout.value), rootComponents]
+ return () => [h(pageLayout.value), clientRootComponents]
},
})
@@ -74,8 +75,8 @@ export const createVueApp: CreateVueAppFunction = async () => {
// mount app in client bundle
if (!__VUEPRESS_SSR__) {
- createVueApp().then(({ app, router }) => {
- router.isReady().then(() => {
+ void createVueApp().then(({ app, router }) => {
+ void router.isReady().then(() => {
app.mount('#app')
})
})
diff --git a/packages/client/src/components/AutoLink.ts b/packages/client/src/components/AutoLink.ts
index f570dcd49d..948a39e066 100644
--- a/packages/client/src/components/AutoLink.ts
+++ b/packages/client/src/components/AutoLink.ts
@@ -9,7 +9,7 @@ export interface AutoLinkConfig {
/**
* Pattern to determine if the link should be active, which has higher priority than `exact`
*/
- activeMatch?: string | RegExp
+ activeMatch?: RegExp | string
/**
* The `aria-label` attribute
@@ -59,9 +59,9 @@ export const AutoLink = defineComponent({
},
slots: Object as SlotsType<{
- default?: (config: AutoLinkConfig) => VNode[] | VNode
- before?: (config: AutoLinkConfig) => VNode[] | VNode | null
- after?: (config: AutoLinkConfig) => VNode[] | VNode | null
+ default?: (config: AutoLinkConfig) => VNode | VNode[]
+ before?: (config: AutoLinkConfig) => VNode | VNode[] | null
+ after?: (config: AutoLinkConfig) => VNode | VNode[] | null
}>,
setup(props, { slots }) {
@@ -134,7 +134,7 @@ export const AutoLink = defineComponent({
return () => {
const { before, after, default: defaultSlot } = slots
- const content = defaultSlot?.(config.value) || [
+ const content = defaultSlot?.(config.value) ?? [
before?.(config.value),
config.value.text,
after?.(config.value),
diff --git a/packages/client/src/components/Content.ts b/packages/client/src/components/Content.ts
index 41204daeb6..e58b46214d 100644
--- a/packages/client/src/components/Content.ts
+++ b/packages/client/src/components/Content.ts
@@ -6,7 +6,6 @@ import { resolveRoute } from '../router/index.js'
* Markdown rendered content
*/
export const Content = defineComponent({
- // eslint-disable-next-line vue/no-reserved-component-names
name: 'Content',
props: {
@@ -22,7 +21,9 @@ export const Content = defineComponent({
const ContentComponent = computed(() => {
if (!props.path) return pageComponent.value
const route = resolveRoute(props.path)
- return defineAsyncComponent(() => route.loader().then(({ comp }) => comp))
+ return defineAsyncComponent(async () =>
+ route.loader().then(({ comp }) => comp),
+ )
})
return () => h(ContentComponent.value)
diff --git a/packages/client/src/components/RouteLink.ts b/packages/client/src/components/RouteLink.ts
index 1b1e62b157..ffff10e430 100644
--- a/packages/client/src/components/RouteLink.ts
+++ b/packages/client/src/components/RouteLink.ts
@@ -1,5 +1,5 @@
-import { computed, defineComponent, h } from 'vue'
import type { SlotsType, VNode } from 'vue'
+import { computed, defineComponent, h } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { resolveRouteFullPath } from '../router/index.js'
@@ -12,6 +12,7 @@ const guardEvent = (event: MouseEvent): boolean | void => {
// don't redirect when preventDefault called
if (event.defaultPrevented) return
// don't redirect on right click
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (event.button !== undefined && event.button !== 0) return
// don't redirect if `target="_blank"`
if (event.currentTarget) {
@@ -81,7 +82,7 @@ export const RouteLink = defineComponent({
},
slots: Object as SlotsType<{
- default: () => string | VNode | (string | VNode)[]
+ default: () => (VNode | string)[] | VNode | string
}>,
setup(props, { slots }) {
@@ -102,11 +103,11 @@ export const RouteLink = defineComponent({
href: path.value,
onClick: (event: MouseEvent = {} as MouseEvent) => {
if (guardEvent(event)) {
- router.push(props.to).catch()
+ void router.push(props.to).catch()
}
},
},
- slots.default?.(),
+ slots.default(),
)
},
})
diff --git a/packages/client/src/composables/clientDataUtils.ts b/packages/client/src/composables/clientDataUtils.ts
index c9338284f8..3dc3109670 100644
--- a/packages/client/src/composables/clientDataUtils.ts
+++ b/packages/client/src/composables/clientDataUtils.ts
@@ -21,11 +21,11 @@ export const usePageComponent = (): PageComponentRef =>
useClientData().pageComponent
export const usePageData = <
- T extends Record = Record,
+ T extends Record = Record,
>(): PageDataRef => useClientData().pageData as PageDataRef
export const usePageFrontmatter = <
- T extends Record = Record,
+ T extends Record = Record,
>(): PageFrontmatterRef =>
useClientData().pageFrontmatter as PageFrontmatterRef
diff --git a/packages/client/src/composables/updateHead.ts b/packages/client/src/composables/updateHead.ts
index 630c378b4a..6fa83074ec 100644
--- a/packages/client/src/composables/updateHead.ts
+++ b/packages/client/src/composables/updateHead.ts
@@ -1,5 +1,5 @@
-import { inject } from 'vue'
import type { InjectionKey } from 'vue'
+import { inject } from 'vue'
/**
* A util function to force update `` of current page
diff --git a/packages/client/src/internal/routes.ts b/packages/client/src/internal/routes.ts
index 796e34bebf..3d395e53f9 100644
--- a/packages/client/src/internal/routes.ts
+++ b/packages/client/src/internal/routes.ts
@@ -2,8 +2,8 @@ import {
redirects as redirectsRaw,
routes as routesRaw,
} from '@internal/routes'
-import { shallowRef } from 'vue'
import type { Ref } from 'vue'
+import { shallowRef } from 'vue'
import type { Redirects, Routes } from '../types/index.js'
/**
diff --git a/packages/client/src/resolvers.ts b/packages/client/src/resolvers.ts
index 7b1fc0f18f..46e85c8da3 100644
--- a/packages/client/src/resolvers.ts
+++ b/packages/client/src/resolvers.ts
@@ -85,6 +85,7 @@ export const resolvers = reactive({
const layoutName = isString(pageData.frontmatter.layout)
? pageData.frontmatter.layout
: LAYOUT_NAME_DEFAULT
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- unsafe indexed access
if (!layouts[layoutName]) {
throw new Error(`[vuepress] Cannot resolve layout: ${layoutName}`)
}
@@ -113,8 +114,9 @@ export const resolvers = reactive({
head: [
// when merging head, the locales head should be placed before root head
// to get higher priority
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- unsafe indexed access
...(locales[routeLocale]?.head ?? []),
- ...(siteData.head ?? []),
+ ...siteData.head,
],
}),
})
diff --git a/packages/client/src/router/createVueRouter.ts b/packages/client/src/router/createVueRouter.ts
index a9dd605096..0c8221b570 100644
--- a/packages/client/src/router/createVueRouter.ts
+++ b/packages/client/src/router/createVueRouter.ts
@@ -1,10 +1,10 @@
import { removeEndingSlash } from '@vuepress/shared'
import type { Router } from 'vue-router'
import {
+ START_LOCATION,
createMemoryHistory,
createRouter,
createWebHistory,
- START_LOCATION,
} from 'vue-router'
import type { PageChunk } from '../types/index.js'
import { resolveRoute } from './resolveRoute.js'
diff --git a/packages/client/src/router/resolveRoute.ts b/packages/client/src/router/resolveRoute.ts
index c8a7f4b8a8..8f848a56a3 100644
--- a/packages/client/src/router/resolveRoute.ts
+++ b/packages/client/src/router/resolveRoute.ts
@@ -24,6 +24,7 @@ export const resolveRoute = (
const routeFullPath = routePath + hashAndQueries
// the route not found
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- unsafe indexed access
if (!routes.value[routePath]) {
return {
...routes.value['/404.html'],
diff --git a/packages/client/src/router/resolveRoutePath.ts b/packages/client/src/router/resolveRoutePath.ts
index 4f815e4c17..74a2620955 100644
--- a/packages/client/src/router/resolveRoutePath.ts
+++ b/packages/client/src/router/resolveRoutePath.ts
@@ -12,11 +12,13 @@ export const resolveRoutePath = (
const normalizedRoutePath = normalizeRoutePath(pathname, currentPath)
// check if the normalized path is in routes
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- unsafe indexed access
if (routes.value[normalizedRoutePath]) return normalizedRoutePath
// check encoded path
const encodedRoutePath = encodeURI(normalizedRoutePath)
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- unsafe indexed access
if (routes.value[encodedRoutePath]) {
return encodedRoutePath
}
diff --git a/packages/client/src/setupDevtools.ts b/packages/client/src/setupDevtools.ts
index ab57f1e43e..a22a731140 100644
--- a/packages/client/src/setupDevtools.ts
+++ b/packages/client/src/setupDevtools.ts
@@ -1,6 +1,6 @@
import { setupDevtoolsPlugin } from '@vue/devtools-api'
-import { watch } from 'vue'
import type { App } from 'vue'
+import { watch } from 'vue'
import type { ClientData } from './types/index.js'
const PLUGIN_ID = 'org.vuejs.vuepress'
@@ -12,11 +12,14 @@ const INSPECTOR_LABEL = PLUGIN_LABEL
const INSPECTOR_CLIENT_DATA_ID = 'client-data'
const INSPECTOR_CLIENT_DATA_LABEL = 'Client Data'
+type ClientDataKey = keyof ClientData
+type ClientDataValue = ClientData[ClientDataKey]
+
export const setupDevtools = (app: App, clientData: ClientData): void => {
setupDevtoolsPlugin(
{
// fix recursive reference
- app: app as any,
+ app: app as never,
id: PLUGIN_ID,
label: PLUGIN_LABEL,
packageName: '@vuepress/client',
@@ -25,9 +28,12 @@ export const setupDevtools = (app: App, clientData: ClientData): void => {
componentStateTypes: [PLUGIN_COMPONENT_STATE_TYPE],
},
(api) => {
- const clientDataEntries = Object.entries(clientData)
- const clientDataKeys = Object.keys(clientData)
- const clientDataValues = Object.values(clientData)
+ const clientDataEntries = Object.entries(clientData) as [
+ ClientDataKey,
+ ClientDataValue,
+ ][]
+ const clientDataKeys = Object.keys(clientData) as ClientDataKey[]
+ const clientDataValues = Object.values(clientData) as ClientDataValue[]
// setup component state
api.on.inspectComponent((payload) => {
@@ -72,12 +78,12 @@ export const setupDevtools = (app: App, clientData: ClientData): void => {
),
}
}
- if (clientDataKeys.includes(payload.nodeId)) {
+ if (clientDataKeys.includes(payload.nodeId as ClientDataKey)) {
payload.state = {
[INSPECTOR_CLIENT_DATA_LABEL]: [
{
key: payload.nodeId,
- value: clientData[payload.nodeId].value,
+ value: clientData[payload.nodeId as ClientDataKey].value,
},
],
}
diff --git a/packages/client/src/setupGlobalComponents.ts b/packages/client/src/setupGlobalComponents.ts
index 6c513cc98a..684f9d5b8a 100644
--- a/packages/client/src/setupGlobalComponents.ts
+++ b/packages/client/src/setupGlobalComponents.ts
@@ -5,9 +5,7 @@ import { ClientOnly, Content, RouteLink } from './components/index.js'
* Register global built-in components
*/
export const setupGlobalComponents = (app: App): void => {
- /* eslint-disable vue/match-component-file-name, vue/no-reserved-component-names */
app.component('ClientOnly', ClientOnly)
app.component('Content', Content)
app.component('RouteLink', RouteLink)
- /* eslint-enable vue/match-component-file-name, vue/no-reserved-component-names */
}
diff --git a/packages/client/src/setupGlobalComputed.ts b/packages/client/src/setupGlobalComputed.ts
index 57197148a6..e258cb7673 100644
--- a/packages/client/src/setupGlobalComputed.ts
+++ b/packages/client/src/setupGlobalComputed.ts
@@ -48,7 +48,7 @@ export const setupGlobalComputed = (
__VUE_HMR_RUNTIME__.updatePageData = async (newPageData: PageData) => {
const oldPageChunk = await routes.value[newPageData.path].loader()
const newPageChunk = { comp: oldPageChunk.comp, data: newPageData }
- routes.value[newPageData.path].loader = () =>
+ routes.value[newPageData.path].loader = async () =>
Promise.resolve(newPageChunk)
if (
newPageData.path ===
diff --git a/packages/client/src/setupUpdateHead.ts b/packages/client/src/setupUpdateHead.ts
index 5757426c82..d3f61e414b 100644
--- a/packages/client/src/setupUpdateHead.ts
+++ b/packages/client/src/setupUpdateHead.ts
@@ -1,12 +1,76 @@
-import { isPlainObject, isString } from '@vuepress/shared'
import type { HeadConfig, VuepressSSRContext } from '@vuepress/shared'
+import { isPlainObject, isString } from '@vuepress/shared'
import { onMounted, provide, useSSRContext, watch } from 'vue'
+import type { UpdateHead } from './composables/index.js'
import {
updateHeadSymbol,
usePageHead,
usePageLang,
} from './composables/index.js'
-import type { UpdateHead } from './composables/index.js'
+
+/**
+ * Query the matched head element of head config
+ */
+export const queryHeadElement = ([
+ tagName,
+ attrs,
+ content = '',
+]: HeadConfig): HTMLElement | null => {
+ const attrsSelector = Object.entries(attrs)
+ .map(([key, value]) => {
+ if (isString(value)) {
+ return `[${key}=${JSON.stringify(value)}]`
+ }
+ if (value) {
+ return `[${key}]`
+ }
+ return ''
+ })
+ .join('')
+
+ const selector = `head > ${tagName}${attrsSelector}`
+ const headElements = Array.from(
+ document.querySelectorAll(selector),
+ )
+ const matchedHeadElement = headElements.find(
+ (item) => item.innerText === content,
+ )
+ return matchedHeadElement ?? null
+}
+
+/**
+ * Create head element from head config
+ */
+export const createHeadElement = ([
+ tagName,
+ attrs,
+ content,
+]: HeadConfig): HTMLElement | null => {
+ if (!isString(tagName)) {
+ return null
+ }
+
+ // create element
+ const headElement = document.createElement(tagName)
+
+ // set attributes
+ if (isPlainObject(attrs)) {
+ Object.entries(attrs).forEach(([key, value]) => {
+ if (isString(value)) {
+ headElement.setAttribute(key, value)
+ } else if (value) {
+ headElement.setAttribute(key, '')
+ }
+ })
+ }
+
+ // set content
+ if (isString(content)) {
+ headElement.appendChild(document.createTextNode(content))
+ }
+
+ return headElement
+}
/**
* Auto update head and provide as global util
@@ -71,7 +135,7 @@ export const setupUpdateHead = (): void => {
// remove the non-intersection from old elements
if (matchedIndex === -1) {
oldEl.remove()
- // use delete to make the index consistent
+ // eslint-disable-next-line @typescript-eslint/no-array-delete -- use delete to make the index consistent
delete managedHeadElements[oldIndex]
}
// keep the intersection in old elements, and remove it from new elements
@@ -85,7 +149,7 @@ export const setupUpdateHead = (): void => {
// update managed head elements
managedHeadElements = [
// filter out empty deleted items
- ...managedHeadElements.filter((item) => !!item),
+ ...managedHeadElements.filter((item: HTMLElement | undefined) => !!item),
...newHeadElements,
]
}
@@ -100,67 +164,3 @@ export const setupUpdateHead = (): void => {
watch(head, updateHead, { immediate: __VUEPRESS_DEV__ })
})
}
-
-/**
- * Query the matched head element of head config
- */
-export const queryHeadElement = ([
- tagName,
- attrs,
- content = '',
-]: HeadConfig): HTMLElement | null => {
- const attrsSelector = Object.entries(attrs)
- .map(([key, value]) => {
- if (isString(value)) {
- return `[${key}=${JSON.stringify(value)}]`
- }
- if (value === true) {
- return `[${key}]`
- }
- return ''
- })
- .join('')
-
- const selector = `head > ${tagName}${attrsSelector}`
- const headElements = Array.from(
- document.querySelectorAll(selector),
- )
- const matchedHeadElement = headElements.find(
- (item) => item.innerText === content,
- )
- return matchedHeadElement || null
-}
-
-/**
- * Create head element from head config
- */
-export const createHeadElement = ([
- tagName,
- attrs,
- content,
-]: HeadConfig): HTMLElement | null => {
- if (!isString(tagName)) {
- return null
- }
-
- // create element
- const headElement = document.createElement(tagName)
-
- // set attributes
- if (isPlainObject(attrs)) {
- Object.entries(attrs).forEach(([key, value]) => {
- if (isString(value)) {
- headElement.setAttribute(key, value)
- } else if (value === true) {
- headElement.setAttribute(key, '')
- }
- })
- }
-
- // set content
- if (isString(content)) {
- headElement.appendChild(document.createTextNode(content))
- }
-
- return headElement
-}
diff --git a/packages/client/src/types/clientConfig.ts b/packages/client/src/types/clientConfig.ts
index 9b0a490bd9..ad2a73eca9 100644
--- a/packages/client/src/types/clientConfig.ts
+++ b/packages/client/src/types/clientConfig.ts
@@ -14,7 +14,7 @@ export interface ClientConfig {
app: App
router: Router
siteData: SiteDataRef
- }) => void | Promise
+ }) => Promise | void
/**
* A function to be called inside the setup function of vue app
diff --git a/packages/client/src/types/clientData.ts b/packages/client/src/types/clientData.ts
index d5af2c224f..5107ac3067 100644
--- a/packages/client/src/types/clientData.ts
+++ b/packages/client/src/types/clientData.ts
@@ -37,10 +37,11 @@ export type RouteLocale = string
export type LayoutsRef = ComputedRef
export type PageComponentRef = ComputedRef
-export type PageDataRef = Record> =
- ComputedRef>
+export type PageDataRef<
+ T extends Record = Record,
+> = ComputedRef>
export type PageFrontmatterRef<
- T extends Record = Record,
+ T extends Record = Record,
> = ComputedRef>
export type PageHeadRef = ComputedRef
export type PageHeadTitleRef = ComputedRef
diff --git a/packages/client/types.d.ts b/packages/client/types.d.ts
index 2d55050eb3..f694351554 100644
--- a/packages/client/types.d.ts
+++ b/packages/client/types.d.ts
@@ -1,7 +1,8 @@
+/* eslint-disable @typescript-eslint/naming-convention, no-underscore-dangle */
declare const __VUEPRESS_VERSION__: string
declare const __VUEPRESS_BASE__: string
declare const __VUEPRESS_DEV__: boolean
declare const __VUEPRESS_SSR__: boolean
-declare const __VUE_HMR_RUNTIME__: Record
+declare const __VUE_HMR_RUNTIME__: Record
declare const __VUE_OPTIONS_API__: boolean
declare const __VUE_PROD_DEVTOOLS__: boolean
diff --git a/packages/core/src/app/createBaseApp.ts b/packages/core/src/app/createBaseApp.ts
index b596ac2031..3e91a42eff 100644
--- a/packages/core/src/app/createBaseApp.ts
+++ b/packages/core/src/app/createBaseApp.ts
@@ -36,8 +36,8 @@ export const createBaseApp = (config: AppConfig, isBuild = false): App => {
// methods
use: (plugin: Plugin) => appUse(app, plugin),
- init: () => appInit(app),
- prepare: () => appPrepare(app),
+ init: async () => appInit(app),
+ prepare: async () => appPrepare(app),
} as App
// setup theme and plugins
diff --git a/packages/core/src/app/createBuildApp.ts b/packages/core/src/app/createBuildApp.ts
index 3be1e3e8e9..36830cbdf8 100644
--- a/packages/core/src/app/createBuildApp.ts
+++ b/packages/core/src/app/createBuildApp.ts
@@ -6,6 +6,6 @@ import { createBaseApp } from './createBaseApp.js'
*/
export const createBuildApp = (config: AppConfig): BuildApp => {
const app = createBaseApp(config, true) as BuildApp
- app.build = () => app.options.bundler.build(app)
+ app.build = async () => app.options.bundler.build(app)
return app
}
diff --git a/packages/core/src/app/createDevApp.ts b/packages/core/src/app/createDevApp.ts
index c611560e3e..59fe0f2ea0 100644
--- a/packages/core/src/app/createDevApp.ts
+++ b/packages/core/src/app/createDevApp.ts
@@ -6,6 +6,6 @@ import { createBaseApp } from './createBaseApp.js'
*/
export const createDevApp = (config: AppConfig): DevApp => {
const app = createBaseApp(config, false) as DevApp
- app.dev = () => app.options.bundler.dev(app)
+ app.dev = async () => app.options.bundler.dev(app)
return app
}
diff --git a/packages/core/src/app/resolveAppDir.ts b/packages/core/src/app/resolveAppDir.ts
index 675c30ee5e..5e78b9d344 100644
--- a/packages/core/src/app/resolveAppDir.ts
+++ b/packages/core/src/app/resolveAppDir.ts
@@ -7,9 +7,10 @@ const require = createRequire(import.meta.url)
/**
* Create directory util function
*/
-export const createAppDirFunction = (baseDir: string): AppDirFunction => {
- return (...args: string[]): string => path.resolve(baseDir, ...args)
-}
+export const createAppDirFunction =
+ (baseDir: string): AppDirFunction =>
+ (...args) =>
+ path.resolve(baseDir, ...args)
/**
* Resolve directory utils for vuepress app
diff --git a/packages/core/src/app/resolveAppMarkdown.ts b/packages/core/src/app/resolveAppMarkdown.ts
index 0875dceaf6..84ce7d0a1a 100644
--- a/packages/core/src/app/resolveAppMarkdown.ts
+++ b/packages/core/src/app/resolveAppMarkdown.ts
@@ -1,5 +1,5 @@
-import { createMarkdown } from '@vuepress/markdown'
import type { Markdown } from '@vuepress/markdown'
+import { createMarkdown } from '@vuepress/markdown'
import type { App } from '../types/index.js'
/**
diff --git a/packages/core/src/app/resolveAppPages.ts b/packages/core/src/app/resolveAppPages.ts
index 2f721fa7fd..1f7d083dc0 100644
--- a/packages/core/src/app/resolveAppPages.ts
+++ b/packages/core/src/app/resolveAppPages.ts
@@ -18,7 +18,7 @@ export const resolveAppPages = async (app: App): Promise => {
// create pages from files
const pages = await Promise.all(
- pageFilePaths.map((filePath) => createPage(app, { filePath })),
+ pageFilePaths.map(async (filePath) => createPage(app, { filePath })),
)
// find the 404 page
diff --git a/packages/core/src/app/resolveAppVersion.ts b/packages/core/src/app/resolveAppVersion.ts
index 0990da5f7e..590340ffc4 100644
--- a/packages/core/src/app/resolveAppVersion.ts
+++ b/packages/core/src/app/resolveAppVersion.ts
@@ -9,6 +9,6 @@ const require = createRequire(import.meta.url)
export const resolveAppVersion = (): string => {
const pkgJson = fs.readJsonSync(
require.resolve('@vuepress/core/package.json'),
- )
+ ) as { version: string }
return pkgJson.version
}
diff --git a/packages/core/src/page/createPage.ts b/packages/core/src/page/createPage.ts
index ab9b05deb6..c0b5e74d26 100644
--- a/packages/core/src/page/createPage.ts
+++ b/packages/core/src/page/createPage.ts
@@ -83,7 +83,7 @@ export const createPage = async (
// resolve page component and extract headers & links
const { componentFilePath, componentFilePathRelative } =
- await resolvePageComponentInfo({
+ resolvePageComponentInfo({
app,
htmlFilePathRelative,
})
diff --git a/packages/core/src/page/renderPageContent.ts b/packages/core/src/page/renderPageContent.ts
index ea430de1f2..3702cd037b 100644
--- a/packages/core/src/page/renderPageContent.ts
+++ b/packages/core/src/page/renderPageContent.ts
@@ -74,6 +74,7 @@ export const renderPageContent = ({
'frontmatter',
),
sfcBlocks,
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-template-expression -- the title from frontmatter is not guaranteed to be a string
title: frontmatter.title ? `${frontmatter.title}` : title,
}
}
diff --git a/packages/core/src/page/resolvePageComponentInfo.ts b/packages/core/src/page/resolvePageComponentInfo.ts
index d27aa1933c..b1ee312cc4 100644
--- a/packages/core/src/page/resolvePageComponentInfo.ts
+++ b/packages/core/src/page/resolvePageComponentInfo.ts
@@ -4,16 +4,16 @@ import type { App } from '../types/index.js'
/**
* Resolve page component and related info
*/
-export const resolvePageComponentInfo = async ({
+export const resolvePageComponentInfo = ({
app,
htmlFilePathRelative,
}: {
app: App
htmlFilePathRelative: string
-}): Promise<{
+}): {
componentFilePath: string
componentFilePathRelative: string
-}> => {
+} => {
// resolve component file path
const componentFilePathRelative = path.join(
'pages',
diff --git a/packages/core/src/page/resolvePageDate.ts b/packages/core/src/page/resolvePageDate.ts
index ab92bcc01a..d371062f68 100644
--- a/packages/core/src/page/resolvePageDate.ts
+++ b/packages/core/src/page/resolvePageDate.ts
@@ -44,6 +44,7 @@ export const resolvePageDate = ({
const matches = filename.match(FILENAME_DATE_RE)
if (matches) {
return formatDateString(
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- unsafe indexed access
`${matches[1]}-${matches[2]}-${matches[3] ?? '01'}`,
DEFAULT_DATE,
)
@@ -56,6 +57,7 @@ export const resolvePageDate = ({
const matches = dirname.match(DIRNAME_DATE_RE)
if (matches) {
return formatDateString(
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- unsafe indexed access
`${matches[1]}-${matches[2]}-${matches[3] ?? '01'}`,
DEFAULT_DATE,
)
diff --git a/packages/core/src/page/resolvePageHtmlInfo.ts b/packages/core/src/page/resolvePageHtmlInfo.ts
index 58d1c63b4b..677921ed04 100644
--- a/packages/core/src/page/resolvePageHtmlInfo.ts
+++ b/packages/core/src/page/resolvePageHtmlInfo.ts
@@ -20,10 +20,10 @@ export const resolvePageHtmlInfo = ({
// /foo/ -> foo/index.html
const htmlFilePathRelative = removeLeadingSlash(
path.endsWith('/')
- ? path + 'index.html'
+ ? `${path}index.html`
: path.endsWith('.html')
? path
- : path + '.html',
+ : `${path}.html`,
)
const htmlFilePath = app.dir.dest(htmlFilePathRelative)
diff --git a/packages/core/src/page/resolvePageLang.ts b/packages/core/src/page/resolvePageLang.ts
index 1f3f49136a..3f2f243256 100644
--- a/packages/core/src/page/resolvePageLang.ts
+++ b/packages/core/src/page/resolvePageLang.ts
@@ -16,5 +16,6 @@ export const resolvePageLang = ({
if (isString(frontmatter.lang) && frontmatter.lang) {
return frontmatter.lang
}
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- unsafe indexed access
return app.siteData.locales[pathLocale]?.lang ?? app.siteData.lang
}
diff --git a/packages/core/src/page/resolvePagePermalink.ts b/packages/core/src/page/resolvePagePermalink.ts
index 6a549085f2..15a421dec1 100644
--- a/packages/core/src/page/resolvePagePermalink.ts
+++ b/packages/core/src/page/resolvePagePermalink.ts
@@ -45,9 +45,9 @@ export const resolvePagePermalink = ({
const link = path.join(
pathLocale,
permalinkPattern
- .replace(/:year/, year!)
- .replace(/:month/, month!)
- .replace(/:day/, day!)
+ .replace(/:year/, year)
+ .replace(/:month/, month)
+ .replace(/:day/, day)
.replace(/:slug/, slug)
.replace(/:raw/, pathInferred?.replace(/^\//, '') ?? ''),
)
diff --git a/packages/core/src/page/resolvePageSlug.ts b/packages/core/src/page/resolvePageSlug.ts
index e538526e47..a7329ffbaa 100644
--- a/packages/core/src/page/resolvePageSlug.ts
+++ b/packages/core/src/page/resolvePageSlug.ts
@@ -15,5 +15,5 @@ export const resolvePageSlug = ({
}
const filename = path.parse(filePathRelative).name
const match = filename.match(DATE_RE)
- return match ? match[3]! : filename
+ return match ? match[3] : filename
}
diff --git a/packages/core/src/pluginApi/createPluginApiRegisterHooks.ts b/packages/core/src/pluginApi/createPluginApiRegisterHooks.ts
index 22ac07b49b..79ee344016 100644
--- a/packages/core/src/pluginApi/createPluginApiRegisterHooks.ts
+++ b/packages/core/src/pluginApi/createPluginApiRegisterHooks.ts
@@ -48,9 +48,10 @@ export const createPluginApiRegisterHooks =
*/
Object.keys(commonHooks).forEach((key) => {
if (hooks[key] && commonHooks[key]) {
- hooks[key].add({
+ hooks[key as keyof typeof hooks].add({
pluginName,
- hook: commonHooks[key],
+ // @ts-expect-error: the type could not be narrowed correctly
+ hook: commonHooks[key as keyof typeof commonHooks],
})
}
})
diff --git a/packages/core/src/types/app/options.ts b/packages/core/src/types/app/options.ts
index 93271fd4bf..4cbcabbc37 100644
--- a/packages/core/src/types/app/options.ts
+++ b/packages/core/src/types/app/options.ts
@@ -67,7 +67,7 @@ export interface AppConfigBuild {
*
* @default true
*/
- shouldPreload?: ((file: string, type: string) => boolean) | boolean
+ shouldPreload?: boolean | ((file: string, type: string) => boolean)
/**
* Determine what resource files should be prefetched. Use boolean value to
@@ -75,7 +75,7 @@ export interface AppConfigBuild {
*
* @default true
*/
- shouldPrefetch?: ((file: string, type: string) => boolean) | boolean
+ shouldPrefetch?: boolean | ((file: string, type: string) => boolean)
/**
* Specify the path of the HTML template to be used for build
@@ -95,7 +95,7 @@ export interface AppConfigBuild {
/**
* Vuepress app config
*/
-export type AppConfig = AppConfigCommon & AppConfigDev & AppConfigBuild
+export type AppConfig = AppConfigBuild & AppConfigCommon & AppConfigDev
/**
* Vuepress app options
diff --git a/packages/core/src/types/bundler.ts b/packages/core/src/types/bundler.ts
index d69f273ec3..cd3b8dc2a7 100644
--- a/packages/core/src/types/bundler.ts
+++ b/packages/core/src/types/bundler.ts
@@ -12,3 +12,5 @@ export interface Bundler {
dev: (app: App) => Promise<() => Promise>
build: (app: App) => Promise
}
+
+export type BundlerOptions = Record
diff --git a/packages/core/src/types/page.ts b/packages/core/src/types/page.ts
index 5aadd8d7ae..178fec9782 100644
--- a/packages/core/src/types/page.ts
+++ b/packages/core/src/types/page.ts
@@ -5,11 +5,14 @@ import type { PageBase, PageData, PageFrontmatter } from '@vuepress/shared'
* Vuepress Page
*/
export type Page<
- ExtraPageData extends Record = Record,
- ExtraPageFrontmatter extends Record = Record,
- ExtraPageFields extends Record = Record,
-> = PageBase &
- ExtraPageFields & {
+ ExtraPageData extends Record = Record,
+ ExtraPageFrontmatter extends Record = Record<
+ string,
+ unknown
+ >,
+ ExtraPageFields extends Record = Record,
+> = ExtraPageFields &
+ PageBase & {
/**
* Data of the page, which will be available in client code
*/
diff --git a/packages/core/src/types/plugin.ts b/packages/core/src/types/plugin.ts
index c7f6bc39ca..ae52a6b334 100644
--- a/packages/core/src/types/plugin.ts
+++ b/packages/core/src/types/plugin.ts
@@ -11,8 +11,8 @@ import type { HooksExposed } from './pluginApi/index.js'
* A plugin package should have a `Plugin` as the default export
*/
export type Plugin =
- | T
| PluginFunction
+ | T
/**
* Vuepress plugin function
diff --git a/packages/core/src/types/pluginApi/hooks.ts b/packages/core/src/types/pluginApi/hooks.ts
index 4e88851256..cab24a8a13 100644
--- a/packages/core/src/types/pluginApi/hooks.ts
+++ b/packages/core/src/types/pluginApi/hooks.ts
@@ -1,5 +1,6 @@
import type { Markdown, MarkdownOptions } from '@vuepress/markdown'
import type { App } from '../app/index.js'
+import type { BundlerOptions } from '../bundler.js'
import type { Page, PageOptions } from '../page.js'
// util type
@@ -12,11 +13,12 @@ interface Closable {
export interface Hook<
Exposed,
Normalized = Exposed,
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- `any` type is required to infer the result type correctly
Result = Normalized extends (...args: any) => infer U
? U extends Promise
? V
: U
- : void,
+ : never,
> {
exposed: Exposed
normalized: Normalized
@@ -41,9 +43,9 @@ export type ClientConfigFileHook = Hook<
// alias and define hook
export type AliasDefineHook = Hook<
- | Record
- | ((app: App, isServer: boolean) => PromiseOrNot>),
- (app: App, isServer: boolean) => Promise>
+ | Record
+ | ((app: App, isServer: boolean) => PromiseOrNot>),
+ (app: App, isServer: boolean) => Promise>
>
/**
@@ -58,7 +60,7 @@ export interface Hooks {
extendsMarkdown: ExtendsHook
extendsPageOptions: ExtendsHook
extendsPage: ExtendsHook
- extendsBundlerOptions: ExtendsHook
+ extendsBundlerOptions: ExtendsHook
clientConfigFile: ClientConfigFileHook
alias: AliasDefineHook
define: AliasDefineHook
diff --git a/packages/core/tests/app/resolveAppEnv.spec.ts b/packages/core/tests/app/resolveAppEnv.spec.ts
index bcdb45210d..6ba685baa6 100644
--- a/packages/core/tests/app/resolveAppEnv.spec.ts
+++ b/packages/core/tests/app/resolveAppEnv.spec.ts
@@ -1,18 +1,17 @@
import { describe, expect, it } from 'vitest'
+import type { Bundler } from '../../src/index.js'
import { resolveAppEnv, resolveAppOptions } from '../../src/index.js'
-const source = '/foo'
-
-const testCases: [
+const TEST_CASES: [
Parameters,
ReturnType,
][] = [
[
[
resolveAppOptions({
- source,
+ source: '/foo',
theme: { name: 'test' },
- bundler: {} as any,
+ bundler: {} as Bundler,
}),
false,
],
@@ -25,9 +24,9 @@ const testCases: [
[
[
resolveAppOptions({
- source,
+ source: '/foo',
theme: { name: 'test' },
- bundler: {} as any,
+ bundler: {} as Bundler,
debug: true,
}),
false,
@@ -41,9 +40,9 @@ const testCases: [
[
[
resolveAppOptions({
- source,
+ source: '/foo',
theme: { name: 'test' },
- bundler: {} as any,
+ bundler: {} as Bundler,
}),
true,
],
@@ -57,7 +56,7 @@ const testCases: [
describe('core > app > resolveAppEnv', () => {
describe('should create app env correctly', () => {
- testCases.forEach(([params, expected], i) => {
+ TEST_CASES.forEach(([params, expected], i) => {
it(`case ${i}`, () => {
expect(resolveAppEnv(...params)).toEqual(expected)
})
diff --git a/packages/core/tests/app/resolveAppOptions.spec.ts b/packages/core/tests/app/resolveAppOptions.spec.ts
index a7f3ff125c..442737587d 100644
--- a/packages/core/tests/app/resolveAppOptions.spec.ts
+++ b/packages/core/tests/app/resolveAppOptions.spec.ts
@@ -1,5 +1,6 @@
import { path, templateRenderer } from '@vuepress/utils'
import { describe, expect, it } from 'vitest'
+import type { Bundler } from '../../src/index.js'
import { resolveAppOptions } from '../../src/index.js'
describe('core > app > resolveAppOptions', () => {
@@ -9,8 +10,8 @@ describe('core > app > resolveAppOptions', () => {
expect(
resolveAppOptions({
source,
- theme: { name: 'theme' } as any,
- bundler: { name: 'bundler' } as any,
+ theme: { name: 'theme' },
+ bundler: { name: 'bundler' } as Bundler,
}),
).toEqual({
base: '/',
diff --git a/packages/core/tests/app/resolveAppPages.spec.ts b/packages/core/tests/app/resolveAppPages.spec.ts
index 8d47875eb2..f394888238 100644
--- a/packages/core/tests/app/resolveAppPages.spec.ts
+++ b/packages/core/tests/app/resolveAppPages.spec.ts
@@ -1,6 +1,7 @@
import { createMarkdown } from '@vuepress/markdown'
import { path } from '@vuepress/utils'
import { describe, expect, it } from 'vitest'
+import type { Bundler } from '../../src/index.js'
import { createBaseApp, resolveAppPages } from '../../src/index.js'
describe('core > app > resolveAppPages', () => {
@@ -8,7 +9,7 @@ describe('core > app > resolveAppPages', () => {
const app = createBaseApp({
source: path.resolve(__dirname, '../__fixtures__/pages'),
theme: { name: 'test' },
- bundler: {} as any,
+ bundler: {} as Bundler,
})
app.markdown = createMarkdown()
@@ -28,7 +29,7 @@ describe('core > app > resolveAppPages', () => {
const app = createBaseApp({
source: path.resolve(__dirname, '../__fixtures__/pages-with-404'),
theme: { name: 'test' },
- bundler: {} as any,
+ bundler: {} as Bundler,
})
app.markdown = createMarkdown()
@@ -47,7 +48,7 @@ describe('core > app > resolveAppPages', () => {
const app = createBaseApp({
source: path.resolve(__dirname, '../__fixtures__/pages-with-404'),
theme: { name: 'test' },
- bundler: {} as any,
+ bundler: {} as Bundler,
})
app.use({
@@ -71,7 +72,7 @@ describe('core > app > resolveAppPages', () => {
const app = createBaseApp({
source: path.resolve(__dirname, '../__fixtures__/pages-with-404'),
theme: { name: 'test' },
- bundler: {} as any,
+ bundler: {} as Bundler,
})
app.use({
diff --git a/packages/core/tests/app/resolvePluginObject.spec.ts b/packages/core/tests/app/resolvePluginObject.spec.ts
index 02d2441e81..d359120252 100644
--- a/packages/core/tests/app/resolvePluginObject.spec.ts
+++ b/packages/core/tests/app/resolvePluginObject.spec.ts
@@ -1,12 +1,12 @@
import { path } from '@vuepress/utils'
import { describe, expect, it, vi } from 'vitest'
+import type { Bundler, PluginFunction, PluginObject } from '../../src/index.js'
import { createBaseApp, resolvePluginObject } from '../../src/index.js'
-import type { PluginFunction, PluginObject } from '../../src/index.js'
const app = createBaseApp({
source: path.resolve(__dirname, 'fake-source'),
theme: { name: 'test' },
- bundler: {} as any,
+ bundler: {} as Bundler,
})
describe('core > app > resolvePluginObject', () => {
@@ -20,7 +20,7 @@ describe('core > app > resolvePluginObject', () => {
})
it('should work with plugin function', () => {
- const pluginFunction: PluginFunction = vi.fn((app) => ({
+ const pluginFunction: PluginFunction = vi.fn(() => ({
name: 'plugin-function',
}))
diff --git a/packages/core/tests/app/resolveThemeInfo.spec.ts b/packages/core/tests/app/resolveThemeInfo.spec.ts
index cc331816d6..631deb2e6a 100644
--- a/packages/core/tests/app/resolveThemeInfo.spec.ts
+++ b/packages/core/tests/app/resolveThemeInfo.spec.ts
@@ -1,55 +1,59 @@
import { importFileDefault, path } from '@vuepress/utils'
import { describe, expect, it } from 'vitest'
+import type { App, Bundler, Theme, ThemeObject } from '../../src/index.js'
import { createBaseApp, resolveThemeInfo } from '../../src/index.js'
-const fixtures = (...args: string[]) =>
+const fixtures = (...args: string[]): string =>
path.resolve(__dirname, '../__fixtures__/', ...args)
-const createTestApp = async (themePath: string) =>
+const createTestApp = async (themePath: string): Promise =>
createBaseApp({
source: path.resolve(__dirname, 'fake-source'),
theme: await importFileDefault(themePath),
- bundler: {} as any,
+ bundler: {} as Bundler,
})
-const themeEntryTypes = ['func', 'obj'] as const
+const THEME_ENTRY_TYPES = ['func', 'obj'] as const
-const getThemePlugin = async (themePath: string) => {
- const theme = await importFileDefault(themePath)
- return typeof theme === 'function' ? theme() : theme
+const getThemePlugin = async (
+ themePath: string,
+ app: App,
+): Promise => {
+ const theme = await importFileDefault(themePath)
+ return typeof theme === 'function' ? theme(app) : theme
}
describe('core > app > resolveThemeInfo', () => {
describe('plugins', () => {
describe('should resolve theme info without plugins correctly', () => {
- themeEntryTypes.forEach((item) =>
+ THEME_ENTRY_TYPES.forEach((item) => {
it(item, async () => {
const themePath = fixtures(`themes/${item}-empty.js`)
const app = await createTestApp(themePath)
expect(resolveThemeInfo(app, app.options.theme).plugins).toEqual([
- await getThemePlugin(themePath),
+ await getThemePlugin(themePath, app),
])
- }),
- )
+ })
+ })
})
describe('should resolve theme info with plugins correctly', () => {
- themeEntryTypes.forEach((item) =>
+ THEME_ENTRY_TYPES.forEach((item) => {
it(item, async () => {
const themePath = fixtures(`themes/${item}.js`)
const app = await createTestApp(themePath)
expect(resolveThemeInfo(app, app.options.theme).plugins).toEqual([
await importFileDefault(fixtures('plugins/obj.js')),
- await getThemePlugin(themePath),
+ await getThemePlugin(themePath, app),
])
- }),
- )
+ })
+ })
})
})
describe('extends', () => {
describe('should resolve theme info with parent theme correctly', () => {
- themeEntryTypes.forEach((item) =>
+ THEME_ENTRY_TYPES.forEach((item) => {
it(item, async () => {
const themePath = fixtures(`themes/${item}-extends-parent.js`)
const parentThemePath = fixtures(`themes/${item}.js`)
@@ -58,19 +62,19 @@ describe('core > app > resolveThemeInfo', () => {
expect(resolveThemeInfo(app, app.options.theme)).toEqual({
plugins: [
await importFileDefault(fixtures('plugins/obj.js')),
- await getThemePlugin(parentThemePath),
+ await getThemePlugin(parentThemePath, app),
await importFileDefault(fixtures('plugins/obj-foo.js')),
- await getThemePlugin(themePath),
+ await getThemePlugin(themePath, app),
],
templateBuild: `theme-${item}-extends-parent-template-build`,
templateDev: `theme-${item}-template-dev`,
})
- }),
- )
+ })
+ })
})
describe('should resolve theme info with grandparent theme correctly', () => {
- themeEntryTypes.forEach((item) =>
+ THEME_ENTRY_TYPES.forEach((item) => {
it(item, async () => {
const themePath = fixtures(`themes/${item}-extends-grandparent.js`)
const parentThemePath = fixtures(`themes/${item}-extends-parent.js`)
@@ -80,17 +84,17 @@ describe('core > app > resolveThemeInfo', () => {
expect(resolveThemeInfo(app, app.options.theme)).toEqual({
plugins: [
await importFileDefault(fixtures('plugins/obj.js')),
- await getThemePlugin(grandparentThemePath),
+ await getThemePlugin(grandparentThemePath, app),
await importFileDefault(fixtures('plugins/obj-foo.js')),
- await getThemePlugin(parentThemePath),
+ await getThemePlugin(parentThemePath, app),
await importFileDefault(fixtures('plugins/obj-bar.js')),
- await getThemePlugin(themePath),
+ await getThemePlugin(themePath, app),
],
templateBuild: `theme-${item}-extends-parent-template-build`,
templateDev: `theme-${item}-extends-grandparent-template-dev`,
})
- }),
- )
+ })
+ })
})
})
})
diff --git a/packages/core/tests/page/createPage.spec.ts b/packages/core/tests/page/createPage.spec.ts
index e2f832b2ab..313fed3876 100644
--- a/packages/core/tests/page/createPage.spec.ts
+++ b/packages/core/tests/page/createPage.spec.ts
@@ -1,18 +1,19 @@
import { path } from '@vuepress/utils'
import { beforeAll, describe, expect, it, vi } from 'vitest'
+import type { Bundler } from '../../src/index.js'
import { createBaseApp, createPage } from '../../src/index.js'
-const app = createBaseApp({
- source: path.resolve(__dirname, 'fake-source'),
- theme: { name: 'test' },
- bundler: {} as any,
-})
+describe('should work without plugins', () => {
+ const app = createBaseApp({
+ source: path.resolve(__dirname, 'fake-source'),
+ theme: { name: 'test' },
+ bundler: {} as Bundler,
+ })
-beforeAll(async () => {
- await app.init()
-})
+ beforeAll(async () => {
+ await app.init()
+ })
-describe('core > page > createPage', () => {
it('should throw an error', async () => {
const consoleError = console.error
console.error = vi.fn()
@@ -86,12 +87,14 @@ describe('core > page > createPage', () => {
)
expect(page.chunkName).toBeTruthy()
})
+})
+describe('should work with plugins', () => {
it('should be extended by plugin correctly', async () => {
const app = createBaseApp({
source: path.resolve(__dirname, 'fake-source'),
theme: { name: 'test' },
- bundler: {} as any,
+ bundler: {} as Bundler,
})
app.use({
name: 'foo',
diff --git a/packages/core/tests/page/inferPagePath.spec.ts b/packages/core/tests/page/inferPagePath.spec.ts
index 5f34327047..f65aced2ad 100644
--- a/packages/core/tests/page/inferPagePath.spec.ts
+++ b/packages/core/tests/page/inferPagePath.spec.ts
@@ -1,11 +1,12 @@
import { path } from '@vuepress/utils'
import { describe, expect, it } from 'vitest'
+import type { Bundler } from '../../src/index.js'
import { createBaseApp, inferPagePath } from '../../src/index.js'
const app = createBaseApp({
source: path.resolve(__dirname, 'fake-source'),
theme: { name: 'test' },
- bundler: {} as any,
+ bundler: {} as Bundler,
locales: {
'/': {},
'/en/': {},
@@ -16,10 +17,10 @@ const app = createBaseApp({
const appWithoutLocales = createBaseApp({
source: path.resolve(__dirname, 'fake-source'),
theme: { name: 'test' },
- bundler: {} as any,
+ bundler: {} as Bundler,
})
-const testCases: [string, ReturnType][] = [
+const TEST_CASES: [string, ReturnType][] = [
[
'foo.md',
{
@@ -50,41 +51,39 @@ const testCases: [string, ReturnType][] = [
],
]
-describe('core > page > inferPagePath', () => {
- describe('should infer page path according to relative path of page file', () => {
- testCases.forEach(([source, expected]) => {
- it(JSON.stringify(source), () => {
- expect(
- inferPagePath({
- app,
- filePathRelative: source,
- }),
- ).toEqual(expected)
- })
+describe('should infer page path according to relative path of page file', () => {
+ TEST_CASES.forEach(([source, expected]) => {
+ it(JSON.stringify(source), () => {
+ expect(
+ inferPagePath({
+ app,
+ filePathRelative: source,
+ }),
+ ).toEqual(expected)
})
})
+})
- it('should use `/` as the default locale path', () => {
- expect(
- inferPagePath({
- app: appWithoutLocales,
- filePathRelative: 'en/foo/bar.md',
- }),
- ).toEqual({
- pathInferred: '/en/foo/bar.html',
- pathLocale: '/',
- })
+it('should use `/` as the default locale path', () => {
+ expect(
+ inferPagePath({
+ app: appWithoutLocales,
+ filePathRelative: 'en/foo/bar.md',
+ }),
+ ).toEqual({
+ pathInferred: '/en/foo/bar.html',
+ pathLocale: '/',
})
+})
- it('should handle empty file relative path', () => {
- expect(
- inferPagePath({
- app,
- filePathRelative: null,
- }),
- ).toEqual({
- pathInferred: null,
- pathLocale: '/',
- })
+it('should handle empty file relative path', () => {
+ expect(
+ inferPagePath({
+ app,
+ filePathRelative: null,
+ }),
+ ).toEqual({
+ pathInferred: null,
+ pathLocale: '/',
})
})
diff --git a/packages/core/tests/page/renderPageContent.spec.ts b/packages/core/tests/page/renderPageContent.spec.ts
index 055beaf0a1..c4c3e756fd 100644
--- a/packages/core/tests/page/renderPageContent.spec.ts
+++ b/packages/core/tests/page/renderPageContent.spec.ts
@@ -1,155 +1,154 @@
import { createMarkdown } from '@vuepress/markdown'
import { path } from '@vuepress/utils'
import { describe, expect, it } from 'vitest'
+import type { Bundler } from '../../src/index.js'
import { createBaseApp, renderPageContent } from '../../src/index.js'
const app = createBaseApp({
source: path.resolve(__dirname, 'fake-source'),
theme: { name: 'test' },
- bundler: {} as any,
+ bundler: {} as Bundler,
})
app.markdown = createMarkdown()
-describe('core > page > renderPageContent', () => {
- it('should render page content correctly', () => {
- const resolved = renderPageContent({
- app,
- content: `\
+it('should render page content correctly', () => {
+ const resolved = renderPageContent({
+ app,
+ content: `\
foobar
`,
- filePath: app.dir.source('foo.md'),
- filePathRelative: 'foo.md',
- options: {},
- })
+ filePath: app.dir.source('foo.md'),
+ filePathRelative: 'foo.md',
+ options: {},
+ })
- expect(resolved).toEqual({
- contentRendered: 'foobar
\n',
- deps: [],
- frontmatter: {},
- headers: [],
- links: [],
- markdownEnv: { excerpt: '' },
- sfcBlocks: {
- template: {
- type: 'template',
- content: 'foobar
\n',
- contentStripped: 'foobar
\n',
- tagClose: '',
- tagOpen: '',
- },
- script: null,
- scriptSetup: {
+ expect(resolved).toEqual({
+ contentRendered: 'foobar
\n',
+ deps: [],
+ frontmatter: {},
+ headers: [],
+ links: [],
+ markdownEnv: { excerpt: '' },
+ sfcBlocks: {
+ template: {
+ type: 'template',
+ content: 'foobar
\n',
+ contentStripped: 'foobar
\n',
+ tagClose: '',
+ tagOpen: '',
+ },
+ script: null,
+ scriptSetup: {
+ type: 'script',
+ content: ``,
+ contentStripped: `\nconst msg = 'msg'\n`,
+ tagClose: '',
+ tagOpen: '`,
contentStripped: `\nconst msg = 'msg'\n`,
tagClose: '',
tagOpen: '`,
- contentStripped: `\nconst msg = 'msg'\n`,
- tagClose: '',
- tagOpen: '