Skip to content

Commit

Permalink
fix(build): handle vite constants replacement (#419) (#888)
Browse files Browse the repository at this point in the history
  • Loading branch information
meteorlxy committed Jul 1, 2022
1 parent a2b1490 commit 9d9db62
Showing 1 changed file with 44 additions and 28 deletions.
72 changes: 44 additions & 28 deletions src/node/markdownToVue.ts
Expand Up @@ -34,14 +34,7 @@ export async function createMarkdownToVueRenderFn(

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

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

return async (
src: string,
Expand Down Expand Up @@ -74,24 +67,9 @@ export async function createMarkdownToVueRenderFn(
md.__path = file
md.__relativePath = relativePath

let html = md.render(content)
const html = md.render(content)
const data = md.__data

if (isBuild) {
// avoid env variables being replaced by vite
html = html
.replace(/\bimport\.meta/g, 'import.<wbr/>meta')
.replace(/\bprocess\.env/g, 'process.<wbr/>env')

// also avoid replacing vite user defines
if (userDefineRegex) {
html = html.replace(
userDefineRegex,
(_) => `${_[0]}<wbr/>${_.slice(1)}`
)
}
}

// validate data.links
const deadLinks: string[] = []
const recordDeadLink = (url: string) => {
Expand Down Expand Up @@ -149,8 +127,14 @@ export async function createMarkdownToVueRenderFn(
}

const vueSrc =
genPageDataCode(data.hoistedTags || [], pageData).join('\n') +
`\n<template><div>${html}</div></template>`
genPageDataCode(data.hoistedTags || [], pageData, replaceRegex).join(
'\n'
) +
`\n<template><div>${replaceConstants(
html,
replaceRegex,
vueTemplateBreaker
)}</div></template>`

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

Expand All @@ -171,10 +155,42 @@ const scriptSetupRE = /<\s*script[^>]*\bsetup\b[^>]*/
const scriptClientRE = /<\s*script[^>]*\bclient\b[^>]*/
const defaultExportRE = /((?:^|\n|;)\s*)export(\s*)default/
const namedDefaultExportRE = /((?:^|\n|;)\s*)export(.+)as(\s*)default/
const jsStringBreaker = '\u200b'
const vueTemplateBreaker = '<wbr>'

function genReplaceRegexp(
userDefines: Record<string, any> = {},
isBuild: boolean
): RegExp {
// `process.env` need to be handled in both dev and build
// @see https://github.com/vitejs/vite/blob/cad27ee8c00bbd5aeeb2be9bfb3eb164c1b77885/packages/vite/src/node/plugins/clientInjections.ts#L57-L64
const replacements = ['process.env']
if (isBuild) {
replacements.push('import.meta', ...Object.keys(userDefines))
}
return new RegExp(
`\\b(${replacements
.map((key) => key.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'))
.join('|')})`,
'g'
)
}

/**
* To avoid env variables being replaced by vite:
* - insert `'\u200b'` char into those strings inside js string (page data)
* - insert `<wbr>` tag into those strings inside html string (vue template)
*
* @see https://vitejs.dev/guide/env-and-mode.html#production-replacement
*/
function replaceConstants(str: string, replaceRegex: RegExp, breaker: string) {
return str.replace(replaceRegex, (_) => `${_[0]}${breaker}${_.slice(1)}`)
}

function genPageDataCode(tags: string[], data: PageData) {
function genPageDataCode(tags: string[], data: PageData, replaceRegex: RegExp) {
const dataJson = JSON.stringify(data)
const code = `\nexport const __pageData = JSON.parse(${JSON.stringify(
JSON.stringify(data)
replaceConstants(dataJson, replaceRegex, jsStringBreaker)
)})`

const existingScriptIndex = tags.findIndex((tag) => {
Expand Down

0 comments on commit 9d9db62

Please sign in to comment.