@dcloudio/uni-cli-shared
Version:
uni-cli-shared
256 lines (229 loc) • 7.13 kB
JavaScript
const path = require('path')
const fs = require('fs')
const hash = require('hash-sum')
const crypto = require('crypto')
const escapeStringRegexp = require('escape-string-regexp')
const escapeGlob = require('glob-escape')
const webpack = require('webpack')
const uniI18n = require('@dcloudio/uni-cli-i18n')
const isWin = /^win/.test(process.platform)
const normalizePath = path => (isWin ? path.replace(/\\/g, '/') : path)
let aboutPkg
try {
aboutPkg = require(path.resolve(__dirname, '../../../../../about/package.json'))
} catch (e) {}
const isInHBuilderX = !!aboutPkg
const isInHBuilderXAlpha = !!(isInHBuilderX && aboutPkg.alpha)
function getCLIContext () {
var context = path.resolve(__dirname, '../../../../')
// const isInHBuilderX = fs.existsSync(path.resolve(context, 'bin/uniapp-cli.js'))
if (isInHBuilderX) {
return context
}
const pnpmFind = __dirname.match(/.+?[/\\].pnpm[/\\]/)
if (pnpmFind) {
const pnpm = pnpmFind[0]
context = path.resolve(pnpm, '../../')
}
const isInCLI = fs.existsSync(path.resolve(context, './src'))
if (isInCLI) {
return context
}
return process.cwd()
}
function removeExt (str, ext) {
if (ext) {
const reg = new RegExp(ext.replace(/\./, '\\.') + '$')
return normalizePath(str.replace(reg, ''))
}
return normalizePath(str.replace(/\.\w+$/g, ''))
}
function hashify (filepath) {
const relativePath = removeExt(path.relative(process.env.UNI_INPUT_DIR, filepath))
return hash(relativePath)
}
function md5 (str) {
const hash = crypto.createHash('md5')
hash.update(str)
return hash.digest('hex')
}
function cached (fn) {
const cache = Object.create(null)
return function cachedFn (str) {
const hit = cache[str]
return hit || (cache[str] = fn(str))
}
}
const camelizeRE = /-(\w)/g
const camelize = cached((str) => {
return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '')
})
function capitalize (str) {
return str.charAt(0).toUpperCase() + str.slice(1)
}
const hyphenateRE = /\B([A-Z])/g
const hyphenate = cached((str) => {
return str.replace(hyphenateRE, '-$1').toLowerCase()
})
const REGEX_PX = /(:|\s|\(|\/)[+-]?\d+(\.\d+)?u?px/g
const REGEX_UPX = /(:|\s|\(|\/)[+-]?\d+(\.\d+)?upx/g
function convertStaticStyle (styleStr) {
if (typeof styleStr === 'string') {
let matches = styleStr.match(REGEX_UPX)
if (matches && matches.length) {
matches.forEach(function (match) {
styleStr = styleStr.replace(match, match.substr(0, match.length - 3) + 'rpx')
})
}
// TODO 不应该再支持 px 转 rpx
if (process.UNI_TRANSFORM_PX) { // 需要转换 px
matches = styleStr.match(REGEX_PX)
if (matches && matches.length) {
matches.forEach(function (match) {
styleStr = styleStr.replace(match, match.substr(0, match.length - 2) + 'rpx')
})
}
}
}
return styleStr
}
function hasModule (name) {
try {
return !!require.resolve(name)
} catch (e) {}
return false
}
const NODE_MODULES_REGEX = /(\.\.\/)?node_modules/g
function normalizeNodeModules (str) {
str = normalizePath(str).replace(NODE_MODULES_REGEX, 'node-modules')
// HBuilderX 内置模块路径转换
str = str.replace(/.*\/plugins\/uniapp-cli\/node[-_]modules/, 'node-modules')
if (process.env.UNI_PLATFORM === 'mp-alipay') {
str = str.replace('node-modules/@', 'node-modules/npm-scope-')
}
return str
}
const _hasOwnProperty = Object.prototype.hasOwnProperty
/**
* pathToRegexp
* @param {string} pathString
* @param {{start:?boolean,end:?boolean,global:?boolean}?} options
* @returns {RegExp}
*/
function pathToRegexp (pathString, options = {}) {
return new RegExp((options.start ? '^' : '') + escapeStringRegexp(pathString) + (options.end ? '$' : ''), 'i' + (options.global ? 'g' : ''))
}
/**
* pathToGlob
* @param {string} pathString
* @param {string} glob
* @param {{windows:?boolean,escape:?boolean}?} options
* @returns {string}
*/
function pathToGlob (pathString, glob, options = {}) {
const isWindows = 'windows' in options ? options.windows : /^win/.test(process.platform)
const useEscape = options.escape
const str = isWindows ? pathString.replace(/\\/g, '/') : pathString
let safeStr = escapeGlob(str)
if (isWindows || !useEscape) {
safeStr = safeStr.replace(/\\(.)/g, '[$1]')
}
return path.posix.join(safeStr, glob)
}
/**
* 字节跳动小程序可以配置 ext:// 开头的插件页面模板,如 ext://microapp-trade-plugin/order-confirm
* @param pagePath
* @returns
*/
function isNormalPage (pagePath) {
return !pagePath.startsWith('ext://')
}
function createSource (content) {
return webpack.version[0] > 4 ? new webpack.sources.RawSource(content) : {
size () {
return Buffer.byteLength(content, 'utf8')
},
source () {
return content
}
}
}
function deleteAsset (compilation, name) {
if ('deleteAsset' in compilation) {
compilation.deleteAsset(name)
} else {
delete compilation.assets[name]
}
}
/**
* cli 项目增加运行方式提示 https://ask.dcloud.net.cn/question/165071
* App 端存在多次编译问题(vue 2 nvue 3),故做防抖处理
* @param delay
* @returns
*/
let runPromptTimer = null
function showRunPrompt (delay = 300) {
if (runPromptTimer) {
clearTimeout(runPromptTimer)
}
runPromptTimer = setTimeout(() => {
const { runByHBuilderX } = require('./platform')
if (!runByHBuilderX) {
const chalk = require('chalk')
const outputDir = path.relative(
process.env.UNI_CLI_CONTEXT,
process.env.UNI_OUTPUT_DIR
)
const platform = process.env.UNI_PLATFORM.startsWith('quickapp-webview') && process.env.UNI_SUB_PLATFORM ? process.env.UNI_SUB_PLATFORM : process.env.UNI_PLATFORM
console.log(uniI18n.__('prompt.run.message', {
devtools: uniI18n.__(`prompt.run.devtools.${platform}`),
outputDir: chalk.cyan(outputDir)
}))
}
runPromptTimer = null
}, delay)
}
module.exports = {
isNormalPage,
isInHBuilderX,
isInHBuilderXAlpha,
getCLIContext,
normalizeNodeModules,
md5,
hasOwn (obj, key) {
return _hasOwnProperty.call(obj, key)
},
hasModule,
parseStyle (style = {}) {
Object.keys(style).forEach(name => {
if (global.uniPlugin.platforms.includes(name)) {
if (name === process.env.UNI_PLATFORM) {
Object.assign(style, style[name] || {})
}
delete style[name]
}
})
return style
},
hashify,
removeExt,
camelize,
capitalize,
hyphenate,
normalizePath,
convertStaticStyle,
pathToRegexp,
pathToGlob,
getComponentName: cached((str) => {
if (str.indexOf('wx-') === 0) {
return str.replace('wx-', 'weixin-')
}
return str
}),
getTemplatePath () {
return path.join(__dirname, '../template')
},
createSource,
deleteAsset,
showRunPrompt
}