11import { isString } from '@vuepress/shared'
2+ import { path } from '@vuepress/utils'
23import type { App , Page } from '../types/index.js'
34
45const TEMPLATE_WRAPPER_TAG_OPEN = '<div>'
@@ -10,6 +11,13 @@ const SCRIPT_TAG_CLOSE = '</script>'
1011const SCRIPT_TAG_OPEN_LANG_TS_REGEX = / < \s * s c r i p t [ ^ > ] * \b l a n g = [ ' " ] t s [ ' " ] [ ^ > ] * /
1112const SCRIPT_TAG_OPEN_LANG_TS = '<script lang="ts">'
1213
14+ const SCRIPT_DEFAULT_EXPORT_REGEX = / ( (?: ^ | \n | ; ) \s * ) e x p o r t ( \s * ) d e f a u l t /
15+ const SCRIPT_DEFAULT_NAMED_EXPORT_REGEX =
16+ / ( (?: ^ | \n | ; ) \s * ) e x p o r t ( .+ ) a s ( \s * ) d e f a u l t /
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+
1321const PAGE_DATA_CODE_VAR_NAME = '_pageData'
1422const PAGE_DATA_CODE_TEMPLATE_OUTLET = '__PAGE_DATA__'
1523const 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