From 3fd20fedb81c88c188cff22b4c03ccc2ad416d2c Mon Sep 17 00:00:00 2001 From: Divyansh Singh <40380293+brc-dd@users.noreply.github.com> Date: Thu, 13 Oct 2022 01:24:07 +0530 Subject: [PATCH] fix(build): better align server and client side filename sanitization --- src/client/app/utils.ts | 3 ++- src/node/build/bundle.ts | 2 ++ src/node/build/render.ts | 5 +++-- src/shared/shared.ts | 15 +++++++++++++++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/client/app/utils.ts b/src/client/app/utils.ts index 2bc3f28b14f..0c3c2ed101e 100644 --- a/src/client/app/utils.ts +++ b/src/client/app/utils.ts @@ -1,5 +1,5 @@ import { siteDataRef } from './data.js' -import { inBrowser, EXTERNAL_URL_RE } from '../shared.js' +import { inBrowser, EXTERNAL_URL_RE, sanitizeFileName } from '../shared.js' export { inBrowser } @@ -30,6 +30,7 @@ export function pathToFile(path: string): string { // always force re-fetch content in dev pagePath += `.md?t=${Date.now()}` } else { + pagePath = sanitizeFileName(pagePath) // in production, each .md file is built into a .md.js file following // the path conversion scheme. // /foo/bar.html -> ./foo_bar.md diff --git a/src/node/build/bundle.ts b/src/node/build/bundle.ts index 1ec51b3707c..8bab50bd541 100644 --- a/src/node/build/bundle.ts +++ b/src/node/build/bundle.ts @@ -7,6 +7,7 @@ import { slash } from '../utils/slash' import { SiteConfig } from '../config' import { APP_PATH } from '../alias' import { createVitePressPlugin } from '../plugin' +import { sanitizeFileName } from '../shared' import { buildMPAClient } from './buildMPAClient' export const okMark = '\x1b[32m✓\x1b[0m' @@ -68,6 +69,7 @@ export async function bundle( // other preserveEntrySignatures: 'allow-extension', output: { + sanitizeFileName, ...rollupOptions?.output, ...(ssr ? { diff --git a/src/node/build/render.ts b/src/node/build/render.ts index 238bb0fff45..89d94167bce 100644 --- a/src/node/build/render.ts +++ b/src/node/build/render.ts @@ -10,7 +10,8 @@ import { createTitle, notFoundPageData, mergeHead, - EXTERNAL_URL_RE + EXTERNAL_URL_RE, + sanitizeFileName } from '../shared' import { slash } from '../utils/slash' import { SiteConfig, resolveSiteDataByRoute } from '../config' @@ -31,7 +32,7 @@ export async function renderPage( // render page const content = await render(routePath) - const pageName = page.replace(/\//g, '_') + const pageName = sanitizeFileName(page.replace(/\//g, '_')) // server build doesn't need hash const pageServerJsFileName = pageName + '.js' // for any initial page load, we only need the lean version of the page js diff --git a/src/shared/shared.ts b/src/shared/shared.ts index 2459bafed1d..ce0052aae46 100644 --- a/src/shared/shared.ts +++ b/src/shared/shared.ts @@ -161,3 +161,18 @@ function hasTag(head: HeadConfig[], tag: HeadConfig) { export function mergeHead(prev: HeadConfig[], curr: HeadConfig[]) { return [...prev.filter((tagAttrs) => !hasTag(curr, tagAttrs)), ...curr] } + +// https://github.com/rollup/rollup/blob/fec513270c6ac350072425cc045db367656c623b/src/utils/sanitizeFileName.ts + +const INVALID_CHAR_REGEX = /[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g +const DRIVE_LETTER_REGEX = /^[a-z]:/i + +export function sanitizeFileName(name: string): string { + const match = DRIVE_LETTER_REGEX.exec(name) + const driveLetter = match ? match[0] : '' + + return ( + driveLetter + + name.slice(driveLetter.length).replace(INVALID_CHAR_REGEX, '_') + ) +}