Add script
When operating component libraries, some operations are quite cumbersome, so add scripts and execute these cumbersome things through scripts.
Create script directory in the project root directory
Add components
Create component directories and fixed structures
Every time a new component is created, Xu Jian requires the following operations:
- Create component directory in packages folder
- Create a directory for component in docs\demos
- Create component directory in docs\components
- ……
By writing some scripts, I can automatically create corresponding folders and files, create files in the script directory, create add folders, and create files under the add folder.
:::demo ${componentName}/index ::: `; // Document directory const directory = (docPath, componentName); // Determine whether there is a tool path const isExists = (directory); if (isExists) { exit(`${directory}The directory already exists`); } // Document path const documentPath = (directory, "/"); (directory); // Write to the file (documentPath, documentTemplate); // tool myLog("Create component documentation", documentPath); // --------- Create component document end ------ // ------------------------------------------------------------------------------------------------------------------------------ // demo path const demoPath = (__dirname, "../../docs/demos"); // demo directory const demoDirectory = (demoPath, componentName); // Create folder (demoDirectory); // File path const demoFilePath = (demoDirectory, "/"); // demo template const demoTemplate = `<template> <div> <${capitalizeFirstLetter(componentName)} /> </div> </template> <script> export default { name: "${componentName}-demo", }; </script> <style lang="scss" scoped> </style>`; // Write to the file (demoFilePath, demoTemplate); // tool myLog("Create demo file", demoFilePath); // ------------------------------------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------------------------------------ // Component path const componentPath = (__dirname, "../../packages"); // Component Directory const componentDirectory = (componentPath, componentName); // Create folder (componentDirectory); // Component home directory const componentMainDirectory = (componentDirectory, "src"); // Create folder (componentMainDirectory); // component main file const componentMainFilePath = (componentMainDirectory, "/"); // Component content const componentTemplate = `<template> <div> <div>${componentName}</div> </div> </template> <script> export default { name: "${componentName}", }; </script> <style lang="scss" scoped> </style>`; (componentMainFilePath, componentTemplate); // Component installation files const componentInstallPath = (componentDirectory, ""); // Determine whether the import component component is in upper case or lower case let subassembly = capitalizeFirstLetter(componentName) === componentName ? lowerFirstLetter(componentName) : capitalizeFirstLetter(componentName); // Component installation const componentInstall = `import ${subassembly} from "./src/"; import { withInstall } from "../withInstall"; const ${capitalizeFirstLetter(componentName)} = withInstall(${subassembly}); export default ${capitalizeFirstLetter(componentName)};`; // Write to the file (componentInstallPath, componentInstall); myLog("Create component directory", componentDirectory); // ------------------------------------------------------------------------------------------------------------------------------};
Component introduction
:::demo ${componentName}/index ::: `; // Document directory const directory = (docPath, componentName); // Determine whether there is a tool path const isExists = (directory); if (isExists) { exit(`${directory}The directory already exists`); } // Document path const documentPath = (directory, "/"); (directory); // Write to the file (documentPath, documentTemplate); // tool myLog("Create component documentation", documentPath); // --------- Create component document end ------ // ------------------------------------------------------------------------------------------------------------------------------ // demo path const demoPath = (__dirname, "../../docs/demos"); // demo directory const demoDirectory = (demoPath, componentName); // Create folder (demoDirectory); // File path const demoFilePath = (demoDirectory, "/"); // demo template const demoTemplate = `<template> <div> <${capitalizeFirstLetter(componentName)} /> </div> </template> <script> export default { name: "${componentName}-demo", }; </script> <style lang="scss" scoped> </style>`; // Write to the file (demoFilePath, demoTemplate); // tool myLog("Create demo file", demoFilePath); // ------------------------------------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------------------------------------ // Component path const componentPath = (__dirname, "../../packages"); // Component Directory const componentDirectory = (componentPath, componentName); // Create folder (componentDirectory); // Component home directory const componentMainDirectory = (componentDirectory, "src"); // Create folder (componentMainDirectory); // component main file const componentMainFilePath = (componentMainDirectory, "/"); // Component content const componentTemplate = `<template> <div> <div>${componentName}</div> </div> </template> <script> export default { name: "${componentName}", }; </script> <style lang="scss" scoped> </style>`; (componentMainFilePath, componentTemplate); // Component installation files const componentInstallPath = (componentDirectory, ""); // Determine whether the import component component is in upper case or lower case let subassembly = capitalizeFirstLetter(componentName) === componentName ? lowerFirstLetter(componentName) : capitalizeFirstLetter(componentName); // Component installation const componentInstall = `import ${subassembly} from "./src/"; import { withInstall } from "../withInstall"; const ${capitalizeFirstLetter(componentName)} = withInstall(${subassembly}); export default ${capitalizeFirstLetter(componentName)};`; // Write to the file (componentInstallPath, componentInstall); myLog("Create component directory", componentDirectory); // ------------------------------------------------------------------------------------------------------------------------------};
Importing on
/* eslint-disable no-undef */ import { warn } from "./"; import { directoryFile } from "./add/"; // Component namelet componentName = [2]; if (!componentName) { warn("Usage: npm run add <component-name>"); (1); } // Create a directory directoryFile();
Then add the command in
"add": "node ./script/"
When creating components, you only need to enter them in the command line
npm run add Component name
Revise
The above operation creates the component directory and basic structure. When creating the component, you need to introduce the component setting type.
So create a file under the add folder and import it in
/* eslint-disable no-undef */ // Add the types in the packages\ file import fs from "fs-extra"; import { myLog, capitalizeFirstLetter } from "../"; const componentName = [2]; // Get component name from command line parameters // File path to processconst filePath = "./packages/"; // File path, please replace it with the actual path// Component path to importconst importPath = `./${()}/src/`; // Assume that the import path of the component is associated with the component name// Import componentsconst importStatement = `import ${capitalizeFirstLetter(componentName)} from "${importPath}";\n`; // Component typeconst componentDeclaration = `\t${capitalizeFirstLetter(componentName)}: typeof ${capitalizeFirstLetter(componentName)};\n`; async function addComponent() { try { let fileContent = await (filePath, "utf8"); // Check whether the import and declaration of the component already exists to avoid repeated additions if (!(importStatement) && !(componentDeclaration)) { // Add new component import in the import section // eslint-disable-next-line quotes const importSectionEndIndex = ('declare module "vue"'); fileContent = (0, importSectionEndIndex) + importStatement + (importSectionEndIndex); // Add new component declaration in GlobalComponents interface const globalComponentsStartIndex = ("{", importSectionEndIndex); const globalComponentsEndIndex = ("}", importSectionEndIndex); // Extract the exported type const globalComponentsSection = ( globalComponentsStartIndex, globalComponentsEndIndex, ); fileContent = ( globalComponentsSection, `${globalComponentsSection}${componentDeclaration}`, ); await (filePath, fileContent, "utf8"); // (`Component ${componentName} has been added successfully.`); myLog(`Component ${componentName} has been added successfully.`); } else { // (`Component ${componentName} is already present in the file.`); myLog(`Component ${componentName} is already present in the file.`); } } catch (error) { ("An error occurred:", error); } } export default addComponent;
Revise
Create a file under the add folder
/* eslint-disable no-undef */ import fs from "fs"; import { myLog, capitalizeFirstLetter } from "../"; // Specify the file path to modifyconst filePath = "./packages/"; // Component name to addconst componentName = [ - 1]; // Get from command line parameters, such as 'abc' // Make sure the component name conforms to the format of the import statementconst formattedComponentName = (/\.vue$/, "").replace(/^\//, ""); export const addIndexTs = () => { // Read file content (filePath, "utf8", (err, data) => { if (err) { (`Failed to read the file: ${err}`); return; } // Add import statement after an existing import statement (if not already exist) const importRegex = /import\s+.+?from\s+["'].*?["'];/g; let lastImportMatch; while ((lastImportMatch = (data)) !== null) { // Find the last matching import statement } const importLine = `\nimport ${capitalizeFirstLetter(formattedComponentName)} from "./${formattedComponentName}";\n`; if (!lastImportMatch || !(importLine)) { const insertPosition = lastImportMatch ? + lastImportMatch[0].length : ("const components:"); data = (0, insertPosition) + importLine + (insertPosition); } // Update component list (if not already exist) const componentsStart = "const components: { [propName: string]: Component } = {"; const componentsEnd = "};"; const componentsIndexStart = (componentsStart); const componentsIndexEnd = (componentsEnd, componentsIndexStart); if (componentsIndexStart !== -1 && componentsIndexEnd !== -1) { let componentsBlock = ( componentsIndexStart, componentsIndexEnd + , ); if (!(`${formattedComponentName}:`)) { componentsBlock = ( componentsEnd, ` ${capitalizeFirstLetter(formattedComponentName)},\n${componentsEnd}`, ); data = (0, componentsIndexStart) + componentsBlock + (componentsIndexEnd + ); } } // Update the export statement const exportStart = "export {"; const exportEnd = "};"; const exportIndexStart = (exportStart); const exportIndexEnd = (exportEnd, exportIndexStart); if (exportIndexStart !== -1 && exportIndexEnd !== -1) { let exportsBlock = (exportIndexStart, exportIndexEnd + ); if (!(`${formattedComponentName},`)) { const currentExports = exportsBlock .replace(exportStart, "") .replace(exportEnd, "") .trim() .split(",") .map(s => ()); if (currentExports[ - 1] !== "") { (capitalizeFirstLetter(formattedComponentName)); exportsBlock = `${exportStart} ${(", ")} ${exportEnd}`; } else { exportsBlock = ( exportEnd, `, ${formattedComponentName}\n${exportEnd}`, ); } data = (0, exportIndexStart) + exportsBlock + (exportIndexEnd + ); } } // Write back the file (filePath, data, "utf8", err => { if (err) { (`Failed to write to file: ${err}`); } else { myLog(`${formattedComponentName} Added to file successfully`, "packages/"); } }); }); };
Add vitePress menu
After the above operations, the components are basically added, and the sidebar of adding the documentation remains
Create in the add folder
/* eslint-disable no-undef */ import fs from "fs"; import { myLog } from "../"; const vitePressConfig = "./docs/.vitepress/"; const componentName = [2]; // Get from command line parameters, such as 'abc'const componentNameCn = [3]; // Get from command line parameters, such as 'abc' const addMenu = `{ text: "${componentNameCn || "Component Name"}", link: "/components/${componentName}/" },`; export const addVitePressConfig = () => { // Read the file (vitePressConfig, "utf8", (err, data) => { if (err) { (`Failed to read the file: ${err}`); return; } let componentsIndexStart = ("items: ["); let componentsEnd = "],"; let componentsIndexEnd = (componentsEnd, componentsIndexStart); let componentsBlock = (componentsIndexStart, componentsIndexEnd); componentsBlock = ` ${componentsBlock} ${addMenu} `; data = (0, componentsIndexStart) + componentsBlock + (componentsIndexEnd); (vitePressConfig, data, "utf8", err => { if (err) { (`Failed to write to file: ${err}`); } else { myLog( `${componentNameCn || "Component"}${componentName} Successfully added to the Document Library menu`, "docs/.vitepress/", ); } }); }); };
use
After completing the component creation script above, we don’t need to modify some files ourselves. Just write component content, demo, and component documents directly.
Use in the command line
npm run add table sheet
- table is the folder name of the component and the name of the component
- Form Used to display and display menus in documentation
Whether it is capital or lowercase, the first letter of the component name needs to be used as capital letters.
Submit git
Every time you need to submit code, you need to execute git add . , git commit -m "" , git push
Write a script to help us submit code automatically
Installation dependencies
npm i child_process -D
Create under the script folder
/* eslint-disable no-undef */ // The exec function in the imported child_process module is used to execute shell commands in child processesimport { exec } from "child_process"; import { finish, warn } from "./"; // This asynchronous function takes a command string as a parameter, executes the command using exec, and wraps it into a promise. If the command executes successfully, it parses the Promise and returns an object containing stdout and stderr; if the execution fails, it rejects the Promise and returns an error.const runCommand = command => new Promise((resolve, reject) => { exec(command, (error, stdout, stderr) => { if (error) { (`exec error: ${error}`); reject(error); } else { resolve({ stdout, stderr }); } }); }); // This is an asynchronous function that performs a series of Git operations: adding all changes, committing based on provided or default commit information, and then pushing changes. It accepts an optional commitMessage parameter with the default value of "Add Component".const main = async (commitMessage = "Add components") => { try { await runCommand("git add ."); const messageOption = commitMessage ? `-m "${commitMessage}"` : ""; await runCommand(`git commit ${messageOption}`); await runCommand("git push"); finish("Code submission successful"); } catch (error) { warn("Error during Git operations:", error); } }; // Read submission information from command line parameters// Read information from the process's command line parameters. is an array containing the path to the executable file that starts the script, the path to the script file, and all subsequent parameters. slice(2) is used to remove the first two elements and only retain the actual parameters passed in. If parameters are provided, they are concatenated into a string as commit information, otherwise the default "new component" is used.const args = (2); const commitMessage = > 0 ? (" ") : "Add components"; // Call the main function and use .catch to handle any errors thrown during execution, and the error message will be printed to the console.main(commitMessage).catch();
Package and deployment
Packaging and deploying the project is divided into the following steps:
- Change version number
- Package npm
- Switch the image source
- Log in to the mirror source
- deploy
Show off your creation and npmPush folders under the script folder
Change version number
Create under npmPush folder
// Modify the version number import fs from "fs"; import path from "path"; import { fileURLToPath } from "url"; import { finish, warn } from "../"; export const bumpVersion = () => { // Current file path const __filename = fileURLToPath(); // Directory of the current file const __dirname = (__filename); // Read the file const packagePath = (__dirname, "../../"); const packageJson = ((packagePath, "utf8")); // Original version const originally = ; // Decompose the version number into an array, which is easy to operate const versionParts = (".").map(Number); // Example: Incremental patch version number versionParts[2]++; // Assume that it is the form of the major version, minor version, patch version // Recombined version number = ("."); // Write the modified content back (packagePath, (packageJson, null, 2), "utf8"); finish(`Version update successfully: ${originally} --> ${}`, packagePath); };
Imported in script\file
import { bumpVersion } from "./npmPush/"; bumpVersion();
Packaging component library
Create under npmPush folder
/* eslint-disable no-undef */ // The exec function in the imported child_process module is used to execute shell commands in child processesimport { finish, warn, runCommand } from "../"; export const packNpm = async () => { // This is an asynchronous function that performs a series of Git operations: adding all changes, committing based on provided or default commit information, and then pushing changes. It accepts an optional commitMessage parameter with the default value of "Add Component". try { await runCommand("npm run lib"); finish("Packaging successfully"); } catch (error) { warn("An error occurred in packaging:", error); } };
Imported in script\file
import { bumpVersion } from "./npmPush/"; import { packNpm } from "./npmPush/"; const npmPush = async () => { await bumpVersion(); await packNpm(); }; npmPush();
Submit npm private library
Create under npmPush folder
/* eslint-disable no-undef */ import { finish, warn, runCommand } from "../"; export const submitNpm = async () => { try { await runCommand("npm publish"); finish("Push successful"); await runCommand("npm run push 'deploy'"); finish("Code submission successful"); } catch (error) { warn("An error occurred in packaging:", error); } };
Imported in script\file
import { bumpVersion } from "./npmPush/"; import { packNpm } from "./npmPush/"; import { submitNpm } from "./npmPush/"; const npmPush = async () => { await bumpVersion(); await packNpm(); await submitNpm(); }; npmPush();
Summarize
Let’s add these three scripts for the time being. It should be noted that you need to log in to the npm library before packaging and deployment.
Files used in the code
/* eslint-disable no-undef */ // The exec function in the imported child_process module is used to execute shell commands in child processesimport { exec } from "child_process"; import ora from "ora"; // Capitalization of the initial letterexport const capitalizeFirstLetter = str => (0).toUpperCase() + (1); // First letter to lowercaseexport const lowerFirstLetter = str => (0).toLowerCase() + (1); // Print// Printing methodexport const myLog = function (text, path) { /* var black="\033[30m black \033[0m"; var red="\033[31m red \033[0m"; var green="\033[32m green \033[0m"; var yellow="\033[33m yellow78979 \033[0m"; var blue="\033[34m blue \033[0m"; var popurse="\033[35m popurse \033[0m"; var indigo="\033[36m indigo \033[0m"; var white="\033[37m white \033[0m"; var mix="\033[37;42m white \033[0m"; (black, red, green, yellow, blue, popurse, white);*/ let popurse = "\x1b[32m Prompt \x1b[0m"; (popurse); let toolPathhint = "\x1b[34m " + text + " \x1b[0m"; let toolPathPath = "\x1b[32m" + path + " \x1b[0m"; (toolPathhint, toolPathPath); }; export const warn = function (text) { /* var black="\033[30m black \033[0m"; var red="\033[31m red \033[0m"; var green="\033[32m green \033[0m"; var yellow="\033[33m yellow78979 \033[0m"; var blue="\033[34m blue \033[0m"; var popurse="\033[35m popurse \033[0m"; var indigo="\033[36m indigo \033[0m"; var white="\033[37m white \033[0m"; var mix="\033[37;42m white \033[0m"; (black, red, green, yellow, blue, popurse, white);*/ let popurse = "\x1b[31m Warning \x1b[0m"; (popurse); let toolPathhint = "\x1b[31m " + text + " \x1b[0m"; (toolPathhint); }; /** * * @param {string} text Output Print */ export const finish = function (text) { /* var black="\033[30m black \033[0m"; var red="\033[31m red \033[0m"; var green="\033[32m green \033[0m"; var yellow="\033[33m yellow78979 \033[0m"; var blue="\033[34m blue \033[0m"; var popurse="\033[35m popurse \033[0m"; var indigo="\033[36m indigo \033[0m"; var white="\033[37m white \033[0m"; var mix="\033[37;42m white \033[0m"; (black, red, green, yellow, blue, popurse, white);*/ let popurse = "\x1b[35m Completed \x1b[0m"; (popurse); let toolPathhint = "\x1b[36m " + text + " \x1b[0m"; (toolPathhint); }; /** * * @param {String} command The command that needs to be executed * @returns */ export const runCommand = command => { let isGit = ("git") === -1; let spinner; if (isGit) { spinner = ora(`Start execution: "${command}"`).start(); } return new Promise((resolve, reject) => { exec(command, (error, stdout, stderr) => { myLog("\nCurrent Command:", command); if (error) { if (isGit) { (`exec error: ${error}`); } reject("error", error); } else { if (isGit) { // Standard output and standard errors of the print command, if necessary if (command === "npm run lib") { // (`Command "${command}" was executed successfully.`); (`Command output: ${stdout}`); (`stderr: ${stderr}`); finish("Packaging Completed"); } else if (command === "git push") { finish("Code submission successful"); } else if (command === "npm publish") { finish("Npm library push successfully"); } (`Order "${command}" Execution successfully.`); resolve(true); // The command is successfully executed, solving Promise } else { resolve({ stdout, stderr }); } } }); }); };
This is the end of this article about the implementation example of the vue3 component library adding scripts. For more related contents of vue3 component library adding scripts, please search for my previous articles or continue browsing the following related articles. I hope everyone will support me in the future!