feat:转账插件
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2024-present, Skiyee (Sky)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -0,0 +1,151 @@
|
||||
import { dirname, relative, resolve } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import process from 'node:process'
|
||||
import { existsSync, mkdirSync, statSync, writeFileSync } from 'node:fs'
|
||||
|
||||
import { createFilter, normalizePath } from 'vite'
|
||||
|
||||
import { transformNvuePage, transformPage } from './page.js'
|
||||
import { rebuildUpApp, registerUpApp } from './root.js'
|
||||
import { loadPagesJson, normalizePlatformPath, toArray } from './utils.js'
|
||||
|
||||
const rootLibPath = normalizePath(dirname(fileURLToPath(import.meta.url)))
|
||||
|
||||
export default function UniUpRoot(options = {}) {
|
||||
const rootOptions = {
|
||||
enabledVirtualHost: false,
|
||||
enabledGlobalRef: false,
|
||||
rootFileName: 'App.up',
|
||||
autoCreateRootFile: true,
|
||||
excludePages: [],
|
||||
...options,
|
||||
}
|
||||
const rootFileName = String(rootOptions.rootFileName || 'App.up').replace(/\.vue$/i, '')
|
||||
|
||||
const detectProjectRoot = () => {
|
||||
const cwd = normalizePath(process.env.INIT_CWD || process.cwd())
|
||||
const envInputDir = process.env.UNI_INPUT_DIR ? normalizePath(process.env.UNI_INPUT_DIR) : ''
|
||||
const cliRootPath = normalizePath(resolve(cwd, 'src'))
|
||||
const hbuilderRootPath = cwd
|
||||
|
||||
const isPageRoot = (path) => existsSync(resolve(path, 'pages.json'))
|
||||
|
||||
if (envInputDir && isPageRoot(envInputDir)) {
|
||||
const projectType = envInputDir.endsWith('/src') ? 'cli' : 'hbuilder'
|
||||
return { rootPath: envInputDir, projectType }
|
||||
}
|
||||
|
||||
if (isPageRoot(cliRootPath)) {
|
||||
return { rootPath: cliRootPath, projectType: 'cli' }
|
||||
}
|
||||
|
||||
if (isPageRoot(hbuilderRootPath)) {
|
||||
return { rootPath: hbuilderRootPath, projectType: 'hbuilder' }
|
||||
}
|
||||
|
||||
return {
|
||||
rootPath: envInputDir || cliRootPath,
|
||||
projectType: envInputDir && !envInputDir.endsWith('/src') ? 'hbuilder' : 'cli',
|
||||
}
|
||||
}
|
||||
|
||||
const projectInfo = detectProjectRoot()
|
||||
const rootPath = normalizePath(projectInfo.rootPath)
|
||||
const appUpPath = normalizePath(resolve(rootPath, `${rootFileName}.vue`))
|
||||
const rootToastHostPath = normalizePath(resolve(rootLibPath, 'root-toast-host.vue'))
|
||||
const nvueRootPath = normalizePath(resolve(rootPath, 'uni_modules/uview-plus/libs/root/nvue-root.vue'))
|
||||
const themeRuntimePath = normalizePath(resolve(rootPath, 'uni_modules/uview-plus/libs/theme/runtime.js'))
|
||||
const pagesPath = normalizePath(resolve(rootPath, 'pages.json'))
|
||||
const excludedPaths = toArray(rootOptions.excludePages)
|
||||
.filter(Boolean)
|
||||
.map(path => normalizePath(resolve(rootPath, path)))
|
||||
|
||||
const mainFiles = [
|
||||
normalizePath(resolve(rootPath, 'main.ts')),
|
||||
normalizePath(resolve(rootPath, 'main.js')),
|
||||
]
|
||||
|
||||
const getRelativeImportPath = (fromFile, toFile) => {
|
||||
let importPath = normalizePath(relative(dirname(fromFile), toFile))
|
||||
if (!importPath.startsWith('.')) {
|
||||
importPath = `./${importPath}`
|
||||
}
|
||||
return importPath
|
||||
}
|
||||
|
||||
let pagesJson = []
|
||||
let pagesJsonMtimeMs = 0
|
||||
let hasPlatformPlugin = false
|
||||
|
||||
const ensureRootFile = () => {
|
||||
if (!rootOptions.autoCreateRootFile) return
|
||||
if (existsSync(appUpPath)) return
|
||||
|
||||
const defaultRootSfc = `<template>
|
||||
\t<UpRootView />
|
||||
</template>
|
||||
`
|
||||
|
||||
mkdirSync(dirname(appUpPath), { recursive: true })
|
||||
writeFileSync(appUpPath, defaultRootSfc, 'utf-8')
|
||||
}
|
||||
|
||||
const refreshPagesJson = () => {
|
||||
if (!existsSync(pagesPath)) return
|
||||
const mtimeMs = statSync(pagesPath).mtimeMs
|
||||
if (mtimeMs === pagesJsonMtimeMs && pagesJson.length) return
|
||||
pagesJson = loadPagesJson(pagesPath, rootPath)
|
||||
pagesJsonMtimeMs = mtimeMs
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'vite-plugin-uni-up-root',
|
||||
enforce: 'pre',
|
||||
configResolved({ plugins }) {
|
||||
hasPlatformPlugin = plugins.some(v => v.name === 'vite-plugin-uni-platform')
|
||||
},
|
||||
buildStart() {
|
||||
ensureRootFile()
|
||||
refreshPagesJson()
|
||||
},
|
||||
async transform(code, id) {
|
||||
let ms = null
|
||||
const isSfcBlock = id.includes('?')
|
||||
const cleanId = normalizePath(id.split('?')[0])
|
||||
|
||||
const filterMain = createFilter(mainFiles)
|
||||
if (filterMain(cleanId)) {
|
||||
ms = await registerUpApp(code, rootFileName, getRelativeImportPath(cleanId, rootToastHostPath))
|
||||
}
|
||||
|
||||
const filterUpRoot = createFilter(appUpPath)
|
||||
if (filterUpRoot(cleanId)) {
|
||||
ms = await rebuildUpApp(code, rootOptions.enabledVirtualHost)
|
||||
}
|
||||
|
||||
refreshPagesJson()
|
||||
const pageId = hasPlatformPlugin ? normalizePlatformPath(cleanId) : cleanId
|
||||
const filterPage = createFilter(pagesJson, excludedPaths)
|
||||
if (!isSfcBlock && filterPage(pageId)) {
|
||||
if (cleanId.endsWith('.nvue')) {
|
||||
ms = await transformNvuePage(
|
||||
code,
|
||||
getRelativeImportPath(cleanId, nvueRootPath),
|
||||
getRelativeImportPath(cleanId, themeRuntimePath),
|
||||
rootOptions.enabledGlobalRef
|
||||
)
|
||||
} else {
|
||||
ms = await transformPage(code, rootOptions.enabledGlobalRef)
|
||||
}
|
||||
}
|
||||
|
||||
if (ms) {
|
||||
return {
|
||||
code: ms.toString(),
|
||||
map: ms.generateMap({ hires: true }),
|
||||
}
|
||||
}
|
||||
return null
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<view class="up-nvue-root" :style="rootStyle">
|
||||
<slot />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { applyNativeThemeUI, getThemePageStyle, getThemeVarsForStyle, syncThemeRuntimeFromStorage } from '../theme/runtime.js'
|
||||
|
||||
export default {
|
||||
name: 'UpNvueRoot',
|
||||
data() {
|
||||
return {
|
||||
rootStyle: {
|
||||
...getThemeVarsForStyle(),
|
||||
...getThemePageStyle()
|
||||
},
|
||||
minPageHeight: '0px'
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.syncPageHeight()
|
||||
this.refreshRootStyle()
|
||||
this.themeChangeHandler = () => {
|
||||
this.refreshRootStyle()
|
||||
}
|
||||
if (typeof uni !== 'undefined' && typeof uni.$on === 'function') {
|
||||
uni.$on('uThemeChange', this.themeChangeHandler)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.refreshRootStyle()
|
||||
},
|
||||
beforeUnmount() {
|
||||
if (this.themeChangeHandler && typeof uni !== 'undefined' && typeof uni.$off === 'function') {
|
||||
uni.$off('uThemeChange', this.themeChangeHandler)
|
||||
}
|
||||
this.themeChangeHandler = null
|
||||
},
|
||||
methods: {
|
||||
syncPageHeight() {
|
||||
let windowHeight = 0
|
||||
try {
|
||||
if (typeof uni !== 'undefined' && typeof uni.getWindowInfo === 'function') {
|
||||
windowHeight = Number((uni.getWindowInfo() || {}).windowHeight || 0)
|
||||
} else if (typeof uni !== 'undefined' && typeof uni.getSystemInfoSync === 'function') {
|
||||
windowHeight = Number((uni.getSystemInfoSync() || {}).windowHeight || 0)
|
||||
}
|
||||
} catch (e) {
|
||||
windowHeight = 0
|
||||
}
|
||||
this.minPageHeight = `${windowHeight || 0}px`
|
||||
},
|
||||
refreshRootStyle() {
|
||||
syncThemeRuntimeFromStorage()
|
||||
this.rootStyle = {
|
||||
...getThemeVarsForStyle(),
|
||||
...getThemePageStyle(),
|
||||
minHeight: this.minPageHeight,
|
||||
width: '750rpx'
|
||||
}
|
||||
applyNativeThemeUI()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.up-nvue-root {
|
||||
width: 750rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,269 @@
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<up-toast ref="upGlobalToastRef" />
|
||||
<up-notify ref="upGlobalNotifyRef" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
|
||||
const upGlobalToastRef = ref(null)
|
||||
const upGlobalNotifyRef = ref(null)
|
||||
|
||||
onMounted(() => {
|
||||
if (typeof uni === 'undefined' || !uni.$u) return
|
||||
if (typeof uni.$u.setRootToastRef === 'function') {
|
||||
uni.$u.setRootToastRef(upGlobalToastRef.value)
|
||||
}
|
||||
if (typeof uni.$u.setRootNotifyRef === 'function') {
|
||||
uni.$u.setRootNotifyRef(upGlobalNotifyRef.value)
|
||||
}
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (typeof uni === 'undefined' || !uni.$u) return
|
||||
if (typeof uni.$u.setRootToastRef === 'function') {
|
||||
uni.$u.setRootToastRef(null)
|
||||
}
|
||||
if (typeof uni.$u.setRootNotifyRef === 'function') {
|
||||
uni.$u.setRootNotifyRef(null)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
@@ -0,0 +1,44 @@
|
||||
import { MagicString } from 'vue/compiler-sfc'
|
||||
|
||||
import { parseSFC } from './utils.js'
|
||||
|
||||
export async function registerUpApp(
|
||||
code,
|
||||
fileName = 'App.up',
|
||||
rootToastHostPath = './uni_modules/uview-plus/libs/root/root-toast-host.vue'
|
||||
) {
|
||||
const ms = new MagicString(code)
|
||||
|
||||
const importCode = `import GlobalUpRoot from "./${fileName}.vue";
|
||||
import UpRootToastHost from "${rootToastHostPath}";`
|
||||
const vueUseComponentCode = 'app.component("global-up-root", GlobalUpRoot);\napp.component("ku-root-toast-host", UpRootToastHost);'
|
||||
|
||||
ms.prepend(`${importCode}\n`).replace(
|
||||
/(createApp[\s\S]*?)(return\s\{\s*app)/,
|
||||
`$1${vueUseComponentCode}\n$2`,
|
||||
)
|
||||
|
||||
return ms
|
||||
}
|
||||
|
||||
export async function rebuildUpApp(code, enabledVirtualHost = false) {
|
||||
const ms = new MagicString(code)
|
||||
const rootTagNameRE = /<(UpRootView|up-root-view)(?:\s*\/>|><\/\1>)/
|
||||
ms.replace(rootTagNameRE, '<slot />\n <ku-root-toast-host />')
|
||||
|
||||
if (enabledVirtualHost) {
|
||||
const sfc = await parseSFC(code)
|
||||
if (sfc.script) {
|
||||
return ms
|
||||
}
|
||||
const langType = sfc.scriptSetup?.lang
|
||||
ms.append(`<script ${langType ? `lang="${langType}"` : ''}>
|
||||
export default {
|
||||
options: {
|
||||
virtualHost: true,
|
||||
}
|
||||
}\n</script>`)
|
||||
}
|
||||
|
||||
return ms
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// Compatibility shim for stale incremental build caches.
|
||||
// New root integration no longer depends on this file.
|
||||
|
||||
export function createGlobalUpRoot(AppRootComponent) {
|
||||
return AppRootComponent
|
||||
}
|
||||
|
||||
export default {
|
||||
createGlobalUpRoot,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
import { existsSync, readFileSync } from 'node:fs'
|
||||
import { extname, join } from 'node:path'
|
||||
import process from 'node:process'
|
||||
|
||||
import { parse as VueParser } from 'vue/compiler-sfc'
|
||||
import { normalizePath } from 'vite'
|
||||
|
||||
function stripJsonComments(jsonText) {
|
||||
return jsonText
|
||||
.replace(/\/\*[\s\S]*?\*\//g, '')
|
||||
.replace(/(^|[^:\\])\/\/.*$/gm, '$1')
|
||||
}
|
||||
|
||||
function parseJsonc(jsonText) {
|
||||
const withoutComments = stripJsonComments(jsonText)
|
||||
const withoutTrailingComma = withoutComments.replace(/,\s*([}\]])/g, '$1')
|
||||
return JSON.parse(withoutTrailingComma)
|
||||
}
|
||||
|
||||
export async function parseSFC(code) {
|
||||
try {
|
||||
return VueParser(code, { pad: 'space' }).descriptor
|
||||
} catch {
|
||||
throw new Error('[@up-root] Vue version must support compiler-sfc parser.')
|
||||
}
|
||||
}
|
||||
|
||||
const PAGE_FILE_EXTS = ['.vue', '.nvue', '.uvue']
|
||||
|
||||
export function formatPagePath(root, path) {
|
||||
const joinedPath = join(root, path)
|
||||
const pathExt = extname(joinedPath)
|
||||
|
||||
if (pathExt) {
|
||||
return normalizePath(joinedPath)
|
||||
}
|
||||
|
||||
const pageFilePath = PAGE_FILE_EXTS
|
||||
.map(fileExt => `${joinedPath}${fileExt}`)
|
||||
.find(filePath => existsSync(filePath))
|
||||
|
||||
return normalizePath(pageFilePath || `${joinedPath}.vue`)
|
||||
}
|
||||
|
||||
export function loadPagesJson(path, rootPath) {
|
||||
const pagesJsonRaw = readFileSync(path, 'utf-8')
|
||||
const parsed = parseJsonc(pagesJsonRaw) || {}
|
||||
const pages = parsed.pages || []
|
||||
const subPackages = parsed.subPackages || []
|
||||
|
||||
return [
|
||||
...pages.map((page) => formatPagePath(rootPath, page.path)),
|
||||
...subPackages
|
||||
.map(({ pages: subPages = [], root = '' }) => {
|
||||
return subPages.map((page) => formatPagePath(join(rootPath, root), page.path))
|
||||
})
|
||||
.flat(),
|
||||
]
|
||||
}
|
||||
|
||||
export function toKebabCase(str) {
|
||||
return str
|
||||
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
||||
.replace(/[_\s]+/g, '-')
|
||||
.toLowerCase()
|
||||
}
|
||||
|
||||
export function toPascalCase(str) {
|
||||
return str
|
||||
.replace(/(^\w|-+\w)/g, (match) => match.toUpperCase().replace(/-/g, ''))
|
||||
}
|
||||
|
||||
export function findNode(sfc, rawTagName) {
|
||||
const templateSource = sfc.template?.content
|
||||
if (!templateSource) return
|
||||
|
||||
let tagName = ''
|
||||
if (templateSource.includes(`<${toKebabCase(rawTagName)}`)) {
|
||||
tagName = toKebabCase(rawTagName)
|
||||
} else if (templateSource.includes(`<${toPascalCase(rawTagName)}`)) {
|
||||
tagName = toPascalCase(rawTagName)
|
||||
}
|
||||
if (!tagName) return
|
||||
|
||||
const nodeAst = sfc.template?.ast
|
||||
if (!nodeAst) return
|
||||
|
||||
const traverse = (nodes) => {
|
||||
for (const node of nodes) {
|
||||
if (node.type === 1) {
|
||||
if (node.tag === tagName) return node
|
||||
if (node.children?.length) {
|
||||
const found = traverse(node.children)
|
||||
if (found) return found
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return traverse(nodeAst.children)
|
||||
}
|
||||
|
||||
const platform = process.env.UNI_PLATFORM
|
||||
|
||||
export function normalizePlatformPath(id) {
|
||||
const idExt = extname(id)
|
||||
if (idExt !== '.vue') return id
|
||||
if (!id.includes(`.${platform}.`)) return id
|
||||
return id.replace(`.${platform}.`, '.')
|
||||
}
|
||||
|
||||
export function toArray(value) {
|
||||
if (!value) return []
|
||||
return Array.isArray(value) ? value : [value]
|
||||
}
|
||||
Reference in New Issue
Block a user