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