'use strict'; var getCommandLineArgs = require('command-line-args'); var prompts = require('prompts'); var npmNameValidate = require('validate-npm-package-name'); var download = require('download-git-repo'); var chalk = require('chalk'); var ora = require('ora'); var path = require('path'); var shelljs = require('shelljs'); var fsExtra = require('fs-extra'); var fs = require('fs'); const defaultProjectName = "vue3-components-project"; const commandLineOptions = [ // {name: "version", alias: "v", type: Boolean}, // {name: "help", alias: "h", type: Boolean}, // {name: "name", alias: "n", type: String}, // {name: "tailwind", alias: "w", type: Boolean}, // {name: "document", alias: "d", type: Boolean}, ]; const promptsOptions = [ { name: "name", type: "text", message: `project-name/npm-package-name(default: ${defaultProjectName})`, onState: (state) => { if (state.aborted) { process.nextTick(() => { process.exit(0); }); } } }, { name: "tailwind", type: "confirm", message: "add tailwindcss?", initial: true, onState: (state) => { if (state.aborted) { process.nextTick(() => { process.exit(0); }); } } }, { name: "document", type: "confirm", message: "generate document?", initial: true, onState: (state) => { if (state.aborted) { process.nextTick(() => { process.exit(0); }); } } } ]; async function getOptions() { const commandLineArgs = getCommandLineArgs(commandLineOptions, { partial: true, caseInsensitive: true }); const questions = promptsOptions.filter((promptsOptions2) => !Object.keys(commandLineArgs).includes(promptsOptions2.name)); const promptsResponse = await prompts(questions); if (promptsResponse.name === "") { promptsResponse.name = defaultProjectName; } const result = { ...commandLineArgs, ...promptsResponse }; checkOptions(result); return result; } function checkOptions(options) { const { name } = options; checkName(name); } function checkName(name) { const checkResult = npmNameValidate(name); if (!checkResult.validForNewPackages && !checkResult.validForOldPackages) { throw new Error(`\u4E0D\u6B63\u786E\u7684\u9879\u76EE\u540D\u79F0\uFF08npm\u5305\u540D\u79F0\uFF09\uFF1A"${name}", \u8BE6\u60C5\u89C1 https://docs.npmjs.com/package-name-guidelines`); } } function deleteFileLines(path, regex, encoding = "utf8") { const fileContent = fs.readFileSync(path, { encoding }); const filteredContent = fileContent.split("\n").filter((line) => typeof regex === "string" ? !line.includes(regex) : !regex.test(line)).join("\n"); fs.writeFileSync(path, filteredContent, encoding); } function replaceFileLetters(path, regex, letter, encoding = "utf8") { const fileContent = fs.readFileSync(path, { encoding }); const filteredContent = fileContent.split("\n").map((line) => line.replace(regex, letter)).join("\n"); fs.writeFileSync(path, filteredContent, encoding); } const templateRemoteUrl = "Maylisten/vue3-lib-template"; let domain = ""; let name = ""; let completeName = ""; let rootPath = ""; let packagesPath = ""; let cliPath = ""; let scriptsPath = ""; let componentsPath = ""; let playPath = ""; let docPath = ""; const setProjectInfo = (option) => { const projectName = option.name; domain = projectName.trim().split("/").at(-2) ?? ""; name = projectName.trim().split("/").at(-1); completeName = `${domain}${domain ? "/" : ""}${name}`; rootPath = path.join(process.cwd(), name); packagesPath = path.join(rootPath, "packages"); cliPath = path.join(packagesPath, "cli"); scriptsPath = path.join(rootPath, "scripts"); componentsPath = path.join(packagesPath, "components"); playPath = path.join(rootPath, "play"); docPath = path.join(rootPath, "doc"); }; const downloadCompleteTemplate = () => { const downSpinner = ora("\u6B63\u5728\u4E0B\u8F7D\u6A21\u677F...").start(); return new Promise((resolve, reject) => { download(templateRemoteUrl, name, { clone: false }, (err) => { if (err) { downSpinner.fail(); reject(err); return; } downSpinner.succeed(chalk.green("\u6A21\u677F\u4E0B\u8F7D\u6210\u529F\uFF01")); resolve(1); }); }); }; const removeCliDir = () => { shelljs.rm("-rf", cliPath); }; const removeCliPackageJsonScripts = () => { const packageJsonPaths = [path.join(rootPath, "package.json"), path.join(scriptsPath, "package.json")]; packageJsonPaths.forEach((path2) => { deleteFileLines(path2, /[Cc]li/); }); }; const removeCliScripts = () => { const scriptsPaths = ["build", "clean", "release"].map((dir) => path.join(scriptsPath, dir, "modules")); const cliFiles = scriptsPaths.map((dir) => path.join(dir, "cli.ts")); const indexFiles = scriptsPaths.map((dir) => path.join(dir, "index.ts")); cliFiles.filter((filePath) => { shelljs.rm("-rf", filePath); }); indexFiles.filter((filePath) => { deleteFileLines(filePath, /[Cc]li/); }); }; const removeCli = () => { removeCliDir(); removeCliPackageJsonScripts(); removeCliScripts(); }; const resetComponentsPackageJson = async () => { const componentsPackageJsonPath = path.join(rootPath, "./packages/components/package.json"); const json = await fsExtra.readJSON(componentsPackageJsonPath, { encoding: "utf8" }); json.name = completeName; json.version = `0.0.0`; json.keywords = []; json.description = ""; json.author = ""; json.homepage = ``; json.main = `./lib/${name}.cjs`; json.module = `./lib/${name}.js`; json.browser = `./lib/${name}.cjs`; json.exports = { ".": { "import": `./lib/${name}.js`, "require": `./lib/${name}.cjs`, "types": "./lib/index.d.ts" }, "./style.css": { "import": "./lib/style.css", "require": "./lib/style.css", "default": "./lib/style.css" } }; json.repository.url = ``; json.bugs.url = ``; await fsExtra.writeJSON(componentsPackageJsonPath, json, { spaces: 2 }); }; const resetPlayDependence = async () => { const replaceFilePaths = [path.join(playPath, "package.json"), path.join(playPath, "src/pages/DemoPage.vue")]; replaceFilePaths.forEach((filePath) => { replaceFileLetters(filePath, "@xuhan57/vue3-lib-template-components", completeName); }); }; const removeTailwind = async () => { const tailwindConfigFilename = "tailwind.config.js"; const tailwindConfigPaths = [path.join(componentsPath, tailwindConfigFilename), path.join(playPath, tailwindConfigFilename)]; tailwindConfigPaths.forEach((filePath) => { shelljs.rm("-rf", filePath); }); const postcssFilePath = path.join(rootPath, "postcss.config.mjs"); shelljs.rm("-rf", postcssFilePath); deleteFileLines(path.join(rootPath, "package.json"), "tailwindcss"); deleteFileLines(path.join(rootPath, "package.json"), "postcss"); const styleCssPaths = [path.join(componentsPath, "style.css"), path.join(playPath, "src/style.css")]; styleCssPaths.forEach((filePath) => shelljs.rm("-rf", filePath)); const entryPaths = [path.join(componentsPath, "index.ts"), path.join(playPath, "src/main.ts")]; entryPaths.forEach((filePath) => deleteFileLines(filePath, "style.css")); const tailwindDemoComponentPath = path.join(componentsPath, "src/tailwind-button"); shelljs.rm("-rf", tailwindDemoComponentPath); const componentsEntryPath = path.join(componentsPath, "src/index.ts"); deleteFileLines(componentsEntryPath, "tailwind-button"); }; const removeDoc = async () => { const deletePaths = [ path.join(docPath), ...["build", "clean", "dev"].map((dir) => path.join(scriptsPath, `${dir}/modules/doc.ts`)), path.join(rootPath, ".github") ]; deletePaths.forEach((targetPath) => shelljs.rm("-rf", targetPath)); const deleteLinePaths = [ path.join(rootPath, "package.json"), path.join(scriptsPath, "package.json"), ...["build", "clean", "dev"].map((dir) => path.join(scriptsPath, `${dir}/modules/index.ts`)) ]; deleteLinePaths.forEach((path2) => { deleteFileLines(path2, /[Dd]oc/); }); }; const shake = async (options) => { const downSpinner = ora("\u6B63\u5728\u521D\u59CB\u5316\u6A21\u677F...").start(); try { const { tailwind, document } = options; removeCli(); await resetComponentsPackageJson(); await resetPlayDependence(); if (!tailwind) { await removeTailwind(); } if (!document) { await removeDoc(); } downSpinner.succeed(chalk.green("\u6A21\u677F\u521D\u59CB\u5316\u6210\u529F\uFF01")); } catch (err) { downSpinner.fail(); throw new Error(err); } }; const downloadTemplate = async (options) => { setProjectInfo(options); await downloadCompleteTemplate(); await shake(options); }; (async function() { try { const options = await getOptions(); await downloadTemplate(options); } catch (err) { console.log(chalk.red(err)); } })();