Skip to content

Commit d45c678

Browse files
committed
feat: inject default export
1 parent 3cfbb6f commit d45c678

File tree

1 file changed

+56
-24
lines changed

1 file changed

+56
-24
lines changed

packages/core/src/page/renderPageToVue.ts

Lines changed: 56 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { isString } from '@vuepress/shared'
2+
import { path } from '@vuepress/utils'
23
import type { App, Page } from '../types/index.js'
34

45
const TEMPLATE_WRAPPER_TAG_OPEN = '<div>'
@@ -10,6 +11,13 @@ const SCRIPT_TAG_CLOSE = '</script>'
1011
const SCRIPT_TAG_OPEN_LANG_TS_REGEX = /<\s*script[^>]*\blang=['"]ts['"][^>]*/
1112
const SCRIPT_TAG_OPEN_LANG_TS = '<script lang="ts">'
1213

14+
const SCRIPT_DEFAULT_EXPORT_REGEX = /((?:^|\n|;)\s*)export(\s*)default/
15+
const SCRIPT_DEFAULT_NAMED_EXPORT_REGEX =
16+
/((?:^|\n|;)\s*)export(.+)as(\s*)default/
17+
18+
const SCRIPT_DEFAULT_EXPORT_CODE_TEMPLATE_OUTLET = '__SCRIPT_DEFAULT_EXPORT__'
19+
const SCRIPT_DEFAULT_EXPORT_CODE_TEMPLATE = `export default { name: ${SCRIPT_DEFAULT_EXPORT_CODE_TEMPLATE_OUTLET} }`
20+
1321
const PAGE_DATA_CODE_VAR_NAME = '_pageData'
1422
const PAGE_DATA_CODE_TEMPLATE_OUTLET = '__PAGE_DATA__'
1523
const PAGE_DATA_CODE_TEMPLATE = `export const ${PAGE_DATA_CODE_VAR_NAME} = JSON.parse(${PAGE_DATA_CODE_TEMPLATE_OUTLET})`
@@ -27,37 +35,65 @@ if (import.meta.hot) {
2735
}
2836
`
2937

30-
/**
31-
* Util to resolve the page data code
32-
*/
33-
const resolvePageDataCode = (data: Page['data']): string =>
34-
PAGE_DATA_CODE_TEMPLATE.replace(
35-
PAGE_DATA_CODE_TEMPLATE_OUTLET,
36-
JSON.stringify(JSON.stringify(data)),
37-
)
38-
3938
/**
4039
* Util to resolve the open tag of script block
4140
*/
42-
const resolveScriptTagOpen = (sfcBlocks: Page['sfcBlocks']): string => {
41+
const resolveScriptTagOpen = (page: Page): string => {
4342
// use existing script open tag
44-
if (sfcBlocks.script?.tagOpen) {
45-
return sfcBlocks.script.tagOpen
43+
if (page.sfcBlocks.script?.tagOpen) {
44+
return page.sfcBlocks.script.tagOpen
4645
}
4746
// if the setup script block is using typescript, we should use the same language for script block
48-
const isUsingTs = sfcBlocks.scriptSetup?.tagOpen.match(
47+
const isUsingTs = page.sfcBlocks.scriptSetup?.tagOpen.match(
4948
SCRIPT_TAG_OPEN_LANG_TS_REGEX,
5049
)
5150
return isUsingTs ? SCRIPT_TAG_OPEN_LANG_TS : SCRIPT_TAG_OPEN
5251
}
5352

53+
/**
54+
* Util to resolve the default export code
55+
*/
56+
const resolveDefaultExportCode = (page: Page): string =>
57+
SCRIPT_DEFAULT_EXPORT_CODE_TEMPLATE.replace(
58+
SCRIPT_DEFAULT_EXPORT_CODE_TEMPLATE_OUTLET,
59+
JSON.stringify(path.basename(page.chunkFilePath)),
60+
)
61+
62+
/**
63+
* Util to resolve the page data code
64+
*/
65+
const resolvePageDataCode = (page: Page): string =>
66+
PAGE_DATA_CODE_TEMPLATE.replace(
67+
PAGE_DATA_CODE_TEMPLATE_OUTLET,
68+
JSON.stringify(JSON.stringify(page.data)),
69+
)
70+
71+
/**
72+
* Resolve the stripped content of script block
73+
*/
74+
const resolveScriptContentStripped = (app: App, page: Page): string => {
75+
const rawContentStripped = page.sfcBlocks.script?.contentStripped
76+
const hasDefaultExport = rawContentStripped
77+
? SCRIPT_DEFAULT_EXPORT_REGEX.test(rawContentStripped) ||
78+
SCRIPT_DEFAULT_NAMED_EXPORT_REGEX.test(rawContentStripped)
79+
: false
80+
return [
81+
rawContentStripped,
82+
resolvePageDataCode(page), // inject page data code
83+
!hasDefaultExport && resolveDefaultExportCode(page), // inject default export with component name
84+
app.env.isDev && HMR_CODE, // inject HMR code in dev mode
85+
]
86+
.filter(isString)
87+
.join('\n')
88+
}
89+
5490
/**
5591
* Render page to vue component
5692
*/
57-
export const renderPageToVue = (
58-
app: App,
59-
{ data, sfcBlocks }: Page,
60-
): string => {
93+
export const renderPageToVue = (app: App, page: Page): string => {
94+
const { sfcBlocks } = page
95+
96+
// get the content of template block
6197
// #688: wrap the content of `<template>` with a `<div>` to avoid some potential issues of fragment component
6298
const templateContent =
6399
sfcBlocks.template &&
@@ -69,14 +105,10 @@ export const renderPageToVue = (
69105
sfcBlocks.template.tagClose,
70106
].join('')
71107

72-
// inject page data code and HMR code into the script content
73-
const scriptTagOpen = resolveScriptTagOpen(sfcBlocks)
74-
const pageDataCode = resolvePageDataCode(data)
108+
// get the content of script block
75109
const scriptContent = [
76-
scriptTagOpen,
77-
sfcBlocks.script?.contentStripped,
78-
pageDataCode,
79-
app.env.isDev && HMR_CODE,
110+
resolveScriptTagOpen(page),
111+
resolveScriptContentStripped(app, page),
80112
sfcBlocks.script?.tagClose ?? SCRIPT_TAG_CLOSE,
81113
]
82114
.filter(isString)

0 commit comments

Comments
 (0)