270 lines
8.8 KiB
JavaScript
270 lines
8.8 KiB
JavaScript
import { MagicString } from 'vue/compiler-sfc'
|
|
|
|
import { findNode, parseSFC } from './utils.js'
|
|
|
|
function getPageRootRefSource(sfc, enabledGlobalRef = false) {
|
|
const pageTempAttrs = sfc.template?.attrs
|
|
if (pageTempAttrs && pageTempAttrs.root) {
|
|
return `ref="${pageTempAttrs.root}"`
|
|
}
|
|
return enabledGlobalRef ? 'ref="uniUpRoot"' : ''
|
|
}
|
|
|
|
function ensureNvueNavigationBar(pageMetaSource) {
|
|
const navigationBarSource = '<navigation-bar :front-color="upThemeNavFrontColor" :background-color="upThemeNavBgColor" />'
|
|
if (!pageMetaSource) return `<page-meta>${navigationBarSource}</page-meta>`
|
|
if (pageMetaSource.indexOf('navigation-bar') > -1 || pageMetaSource.indexOf('NavigationBar') > -1) {
|
|
return pageMetaSource
|
|
}
|
|
return pageMetaSource.replace(/<page-meta([^>]*)>/i, `<page-meta$1>${navigationBarSource}`)
|
|
}
|
|
|
|
function wrapTemplate(ms, sfc, tagName, rootRefSource = '', withNvueNavigationBar = false) {
|
|
const pageTempStart = sfc.template?.loc.start.offset
|
|
const pageTempEnd = sfc.template?.loc.end.offset
|
|
|
|
let pageMetaSource = ''
|
|
const pageMetaNode = findNode(sfc, 'PageMeta')
|
|
|
|
if (pageMetaNode) {
|
|
pageMetaSource = pageMetaNode.loc.source
|
|
const metaTempStart = pageMetaNode.loc.start.offset
|
|
const metaTempEnd = pageMetaNode.loc.end.offset
|
|
ms.remove(metaTempStart, metaTempEnd)
|
|
}
|
|
|
|
if (withNvueNavigationBar) {
|
|
pageMetaSource = ensureNvueNavigationBar(pageMetaSource)
|
|
}
|
|
|
|
if (pageTempStart != null && pageTempEnd != null) {
|
|
ms.appendLeft(pageTempStart, `\n${pageMetaSource}\n<${tagName} ${rootRefSource}>`)
|
|
ms.appendRight(pageTempEnd, `\n</${tagName}>\n`)
|
|
}
|
|
}
|
|
|
|
export async function transformPage(code, enabledGlobalRef = false) {
|
|
const sfc = await parseSFC(code)
|
|
const ms = new MagicString(code)
|
|
|
|
wrapTemplate(ms, sfc, 'global-up-root', getPageRootRefSource(sfc, enabledGlobalRef))
|
|
|
|
return ms
|
|
}
|
|
|
|
function ensureOptionsComponent(ms, scriptContent) {
|
|
if (scriptContent.includes('UpNvueRoot')) return
|
|
|
|
const componentsMatch = scriptContent.match(/components\s*:\s*\{/)
|
|
if (componentsMatch) {
|
|
ms.appendLeft(componentsMatch.index + componentsMatch[0].length, ' UpNvueRoot,')
|
|
return
|
|
}
|
|
|
|
const exportDefaultMatch = scriptContent.match(/export\s+default\s+(?:defineComponent\s*\()?\s*\{/)
|
|
if (exportDefaultMatch) {
|
|
ms.appendLeft(
|
|
exportDefaultMatch.index + exportDefaultMatch[0].length,
|
|
'\n components: { UpNvueRoot },'
|
|
)
|
|
}
|
|
}
|
|
|
|
function ensureOptionsThemeMixin(ms, scriptContent) {
|
|
if (scriptContent.includes('__upNvueThemeMixin')) return
|
|
|
|
const mixinsMatch = scriptContent.match(/mixins\s*:\s*\[/)
|
|
if (mixinsMatch) {
|
|
ms.appendLeft(mixinsMatch.index + mixinsMatch[0].length, ' __upNvueThemeMixin,')
|
|
return
|
|
}
|
|
|
|
const exportDefaultMatch = scriptContent.match(/export\s+default\s+(?:defineComponent\s*\()?\s*\{/)
|
|
if (exportDefaultMatch) {
|
|
ms.appendLeft(
|
|
exportDefaultMatch.index + exportDefaultMatch[0].length,
|
|
'\n mixins: [__upNvueThemeMixin],'
|
|
)
|
|
}
|
|
}
|
|
|
|
function getScriptSetupImports(componentImportPath, runtimeImportPath) {
|
|
return `import UpNvueRoot from '${componentImportPath}'
|
|
import { computed as __upComputed, onBeforeUnmount as __upOnBeforeUnmount, onMounted as __upOnMounted, ref as __upRef } from 'vue'
|
|
import { onShow as __upOnShow } from '@dcloudio/uni-app'
|
|
import {
|
|
applyNativeThemeUI as __upApplyNativeThemeUI,
|
|
applyNativeThemeUIDeferred as __upApplyNativeThemeUIDeferred,
|
|
getThemeCardStyle as __upGetThemeCardStyle,
|
|
getThemeIsDark as __upGetThemeIsDark,
|
|
getThemePageStyle as __upGetThemePageStyle,
|
|
getThemeVar as __upThemeVar,
|
|
syncThemeRuntimeFromStorage as __upSyncThemeRuntimeFromStorage
|
|
} from '${runtimeImportPath}'
|
|
|
|
const __upThemeVersion = __upRef(0)
|
|
let __upThemeChangeHandler = null
|
|
const __upReadThemeVersion = () => Number((typeof uni !== 'undefined' && uni.$u && uni.$u.theme && uni.$u.theme.version) || 0)
|
|
const __upSyncThemeVersion = (payload = {}) => {
|
|
const version = Number(payload.version || __upReadThemeVersion() || 0)
|
|
__upThemeVersion.value = version || Number(__upThemeVersion.value || 0) + 1
|
|
}
|
|
__upOnMounted(() => {
|
|
__upSyncThemeRuntimeFromStorage()
|
|
__upSyncThemeVersion()
|
|
__upApplyNativeThemeUI()
|
|
if (typeof uni !== 'undefined' && typeof uni.$on === 'function') {
|
|
__upThemeChangeHandler = (payload = {}) => {
|
|
__upSyncThemeRuntimeFromStorage()
|
|
__upSyncThemeVersion(payload)
|
|
__upApplyNativeThemeUI()
|
|
}
|
|
uni.$on('uThemeChange', __upThemeChangeHandler)
|
|
}
|
|
})
|
|
__upOnShow(() => {
|
|
__upSyncThemeRuntimeFromStorage()
|
|
__upSyncThemeVersion()
|
|
__upApplyNativeThemeUIDeferred()
|
|
})
|
|
__upOnBeforeUnmount(() => {
|
|
if (typeof uni !== 'undefined' && typeof uni.$off === 'function' && __upThemeChangeHandler) {
|
|
uni.$off('uThemeChange', __upThemeChangeHandler)
|
|
__upThemeChangeHandler = null
|
|
}
|
|
})
|
|
const upThemeVar = (varName, fallbackColor) => {
|
|
__upThemeVersion.value
|
|
return __upThemeVar(varName, fallbackColor)
|
|
}
|
|
const upThemeCardStyle = __upComputed(() => {
|
|
__upThemeVersion.value
|
|
return __upGetThemeCardStyle()
|
|
})
|
|
const upThemePageStyle = __upComputed(() => {
|
|
__upThemeVersion.value
|
|
return __upGetThemePageStyle()
|
|
})
|
|
const upThemeIsDark = __upComputed(() => {
|
|
__upThemeVersion.value
|
|
return __upGetThemeIsDark()
|
|
})
|
|
const upThemeNavFrontColor = __upComputed(() => {
|
|
__upThemeVersion.value
|
|
return __upGetThemeIsDark() ? '#ffffff' : '#000000'
|
|
})
|
|
const upThemeNavBgColor = __upComputed(() => {
|
|
__upThemeVersion.value
|
|
return __upThemeVar('--up-navbar-bg-color', __upGetThemeIsDark() ? '#1c1c1e' : '#ffffff')
|
|
})
|
|
`
|
|
}
|
|
|
|
function getOptionsImports(componentImportPath, runtimeImportPath) {
|
|
return `import UpNvueRoot from '${componentImportPath}'
|
|
import {
|
|
applyNativeThemeUI as __upApplyNativeThemeUI,
|
|
applyNativeThemeUIDeferred as __upApplyNativeThemeUIDeferred,
|
|
getThemeCardStyle as __upGetThemeCardStyle,
|
|
getThemeIsDark as __upGetThemeIsDark,
|
|
getThemePageStyle as __upGetThemePageStyle,
|
|
getThemeVar as __upThemeVar,
|
|
syncThemeRuntimeFromStorage as __upSyncThemeRuntimeFromStorage
|
|
} from '${runtimeImportPath}'
|
|
|
|
const __upNvueThemeMixin = {
|
|
data() {
|
|
return {
|
|
__upNvueThemeVersion: 0,
|
|
__upNvueThemeChangeHandler: null
|
|
}
|
|
},
|
|
created() {
|
|
__upSyncThemeRuntimeFromStorage()
|
|
this.__upSyncNvueThemeVersion()
|
|
__upApplyNativeThemeUI()
|
|
if (typeof uni !== 'undefined' && typeof uni.$on === 'function') {
|
|
this.__upNvueThemeChangeHandler = (payload = {}) => {
|
|
__upSyncThemeRuntimeFromStorage()
|
|
this.__upSyncNvueThemeVersion(payload)
|
|
__upApplyNativeThemeUI()
|
|
}
|
|
uni.$on('uThemeChange', this.__upNvueThemeChangeHandler)
|
|
}
|
|
},
|
|
onShow() {
|
|
__upSyncThemeRuntimeFromStorage()
|
|
this.__upSyncNvueThemeVersion()
|
|
__upApplyNativeThemeUIDeferred()
|
|
},
|
|
beforeUnmount() {
|
|
if (typeof uni !== 'undefined' && typeof uni.$off === 'function' && this.__upNvueThemeChangeHandler) {
|
|
uni.$off('uThemeChange', this.__upNvueThemeChangeHandler)
|
|
this.__upNvueThemeChangeHandler = null
|
|
}
|
|
},
|
|
computed: {
|
|
upThemeCardStyle() {
|
|
this.__upNvueThemeVersion
|
|
return __upGetThemeCardStyle()
|
|
},
|
|
upThemePageStyle() {
|
|
this.__upNvueThemeVersion
|
|
return __upGetThemePageStyle()
|
|
},
|
|
upThemeIsDark() {
|
|
this.__upNvueThemeVersion
|
|
return __upGetThemeIsDark()
|
|
},
|
|
upThemeNavFrontColor() {
|
|
this.__upNvueThemeVersion
|
|
return __upGetThemeIsDark() ? '#ffffff' : '#000000'
|
|
},
|
|
upThemeNavBgColor() {
|
|
this.__upNvueThemeVersion
|
|
return __upThemeVar('--up-navbar-bg-color', __upGetThemeIsDark() ? '#1c1c1e' : '#ffffff')
|
|
}
|
|
},
|
|
methods: {
|
|
__upReadNvueThemeVersion() {
|
|
return Number((typeof uni !== 'undefined' && uni.$u && uni.$u.theme && uni.$u.theme.version) || 0)
|
|
},
|
|
__upSyncNvueThemeVersion(payload = {}) {
|
|
const version = Number(payload.version || this.__upReadNvueThemeVersion() || 0)
|
|
this.__upNvueThemeVersion = version || Number(this.__upNvueThemeVersion || 0) + 1
|
|
},
|
|
upThemeVar(varName, fallbackColor) {
|
|
this.__upNvueThemeVersion
|
|
return __upThemeVar(varName, fallbackColor)
|
|
}
|
|
}
|
|
}
|
|
`
|
|
}
|
|
|
|
export async function transformNvuePage(
|
|
code,
|
|
componentImportPath,
|
|
runtimeImportPath,
|
|
enabledGlobalRef = false
|
|
) {
|
|
const sfc = await parseSFC(code)
|
|
const ms = new MagicString(code)
|
|
|
|
wrapTemplate(ms, sfc, 'UpNvueRoot', getPageRootRefSource(sfc, enabledGlobalRef), true)
|
|
|
|
if (sfc.scriptSetup) {
|
|
ms.appendLeft(sfc.scriptSetup.loc.start.offset, getScriptSetupImports(componentImportPath, runtimeImportPath))
|
|
} else if (sfc.script) {
|
|
ms.appendLeft(sfc.script.loc.start.offset, getOptionsImports(componentImportPath, runtimeImportPath))
|
|
ensureOptionsComponent(ms, sfc.script.content)
|
|
ensureOptionsThemeMixin(ms, sfc.script.content)
|
|
} else {
|
|
ms.append(
|
|
`\n<script>\n${getOptionsImports(componentImportPath, runtimeImportPath)}export default {\n components: { UpNvueRoot },\n mixins: [__upNvueThemeMixin]\n}\n</script>\n`
|
|
)
|
|
}
|
|
|
|
return ms
|
|
}
|