Skip to content

Commit 1b3304e

Browse files
authored
fix: normalize Vue Vite import paths on Windows (#207)
1 parent cfd85fc commit 1b3304e

2 files changed

Lines changed: 67 additions & 2 deletions

File tree

packages/comark-vue/src/vite.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ import { existsSync } from 'node:fs'
77

88
const runtimeDir = fileURLToPath(new URL('./utils', import.meta.url))
99

10+
function toImportPath(filePath: string): string {
11+
return filePath.replace(/\\/g, '/')
12+
}
13+
1014
function viteComarkSlot(node: ElementNode, context: TransformContext) {
1115
const isVueSlotWithUnwrap =
1216
node.tag === 'slot' &&
@@ -39,7 +43,7 @@ function viteComarkSlot(node: ElementNode, context: TransformContext) {
3943
if (!context.imports.some((i) => String(i.exp) === importExp)) {
4044
context.imports.push({
4145
exp: importExp,
42-
path: `${runtimeDir}/${context.ssr ? 'ssrSlot' : 'slot'}`,
46+
path: `${toImportPath(runtimeDir)}/${context.ssr ? 'ssrSlot' : 'slot'}`,
4347
})
4448
}
4549
}
@@ -84,7 +88,7 @@ function generateComponentsModule(files: string[]): string {
8488

8589
const lines: string[] = []
8690
for (let i = 0; i < files.length; i++) {
87-
lines.push(`import __comp_${i} from ${JSON.stringify(files[i]!.replace(/\\/g, '/'))}`)
91+
lines.push(`import __comp_${i} from ${JSON.stringify(toImportPath(files[i]!))}`)
8892
}
8993
lines.push('')
9094
lines.push('export default {')
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { afterEach, describe, expect, it, vi } from 'vitest'
2+
3+
afterEach(() => {
4+
vi.resetModules()
5+
vi.doUnmock('node:url')
6+
})
7+
8+
describe('@comark/vue vite plugin', () => {
9+
it('normalizes injected runtime import paths to forward slashes on Windows', async () => {
10+
vi.doMock('node:url', async () => {
11+
const actual = await vi.importActual<typeof import('node:url')>('node:url')
12+
return {
13+
...actual,
14+
fileURLToPath: () => String.raw`D:\Code\gqt\packages\comark-vue\src\utils`,
15+
}
16+
})
17+
18+
const { default: comark } = await import('../src/vite.ts')
19+
const plugin = comark()
20+
const vueOptions: Record<string, any> = {}
21+
22+
plugin.configResolved?.({
23+
root: '/repo',
24+
plugins: [
25+
{
26+
name: 'vite:vue',
27+
api: {
28+
options: vueOptions,
29+
},
30+
},
31+
],
32+
} as any)
33+
34+
const transform = vueOptions.template.compilerOptions.nodeTransforms[0]
35+
36+
function transformSlotOutlet(node: Record<string, any>) {
37+
node.codegenNode = { callee: 'renderSlot' }
38+
}
39+
40+
const node = {
41+
tag: 'slot',
42+
props: [{ name: 'unwrap' }],
43+
}
44+
45+
const context = {
46+
ssr: false,
47+
nodeTransforms: [transformSlotOutlet],
48+
imports: [],
49+
}
50+
51+
const run = transform(node, context)
52+
run?.()
53+
54+
expect(node.codegenNode.callee).toBe('_renderComarkSlot')
55+
expect(context.imports).toHaveLength(1)
56+
expect(context.imports[0]).toMatchObject({
57+
exp: '{ renderSlot as _renderComarkSlot }',
58+
path: 'D:/Code/gqt/packages/comark-vue/src/utils/slot',
59+
})
60+
})
61+
})

0 commit comments

Comments
 (0)