返回 slidev
import-guard.test.ts
根目录 / test / import-guard.test.ts
1 import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'
2 import { tmpdir } from 'node:os'
3 import { join } from 'node:path'
4 import { afterAll, beforeAll, describe, expect, it } from 'vitest'
5 import { extractImportSources, isPublicAsset } from '../packages/slidev/node/vite/importGuard'
6
7 describe('slide-import-guard', () => {
8 describe('isPublicAsset', () => {
9 let publicDir: string
10
11 beforeAll(() => {
12 publicDir = mkdtempSync(join(tmpdir(), 'slidev-public-'))
13 mkdirSync(join(publicDir, 'avatars'), { recursive: true })
14 writeFileSync(join(publicDir, 'logo.png'), '')
15 writeFileSync(join(publicDir, 'avatars', 'foo.png'), '')
16 })
17
18 afterAll(() => {
19 rmSync(publicDir, { recursive: true, force: true })
20 })
21
22 it('exempts a root-absolute URL pointing at an existing public asset', () => {
23 // The exact case from the bug: `<img src="/logo.png">` compiles to
24 // `import _imports_0 from '/logo.png'`.
25 expect(isPublicAsset('/logo.png', { publicDir })).toBe(true)
26 expect(isPublicAsset('/avatars/foo.png', { publicDir })).toBe(true)
27 })
28
29 it('ignores query and hash suffixes when mapping to disk', () => {
30 expect(isPublicAsset('/logo.png?url', { publicDir })).toBe(true)
31 expect(isPublicAsset('/logo.png#frag', { publicDir })).toBe(true)
32 })
33
34 it('does not exempt root-absolute URLs missing from the public dir', () => {
35 expect(isPublicAsset('/nope.png', { publicDir })).toBe(false)
36 })
37
38 it('does not exempt path-traversal URLs escaping the public dir', () => {
39 expect(isPublicAsset('/../logo.png', { publicDir })).toBe(false)
40 expect(isPublicAsset('/../../etc/passwd', { publicDir })).toBe(false)
41 })
42
43 it('does not exempt Vite internal URLs', () => {
44 expect(isPublicAsset('/@fs/logo.png', { publicDir })).toBe(false)
45 expect(isPublicAsset('/@id/virtual', { publicDir })).toBe(false)
46 })
47
48 it('does not exempt bare or relative imports', () => {
49 expect(isPublicAsset('vue', { publicDir })).toBe(false)
50 expect(isPublicAsset('./local.png', { publicDir })).toBe(false)
51 expect(isPublicAsset('../local.png', { publicDir })).toBe(false)
52 })
53
54 it('is disabled when publicDir is falsy', () => {
55 expect(isPublicAsset('/logo.png', { publicDir: '' })).toBe(false)
56 })
57 })
58
59 describe('extractImportSources', () => {
60 it('finds the static import the SFC compiler emits for a public img src', () => {
61 const compiled = `import _imports_0 from '/logo.png'\nexport default {}\n`
62 const sources = extractImportSources(compiled, 'slides.md__slidev_1.md')
63 expect(sources.map(s => s.value)).toContain('/logo.png')
64 })
65 })
66 })
67
67 lines TYPESCRIPT