@honor-minigame/cli
Version:
honor minigame pack cli
197 lines (187 loc) • 6.06 kB
JavaScript
import fs from 'fs'
import $path from 'path'
import { info } from './logger.js'
// path <string> | <Buffer> | <URL>
// options <Object>
// recursive <boolean> 如果为 true,则执行递归的目录删除。在递归模式中,如果 path 不存在则不报告错误,并且在失败时重试操作。默认值: false。
// exclude <Regexp> 符合该正则的就不删除
// 在文件(而不是目录)上使用 fs.rmdirSync() 会导致在 Windows 上出现 ENOENT 错误、在 POSIX 上出现 ENOTDIR 错误。
// 稳定性 - 递归的删除是实验性的(因此不在生产环境中使用原来的参数,2而采用更兼容的方式)
const rmdirSync = (path, options) => {
if (options && options.recursive) {
let files = []
if (fs.existsSync(path)) {
if (fs.statSync(path).isDirectory()) {
files = fs.readdirSync(path)
for (const file of files) {
const currentPath = $path.join(path, file)
if (fs.statSync(currentPath).isDirectory()) {
rmdirSync(currentPath, options)
} else {
fs.unlinkSync(currentPath)
}
}
}
}
}
return fs.rmdirSync(path)
}
// 拓展
// 将指定路径上的文件内容解析为json对象
const parse = (path) => {
const json = fs.readFileSync(path)
return JSON.parse(json) || {}
}
// 依赖 rmdirSync
const clearDir = (path, options) => {
if (fs.existsSync(path)) {
let files = []
if (fs.existsSync(path)) {
files = fs.readdirSync(path)
for (const file of files) {
const currentPath = $path.join(path, file)
if (options && options.exclude && options.exclude.test(currentPath)) {
console.log(`不删除${currentPath}`)
continue
}
if (fs.statSync(currentPath).isDirectory()) {
clearDir(currentPath, options)
let currentFiles = []
currentFiles = fs.readdirSync(currentPath)
if (!currentFiles.length) {
fs.rmdirSync(currentPath)
}
} else {
fs.unlinkSync(currentPath)
}
}
}
} else {
if (options && options.build) {
console.log(`创建目录${path}`)
fs.mkdirSync(path)
}
}
}
const overwrite = (src, dest, options) => {
if (options) {
options.basePath = $path.normalize(src)
}
overwriteFile(src, dest, options)
}
// 覆盖指定的文件或者文件夹中同名的文件和文件夹(不会删除dest中存在但是src中不存在的文件和文件夹)
const overwriteFile = (src, dest, options) => {
if (!fs.existsSync(src)) {
console.log(`不存在${src}`)
return
}
if (options && options.exclude) {
const relativePath = $path.relative(options.basePath, $path.normalize(src))
if (options.basePath !== $path.normalize(src) && options.exclude.test(relativePath)) {
console.log(`${src}-x->${dest}`)
return
}
}
if (fs.statSync(src).isDirectory()) {
if (!fs.existsSync(dest)) {
fs.mkdirSync(dest)
}
let files = []
files = fs.readdirSync(src)
for (const file of files) {
if (options && options.exclude && options.exclude.test(file)) {
continue
}
overwriteFile($path.join(src, file), $path.join(dest, file), options)
}
} else {
const directory = $path.dirname(dest)
fs.mkdirSync(directory, { recursive: true })
// 默认情况下,如果 dest 已经存在,则覆盖它。
fs.copyFileSync(src, dest)
}
return true
}
/**
* 遍历目录文件 同步方法
* @param dir
* @param files 收集的文件列表
*/
const traverseDirSync = function (dir, files, options) {
const st = fs.statSync(dir)
if (st && st.isFile()) {
files.push(dir)
return
}
const list = fs.readdirSync(dir)
list.forEach(function (file) {
const isExclude = options && options.exclude && options.exclude.test(file)
if (!isExclude) {
file = $path.join(dir, file)
const stat = fs.statSync(file)
if (stat && stat.isDirectory()) {
traverseDirSync(file, files, options)
} else {
if (options && options.include) {
if (options.include.test(file)) {
files.push(file)
}
return
}
files.push(file)
}
}
})
}
/**
* 替换文件夹中文件的字符串
* @param {*} dir 文件夹
* @param {*} options {include: 需要替换的文件, exclude: 需要排除的文件或文件夹,map: 需要替换的字符串, to:需要替换成该字符串}
* options: replaceFrom:map找到字符串,其中需要被替换的字符串,replaceTo:其中需要替换成的字符串
* @returns
*/
const replaceFiles = (dir, options) => {
if (!fs.existsSync(dir)) {
console.log(`不存在${dir}`)
return
}
if (!options || !options.map) {
console.log(`options或map、to为空,${options}`)
return
}
const files = []
traverseDirSync(dir, files, options)
// console.log(files)
for (const file of files) {
let content = fs.readFileSync(file, {
encoding: 'utf-8'
})
const regexp = new RegExp(options.map, 'g')
if (content && options.map.test(content)) {
if (options.replaceFrom && options.replaceTo) {
info(`>>>> ${file} replaceTo ${options.replaceTo}`)
var match
while ((match = regexp.exec(content)) !== null) {
var replaceStr = match[0].replace(options.replaceFrom, options.replaceTo)
content = content.replace(match[0], replaceStr)
}
fs.writeFileSync(file, content)
} else if (options.to) {
info(`>>>> ${file} replaceTo ${options.to}`)
content = content.replace(regexp, options.to)
fs.writeFileSync(file, content)
}
}
}
return true
}
const fsExt = {
clearDir,
parse,
overwrite
}
export {
rmdirSync,
replaceFiles,
fsExt
}