Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions e2e/docs/.vuepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,13 @@ export default defineUserConfig({
},

plugins: [fooPlugin],

// The alias entries are intentionally ordered by key length to ensure
// that more specific aliases (e.g., '@dir/a.js') take precedence over
// less specific ones (e.g., '@dir'). Do not reorder these entries.
alias: {
'@dir/a.js': path.resolve(__dirname, '../../modules/dir2/a.js'),
'@dir': path.resolve(__dirname, '../../modules/dir1'),
'@dir/b.js': path.resolve(__dirname, '../../modules/dir2/b.js'),
},
})
5 changes: 5 additions & 0 deletions e2e/docs/alias/dir.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<p id="result">{{result}}</p>

<script setup>
import { result } from '@dir/c.js'
</script>
7 changes: 7 additions & 0 deletions e2e/docs/alias/override.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<p id="a">{{aResult}}</p>
<p id="b">{{bResult}}</p>

<script setup>
import { result as aResult } from '@dir/a.js'
import { result as bResult } from '@dir/b.js'
</script>
1 change: 1 addition & 0 deletions e2e/modules/dir1/a.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const result = 'dir1 > a'
1 change: 1 addition & 0 deletions e2e/modules/dir1/b.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const result = 'dir1 > b'
1 change: 1 addition & 0 deletions e2e/modules/dir1/c.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const result = 'dir1 > c'
1 change: 1 addition & 0 deletions e2e/modules/dir2/a.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const result = 'dir2 > a'
1 change: 1 addition & 0 deletions e2e/modules/dir2/b.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const result = 'dir2 > b'
6 changes: 6 additions & 0 deletions e2e/tests/alias/dir.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { expect, test } from '@playwright/test'

test('should apply alias to subpath', async ({ page }) => {
await page.goto('alias/dir.html')
await expect(page.locator('#result')).toHaveText('dir1 > c')
})
7 changes: 7 additions & 0 deletions e2e/tests/alias/override.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { expect, test } from '@playwright/test'

test('longer alias shall override shorter ones', async ({ page }) => {
await page.goto('alias/override.html')
await expect(page.locator('#a')).toHaveText('dir2 > a')
await expect(page.locator('#b')).toHaveText('dir2 > b')
})
14 changes: 7 additions & 7 deletions packages/bundler-vite/src/plugins/vuepressConfigPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@ const resolveAlias = async ({
const aliasResult = await app.pluginApi.hooks.alias.process(app, isServer)

aliasResult.forEach((aliasObject) => {
Object.entries(aliasObject).forEach(([key, value]) => {
alias[key] = value as string
})
Object.assign(alias, aliasObject)
})

return [
...Object.keys(alias).map((item) => ({
find: item,
replacement: alias[item],
})),
...Object.keys(alias)
.sort((a, b) => b.length - a.length)
.map((item) => ({
find: item,
replacement: alias[item],
})),
...(isServer
? []
: [
Expand Down
37 changes: 21 additions & 16 deletions packages/bundler-webpack/src/config/handleResolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,26 @@ export const handleResolve = async ({
isServer: boolean
}): Promise<void> => {
// aliases
config.resolve.alias
.set('@source', app.dir.source())
.set('@temp', app.dir.temp())
.set('@internal', app.dir.temp('internal'))
const alias = {
'@source': app.dir.source(),
'@temp': app.dir.temp(),
'@internal': app.dir.temp('internal'),
}

// extensionAlias
config.resolve.extensionAlias.merge({
'.js': ['.js', '.ts'],
'.mjs': ['.mjs', '.mts'],
// plugin hook: alias
const aliasResult = await app.pluginApi.hooks.alias.process(app, isServer)

aliasResult.forEach((aliasObject) => {
Object.assign(alias, aliasObject)
})

// set aliases
config.resolve.alias.merge(
Object.fromEntries(
Object.entries(alias).sort(([a], [b]) => b.length - a.length),
),
)

// extensions
config.resolve.extensions.merge([
'.js',
Expand All @@ -35,13 +44,9 @@ export const handleResolve = async ({
'.json',
])

// plugin hook: alias
const aliasResult = await app.pluginApi.hooks.alias.process(app, isServer)

// set aliases
aliasResult.forEach((aliasObject) => {
Object.entries(aliasObject).forEach(([key, value]) => {
config.resolve.alias.set(key, value as string)
})
// extensionAlias
config.resolve.extensionAlias.merge({
'.js': ['.js', '.ts'],
'.mjs': ['.mjs', '.mts'],
})
}
6 changes: 3 additions & 3 deletions packages/core/src/pluginApi/createPluginApiRegisterHooks.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { PluginApi } from '../types/index.js'
import type { AliasHook, DefineHook, PluginApi } from '../types/index.js'
import { normalizeAliasDefineHook } from './normalizeAliasDefineHook.js'
import { normalizeClientConfigFileHook } from './normalizeClientConfigFileHook.js'

Expand Down Expand Up @@ -30,14 +30,14 @@ export const createPluginApiRegisterHooks =
if (alias) {
hooks.alias.add({
pluginName,
hook: normalizeAliasDefineHook(alias),
hook: normalizeAliasDefineHook<AliasHook>(alias),
})
}

if (define) {
hooks.define.add({
pluginName,
hook: normalizeAliasDefineHook(define),
hook: normalizeAliasDefineHook<DefineHook>(define),
})
}

Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/pluginApi/normalizeAliasDefineHook.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { isFunction } from '@vuepress/shared'
import type { AliasDefineHook } from '../types/index.js'
import type { AliasHook, DefineHook } from '../types/index.js'

/**
* Normalize alias and define hook
*
* @internal
*/
export const normalizeAliasDefineHook =
(hook: AliasDefineHook['exposed']): AliasDefineHook['normalized'] =>
<T extends AliasHook | DefineHook>(hook: T['exposed']): T['normalized'] =>
async (app, isServer) =>
isFunction(hook) ? hook(app, isServer) : hook
15 changes: 11 additions & 4 deletions packages/core/src/types/pluginApi/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,15 @@ export type ClientConfigFileHook = Hook<
(app: App) => Promise<string>
>

// alias and define hook
export type AliasDefineHook = Hook<
// alias hook
export type AliasHook = Hook<
| Record<string, string>
| ((app: App, isServer: boolean) => PromiseOrNot<Record<string, string>>),
(app: App, isServer: boolean) => Promise<Record<string, string>>
>

// define hook
export type DefineHook = Hook<
| Record<string, unknown>
| ((app: App, isServer: boolean) => PromiseOrNot<Record<string, unknown>>),
(app: App, isServer: boolean) => Promise<Record<string, unknown>>
Expand All @@ -62,8 +69,8 @@ export interface Hooks {
extendsPage: ExtendsHook<Page>
extendsBundlerOptions: ExtendsHook<BundlerOptions>
clientConfigFile: ClientConfigFileHook
alias: AliasDefineHook
define: AliasDefineHook
alias: AliasHook
define: DefineHook
}

/**
Expand Down
28 changes: 13 additions & 15 deletions packages/core/tests/pluginApi/normalizeAliasDefineHook.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { path } from '@vuepress/utils'
import { expect, it, vi } from 'vitest'
import type { AliasDefineHook, Bundler } from '../../src/index.js'
import type { AliasHook, Bundler, DefineHook } from '../../src/index.js'
import { createBaseApp, normalizeAliasDefineHook } from '../../src/index.js'

const app = createBaseApp({
Expand All @@ -9,13 +9,19 @@ const app = createBaseApp({
bundler: {} as Bundler,
})

it('should wrap object with a function', async () => {
const rawHook: AliasHook['exposed'] = {
foo: 'bar',
}
const normalizedHook = normalizeAliasDefineHook(rawHook)
expect(await normalizedHook(app, true)).toEqual({ foo: 'bar' })
})

it('should keep function as is', async () => {
const rawHook: AliasDefineHook['exposed'] = vi.fn(
(_app, isServer: boolean) => ({
foo: 'bar',
isServer,
}),
)
const rawHook: DefineHook['exposed'] = vi.fn((_app, isServer: boolean) => ({
foo: 'bar',
isServer,
}))
const normalizedHook = normalizeAliasDefineHook(rawHook)
expect(await normalizedHook(app, true)).toEqual({
foo: 'bar',
Expand All @@ -24,11 +30,3 @@ it('should keep function as is', async () => {
expect(rawHook).toHaveBeenCalledTimes(1)
expect(rawHook).toHaveBeenCalledWith(app, true)
})

it('should wrap object with a function', async () => {
const rawHook: AliasDefineHook['exposed'] = {
foo: 'bar',
}
const normalizedHook = normalizeAliasDefineHook(rawHook)
expect(await normalizedHook(app, true)).toEqual({ foo: 'bar' })
})
Loading