@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.
- package/dist/build/build-eslint.js +1 -1
- package/dist/build/build-prettier.js +10 -10
- package/dist/create/create.js +4 -0
- package/dist/create/plugin/create-plugin.js +86 -0
- package/dist/create/plugin/plugin.js +58 -0
- package/dist/create/shape/create-shape.js +86 -0
- package/dist/create/shape/shape.js +58 -0
- package/dist/utils/template-utils.js +1 -4
- package/files/create-plugin/README.md +74 -0
- package/files/create-plugin/src/PluginInstance.ts +15 -0
- package/files/create-plugin/src/index.ts +39 -0
- package/files/create-preset/README.md +30 -26
- package/files/create-shape/README.md +75 -0
- package/files/create-shape/src/ShapeDrawer.ts +19 -0
- package/files/create-shape/src/index.ts +9 -0
- package/files/empty-project/package.json +8 -8
- package/files/empty-project/webpack.config.js +1 -1
- package/package.json +14 -15
- package/src/build/build-eslint.ts +2 -2
- package/src/build/build-prettier.ts +10 -10
- package/src/build/build.ts +2 -2
- package/src/create/create.ts +5 -0
- package/src/create/plugin/create-plugin.ts +178 -0
- package/src/create/plugin/plugin.ts +65 -0
- package/src/create/preset/create-preset.ts +11 -11
- package/src/create/shape/create-shape.ts +175 -0
- package/src/create/shape/shape.ts +65 -0
- package/src/utils/template-utils.ts +4 -8
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
[](https://particles.js.org)
|
|
2
|
+
|
|
3
|
+
# tsParticles Template Shape
|
|
4
|
+
|
|
5
|
+
[](https://www.jsdelivr.com/package/npm/tsparticles-shape-template)
|
|
6
|
+
[](https://www.npmjs.com/package/tsparticles-shape-template)
|
|
7
|
+
[](https://www.npmjs.com/package/tsparticles-shape-template) [](https://github.com/sponsors/matteobruni)
|
|
8
|
+
|
|
9
|
+
[tsParticles](https://github.com/matteobruni/tsparticles) additional template shape.
|
|
10
|
+
|
|
11
|
+
## How to use it
|
|
12
|
+
|
|
13
|
+
### CDN / Vanilla JS / jQuery
|
|
14
|
+
|
|
15
|
+
The CDN/Vanilla version JS has one required file in vanilla configuration:
|
|
16
|
+
|
|
17
|
+
Including the `tsparticles.shape.template.min.js` file will export the function to load the shape:
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
loadTemplateShape
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Usage
|
|
24
|
+
|
|
25
|
+
Once the scripts are loaded you can set up `tsParticles` and the shape like this:
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
(async () => {
|
|
29
|
+
await loadTemplateShape(tsParticles);
|
|
30
|
+
|
|
31
|
+
await tsParticles.load({
|
|
32
|
+
id: "tsparticles",
|
|
33
|
+
options: {
|
|
34
|
+
/* options */
|
|
35
|
+
/* here you can use particles.shape.type: "template" */
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
})();
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### ESM / CommonJS
|
|
42
|
+
|
|
43
|
+
This package is compatible also with ES or CommonJS modules, firstly this needs to be installed, like this:
|
|
44
|
+
|
|
45
|
+
```shell
|
|
46
|
+
$ npm install tsparticles-shape-template
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
or
|
|
50
|
+
|
|
51
|
+
```shell
|
|
52
|
+
$ yarn add tsparticles-shape-template
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Then you need to import it in the app, like this:
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
const { tsParticles } = require("tsparticles-engine");
|
|
59
|
+
const { loadTemplateShape } = require("tsparticles-shape-template");
|
|
60
|
+
|
|
61
|
+
(async () => {
|
|
62
|
+
await loadTemplateShape(tsParticles);
|
|
63
|
+
})();
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
or
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
import { tsParticles } from "tsparticles-engine";
|
|
70
|
+
import { loadTemplateShape } from "tsparticles-shape-template";
|
|
71
|
+
|
|
72
|
+
(async () => {
|
|
73
|
+
await loadTemplateShape(tsParticles);
|
|
74
|
+
})();
|
|
75
|
+
```
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { IDelta, IShapeDrawer, Particle } from "tsparticles-engine";
|
|
2
|
+
|
|
3
|
+
export class ShapeDrawer implements IShapeDrawer {
|
|
4
|
+
draw(_context: CanvasRenderingContext2D,
|
|
5
|
+
_particle: Particle,
|
|
6
|
+
_radius: number,
|
|
7
|
+
_opacity: number,
|
|
8
|
+
_delta: IDelta,
|
|
9
|
+
_pixelRatio: number): void {
|
|
10
|
+
// draw the particle using the context
|
|
11
|
+
// which is already centered in the particle position
|
|
12
|
+
// colors are already handles, just draw the shape
|
|
13
|
+
// the bounds are -radius to radius
|
|
14
|
+
// delta is the frame time difference between the last frame and this one, in ms, use it for animated shapes
|
|
15
|
+
// pixelRatio is the canvas ratio used by the tsParticles instance, you may need it for density-independent shapes
|
|
16
|
+
// the parameters have an underscore prefix because they're not used in this example
|
|
17
|
+
// the underscore prefix can be removed for used parameters, the unused ones can be removed too
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Engine } from "tsparticles-engine";
|
|
2
|
+
import { ShapeDrawer } from "./ShapeDrawer";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @param engine - the engine instance to load the shape into
|
|
6
|
+
*/
|
|
7
|
+
export async function loadTemplateShape(engine: Engine): Promise<void> {
|
|
8
|
+
await engine.addShape("#template#", new ShapeDrawer());
|
|
9
|
+
}
|
|
@@ -83,14 +83,14 @@
|
|
|
83
83
|
"prettier": "@tsparticles/prettier-config",
|
|
84
84
|
"devDependencies": {
|
|
85
85
|
"@babel/core": "^7.22.5",
|
|
86
|
-
"@tsparticles/cli": "1.
|
|
87
|
-
"@tsparticles/eslint-config": "^1.
|
|
86
|
+
"@tsparticles/cli": "1.8.0",
|
|
87
|
+
"@tsparticles/eslint-config": "^1.14.0",
|
|
88
88
|
"@tsparticles/prettier-config": "^1.10.0",
|
|
89
|
-
"@tsparticles/tsconfig": "^1.
|
|
90
|
-
"@tsparticles/webpack-plugin": "^1.
|
|
89
|
+
"@tsparticles/tsconfig": "^1.14.0",
|
|
90
|
+
"@tsparticles/webpack-plugin": "^1.16.0",
|
|
91
91
|
"@types/webpack-env": "^1.18.1",
|
|
92
|
-
"@typescript-eslint/eslint-plugin": "^5.60.
|
|
93
|
-
"@typescript-eslint/parser": "^5.60.
|
|
92
|
+
"@typescript-eslint/eslint-plugin": "^5.60.1",
|
|
93
|
+
"@typescript-eslint/parser": "^5.60.1",
|
|
94
94
|
"babel-loader": "^9.1.2",
|
|
95
95
|
"browserslist": "^4.21.9",
|
|
96
96
|
"copyfiles": "^2.4.1",
|
|
@@ -99,8 +99,8 @@
|
|
|
99
99
|
"prettier": "^2.8.8",
|
|
100
100
|
"rimraf": "^5.0.1",
|
|
101
101
|
"terser-webpack-plugin": "^5.3.9",
|
|
102
|
-
"typescript": "^5.1.
|
|
103
|
-
"webpack": "^5.
|
|
102
|
+
"typescript": "^5.1.6",
|
|
103
|
+
"webpack": "^5.88.1",
|
|
104
104
|
"webpack-bundle-analyzer": "^4.9.0",
|
|
105
105
|
"webpack-cli": "^5.1.4"
|
|
106
106
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
const { loadParticlesTemplate } = require("@tsparticles/webpack-plugin"),
|
|
2
2
|
version = require("./package.json").version;
|
|
3
3
|
|
|
4
|
-
module.exports = loadParticlesTemplate("empty", "Empty", version, __dirname);
|
|
4
|
+
module.exports = loadParticlesTemplate({ moduleName: "empty", templateName: "Empty", version, dir: __dirname });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsparticles/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bin": {
|
|
6
6
|
"tsparticles-cli": "dist/cli.js"
|
|
@@ -10,32 +10,31 @@
|
|
|
10
10
|
},
|
|
11
11
|
"prettier": "@tsparticles/prettier-config",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@tsparticles/eslint-config": "^1.
|
|
14
|
-
"@tsparticles/prettier-config": "^1.
|
|
15
|
-
"@tsparticles/tsconfig": "^1.
|
|
16
|
-
"@tsparticles/webpack-plugin": "^1.
|
|
17
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
18
|
-
"@typescript-eslint/parser": "^5.
|
|
13
|
+
"@tsparticles/eslint-config": "^1.15.0",
|
|
14
|
+
"@tsparticles/prettier-config": "^1.11.0",
|
|
15
|
+
"@tsparticles/tsconfig": "^1.14.0",
|
|
16
|
+
"@tsparticles/webpack-plugin": "^1.17.1",
|
|
17
|
+
"@typescript-eslint/eslint-plugin": "^5.61.0",
|
|
18
|
+
"@typescript-eslint/parser": "^5.61.0",
|
|
19
19
|
"commander": "^11.0.0",
|
|
20
|
-
"eslint": "^8.
|
|
20
|
+
"eslint": "^8.44.0",
|
|
21
21
|
"eslint-config-prettier": "^8.8.0",
|
|
22
|
-
"eslint-plugin-jsdoc": "^46.
|
|
22
|
+
"eslint-plugin-jsdoc": "^46.4.3",
|
|
23
23
|
"eslint-plugin-tsdoc": "^0.2.17",
|
|
24
24
|
"fs-extra": "^11.1.1",
|
|
25
25
|
"klaw": "^4.1.0",
|
|
26
|
-
"path-scurry": "^1.
|
|
27
|
-
"prettier": "^
|
|
26
|
+
"path-scurry": "^1.10.0",
|
|
27
|
+
"prettier": "^3.0.0",
|
|
28
28
|
"prompts": "^2.4.2",
|
|
29
29
|
"rimraf": "^5.0.1",
|
|
30
|
-
"typescript": "^5.1.
|
|
31
|
-
"webpack": "^5.
|
|
30
|
+
"typescript": "^5.1.6",
|
|
31
|
+
"webpack": "^5.88.1"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/eslint": "^8.40.2",
|
|
35
35
|
"@types/fs-extra": "^11.0.1",
|
|
36
36
|
"@types/klaw": "^3.0.3",
|
|
37
|
-
"@types/node": "^20.3.
|
|
38
|
-
"@types/prettier": "^2.7.3",
|
|
37
|
+
"@types/node": "^20.3.2",
|
|
39
38
|
"@types/prompts": "^2.4.4"
|
|
40
39
|
},
|
|
41
40
|
"description": "tsParticles CLI",
|
|
@@ -7,7 +7,7 @@ import { ESLint } from "eslint";
|
|
|
7
7
|
export async function lint(ci: boolean): Promise<boolean> {
|
|
8
8
|
console.log("ESLint - started on src");
|
|
9
9
|
|
|
10
|
-
let res
|
|
10
|
+
let res: boolean;
|
|
11
11
|
|
|
12
12
|
try {
|
|
13
13
|
const eslint = new ESLint({
|
|
@@ -28,7 +28,7 @@ export async function lint(ci: boolean): Promise<boolean> {
|
|
|
28
28
|
|
|
29
29
|
if (errors.length > 0) {
|
|
30
30
|
const messages = errors.map(t =>
|
|
31
|
-
t.messages.map(m => `${t.filePath} (${m.line},${m.column}): ${m.message}`).join("\n")
|
|
31
|
+
t.messages.map(m => `${t.filePath} (${m.line},${m.column}): ${m.message}`).join("\n"),
|
|
32
32
|
);
|
|
33
33
|
|
|
34
34
|
throw new Error(messages.join("\n"));
|
|
@@ -12,7 +12,7 @@ import prettier from "prettier";
|
|
|
12
12
|
export async function prettifySrc(basePath: string, srcPath: string, ci: boolean): Promise<boolean> {
|
|
13
13
|
console.log("Prettier - started on src");
|
|
14
14
|
|
|
15
|
-
let res
|
|
15
|
+
let res: boolean;
|
|
16
16
|
|
|
17
17
|
try {
|
|
18
18
|
for await (const file of klaw(srcPath)) {
|
|
@@ -29,11 +29,11 @@ export async function prettifySrc(basePath: string, srcPath: string, ci: boolean
|
|
|
29
29
|
options.tabWidth = 4;
|
|
30
30
|
|
|
31
31
|
if (ci) {
|
|
32
|
-
if (!prettier.check(contents, options)) {
|
|
32
|
+
if (!(await prettier.check(contents, options))) {
|
|
33
33
|
throw new Error(`${file.path} is not formatted correctly`);
|
|
34
34
|
}
|
|
35
35
|
} else {
|
|
36
|
-
const formatted = prettier.format(contents, options);
|
|
36
|
+
const formatted = await prettier.format(contents, options);
|
|
37
37
|
|
|
38
38
|
await fs.writeFile(file.path, formatted, "utf8");
|
|
39
39
|
}
|
|
@@ -59,7 +59,7 @@ export async function prettifySrc(basePath: string, srcPath: string, ci: boolean
|
|
|
59
59
|
export async function prettifyReadme(basePath: string, ci: boolean): Promise<boolean> {
|
|
60
60
|
console.log("Prettier - started on README.md");
|
|
61
61
|
|
|
62
|
-
let res
|
|
62
|
+
let res: boolean;
|
|
63
63
|
|
|
64
64
|
try {
|
|
65
65
|
const contents = await fs.readFile("README.md", "utf8"),
|
|
@@ -70,11 +70,11 @@ export async function prettifyReadme(basePath: string, ci: boolean): Promise<boo
|
|
|
70
70
|
options.parser = "markdown";
|
|
71
71
|
|
|
72
72
|
if (ci) {
|
|
73
|
-
if (!prettier.check(contents, options)) {
|
|
73
|
+
if (!(await prettier.check(contents, options))) {
|
|
74
74
|
throw new Error(`README.md is not formatted correctly`);
|
|
75
75
|
}
|
|
76
76
|
} else {
|
|
77
|
-
const formatted = prettier.format(contents, options);
|
|
77
|
+
const formatted = await prettier.format(contents, options);
|
|
78
78
|
|
|
79
79
|
await fs.writeFile("README.md", formatted, "utf8");
|
|
80
80
|
}
|
|
@@ -123,11 +123,11 @@ async function prettifyTraductions(basePath: string, ci: boolean): Promise<boole
|
|
|
123
123
|
options.parser = "markdown";
|
|
124
124
|
|
|
125
125
|
if (ci) {
|
|
126
|
-
if (!prettier.check(contents, options)) {
|
|
126
|
+
if (!(await prettier.check(contents, options))) {
|
|
127
127
|
throw new Error(`${file.path} is not formatted correctly`);
|
|
128
128
|
}
|
|
129
129
|
} else {
|
|
130
|
-
const formatted = prettier.format(contents, options);
|
|
130
|
+
const formatted = await prettier.format(contents, options);
|
|
131
131
|
|
|
132
132
|
await fs.writeFile(file.path, formatted, "utf8");
|
|
133
133
|
}
|
|
@@ -178,11 +178,11 @@ async function prettifyMarkdownTypeDocFiles(basePath: string, ci: boolean): Prom
|
|
|
178
178
|
options.parser = "markdown";
|
|
179
179
|
|
|
180
180
|
if (ci) {
|
|
181
|
-
if (!prettier.check(contents, options)) {
|
|
181
|
+
if (!(await prettier.check(contents, options))) {
|
|
182
182
|
throw new Error(`${file.path} is not formatted correctly`);
|
|
183
183
|
}
|
|
184
184
|
} else {
|
|
185
|
-
const formatted = prettier.format(contents, options);
|
|
185
|
+
const formatted = await prettier.format(contents, options);
|
|
186
186
|
|
|
187
187
|
await fs.writeFile(file.path, formatted, "utf8");
|
|
188
188
|
}
|
package/src/build/build.ts
CHANGED
|
@@ -15,14 +15,14 @@ buildCommand.description("Build the library using TypeScript");
|
|
|
15
15
|
buildCommand.option(
|
|
16
16
|
"-a, --all",
|
|
17
17
|
"Do all build steps (default if no flags are specified) (same as -b -c -d -l -p -t)",
|
|
18
|
-
true
|
|
18
|
+
true,
|
|
19
19
|
);
|
|
20
20
|
buildCommand.option("-b, --bundle", "Bundle the library using Webpack", false);
|
|
21
21
|
buildCommand.option("-c, --clean", "Clean the dist folder", false);
|
|
22
22
|
buildCommand.option(
|
|
23
23
|
"--ci",
|
|
24
24
|
"Do all build steps for CI, no fixing files, only checking if they are formatted correctly",
|
|
25
|
-
false
|
|
25
|
+
false,
|
|
26
26
|
);
|
|
27
27
|
buildCommand.option("-d, --dist", "Build the dist files", false);
|
|
28
28
|
buildCommand.option("-l, --lint", "Lint the source files", false);
|
package/src/create/create.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
+
import { pluginCommand } from "./plugin/plugin";
|
|
2
3
|
import { presetCommand } from "./preset/preset";
|
|
4
|
+
import { shapeCommand } from "./shape/shape";
|
|
3
5
|
|
|
4
6
|
const createCommand = new Command("create");
|
|
5
7
|
|
|
6
8
|
createCommand.description("Create a new tsParticles project");
|
|
9
|
+
|
|
10
|
+
createCommand.addCommand(pluginCommand);
|
|
7
11
|
createCommand.addCommand(presetCommand);
|
|
12
|
+
createCommand.addCommand(shapeCommand);
|
|
8
13
|
|
|
9
14
|
export { createCommand };
|
|
@@ -0,0 +1,178 @@
|
|
|
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 = /loadTemplatePlugin/g,
|
|
25
|
+
replacedFuncText = index.replace(indexFunctionRegex, `load${capitalizedName}Plugin`),
|
|
26
|
+
indexNameRegex = /"#template#"/g,
|
|
27
|
+
replacedNameText = replacedFuncText.replace(indexNameRegex, `"${camelizedName}"`);
|
|
28
|
+
|
|
29
|
+
await fs.writeFile(indexPath, replacedNameText);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Updates the plugin 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 updatePluginPackageFile(
|
|
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-plugin-${dashedName}"`,
|
|
51
|
+
description,
|
|
52
|
+
`"tsparticles.plugin.${camelizedName}.min.js"`,
|
|
53
|
+
repoUrl,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Updates the plugin 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 updatePluginPackageDistFile(
|
|
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-plugin-${dashedName}"`,
|
|
76
|
+
description,
|
|
77
|
+
`"tsparticles.plugin.${camelizedName}.min.js"`,
|
|
78
|
+
repoUrl,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Updates the plugin 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 Plugin/g,
|
|
96
|
+
replacedDescriptionText = readme.replace(readmeDescriptionRegex, `tsParticles ${description} Plugin`),
|
|
97
|
+
readmePackageNameRegex = /tsparticles-plugin-template/g,
|
|
98
|
+
replacedPackageNameText = replacedDescriptionText.replace(
|
|
99
|
+
readmePackageNameRegex,
|
|
100
|
+
`tsparticles-plugin-${dashedName}`,
|
|
101
|
+
),
|
|
102
|
+
readmeFileNameRegex = /tsparticles\.plugin\.template(\.bundle)?\.min\.js/g,
|
|
103
|
+
replacedFileNameText = replacedPackageNameText.replace(
|
|
104
|
+
readmeFileNameRegex,
|
|
105
|
+
`tsparticles.plugin.${camelizedName}$1.min.js`,
|
|
106
|
+
),
|
|
107
|
+
readmeFunctionNameRegex = /loadTemplatePlugin/g,
|
|
108
|
+
replacedFunctionNameText = replacedFileNameText.replace(
|
|
109
|
+
readmeFunctionNameRegex,
|
|
110
|
+
`load${capitalizedName}Plugin`,
|
|
111
|
+
),
|
|
112
|
+
readmeMiniDescriptionRegex =
|
|
113
|
+
/\[tsParticles]\(https:\/\/github.com\/matteobruni\/tsparticles\) additional template plugin\./g,
|
|
114
|
+
replacedMiniDescriptionText = replacedFunctionNameText.replace(
|
|
115
|
+
readmeMiniDescriptionRegex,
|
|
116
|
+
`[tsParticles](https://github.com/matteobruni/tsparticles) additional ${name} plugin.`,
|
|
117
|
+
),
|
|
118
|
+
readmeUsageRegex = /plugin\.type: "template"/g,
|
|
119
|
+
replacedUsageText = replacedMiniDescriptionText.replace(readmeUsageRegex, `plugin.type: "${camelizedName}`),
|
|
120
|
+
sampleImageRegex =
|
|
121
|
+
/!\[demo]\(https:\/\/raw.githubusercontent.com\/tsparticles\/plugin-template\/main\/images\/sample.png\)/g,
|
|
122
|
+
repoPath = repoUrl.includes("github.com")
|
|
123
|
+
? repoUrl.substring(repoUrl.indexOf("github.com/") + 11, repoUrl.indexOf(".git"))
|
|
124
|
+
: "tsparticles/plugin-template",
|
|
125
|
+
replacedText = replacedUsageText.replace(
|
|
126
|
+
sampleImageRegex,
|
|
127
|
+
``,
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
await fs.writeFile(readmePath, replacedText);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Updates the plugin webpack file
|
|
135
|
+
* @param destPath - The path where the project is located
|
|
136
|
+
* @param name - The name of the project
|
|
137
|
+
* @param description - The description of the project
|
|
138
|
+
*/
|
|
139
|
+
async function updatePluginWebpackFile(destPath: string, name: string, description: string): Promise<void> {
|
|
140
|
+
await updateWebpackFile(
|
|
141
|
+
destPath,
|
|
142
|
+
camelize(capitalize(capitalize(name, "-"), " ")),
|
|
143
|
+
`tsParticles ${description} Plugin`,
|
|
144
|
+
"loadParticlesPlugin",
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Creates the plugin project
|
|
150
|
+
* @param name - The name of the project
|
|
151
|
+
* @param description - The description of the project
|
|
152
|
+
* @param repoUrl - The repository url
|
|
153
|
+
* @param destPath - The path where the project is located
|
|
154
|
+
*/
|
|
155
|
+
export async function createPluginTemplate(
|
|
156
|
+
name: string,
|
|
157
|
+
description: string,
|
|
158
|
+
repoUrl: string,
|
|
159
|
+
destPath: string,
|
|
160
|
+
): Promise<void> {
|
|
161
|
+
const sourcePath = path.resolve(__dirname, "..", "..", "..", "files", "create-plugin");
|
|
162
|
+
|
|
163
|
+
await copyEmptyTemplateFiles(destPath);
|
|
164
|
+
|
|
165
|
+
await fs.copy(sourcePath, destPath, {
|
|
166
|
+
overwrite: true,
|
|
167
|
+
filter: copyFilter,
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
await updateIndexFile(destPath, name);
|
|
171
|
+
await updatePluginPackageFile(destPath, name, description, repoUrl);
|
|
172
|
+
await updatePluginPackageDistFile(destPath, name, description, repoUrl);
|
|
173
|
+
await updateReadmeFile(destPath, name, description, repoUrl);
|
|
174
|
+
await updatePluginWebpackFile(destPath, name, description);
|
|
175
|
+
|
|
176
|
+
runInstall(destPath);
|
|
177
|
+
runBuild(destPath);
|
|
178
|
+
}
|
|
@@ -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 { createPluginTemplate } from "./create-plugin";
|
|
5
|
+
import { execSync } from "child_process";
|
|
6
|
+
import fs from "fs-extra";
|
|
7
|
+
import path from "path";
|
|
8
|
+
|
|
9
|
+
const pluginCommand = new Command("plugin");
|
|
10
|
+
|
|
11
|
+
pluginCommand.description("Create a new tsParticles plugin");
|
|
12
|
+
pluginCommand.argument("<destination>", "Destination folder");
|
|
13
|
+
pluginCommand.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 plugin?",
|
|
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 plugin?",
|
|
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
|
+
createPluginTemplate(name.trim(), description.trim(), repositoryUrl.trim(), destPath);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
export { pluginCommand };
|
|
@@ -55,7 +55,7 @@ async function updatePresetPackageFile(
|
|
|
55
55
|
destPath: string,
|
|
56
56
|
name: string,
|
|
57
57
|
description: string,
|
|
58
|
-
repoUrl: string
|
|
58
|
+
repoUrl: string,
|
|
59
59
|
): Promise<void> {
|
|
60
60
|
const camelizedName = camelize(camelize(name, "-"), " "),
|
|
61
61
|
dashedName = dash(camelizedName);
|
|
@@ -65,7 +65,7 @@ async function updatePresetPackageFile(
|
|
|
65
65
|
`"tsparticles-preset-${dashedName}"`,
|
|
66
66
|
description,
|
|
67
67
|
`"tsparticles.preset.${camelizedName}.min.js"`,
|
|
68
|
-
repoUrl
|
|
68
|
+
repoUrl,
|
|
69
69
|
);
|
|
70
70
|
}
|
|
71
71
|
|
|
@@ -80,7 +80,7 @@ async function updatePresetPackageDistFile(
|
|
|
80
80
|
destPath: string,
|
|
81
81
|
name: string,
|
|
82
82
|
description: string,
|
|
83
|
-
repoUrl: string
|
|
83
|
+
repoUrl: string,
|
|
84
84
|
): Promise<void> {
|
|
85
85
|
const camelizedName = camelize(camelize(name, "-"), " "),
|
|
86
86
|
dashedName = dash(camelizedName);
|
|
@@ -90,7 +90,7 @@ async function updatePresetPackageDistFile(
|
|
|
90
90
|
`"tsparticles-preset-${dashedName}"`,
|
|
91
91
|
description,
|
|
92
92
|
`"tsparticles.preset.${camelizedName}.min.js"`,
|
|
93
|
-
repoUrl
|
|
93
|
+
repoUrl,
|
|
94
94
|
);
|
|
95
95
|
}
|
|
96
96
|
|
|
@@ -112,23 +112,23 @@ async function updateReadmeFile(destPath: string, name: string, description: str
|
|
|
112
112
|
readmePackageNameRegex = /tsparticles-preset-template/g,
|
|
113
113
|
replacedPackageNameText = replacedDescriptionText.replace(
|
|
114
114
|
readmePackageNameRegex,
|
|
115
|
-
`tsparticles-preset-${dashedName}
|
|
115
|
+
`tsparticles-preset-${dashedName}`,
|
|
116
116
|
),
|
|
117
117
|
readmeFileNameRegex = /tsparticles\.preset\.template(\.bundle)?\.min\.js/g,
|
|
118
118
|
replacedFileNameText = replacedPackageNameText.replace(
|
|
119
119
|
readmeFileNameRegex,
|
|
120
|
-
`tsparticles.preset.${camelizedName}$1.min.js
|
|
120
|
+
`tsparticles.preset.${camelizedName}$1.min.js`,
|
|
121
121
|
),
|
|
122
122
|
readmeFunctionNameRegex = /loadTemplatePreset/g,
|
|
123
123
|
replacedFunctionNameText = replacedFileNameText.replace(
|
|
124
124
|
readmeFunctionNameRegex,
|
|
125
|
-
`load${capitalizedName}Preset
|
|
125
|
+
`load${capitalizedName}Preset`,
|
|
126
126
|
),
|
|
127
127
|
readmeMiniDescriptionRegex =
|
|
128
128
|
/\[tsParticles]\(https:\/\/github.com\/matteobruni\/tsparticles\) preset template\./g,
|
|
129
129
|
replacedMiniDescriptionText = replacedFunctionNameText.replace(
|
|
130
130
|
readmeMiniDescriptionRegex,
|
|
131
|
-
`[tsParticles](https://github.com/matteobruni/tsparticles) preset ${name}
|
|
131
|
+
`[tsParticles](https://github.com/matteobruni/tsparticles) preset ${name}.`,
|
|
132
132
|
),
|
|
133
133
|
readmeUsageRegex = /preset: "template"/g,
|
|
134
134
|
replacedUsageText = replacedMiniDescriptionText.replace(readmeUsageRegex, `preset: "${camelizedName}`),
|
|
@@ -139,7 +139,7 @@ async function updateReadmeFile(destPath: string, name: string, description: str
|
|
|
139
139
|
: "tsparticles/preset-template",
|
|
140
140
|
replacedText = replacedUsageText.replace(
|
|
141
141
|
sampleImageRegex,
|
|
142
|
-
`
|
|
142
|
+
``,
|
|
143
143
|
);
|
|
144
144
|
|
|
145
145
|
await fs.writeFile(readmePath, replacedText);
|
|
@@ -156,7 +156,7 @@ async function updatePresetWebpackFile(destPath: string, name: string, descripti
|
|
|
156
156
|
destPath,
|
|
157
157
|
camelize(capitalize(capitalize(name, "-"), " ")),
|
|
158
158
|
`tsParticles ${description} Preset`,
|
|
159
|
-
"loadParticlesPreset"
|
|
159
|
+
"loadParticlesPreset",
|
|
160
160
|
);
|
|
161
161
|
}
|
|
162
162
|
|
|
@@ -171,7 +171,7 @@ export async function createPresetTemplate(
|
|
|
171
171
|
name: string,
|
|
172
172
|
description: string,
|
|
173
173
|
repoUrl: string,
|
|
174
|
-
destPath: string
|
|
174
|
+
destPath: string,
|
|
175
175
|
): Promise<void> {
|
|
176
176
|
const sourcePath = path.resolve(__dirname, "..", "..", "..", "files", "create-preset");
|
|
177
177
|
|