Skip to content

Commit 9d9db62

Browse files
authored
fix(build): handle vite constants replacement (#419) (#888)
1 parent a2b1490 commit 9d9db62

File tree

1 file changed

+44
-28
lines changed

1 file changed

+44
-28
lines changed

src/node/markdownToVue.ts

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,7 @@ export async function createMarkdownToVueRenderFn(
3434

3535
pages = pages.map((p) => slash(p.replace(/\.md$/, '')))
3636

37-
const userDefineRegex = userDefines
38-
? new RegExp(
39-
`\\b(${Object.keys(userDefines)
40-
.map((key) => key.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'))
41-
.join('|')})`,
42-
'g'
43-
)
44-
: null
37+
const replaceRegex = genReplaceRegexp(userDefines, isBuild)
4538

4639
return async (
4740
src: string,
@@ -74,24 +67,9 @@ export async function createMarkdownToVueRenderFn(
7467
md.__path = file
7568
md.__relativePath = relativePath
7669

77-
let html = md.render(content)
70+
const html = md.render(content)
7871
const data = md.__data
7972

80-
if (isBuild) {
81-
// avoid env variables being replaced by vite
82-
html = html
83-
.replace(/\bimport\.meta/g, 'import.<wbr/>meta')
84-
.replace(/\bprocess\.env/g, 'process.<wbr/>env')
85-
86-
// also avoid replacing vite user defines
87-
if (userDefineRegex) {
88-
html = html.replace(
89-
userDefineRegex,
90-
(_) => `${_[0]}<wbr/>${_.slice(1)}`
91-
)
92-
}
93-
}
94-
9573
// validate data.links
9674
const deadLinks: string[] = []
9775
const recordDeadLink = (url: string) => {
@@ -149,8 +127,14 @@ export async function createMarkdownToVueRenderFn(
149127
}
150128

151129
const vueSrc =
152-
genPageDataCode(data.hoistedTags || [], pageData).join('\n') +
153-
`\n<template><div>${html}</div></template>`
130+
genPageDataCode(data.hoistedTags || [], pageData, replaceRegex).join(
131+
'\n'
132+
) +
133+
`\n<template><div>${replaceConstants(
134+
html,
135+
replaceRegex,
136+
vueTemplateBreaker
137+
)}</div></template>`
154138

155139
debug(`[render] ${file} in ${Date.now() - start}ms.`)
156140

@@ -171,10 +155,42 @@ const scriptSetupRE = /<\s*script[^>]*\bsetup\b[^>]*/
171155
const scriptClientRE = /<\s*script[^>]*\bclient\b[^>]*/
172156
const defaultExportRE = /((?:^|\n|;)\s*)export(\s*)default/
173157
const namedDefaultExportRE = /((?:^|\n|;)\s*)export(.+)as(\s*)default/
158+
const jsStringBreaker = '\u200b'
159+
const vueTemplateBreaker = '<wbr>'
160+
161+
function genReplaceRegexp(
162+
userDefines: Record<string, any> = {},
163+
isBuild: boolean
164+
): RegExp {
165+
// `process.env` need to be handled in both dev and build
166+
// @see https://github.com/vitejs/vite/blob/cad27ee8c00bbd5aeeb2be9bfb3eb164c1b77885/packages/vite/src/node/plugins/clientInjections.ts#L57-L64
167+
const replacements = ['process.env']
168+
if (isBuild) {
169+
replacements.push('import.meta', ...Object.keys(userDefines))
170+
}
171+
return new RegExp(
172+
`\\b(${replacements
173+
.map((key) => key.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'))
174+
.join('|')})`,
175+
'g'
176+
)
177+
}
178+
179+
/**
180+
* To avoid env variables being replaced by vite:
181+
* - insert `'\u200b'` char into those strings inside js string (page data)
182+
* - insert `<wbr>` tag into those strings inside html string (vue template)
183+
*
184+
* @see https://vitejs.dev/guide/env-and-mode.html#production-replacement
185+
*/
186+
function replaceConstants(str: string, replaceRegex: RegExp, breaker: string) {
187+
return str.replace(replaceRegex, (_) => `${_[0]}${breaker}${_.slice(1)}`)
188+
}
174189

175-
function genPageDataCode(tags: string[], data: PageData) {
190+
function genPageDataCode(tags: string[], data: PageData, replaceRegex: RegExp) {
191+
const dataJson = JSON.stringify(data)
176192
const code = `\nexport const __pageData = JSON.parse(${JSON.stringify(
177-
JSON.stringify(data)
193+
replaceConstants(dataJson, replaceRegex, jsStringBreaker)
178194
)})`
179195

180196
const existingScriptIndex = tags.findIndex((tag) => {

0 commit comments

Comments
 (0)