niucloud/uni-app/scripts/addon-utils.cjs
wangchen14709853322 6d9c8ff7f5 v2.0-beta-20260626
v2框架公测版测试流程请看v2.0-beta.md
2026-07-01 12:15:20 +08:00

138 lines
4.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* uni-app 插件构建公共工具
*/
const fs = require('fs')
const path = require('path')
const ROOT = path.resolve(__dirname, '..')
const ADDON_DIR = path.join(ROOT, 'src', 'addon')
const PAGES_JSON = path.join(ROOT, 'src', 'pages.json')
const BUILD_DIR = path.join(ROOT, '.build')
/** 分构建桥接层addon 页面桥接 + 组件 stub原 src/_bridge */
const BRIDGE_DIR = path.join(BUILD_DIR, 'bridges')
const BRIDGE_ADDON_ROOT = path.join(BRIDGE_DIR, 'addon')
const BRIDGE_STUB_ROOT = path.join(BRIDGE_DIR, 'component-stubs')
const SKIP_ADDON_DIRS = new Set(['components'])
function stripJsonComments(text) {
return text
.replace(/\/\*[\s\S]*?\*\//g, '')
.replace(/^(\s*)\/\/.*$/gm, '$1') // 移除行首注释(保留缩进)
.replace(/^(\s*),\s*$/gm, '$1') // 移除孤立逗号行(保留缩进)
.replace(/,\s*\/\/.*$/gm, ',') // 移除行内注释 "val", // comment → "val",
.replace(/,\s*([}\]])/g, '$1') // 移除尾部逗号
.replace(/,\s*,/g, ',') // 合并连续逗号
}
function parsePagesJson() {
const raw = stripJsonComments(fs.readFileSync(PAGES_JSON, 'utf-8'))
return JSON.parse(raw)
}
function listAddonKeys() {
if (!fs.existsSync(ADDON_DIR)) return []
return fs.readdirSync(ADDON_DIR, { withFileTypes: true })
.filter((d) => d.isDirectory() && !SKIP_ADDON_DIRS.has(d.name))
.map((d) => d.name)
.sort()
}
function walkFiles(dir, filter, base = dir) {
const out = []
if (!fs.existsSync(dir)) return out
for (const name of fs.readdirSync(dir)) {
const full = path.join(dir, name)
const stat = fs.statSync(full)
if (stat.isDirectory()) {
out.push(...walkFiles(full, filter, base))
} else if (filter(full)) {
out.push(path.relative(base, full).replace(/\\/g, '/'))
}
}
return out
}
/** 从 pages.json 解析插件分包页面 */
function scanSubPackagePages() {
const pagesJson = parsePagesJson()
const rows = []
for (const sub of pagesJson.subPackages || []) {
const root = sub.root
if (!root || !root.startsWith('addon/')) continue
const addonKey = root.split('/')[1]
if (!addonKey || SKIP_ADDON_DIRS.has(addonKey)) continue
for (const page of sub.pages || []) {
if (!page.path) continue
const importPath = `${root.replace(/^addon\//, '')}/${page.path}`
rows.push({
addonKey,
root,
path: page.path,
importPath,
fullRoute: `/${root}/${page.path}`,
vueFile: path.join(ROOT, 'src', root, `${page.path}.vue`)
})
}
}
return rows
}
/** 扫描插件 pages 目录下所有 .vue含 home_service 等多端结构) */
function scanAddonPages(key) {
const base = path.join(ADDON_DIR, key)
return walkFiles(base, (f) => f.includes(`${path.sep}pages${path.sep}`) && f.endsWith('.vue'), base)
.map((p) => p.replace(/\.vue$/, ''))
}
/**
* 扫描插件 locale
* @returns {Record<string, string[]>}
*/
function scanAddonLocale(key) {
const localeDir = path.join(ADDON_DIR, key, 'locale')
const out = {}
if (!fs.existsSync(localeDir)) return out
for (const locale of fs.readdirSync(localeDir)) {
const localePath = path.join(localeDir, locale)
if (!fs.statSync(localePath).isDirectory()) continue
out[locale] = fs.readdirSync(localePath)
.filter((f) => f.endsWith('.json'))
.map((f) => f.replace(/\.json$/, ''))
.sort()
}
return out
}
/** 扫描插件 diy 组件 */
function scanAddonDiyComponents(key) {
const diyDir = path.join(ADDON_DIR, key, 'components', 'diy')
const out = []
if (!fs.existsSync(diyDir)) return out
for (const name of fs.readdirSync(diyDir)) {
const compDir = path.join(diyDir, name)
if (!fs.statSync(compDir).isDirectory()) continue
if (fs.existsSync(path.join(compDir, 'index.vue'))) {
out.push(name)
}
}
return out.sort()
}
module.exports = {
ROOT,
ADDON_DIR,
PAGES_JSON,
BUILD_DIR,
BRIDGE_DIR,
BRIDGE_ADDON_ROOT,
BRIDGE_STUB_ROOT,
listAddonKeys,
walkFiles,
parsePagesJson,
scanSubPackagePages,
scanAddonPages,
scanAddonLocale,
scanAddonDiyComponents,
stripJsonComments
}