@tsparticles/cli 1.6.5 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,175 @@
1
+ import { camelize, capitalize, dash } from "../../utils/string-utils";
2
+ import {
3
+ copyEmptyTemplateFiles,
4
+ copyFilter,
5
+ runBuild,
6
+ runInstall,
7
+ updatePackageDistFile,
8
+ updatePackageFile,
9
+ updateWebpackFile,
10
+ } from "../../utils/template-utils";
11
+ import fs from "fs-extra";
12
+ import path from "path";
13
+
14
+ /**
15
+ * Updates the index file with the correct function name
16
+ * @param destPath - The path where the project is located
17
+ * @param name - The name of the project
18
+ */
19
+ async function updateIndexFile(destPath: string, name: string): Promise<void> {
20
+ const indexPath = path.resolve(destPath, "src", "index.ts"),
21
+ index = await fs.readFile(indexPath, "utf-8"),
22
+ capitalizedName = capitalize(capitalize(name, "-"), " "),
23
+ camelizedName = camelize(capitalizedName),
24
+ indexFunctionRegex = /loadTemplateShape/g,
25
+ replacedFuncText = index.replace(indexFunctionRegex, `load${capitalizedName}Shape`),
26
+ indexNameRegex = /"#template#"/g,
27
+ replacedNameText = replacedFuncText.replace(indexNameRegex, `"${camelizedName}"`);
28
+
29
+ await fs.writeFile(indexPath, replacedNameText);
30
+ }
31
+
32
+ /**
33
+ * Updates the shape package file
34
+ * @param destPath - The path where the project is located
35
+ * @param name - The name of the project
36
+ * @param description - The description of the project
37
+ * @param repoUrl - The repository url
38
+ */
39
+ async function updateShapePackageFile(
40
+ destPath: string,
41
+ name: string,
42
+ description: string,
43
+ repoUrl: string,
44
+ ): Promise<void> {
45
+ const camelizedName = camelize(camelize(name, "-"), " "),
46
+ dashedName = dash(camelizedName);
47
+
48
+ updatePackageFile(
49
+ destPath,
50
+ `"tsparticles-shape-${dashedName}"`,
51
+ description,
52
+ `"tsparticles.shape.${camelizedName}.min.js"`,
53
+ repoUrl,
54
+ );
55
+ }
56
+
57
+ /**
58
+ * Updates the shape package dist file
59
+ * @param destPath - The path where the project is located
60
+ * @param name - The name of the project
61
+ * @param description - The description of the project
62
+ * @param repoUrl - The repository url
63
+ */
64
+ async function updateShapePackageDistFile(
65
+ destPath: string,
66
+ name: string,
67
+ description: string,
68
+ repoUrl: string,
69
+ ): Promise<void> {
70
+ const camelizedName = camelize(camelize(name, "-"), " "),
71
+ dashedName = dash(camelizedName);
72
+
73
+ updatePackageDistFile(
74
+ destPath,
75
+ `"tsparticles-shape-${dashedName}"`,
76
+ description,
77
+ `"tsparticles.shape.${camelizedName}.min.js"`,
78
+ repoUrl,
79
+ );
80
+ }
81
+
82
+ /**
83
+ * Updates the shape readme file
84
+ * @param destPath - The path where the project is located
85
+ * @param name - The name of the project
86
+ * @param description - The description of the project
87
+ * @param repoUrl - The repository url
88
+ */
89
+ async function updateReadmeFile(destPath: string, name: string, description: string, repoUrl: string): Promise<void> {
90
+ const readmePath = path.resolve(destPath, "README.md"),
91
+ readme = await fs.readFile(readmePath, "utf-8"),
92
+ capitalizedName = capitalize(capitalize(name, "-"), " "),
93
+ camelizedName = camelize(capitalizedName),
94
+ dashedName = dash(camelizedName),
95
+ readmeDescriptionRegex = /tsParticles Template Shape/g,
96
+ replacedDescriptionText = readme.replace(readmeDescriptionRegex, `tsParticles ${description} Shape`),
97
+ readmePackageNameRegex = /tsparticles-shape-template/g,
98
+ replacedPackageNameText = replacedDescriptionText.replace(
99
+ readmePackageNameRegex,
100
+ `tsparticles-shape-${dashedName}`,
101
+ ),
102
+ readmeFileNameRegex = /tsparticles\.shape\.template(\.bundle)?\.min\.js/g,
103
+ replacedFileNameText = replacedPackageNameText.replace(
104
+ readmeFileNameRegex,
105
+ `tsparticles.shape.${camelizedName}$1.min.js`,
106
+ ),
107
+ readmeFunctionNameRegex = /loadTemplateShape/g,
108
+ replacedFunctionNameText = replacedFileNameText.replace(readmeFunctionNameRegex, `load${capitalizedName}Shape`),
109
+ readmeMiniDescriptionRegex =
110
+ /\[tsParticles]\(https:\/\/github.com\/matteobruni\/tsparticles\) additional template shape\./g,
111
+ replacedMiniDescriptionText = replacedFunctionNameText.replace(
112
+ readmeMiniDescriptionRegex,
113
+ `[tsParticles](https://github.com/matteobruni/tsparticles) additional ${name} shape.`,
114
+ ),
115
+ readmeUsageRegex = /shape\.type: "template"/g,
116
+ replacedUsageText = replacedMiniDescriptionText.replace(readmeUsageRegex, `shape.type: "${camelizedName}`),
117
+ sampleImageRegex =
118
+ /!\[demo]\(https:\/\/raw.githubusercontent.com\/tsparticles\/shape-template\/main\/images\/sample.png\)/g,
119
+ repoPath = repoUrl.includes("github.com")
120
+ ? repoUrl.substring(repoUrl.indexOf("github.com/") + 11, repoUrl.indexOf(".git"))
121
+ : "tsparticles/shape-template",
122
+ replacedText = replacedUsageText.replace(
123
+ sampleImageRegex,
124
+ `![demo](https://raw.githubusercontent.com/${repoPath}/main/images/sample.png)`,
125
+ );
126
+
127
+ await fs.writeFile(readmePath, replacedText);
128
+ }
129
+
130
+ /**
131
+ * Updates the shape webpack file
132
+ * @param destPath - The path where the project is located
133
+ * @param name - The name of the project
134
+ * @param description - The description of the project
135
+ */
136
+ async function updateShapeWebpackFile(destPath: string, name: string, description: string): Promise<void> {
137
+ await updateWebpackFile(
138
+ destPath,
139
+ camelize(capitalize(capitalize(name, "-"), " ")),
140
+ `tsParticles ${description} Shape`,
141
+ "loadParticlesShape",
142
+ );
143
+ }
144
+
145
+ /**
146
+ * Creates the shape project
147
+ * @param name - The name of the project
148
+ * @param description - The description of the project
149
+ * @param repoUrl - The repository url
150
+ * @param destPath - The path where the project is located
151
+ */
152
+ export async function createShapeTemplate(
153
+ name: string,
154
+ description: string,
155
+ repoUrl: string,
156
+ destPath: string,
157
+ ): Promise<void> {
158
+ const sourcePath = path.resolve(__dirname, "..", "..", "..", "files", "create-shape");
159
+
160
+ await copyEmptyTemplateFiles(destPath);
161
+
162
+ await fs.copy(sourcePath, destPath, {
163
+ overwrite: true,
164
+ filter: copyFilter,
165
+ });
166
+
167
+ await updateIndexFile(destPath, name);
168
+ await updateShapePackageFile(destPath, name, description, repoUrl);
169
+ await updateShapePackageDistFile(destPath, name, description, repoUrl);
170
+ await updateReadmeFile(destPath, name, description, repoUrl);
171
+ await updateShapeWebpackFile(destPath, name, description);
172
+
173
+ runInstall(destPath);
174
+ runBuild(destPath);
175
+ }
@@ -0,0 +1,65 @@
1
+ import prompts, { type PromptObject } from "prompts";
2
+ import { Command } from "commander";
3
+ import { capitalize } from "../../utils/string-utils";
4
+ import { createShapeTemplate } from "./create-shape";
5
+ import { execSync } from "child_process";
6
+ import fs from "fs-extra";
7
+ import path from "path";
8
+
9
+ const shapeCommand = new Command("shape");
10
+
11
+ shapeCommand.description("Create a new tsParticles shape");
12
+ shapeCommand.argument("<destination>", "Destination folder");
13
+ shapeCommand.action(async (destination: string) => {
14
+ let repoUrl: string;
15
+
16
+ const destPath = path.resolve(path.join(process.cwd(), destination)),
17
+ destExists = await fs.pathExists(destPath);
18
+
19
+ if (destExists) {
20
+ const destContents = await fs.readdir(destPath),
21
+ destContentsNoGit = destContents.filter(t => t !== ".git" && t !== ".gitignore");
22
+
23
+ if (destContentsNoGit.length) {
24
+ throw new Error("Destination folder already exists and is not empty");
25
+ }
26
+ }
27
+
28
+ await fs.ensureDir(destPath);
29
+
30
+ try {
31
+ repoUrl = execSync("git config --get remote.origin.url").toString();
32
+ } catch {
33
+ repoUrl = "";
34
+ }
35
+
36
+ const initialName = destPath.split(path.sep).pop(),
37
+ questions: PromptObject[] = [
38
+ {
39
+ type: "text",
40
+ name: "name",
41
+ message: "What is the name of the shape?",
42
+ validate: (value: string) => (value ? true : "The name can't be empty"),
43
+ initial: initialName,
44
+ },
45
+ {
46
+ type: "text",
47
+ name: "description",
48
+ message: "What is the description of the shape?",
49
+ validate: (value: string) => (value ? true : "The description can't be empty"),
50
+ initial: capitalize(initialName || ""),
51
+ },
52
+ {
53
+ type: "text",
54
+ name: "repositoryUrl",
55
+ message: "What is the repository URL? (optional)",
56
+ initial: repoUrl.trim(),
57
+ },
58
+ ];
59
+
60
+ const { name, description, repositoryUrl } = await prompts(questions);
61
+
62
+ createShapeTemplate(name.trim(), description.trim(), repositoryUrl.trim(), destPath);
63
+ });
64
+
65
+ export { shapeCommand };
@@ -15,7 +15,7 @@ export async function updatePackageFile(
15
15
  packageName: string,
16
16
  description: string,
17
17
  fileName: string,
18
- repoUrl: string
18
+ repoUrl: string,
19
19
  ): Promise<void> {
20
20
  const packagePath = path.resolve(destPath, "package.json"),
21
21
  packageContents = await fs.readFile(packagePath, "utf-8"),
@@ -48,7 +48,7 @@ export async function updatePackageDistFile(
48
48
  packageName: string,
49
49
  description: string,
50
50
  fileName: string,
51
- repoUrl: string
51
+ repoUrl: string,
52
52
  ): Promise<void> {
53
53
  const packagePath = path.resolve(destPath, "package.dist.json"),
54
54
  packageContents = await fs.readFile(packagePath, "utf-8"),
@@ -79,7 +79,7 @@ export async function updateWebpackFile(
79
79
  destPath: string,
80
80
  name: string,
81
81
  description: string,
82
- fnName: string
82
+ fnName: string,
83
83
  ): Promise<void> {
84
84
  const webpackPath = path.resolve(destPath, "webpack.config.js"),
85
85
  webpack = await fs.readFile(webpackPath, "utf-8"),
@@ -112,11 +112,7 @@ export async function copyEmptyTemplateFiles(destPath: string): Promise<void> {
112
112
  * @returns true if the file should be copied
113
113
  */
114
114
  export function copyFilter(src: string): boolean {
115
- if (src.endsWith("node_modules") || src.endsWith("dist")) {
116
- return false;
117
- }
118
-
119
- return true;
115
+ return !(src.endsWith("node_modules") || src.endsWith("dist"));
120
116
  }
121
117
 
122
118
  /**