UNPKG

@quick-game/cli

Version:

Command line interface for rapid qg development

201 lines (192 loc) 6.05 kB
"use strict"; /** * author: * time: * describtion: fs适配层 */ const { warn } = require('../../cli-shared-utils'); const fs = require('fs'); const $path = require('path'); // 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) { warn(`>>>> ${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) { warn(`>>>> ${file} replaceTo ${options.to}`); content = content.replace(regexp, options.to); fs.writeFileSync(file, content); } } } return true; }; const fsExt = { clearDir, parse, overwrite }; module.exports = { rmdirSync, replaceFiles, fsExt };