Skip to content

Commit 1de0069

Browse files
authored
fix(build): better align server and client side filename sanitization (vuejs#1488)
1 parent 0b61665 commit 1de0069

File tree

4 files changed

+30
-5
lines changed

4 files changed

+30
-5
lines changed

src/client/app/utils.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { siteDataRef } from './data.js'
2-
import { inBrowser, EXTERNAL_URL_RE } from '../shared.js'
2+
import { inBrowser, EXTERNAL_URL_RE, sanitizeFileName } from '../shared.js'
33

44
export { inBrowser }
55

@@ -36,14 +36,18 @@ export function pathToFile(path: string): string {
3636
if (inBrowser) {
3737
const base = import.meta.env.BASE_URL
3838
pagePath =
39-
(pagePath.slice(base.length).replace(/\//g, '_') || 'index') + '.md'
39+
sanitizeFileName(
40+
pagePath.slice(base.length).replace(/\//g, '_') || 'index'
41+
) + '.md'
4042
// client production build needs to account for page hash, which is
4143
// injected directly in the page's html
4244
const pageHash = __VP_HASH_MAP__[pagePath.toLowerCase()]
4345
pagePath = `${base}assets/${pagePath}.${pageHash}.js`
4446
} else {
4547
// ssr build uses much simpler name mapping
46-
pagePath = `./${pagePath.slice(1).replace(/\//g, '_')}.md.js`
48+
pagePath = `./${sanitizeFileName(
49+
pagePath.slice(1).replace(/\//g, '_')
50+
)}.md.js`
4751
}
4852
}
4953

src/node/build/bundle.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { slash } from '../utils/slash'
77
import { SiteConfig } from '../config'
88
import { APP_PATH } from '../alias'
99
import { createVitePressPlugin } from '../plugin'
10+
import { sanitizeFileName } from '../shared'
1011
import { buildMPAClient } from './buildMPAClient'
1112

1213
export const okMark = '\x1b[32m✓\x1b[0m'
@@ -68,6 +69,7 @@ export async function bundle(
6869
// other
6970
preserveEntrySignatures: 'allow-extension',
7071
output: {
72+
sanitizeFileName,
7173
...rollupOptions?.output,
7274
...(ssr
7375
? {

src/node/build/render.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import {
1010
createTitle,
1111
notFoundPageData,
1212
mergeHead,
13-
EXTERNAL_URL_RE
13+
EXTERNAL_URL_RE,
14+
sanitizeFileName
1415
} from '../shared'
1516
import { slash } from '../utils/slash'
1617
import { SiteConfig, resolveSiteDataByRoute } from '../config'
@@ -31,7 +32,7 @@ export async function renderPage(
3132
// render page
3233
const content = await render(routePath)
3334

34-
const pageName = page.replace(/\//g, '_')
35+
const pageName = sanitizeFileName(page.replace(/\//g, '_'))
3536
// server build doesn't need hash
3637
const pageServerJsFileName = pageName + '.js'
3738
// for any initial page load, we only need the lean version of the page js

src/shared/shared.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,21 @@ function hasTag(head: HeadConfig[], tag: HeadConfig) {
161161
export function mergeHead(prev: HeadConfig[], curr: HeadConfig[]) {
162162
return [...prev.filter((tagAttrs) => !hasTag(curr, tagAttrs)), ...curr]
163163
}
164+
165+
// https://github.com/rollup/rollup/blob/fec513270c6ac350072425cc045db367656c623b/src/utils/sanitizeFileName.ts
166+
167+
const INVALID_CHAR_REGEX = /[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g
168+
const DRIVE_LETTER_REGEX = /^[a-z]:/i
169+
170+
export function sanitizeFileName(name: string): string {
171+
const match = DRIVE_LETTER_REGEX.exec(name)
172+
const driveLetter = match ? match[0] : ''
173+
174+
return (
175+
driveLetter +
176+
name
177+
.slice(driveLetter.length)
178+
.replace(INVALID_CHAR_REGEX, '_')
179+
.replace(/(^|\/)_+(?=[^/]*$)/, '$1')
180+
)
181+
}

0 commit comments

Comments
 (0)