Refactor: 重构cli (#238)
* refactor: 重构shared/utils * fix: 修复shared/utils类型错误 * refactor: 重构cli
This commit is contained in:
parent
b319be37ef
commit
8cf6d4adaa
|
@ -8,10 +8,11 @@ import Handlebars from 'handlebars'
|
|||
let RegCache = {}
|
||||
let HandlebarsCompile
|
||||
|
||||
const replaceDelimiters = function (str, sourceReg, escape) {
|
||||
const replaceDelimiters = function (str, sourceReg, escape?: boolean) {
|
||||
let regex = RegCache[sourceReg] || (RegCache[sourceReg] = new RegExp(sourceReg, 'g'))
|
||||
let match
|
||||
|
||||
// eslint-disable-next-line no-cond-assign
|
||||
while ((match = regex.exec(str))) {
|
||||
let prefix = str.slice(0, match.index)
|
||||
let inner = (escape ? '\\' : '') + '{{' + match[1] + '}}'
|
||||
|
@ -23,31 +24,34 @@ const replaceDelimiters = function (str, sourceReg, escape) {
|
|||
return str
|
||||
}
|
||||
|
||||
Handlebars.setDelimiter = function (delimiters) {
|
||||
if (delimiters[0].slice(-1) !== '=') {
|
||||
delimiters[0] += '(?!=)'
|
||||
}
|
||||
|
||||
let source = delimiters[0] + '([\\s\\S]+?)' + delimiters[1]
|
||||
|
||||
if (!HandlebarsCompile) {
|
||||
HandlebarsCompile = Handlebars.compile
|
||||
}
|
||||
|
||||
Handlebars.compile = function (str) {
|
||||
let args = [].slice.call(arguments)
|
||||
|
||||
if (typeof str === 'string') {
|
||||
if (delimiters[0] !== '{{' && delimiters[1] !== '}}') {
|
||||
args[0] = replaceDelimiters(args[0], '{{([\\s\\S]+?)}}', true)
|
||||
}
|
||||
|
||||
args[0] = replaceDelimiters(args[0], source)
|
||||
Object.defineProperty(Handlebars, 'setDelimiter', {
|
||||
value(delimiters: string[]) {
|
||||
if (delimiters[0].slice(-1) !== '=') {
|
||||
delimiters[0] += '(?!=)'
|
||||
}
|
||||
|
||||
return HandlebarsCompile.apply(Handlebars, args)
|
||||
let source = delimiters[0] + '([\\s\\S]+?)' + delimiters[1]
|
||||
|
||||
if (!HandlebarsCompile) {
|
||||
HandlebarsCompile = Handlebars.compile
|
||||
}
|
||||
|
||||
Handlebars.compile = function (str) {
|
||||
// eslint-disable-next-line prefer-rest-params
|
||||
let args = [].slice.call(arguments)
|
||||
|
||||
if (typeof str === 'string') {
|
||||
if (delimiters[0] !== '{{' && delimiters[1] !== '}}') {
|
||||
args[0] = replaceDelimiters(args[0], '{{([\\s\\S]+?)}}', true)
|
||||
}
|
||||
|
||||
args[0] = replaceDelimiters(args[0], source)
|
||||
}
|
||||
|
||||
return HandlebarsCompile.apply(Handlebars, args)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* 格式化模板
|
||||
|
@ -59,8 +63,13 @@ Handlebars.setDelimiter = function (delimiters) {
|
|||
* @param {Object} delimiter
|
||||
* @returns {String}
|
||||
*/
|
||||
export default function ({ delimiter, template, options, data }) {
|
||||
delimiter && Handlebars.setDelimiter(delimiter)
|
||||
|
||||
return Handlebars.compile(template, options)(data)
|
||||
export default function ({ delimiter, template, options, data }: {
|
||||
delimiter?: string[]
|
||||
template: string
|
||||
options?: CompileOptions
|
||||
data: any
|
||||
}) {
|
||||
delimiter && (Handlebars as typeof Handlebars & { setDelimiter: (delimiter: string[]) => any }).setDelimiter(delimiter)
|
||||
const compile = Handlebars.compile(template, options)
|
||||
return compile(data)
|
||||
}
|
||||
|
|
|
@ -5,21 +5,21 @@
|
|||
* yarn create:ui img-preview -single 输出纯净模板(没有 pc 等模板/单层组件)
|
||||
* yarn create:ui img-preview -mobile 创建纯移动组件
|
||||
*/
|
||||
const path = require('path')
|
||||
const fs = require('fs-extra')
|
||||
const semver = require('semver')
|
||||
const utils = require('./utils')
|
||||
const { createModuleMapping } = require('./module-utils')
|
||||
const handlebarsRender = require('./handlebars.render')
|
||||
import path from 'path'
|
||||
import fs from 'fs-extra'
|
||||
import semver from 'semver'
|
||||
import * as utils from '../../shared/utils'
|
||||
import { createModuleMapping } from '../../shared/module-utils'
|
||||
import handlebarsRender from '../build/handlebars.render'
|
||||
|
||||
const args = utils.getInputCmd()
|
||||
|
||||
if (args.length > 0) {
|
||||
const commands = []
|
||||
const components = []
|
||||
const templateDir = utils.pathJoin('../template/component')
|
||||
const componetDir = utils.pathJoin('../../packages/vue/components')
|
||||
const { version } = fs.readJSONSync(utils.pathJoin('../../packages/vue/package.json'))
|
||||
const commands: string[] = []
|
||||
const components: string[] = []
|
||||
const templateDir = utils.pathJoin('../../public/template/component')
|
||||
const componetDir = utils.pathJoin('../../../../packages/vue/src')
|
||||
const { version } = fs.readJSONSync(utils.pathJoin('../../../../packages/vue/package.json'))
|
||||
|
||||
args.forEach((item) => {
|
||||
if (item.indexOf('-') === 0) {
|
||||
|
|
|
@ -47,7 +47,7 @@ export interface Module {
|
|||
* @param {Boolean} isSort 是否需要排序
|
||||
* @returns 模块对象
|
||||
*/
|
||||
const getAllModules = (isSort) => {
|
||||
const getAllModules = (isSort: boolean) => {
|
||||
return getSortModules({ filterIntercept: () => true, isSort })
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ const getAllModules = (isSort) => {
|
|||
* @param {String} key 根据模块对象的 Key 获取对应的值
|
||||
* @returns 模块对象
|
||||
*/
|
||||
const getModuleInfo = (key) => {
|
||||
const getModuleInfo = (key: string) => {
|
||||
return moduleMap[key] || {}
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,10 @@ const getModuleInfo = (key) => {
|
|||
* @param {Boolean} isOriginal 是否取原始数据
|
||||
* @param {Boolean} isSort 是否需要排序
|
||||
*/
|
||||
const getByName = ({ name, inversion = false, isOriginal = false, isSort = true }) => {
|
||||
const getByName = (
|
||||
{ name, inversion = false, isOriginal = false, isSort = true }:
|
||||
{ name: string;inversion: boolean;isOriginal: boolean;isSort: boolean }
|
||||
) => {
|
||||
const callback = (item) => {
|
||||
const result = new RegExp(`/${name}/|^vue-${name}/`).test(item.path)
|
||||
return inversion ? !result : result
|
||||
|
@ -80,7 +83,7 @@ const getByName = ({ name, inversion = false, isOriginal = false, isSort = true
|
|||
* @private
|
||||
* @param {Function} filterIntercept 搜索条件
|
||||
*/
|
||||
const getModules = (filterIntercept) => {
|
||||
const getModules = (filterIntercept: Function) => {
|
||||
let modules = {}
|
||||
|
||||
if (typeof filterIntercept === 'function') {
|
||||
|
@ -104,7 +107,7 @@ const getModules = (filterIntercept) => {
|
|||
* @param {Function} filterIntercept 搜索条件
|
||||
* @param {Boolean} isSort 是否需要排序
|
||||
*/
|
||||
const getSortModules = ({ filterIntercept, isSort = true }) => {
|
||||
const getSortModules = ({ filterIntercept, isSort = true }: { filterIntercept: Function; isSort: boolean }) => {
|
||||
let modules: Module[] = []
|
||||
let componentCount = 0
|
||||
const importName = '@opentiny/vue'
|
||||
|
@ -119,7 +122,7 @@ const getSortModules = ({ filterIntercept, isSort = true }) => {
|
|||
// 这段逻辑暂时没有用到
|
||||
const componentName = dirs.slice(1, dirs.indexOf('src'))
|
||||
// UpperName: Todo
|
||||
component.UpperName = utils.capitalizeKebabCase(componentName.pop())
|
||||
component.UpperName = utils.capitalizeKebabCase(componentName.pop() ?? '')
|
||||
|
||||
// LowerName: todo
|
||||
component.LowerName = utils.kebabCase({ str: component.UpperName })
|
||||
|
@ -331,7 +334,7 @@ const isNotArrayObject = (sortData, key, setIndex) => {
|
|||
let sortItem = {}
|
||||
|
||||
if (typeof dataItem !== 'object') {
|
||||
sortItem.__real_value = dataItem
|
||||
(sortItem as unknown as Record<string, any>).__real_value = dataItem
|
||||
} else {
|
||||
sortItem = {
|
||||
...sortData[sortKey]
|
||||
|
@ -375,11 +378,13 @@ const getComponents = (mode, isSort = true) => {
|
|||
* 获取模块项的模块
|
||||
* @param {String} componentName 组件名称(大写,例如:img-preview)
|
||||
* @param {Oject} newObj 新增对象
|
||||
* @param {Boolean} isMobile 是否为移动组件
|
||||
* @returns 模块对象
|
||||
*/
|
||||
export const addModule = ({ componentName, templateName, newObj = {}, isMobile = false }) => {
|
||||
const isEntry = templateName.endsWith('index')
|
||||
export const addModule = (
|
||||
{ componentName, templateName, newObj = {} }:
|
||||
{ componentName: string; templateName?: string; newObj?: object; isMobile: boolean }
|
||||
) => {
|
||||
const isEntry = templateName?.endsWith('index') ?? false
|
||||
return {
|
||||
path: `vue/src/${componentName}/` + (isEntry ? `${templateName}.ts` : `src/${templateName}.vue`),
|
||||
type: isEntry ? 'component' : 'template',
|
||||
|
|
|
@ -8,7 +8,7 @@ import { fileURLToPath } from 'node:url'
|
|||
import { searchForWorkspaceRoot } from 'vite'
|
||||
|
||||
const workspaceRoot = searchForWorkspaceRoot(process.cwd())
|
||||
const pathFromWorkspaceRoot = (...args) => path.resolve(workspaceRoot, ...args)
|
||||
const pathFromWorkspaceRoot = (...args: string[]) => path.resolve(workspaceRoot, ...args)
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
@ -17,7 +17,7 @@ const dirname = path.dirname(filename)
|
|||
* 根据运行上下文获取路径(运行时打包用)
|
||||
* @returns 文件绝对路径
|
||||
*/
|
||||
const resolveCwd = (...args) => {
|
||||
const resolveCwd = (...args: any[]) => {
|
||||
return path.join(process.cwd(), ...args)
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ const resolveCwd = (...args) => {
|
|||
* @param {String} posixPath 路径
|
||||
* @returns 文件绝对路径
|
||||
*/
|
||||
const assetsPath = (posixPath) => {
|
||||
const assetsPath = (posixPath: string) => {
|
||||
return path.posix.join('static', posixPath)
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ const getComponentName = () => {
|
|||
* 获取当前上下文的路径
|
||||
* @returns 文件绝对路径
|
||||
*/
|
||||
const pathJoin = (...args) => {
|
||||
const pathJoin = (...args: string[]) => {
|
||||
return path.join(dirname, ...args)
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ const getCurrentCliTool = () => {
|
|||
* 执行 node 命令
|
||||
* @param {String} cmdStr 命令字符串
|
||||
*/
|
||||
const execCmd = (cmdStr) => {
|
||||
const execCmd = (cmdStr: string) => {
|
||||
cmdStr && execSync(cmdStr, { stdio: 'inherit' })
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ const execCmd = (cmdStr) => {
|
|||
* @param {String} str 字符串
|
||||
* @returns 字符串
|
||||
*/
|
||||
const capitalize = (str) => {
|
||||
const capitalize = (str: string) => {
|
||||
return typeof str === 'string' ? str.slice(0, 1).toUpperCase() + str.slice(1) : str
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,7 @@ const capitalize = (str) => {
|
|||
* @param {String} str 字符串
|
||||
* @returns 字符串
|
||||
*/
|
||||
const capitalizeKebabCase = (str, splitChar = '-') => {
|
||||
const capitalizeKebabCase = (str: string, splitChar = '-') => {
|
||||
return typeof str === 'string' ? str.split(splitChar).map(capitalize).join('') : str
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ const capitalizeKebabCase = (str, splitChar = '-') => {
|
|||
* @param str 字符串
|
||||
* @param splitChar 分隔符
|
||||
*/
|
||||
const kebabCase = ({ str, splitChar = '-' }) => {
|
||||
const kebabCase = ({ str, splitChar = '-' }: { str: string; splitChar?: string }) => {
|
||||
if (!str || typeof str !== 'string') return str
|
||||
|
||||
return str
|
||||
|
@ -119,7 +119,7 @@ const kebabCase = ({ str, splitChar = '-' }) => {
|
|||
|
||||
if (charCod < 65 || charCod > 122) return char
|
||||
|
||||
return (charCod >= 65 && charCod) <= 90 ? (index !== 0 ? splitChar : '') + char.toLowerCase() : char
|
||||
return (charCod >= 65 && charCod <= 90) ? (index !== 0 ? splitChar : '') + char.toLowerCase() : char
|
||||
})
|
||||
.join('')
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ const kebabCase = ({ str, splitChar = '-' }) => {
|
|||
* @param {String} str 格式字符
|
||||
* @param {Object} options 格式字符
|
||||
*/
|
||||
const prettierFormat = ({ str, options = {} }) => {
|
||||
const prettierFormat = ({ str, options = {} }: { str: string; options: object }) => {
|
||||
return prettier.format(
|
||||
str,
|
||||
Object.assign(
|
||||
|
@ -156,7 +156,10 @@ const prettierFormat = ({ str, options = {} }) => {
|
|||
* @param {Function} fileFilter 文件筛选拦截函数
|
||||
* @param {Function} callback 遍历回调
|
||||
*/
|
||||
const walkFileTree = ({ dirPath, isDeep = false, fileFilter, callback }) => {
|
||||
const walkFileTree = (
|
||||
{ dirPath, isDeep = false, fileFilter, callback }:
|
||||
{ dirPath: string; isDeep: boolean; fileFilter?: Function; callback: Function }
|
||||
) => {
|
||||
if (!dirPath || typeof callback !== 'function') {
|
||||
return
|
||||
}
|
||||
|
@ -192,7 +195,7 @@ const walkFileTree = ({ dirPath, isDeep = false, fileFilter, callback }) => {
|
|||
* @param {Boolean} 是否为 vue2 环境
|
||||
* @returns 版本号
|
||||
*/
|
||||
const getVersion = ({ name, context, isVue2 }) => {
|
||||
const getVersion = ({ name, context, isVue2 }: { name: string; context: string; isVue2: boolean }) => {
|
||||
return getComponentVersion({ name, context, dir: 'node_modules', isVue2 })
|
||||
}
|
||||
|
||||
|
@ -204,8 +207,11 @@ const getVersion = ({ name, context, isVue2 }) => {
|
|||
* @param {Boolean} 是否为 vue2 环境
|
||||
* @returns 版本号
|
||||
*/
|
||||
const getComponentVersion = ({ name, context = '..', dir = 'packages', isOrigin = false, isVue2 }) => {
|
||||
let version
|
||||
const getComponentVersion = (
|
||||
{ name, context = '..', dir = 'packages', isOrigin = false, isVue2 }:
|
||||
{ name: string; context?: string; dir?: string; isOrigin?: boolean; isVue2: boolean }
|
||||
) => {
|
||||
let version: string
|
||||
const packageJSONPath = pathJoin(context, dir, name, 'package.json')
|
||||
|
||||
if (fs.existsSync(packageJSONPath)) {
|
||||
|
@ -228,7 +234,7 @@ const getComponentVersion = ({ name, context = '..', dir = 'packages', isOrigin
|
|||
* @param {Boolean} 是否为 vue2 环境
|
||||
* @returns
|
||||
*/
|
||||
const getPublichVersion = ({ version, isVue2 }) => {
|
||||
const getPublichVersion = ({ version, isVue2 }: { version: string; isVue2: boolean }) => {
|
||||
if (isVue2) {
|
||||
return version.replace(/^4/, '3').replace('?v=4', '?v=3')
|
||||
}
|
||||
|
@ -243,7 +249,7 @@ const getPublichVersion = ({ version, isVue2 }) => {
|
|||
* @param {Boolean} 是否为 vue2 环境
|
||||
* @returns 版本号
|
||||
*/
|
||||
const getPackageVersion = ({ name, isRoot = false, isVue2 = false }) => {
|
||||
const getPackageVersion = ({ name, isRoot = false, isVue2 = false }: { name: string; isRoot: boolean; isVue2: boolean }) => {
|
||||
let version = isRoot ? getopentinyVersion({ key: name }) : getComponentVersion({ name, isOrigin: true, isVue2 })
|
||||
|
||||
return getBigVersion(version)
|
||||
|
@ -259,7 +265,7 @@ const getBigVersion = (version) => {
|
|||
* @param {Boolean} 是否为 vue2 环境
|
||||
* @returns 版本号
|
||||
*/
|
||||
const getComponentOriginVersion = ({ name, isVue2 }) => {
|
||||
const getComponentOriginVersion = ({ name, isVue2 }: { name: string; isVue2: boolean }) => {
|
||||
return getComponentVersion({ name, isOrigin: true, isVue2 })
|
||||
}
|
||||
|
||||
|
@ -269,7 +275,7 @@ const getComponentOriginVersion = ({ name, isVue2 }) => {
|
|||
* @param {Boolean} 是否为 vue2 环境
|
||||
* @returns 版本号
|
||||
*/
|
||||
const getopentinyVersion = ({ key = 'version' }) => {
|
||||
const getopentinyVersion = ({ key = 'version' }: { key: string }) => {
|
||||
const packageJson = fs.readJsonSync(pathFromWorkspaceRoot('packages/vue/package.json'))
|
||||
const packageJsonOption = packageJson[key] || packageJson
|
||||
|
||||
|
@ -318,7 +324,7 @@ const getInnerDependenciesVersion = ({ isTestEnv, tag, version }) => {
|
|||
* 在控制台显示绿色提示
|
||||
* @param {String} 提示内容
|
||||
*/
|
||||
const logGreen = (str) => {
|
||||
const logGreen = (str: string) => {
|
||||
/* eslint-disable no-console */
|
||||
console.log(chalk.green('### ' + str))
|
||||
}
|
||||
|
@ -327,7 +333,7 @@ const logGreen = (str) => {
|
|||
* 在控制台显示黄色提示
|
||||
* @param {String} 提示内容
|
||||
*/
|
||||
const logYellow = (str) => {
|
||||
const logYellow = (str: string) => {
|
||||
console.log(chalk.yellow('### ' + str))
|
||||
}
|
||||
|
||||
|
@ -335,7 +341,7 @@ const logYellow = (str) => {
|
|||
* 在控制台显示青色提示
|
||||
* @param {String} 提示内容
|
||||
*/
|
||||
const logCyan = (str) => {
|
||||
const logCyan = (str: string) => {
|
||||
console.log(chalk.cyan('### ' + str))
|
||||
}
|
||||
|
||||
|
@ -343,7 +349,7 @@ const logCyan = (str) => {
|
|||
* 在控制台显示红色提示
|
||||
* @param {String} 提示内容
|
||||
*/
|
||||
const logRed = (str) => {
|
||||
const logRed = (str: string) => {
|
||||
console.log(chalk.red('### ' + str))
|
||||
}
|
||||
|
||||
|
@ -421,7 +427,7 @@ const getBuildTag = ({ version }) => {
|
|||
*
|
||||
* @return {Array<string>} filesPath
|
||||
*/
|
||||
const getFilesPath = (folderPath) => {
|
||||
const getFilesPath = (folderPath: string): Array<string> => {
|
||||
let filesPath: string[] = []
|
||||
try {
|
||||
let files = fs.readdirSync(folderPath)
|
||||
|
@ -430,6 +436,7 @@ const getFilesPath = (folderPath) => {
|
|||
let stats = fs.statSync(tempPath)
|
||||
|
||||
if (stats.isDirectory()) {
|
||||
// eslint-disable-next-line prefer-spread
|
||||
filesPath.push.apply(filesPath, getFilesPath(tempPath))
|
||||
} else {
|
||||
filesPath.push(tempPath)
|
||||
|
@ -469,7 +476,7 @@ const fragmentReplace = (filePath, regExpStr, targetStr) => {
|
|||
* @param {Array<string> | string} regExpStr
|
||||
* @param {Array<string> | string} targetStr
|
||||
*/
|
||||
const filesFragmentReplace = (folderPath, regExpStr, targetStr) => {
|
||||
const filesFragmentReplace = (folderPath, regExpStr: Array<string> | string, targetStr: Array<string> | string) => {
|
||||
let filesPath = getFilesPath(folderPath)
|
||||
|
||||
if (filesPath) {
|
||||
|
|
Loading…
Reference in New Issue