uview-plus
Version:
零云®uview-plus已兼容vue3支持多语言,120+全面的组件和便捷的工具会让您信手拈来。近期新增拖动排序、条码、图片裁剪、下拉刷新、虚拟列表、签名、Markdown等。
270 lines (244 loc) • 9.06 kB
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
}