@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
|
@@ -16,7 +16,7 @@ const prettier_1 = __importDefault(require("prettier"));
|
|
|
16
16
|
*/
|
|
17
17
|
async function prettifySrc(basePath, srcPath, ci) {
|
|
18
18
|
console.log("Prettier - started on src");
|
|
19
|
-
let res
|
|
19
|
+
let res;
|
|
20
20
|
try {
|
|
21
21
|
for await (const file of (0, klaw_1.default)(srcPath)) {
|
|
22
22
|
if (file.stats.isDirectory()) {
|
|
@@ -28,12 +28,12 @@ async function prettifySrc(basePath, srcPath, ci) {
|
|
|
28
28
|
options.parser = "typescript";
|
|
29
29
|
options.tabWidth = 4;
|
|
30
30
|
if (ci) {
|
|
31
|
-
if (!prettier_1.default.check(contents, options)) {
|
|
31
|
+
if (!(await prettier_1.default.check(contents, options))) {
|
|
32
32
|
throw new Error(`${file.path} is not formatted correctly`);
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
else {
|
|
36
|
-
const formatted = prettier_1.default.format(contents, options);
|
|
36
|
+
const formatted = await prettier_1.default.format(contents, options);
|
|
37
37
|
await fs_extra_1.default.writeFile(file.path, formatted, "utf8");
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -54,19 +54,19 @@ exports.prettifySrc = prettifySrc;
|
|
|
54
54
|
*/
|
|
55
55
|
async function prettifyReadme(basePath, ci) {
|
|
56
56
|
console.log("Prettier - started on README.md");
|
|
57
|
-
let res
|
|
57
|
+
let res;
|
|
58
58
|
try {
|
|
59
59
|
const contents = await fs_extra_1.default.readFile("README.md", "utf8"), options = (await prettier_1.default.resolveConfig(basePath)) ?? {};
|
|
60
60
|
options.printWidth = 120;
|
|
61
61
|
options.endOfLine = "lf";
|
|
62
62
|
options.parser = "markdown";
|
|
63
63
|
if (ci) {
|
|
64
|
-
if (!prettier_1.default.check(contents, options)) {
|
|
64
|
+
if (!(await prettier_1.default.check(contents, options))) {
|
|
65
65
|
throw new Error(`README.md is not formatted correctly`);
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
else {
|
|
69
|
-
const formatted = prettier_1.default.format(contents, options);
|
|
69
|
+
const formatted = await prettier_1.default.format(contents, options);
|
|
70
70
|
await fs_extra_1.default.writeFile("README.md", formatted, "utf8");
|
|
71
71
|
}
|
|
72
72
|
res = (await prettifyTraductions(basePath, ci)) && (await prettifyMarkdownTypeDocFiles(basePath, ci));
|
|
@@ -102,12 +102,12 @@ async function prettifyTraductions(basePath, ci) {
|
|
|
102
102
|
options.endOfLine = "lf";
|
|
103
103
|
options.parser = "markdown";
|
|
104
104
|
if (ci) {
|
|
105
|
-
if (!prettier_1.default.check(contents, options)) {
|
|
105
|
+
if (!(await prettier_1.default.check(contents, options))) {
|
|
106
106
|
throw new Error(`${file.path} is not formatted correctly`);
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
else {
|
|
110
|
-
const formatted = prettier_1.default.format(contents, options);
|
|
110
|
+
const formatted = await prettier_1.default.format(contents, options);
|
|
111
111
|
await fs_extra_1.default.writeFile(file.path, formatted, "utf8");
|
|
112
112
|
}
|
|
113
113
|
}
|
|
@@ -144,12 +144,12 @@ async function prettifyMarkdownTypeDocFiles(basePath, ci) {
|
|
|
144
144
|
options.endOfLine = "lf";
|
|
145
145
|
options.parser = "markdown";
|
|
146
146
|
if (ci) {
|
|
147
|
-
if (!prettier_1.default.check(contents, options)) {
|
|
147
|
+
if (!(await prettier_1.default.check(contents, options))) {
|
|
148
148
|
throw new Error(`${file.path} is not formatted correctly`);
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
else {
|
|
152
|
-
const formatted = prettier_1.default.format(contents, options);
|
|
152
|
+
const formatted = await prettier_1.default.format(contents, options);
|
|
153
153
|
await fs_extra_1.default.writeFile(file.path, formatted, "utf8");
|
|
154
154
|
}
|
|
155
155
|
}
|
package/dist/create/create.js
CHANGED
|
@@ -2,8 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createCommand = void 0;
|
|
4
4
|
const commander_1 = require("commander");
|
|
5
|
+
const plugin_1 = require("./plugin/plugin");
|
|
5
6
|
const preset_1 = require("./preset/preset");
|
|
7
|
+
const shape_1 = require("./shape/shape");
|
|
6
8
|
const createCommand = new commander_1.Command("create");
|
|
7
9
|
exports.createCommand = createCommand;
|
|
8
10
|
createCommand.description("Create a new tsParticles project");
|
|
11
|
+
createCommand.addCommand(plugin_1.pluginCommand);
|
|
9
12
|
createCommand.addCommand(preset_1.presetCommand);
|
|
13
|
+
createCommand.addCommand(shape_1.shapeCommand);
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createPluginTemplate = void 0;
|
|
7
|
+
const string_utils_1 = require("../../utils/string-utils");
|
|
8
|
+
const template_utils_1 = require("../../utils/template-utils");
|
|
9
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
/**
|
|
12
|
+
* Updates the index file with the correct function name
|
|
13
|
+
* @param destPath - The path where the project is located
|
|
14
|
+
* @param name - The name of the project
|
|
15
|
+
*/
|
|
16
|
+
async function updateIndexFile(destPath, name) {
|
|
17
|
+
const indexPath = path_1.default.resolve(destPath, "src", "index.ts"), index = await fs_extra_1.default.readFile(indexPath, "utf-8"), capitalizedName = (0, string_utils_1.capitalize)((0, string_utils_1.capitalize)(name, "-"), " "), camelizedName = (0, string_utils_1.camelize)(capitalizedName), indexFunctionRegex = /loadTemplatePlugin/g, replacedFuncText = index.replace(indexFunctionRegex, `load${capitalizedName}Plugin`), indexNameRegex = /"#template#"/g, replacedNameText = replacedFuncText.replace(indexNameRegex, `"${camelizedName}"`);
|
|
18
|
+
await fs_extra_1.default.writeFile(indexPath, replacedNameText);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Updates the plugin package file
|
|
22
|
+
* @param destPath - The path where the project is located
|
|
23
|
+
* @param name - The name of the project
|
|
24
|
+
* @param description - The description of the project
|
|
25
|
+
* @param repoUrl - The repository url
|
|
26
|
+
*/
|
|
27
|
+
async function updatePluginPackageFile(destPath, name, description, repoUrl) {
|
|
28
|
+
const camelizedName = (0, string_utils_1.camelize)((0, string_utils_1.camelize)(name, "-"), " "), dashedName = (0, string_utils_1.dash)(camelizedName);
|
|
29
|
+
(0, template_utils_1.updatePackageFile)(destPath, `"tsparticles-plugin-${dashedName}"`, description, `"tsparticles.plugin.${camelizedName}.min.js"`, repoUrl);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Updates the plugin package dist file
|
|
33
|
+
* @param destPath - The path where the project is located
|
|
34
|
+
* @param name - The name of the project
|
|
35
|
+
* @param description - The description of the project
|
|
36
|
+
* @param repoUrl - The repository url
|
|
37
|
+
*/
|
|
38
|
+
async function updatePluginPackageDistFile(destPath, name, description, repoUrl) {
|
|
39
|
+
const camelizedName = (0, string_utils_1.camelize)((0, string_utils_1.camelize)(name, "-"), " "), dashedName = (0, string_utils_1.dash)(camelizedName);
|
|
40
|
+
(0, template_utils_1.updatePackageDistFile)(destPath, `"tsparticles-plugin-${dashedName}"`, description, `"tsparticles.plugin.${camelizedName}.min.js"`, repoUrl);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Updates the plugin readme file
|
|
44
|
+
* @param destPath - The path where the project is located
|
|
45
|
+
* @param name - The name of the project
|
|
46
|
+
* @param description - The description of the project
|
|
47
|
+
* @param repoUrl - The repository url
|
|
48
|
+
*/
|
|
49
|
+
async function updateReadmeFile(destPath, name, description, repoUrl) {
|
|
50
|
+
const readmePath = path_1.default.resolve(destPath, "README.md"), readme = await fs_extra_1.default.readFile(readmePath, "utf-8"), capitalizedName = (0, string_utils_1.capitalize)((0, string_utils_1.capitalize)(name, "-"), " "), camelizedName = (0, string_utils_1.camelize)(capitalizedName), dashedName = (0, string_utils_1.dash)(camelizedName), readmeDescriptionRegex = /tsParticles Template Plugin/g, replacedDescriptionText = readme.replace(readmeDescriptionRegex, `tsParticles ${description} Plugin`), readmePackageNameRegex = /tsparticles-plugin-template/g, replacedPackageNameText = replacedDescriptionText.replace(readmePackageNameRegex, `tsparticles-plugin-${dashedName}`), readmeFileNameRegex = /tsparticles\.plugin\.template(\.bundle)?\.min\.js/g, replacedFileNameText = replacedPackageNameText.replace(readmeFileNameRegex, `tsparticles.plugin.${camelizedName}$1.min.js`), readmeFunctionNameRegex = /loadTemplatePlugin/g, replacedFunctionNameText = replacedFileNameText.replace(readmeFunctionNameRegex, `load${capitalizedName}Plugin`), readmeMiniDescriptionRegex = /\[tsParticles]\(https:\/\/github.com\/matteobruni\/tsparticles\) additional template plugin\./g, replacedMiniDescriptionText = replacedFunctionNameText.replace(readmeMiniDescriptionRegex, `[tsParticles](https://github.com/matteobruni/tsparticles) additional ${name} plugin.`), readmeUsageRegex = /plugin\.type: "template"/g, replacedUsageText = replacedMiniDescriptionText.replace(readmeUsageRegex, `plugin.type: "${camelizedName}`), sampleImageRegex = /!\[demo]\(https:\/\/raw.githubusercontent.com\/tsparticles\/plugin-template\/main\/images\/sample.png\)/g, repoPath = repoUrl.includes("github.com")
|
|
51
|
+
? repoUrl.substring(repoUrl.indexOf("github.com/") + 11, repoUrl.indexOf(".git"))
|
|
52
|
+
: "tsparticles/plugin-template", replacedText = replacedUsageText.replace(sampleImageRegex, ``);
|
|
53
|
+
await fs_extra_1.default.writeFile(readmePath, replacedText);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Updates the plugin webpack file
|
|
57
|
+
* @param destPath - The path where the project is located
|
|
58
|
+
* @param name - The name of the project
|
|
59
|
+
* @param description - The description of the project
|
|
60
|
+
*/
|
|
61
|
+
async function updatePluginWebpackFile(destPath, name, description) {
|
|
62
|
+
await (0, template_utils_1.updateWebpackFile)(destPath, (0, string_utils_1.camelize)((0, string_utils_1.capitalize)((0, string_utils_1.capitalize)(name, "-"), " ")), `tsParticles ${description} Plugin`, "loadParticlesPlugin");
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Creates the plugin project
|
|
66
|
+
* @param name - The name of the project
|
|
67
|
+
* @param description - The description of the project
|
|
68
|
+
* @param repoUrl - The repository url
|
|
69
|
+
* @param destPath - The path where the project is located
|
|
70
|
+
*/
|
|
71
|
+
async function createPluginTemplate(name, description, repoUrl, destPath) {
|
|
72
|
+
const sourcePath = path_1.default.resolve(__dirname, "..", "..", "..", "files", "create-plugin");
|
|
73
|
+
await (0, template_utils_1.copyEmptyTemplateFiles)(destPath);
|
|
74
|
+
await fs_extra_1.default.copy(sourcePath, destPath, {
|
|
75
|
+
overwrite: true,
|
|
76
|
+
filter: template_utils_1.copyFilter,
|
|
77
|
+
});
|
|
78
|
+
await updateIndexFile(destPath, name);
|
|
79
|
+
await updatePluginPackageFile(destPath, name, description, repoUrl);
|
|
80
|
+
await updatePluginPackageDistFile(destPath, name, description, repoUrl);
|
|
81
|
+
await updateReadmeFile(destPath, name, description, repoUrl);
|
|
82
|
+
await updatePluginWebpackFile(destPath, name, description);
|
|
83
|
+
(0, template_utils_1.runInstall)(destPath);
|
|
84
|
+
(0, template_utils_1.runBuild)(destPath);
|
|
85
|
+
}
|
|
86
|
+
exports.createPluginTemplate = createPluginTemplate;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.pluginCommand = void 0;
|
|
7
|
+
const prompts_1 = __importDefault(require("prompts"));
|
|
8
|
+
const commander_1 = require("commander");
|
|
9
|
+
const string_utils_1 = require("../../utils/string-utils");
|
|
10
|
+
const create_plugin_1 = require("./create-plugin");
|
|
11
|
+
const child_process_1 = require("child_process");
|
|
12
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
const pluginCommand = new commander_1.Command("plugin");
|
|
15
|
+
exports.pluginCommand = pluginCommand;
|
|
16
|
+
pluginCommand.description("Create a new tsParticles plugin");
|
|
17
|
+
pluginCommand.argument("<destination>", "Destination folder");
|
|
18
|
+
pluginCommand.action(async (destination) => {
|
|
19
|
+
let repoUrl;
|
|
20
|
+
const destPath = path_1.default.resolve(path_1.default.join(process.cwd(), destination)), destExists = await fs_extra_1.default.pathExists(destPath);
|
|
21
|
+
if (destExists) {
|
|
22
|
+
const destContents = await fs_extra_1.default.readdir(destPath), destContentsNoGit = destContents.filter(t => t !== ".git" && t !== ".gitignore");
|
|
23
|
+
if (destContentsNoGit.length) {
|
|
24
|
+
throw new Error("Destination folder already exists and is not empty");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
await fs_extra_1.default.ensureDir(destPath);
|
|
28
|
+
try {
|
|
29
|
+
repoUrl = (0, child_process_1.execSync)("git config --get remote.origin.url").toString();
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
repoUrl = "";
|
|
33
|
+
}
|
|
34
|
+
const initialName = destPath.split(path_1.default.sep).pop(), questions = [
|
|
35
|
+
{
|
|
36
|
+
type: "text",
|
|
37
|
+
name: "name",
|
|
38
|
+
message: "What is the name of the plugin?",
|
|
39
|
+
validate: (value) => (value ? true : "The name can't be empty"),
|
|
40
|
+
initial: initialName,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
type: "text",
|
|
44
|
+
name: "description",
|
|
45
|
+
message: "What is the description of the plugin?",
|
|
46
|
+
validate: (value) => (value ? true : "The description can't be empty"),
|
|
47
|
+
initial: (0, string_utils_1.capitalize)(initialName || ""),
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
type: "text",
|
|
51
|
+
name: "repositoryUrl",
|
|
52
|
+
message: "What is the repository URL? (optional)",
|
|
53
|
+
initial: repoUrl.trim(),
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
const { name, description, repositoryUrl } = await (0, prompts_1.default)(questions);
|
|
57
|
+
(0, create_plugin_1.createPluginTemplate)(name.trim(), description.trim(), repositoryUrl.trim(), destPath);
|
|
58
|
+
});
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createShapeTemplate = void 0;
|
|
7
|
+
const string_utils_1 = require("../../utils/string-utils");
|
|
8
|
+
const template_utils_1 = require("../../utils/template-utils");
|
|
9
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
/**
|
|
12
|
+
* Updates the index file with the correct function name
|
|
13
|
+
* @param destPath - The path where the project is located
|
|
14
|
+
* @param name - The name of the project
|
|
15
|
+
*/
|
|
16
|
+
async function updateIndexFile(destPath, name) {
|
|
17
|
+
const indexPath = path_1.default.resolve(destPath, "src", "index.ts"), index = await fs_extra_1.default.readFile(indexPath, "utf-8"), capitalizedName = (0, string_utils_1.capitalize)((0, string_utils_1.capitalize)(name, "-"), " "), camelizedName = (0, string_utils_1.camelize)(capitalizedName), indexFunctionRegex = /loadTemplateShape/g, replacedFuncText = index.replace(indexFunctionRegex, `load${capitalizedName}Shape`), indexNameRegex = /"#template#"/g, replacedNameText = replacedFuncText.replace(indexNameRegex, `"${camelizedName}"`);
|
|
18
|
+
await fs_extra_1.default.writeFile(indexPath, replacedNameText);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Updates the shape package file
|
|
22
|
+
* @param destPath - The path where the project is located
|
|
23
|
+
* @param name - The name of the project
|
|
24
|
+
* @param description - The description of the project
|
|
25
|
+
* @param repoUrl - The repository url
|
|
26
|
+
*/
|
|
27
|
+
async function updateShapePackageFile(destPath, name, description, repoUrl) {
|
|
28
|
+
const camelizedName = (0, string_utils_1.camelize)((0, string_utils_1.camelize)(name, "-"), " "), dashedName = (0, string_utils_1.dash)(camelizedName);
|
|
29
|
+
(0, template_utils_1.updatePackageFile)(destPath, `"tsparticles-shape-${dashedName}"`, description, `"tsparticles.shape.${camelizedName}.min.js"`, repoUrl);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Updates the shape package dist file
|
|
33
|
+
* @param destPath - The path where the project is located
|
|
34
|
+
* @param name - The name of the project
|
|
35
|
+
* @param description - The description of the project
|
|
36
|
+
* @param repoUrl - The repository url
|
|
37
|
+
*/
|
|
38
|
+
async function updateShapePackageDistFile(destPath, name, description, repoUrl) {
|
|
39
|
+
const camelizedName = (0, string_utils_1.camelize)((0, string_utils_1.camelize)(name, "-"), " "), dashedName = (0, string_utils_1.dash)(camelizedName);
|
|
40
|
+
(0, template_utils_1.updatePackageDistFile)(destPath, `"tsparticles-shape-${dashedName}"`, description, `"tsparticles.shape.${camelizedName}.min.js"`, repoUrl);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Updates the shape readme file
|
|
44
|
+
* @param destPath - The path where the project is located
|
|
45
|
+
* @param name - The name of the project
|
|
46
|
+
* @param description - The description of the project
|
|
47
|
+
* @param repoUrl - The repository url
|
|
48
|
+
*/
|
|
49
|
+
async function updateReadmeFile(destPath, name, description, repoUrl) {
|
|
50
|
+
const readmePath = path_1.default.resolve(destPath, "README.md"), readme = await fs_extra_1.default.readFile(readmePath, "utf-8"), capitalizedName = (0, string_utils_1.capitalize)((0, string_utils_1.capitalize)(name, "-"), " "), camelizedName = (0, string_utils_1.camelize)(capitalizedName), dashedName = (0, string_utils_1.dash)(camelizedName), readmeDescriptionRegex = /tsParticles Template Shape/g, replacedDescriptionText = readme.replace(readmeDescriptionRegex, `tsParticles ${description} Shape`), readmePackageNameRegex = /tsparticles-shape-template/g, replacedPackageNameText = replacedDescriptionText.replace(readmePackageNameRegex, `tsparticles-shape-${dashedName}`), readmeFileNameRegex = /tsparticles\.shape\.template(\.bundle)?\.min\.js/g, replacedFileNameText = replacedPackageNameText.replace(readmeFileNameRegex, `tsparticles.shape.${camelizedName}$1.min.js`), readmeFunctionNameRegex = /loadTemplateShape/g, replacedFunctionNameText = replacedFileNameText.replace(readmeFunctionNameRegex, `load${capitalizedName}Shape`), readmeMiniDescriptionRegex = /\[tsParticles]\(https:\/\/github.com\/matteobruni\/tsparticles\) additional template shape\./g, replacedMiniDescriptionText = replacedFunctionNameText.replace(readmeMiniDescriptionRegex, `[tsParticles](https://github.com/matteobruni/tsparticles) additional ${name} shape.`), readmeUsageRegex = /shape\.type: "template"/g, replacedUsageText = replacedMiniDescriptionText.replace(readmeUsageRegex, `shape.type: "${camelizedName}`), sampleImageRegex = /!\[demo]\(https:\/\/raw.githubusercontent.com\/tsparticles\/shape-template\/main\/images\/sample.png\)/g, repoPath = repoUrl.includes("github.com")
|
|
51
|
+
? repoUrl.substring(repoUrl.indexOf("github.com/") + 11, repoUrl.indexOf(".git"))
|
|
52
|
+
: "tsparticles/shape-template", replacedText = replacedUsageText.replace(sampleImageRegex, ``);
|
|
53
|
+
await fs_extra_1.default.writeFile(readmePath, replacedText);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Updates the shape webpack file
|
|
57
|
+
* @param destPath - The path where the project is located
|
|
58
|
+
* @param name - The name of the project
|
|
59
|
+
* @param description - The description of the project
|
|
60
|
+
*/
|
|
61
|
+
async function updateShapeWebpackFile(destPath, name, description) {
|
|
62
|
+
await (0, template_utils_1.updateWebpackFile)(destPath, (0, string_utils_1.camelize)((0, string_utils_1.capitalize)((0, string_utils_1.capitalize)(name, "-"), " ")), `tsParticles ${description} Shape`, "loadParticlesShape");
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Creates the shape project
|
|
66
|
+
* @param name - The name of the project
|
|
67
|
+
* @param description - The description of the project
|
|
68
|
+
* @param repoUrl - The repository url
|
|
69
|
+
* @param destPath - The path where the project is located
|
|
70
|
+
*/
|
|
71
|
+
async function createShapeTemplate(name, description, repoUrl, destPath) {
|
|
72
|
+
const sourcePath = path_1.default.resolve(__dirname, "..", "..", "..", "files", "create-shape");
|
|
73
|
+
await (0, template_utils_1.copyEmptyTemplateFiles)(destPath);
|
|
74
|
+
await fs_extra_1.default.copy(sourcePath, destPath, {
|
|
75
|
+
overwrite: true,
|
|
76
|
+
filter: template_utils_1.copyFilter,
|
|
77
|
+
});
|
|
78
|
+
await updateIndexFile(destPath, name);
|
|
79
|
+
await updateShapePackageFile(destPath, name, description, repoUrl);
|
|
80
|
+
await updateShapePackageDistFile(destPath, name, description, repoUrl);
|
|
81
|
+
await updateReadmeFile(destPath, name, description, repoUrl);
|
|
82
|
+
await updateShapeWebpackFile(destPath, name, description);
|
|
83
|
+
(0, template_utils_1.runInstall)(destPath);
|
|
84
|
+
(0, template_utils_1.runBuild)(destPath);
|
|
85
|
+
}
|
|
86
|
+
exports.createShapeTemplate = createShapeTemplate;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.shapeCommand = void 0;
|
|
7
|
+
const prompts_1 = __importDefault(require("prompts"));
|
|
8
|
+
const commander_1 = require("commander");
|
|
9
|
+
const string_utils_1 = require("../../utils/string-utils");
|
|
10
|
+
const create_shape_1 = require("./create-shape");
|
|
11
|
+
const child_process_1 = require("child_process");
|
|
12
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
const shapeCommand = new commander_1.Command("shape");
|
|
15
|
+
exports.shapeCommand = shapeCommand;
|
|
16
|
+
shapeCommand.description("Create a new tsParticles shape");
|
|
17
|
+
shapeCommand.argument("<destination>", "Destination folder");
|
|
18
|
+
shapeCommand.action(async (destination) => {
|
|
19
|
+
let repoUrl;
|
|
20
|
+
const destPath = path_1.default.resolve(path_1.default.join(process.cwd(), destination)), destExists = await fs_extra_1.default.pathExists(destPath);
|
|
21
|
+
if (destExists) {
|
|
22
|
+
const destContents = await fs_extra_1.default.readdir(destPath), destContentsNoGit = destContents.filter(t => t !== ".git" && t !== ".gitignore");
|
|
23
|
+
if (destContentsNoGit.length) {
|
|
24
|
+
throw new Error("Destination folder already exists and is not empty");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
await fs_extra_1.default.ensureDir(destPath);
|
|
28
|
+
try {
|
|
29
|
+
repoUrl = (0, child_process_1.execSync)("git config --get remote.origin.url").toString();
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
repoUrl = "";
|
|
33
|
+
}
|
|
34
|
+
const initialName = destPath.split(path_1.default.sep).pop(), questions = [
|
|
35
|
+
{
|
|
36
|
+
type: "text",
|
|
37
|
+
name: "name",
|
|
38
|
+
message: "What is the name of the shape?",
|
|
39
|
+
validate: (value) => (value ? true : "The name can't be empty"),
|
|
40
|
+
initial: initialName,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
type: "text",
|
|
44
|
+
name: "description",
|
|
45
|
+
message: "What is the description of the shape?",
|
|
46
|
+
validate: (value) => (value ? true : "The description can't be empty"),
|
|
47
|
+
initial: (0, string_utils_1.capitalize)(initialName || ""),
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
type: "text",
|
|
51
|
+
name: "repositoryUrl",
|
|
52
|
+
message: "What is the repository URL? (optional)",
|
|
53
|
+
initial: repoUrl.trim(),
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
const { name, description, repositoryUrl } = await (0, prompts_1.default)(questions);
|
|
57
|
+
(0, create_shape_1.createShapeTemplate)(name.trim(), description.trim(), repositoryUrl.trim(), destPath);
|
|
58
|
+
});
|
|
@@ -63,10 +63,7 @@ exports.copyEmptyTemplateFiles = copyEmptyTemplateFiles;
|
|
|
63
63
|
* @returns true if the file should be copied
|
|
64
64
|
*/
|
|
65
65
|
function copyFilter(src) {
|
|
66
|
-
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
return true;
|
|
66
|
+
return !(src.endsWith("node_modules") || src.endsWith("dist"));
|
|
70
67
|
}
|
|
71
68
|
exports.copyFilter = copyFilter;
|
|
72
69
|
/**
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
[](https://particles.js.org)
|
|
2
|
+
|
|
3
|
+
# tsParticles Template Plugin
|
|
4
|
+
|
|
5
|
+
[](https://www.jsdelivr.com/package/npm/tsparticles-plugin-template)
|
|
6
|
+
[](https://www.npmjs.com/package/tsparticles-plugin-template)
|
|
7
|
+
[](https://www.npmjs.com/package/tsparticles-plugin-template) [](https://github.com/sponsors/matteobruni)
|
|
8
|
+
|
|
9
|
+
[tsParticles](https://github.com/matteobruni/tsparticles) plugin for particles template.
|
|
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.plugin.template.min.js` file will export the function to load the plugin:
|
|
18
|
+
|
|
19
|
+
```javascript
|
|
20
|
+
loadTemplatePlugin;
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Usage
|
|
24
|
+
|
|
25
|
+
Once the scripts are loaded you can set up `tsParticles` and the plugin like this:
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
(async () => {
|
|
29
|
+
await loadTemplatePlugin(tsParticles);
|
|
30
|
+
|
|
31
|
+
await tsParticles.load({
|
|
32
|
+
id: "tsparticles",
|
|
33
|
+
options: {
|
|
34
|
+
/* options */
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
})();
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### ESM / CommonJS
|
|
41
|
+
|
|
42
|
+
This package is compatible also with ES or CommonJS modules, firstly this needs to be installed, like this:
|
|
43
|
+
|
|
44
|
+
```shell
|
|
45
|
+
$ npm install tsparticles-plugin-template
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
or
|
|
49
|
+
|
|
50
|
+
```shell
|
|
51
|
+
$ yarn add tsparticles-plugin-template
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Then you need to import it in the app, like this:
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
const { tsParticles } = require("tsparticles-engine");
|
|
58
|
+
const { loadTemplatePlugin } = require("tsparticles-plugin-template");
|
|
59
|
+
|
|
60
|
+
(async () => {
|
|
61
|
+
await loadTemplatePlugin(tsParticles);
|
|
62
|
+
})();
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
or
|
|
66
|
+
|
|
67
|
+
```javascript
|
|
68
|
+
import { tsParticles } from "tsparticles-engine";
|
|
69
|
+
import { loadTemplatePlugin } from "tsparticles-plugin-template";
|
|
70
|
+
|
|
71
|
+
(async () => {
|
|
72
|
+
await loadTemplatePlugin(tsParticles);
|
|
73
|
+
})();
|
|
74
|
+
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type Container, type Engine, type IContainerPlugin } from "tsparticles-engine";
|
|
2
|
+
|
|
3
|
+
export class PluginInstance implements IContainerPlugin {
|
|
4
|
+
private readonly _container;
|
|
5
|
+
private readonly _engine;
|
|
6
|
+
|
|
7
|
+
constructor(container: Container, engine: Engine) {
|
|
8
|
+
this._container = container;
|
|
9
|
+
this._engine = engine;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async init(): Promise<void> {
|
|
13
|
+
// add your plugin initialization here
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Container, Engine, IPlugin, ISourceOptions, Options } from "tsparticles-engine";
|
|
2
|
+
import { PluginInstance } from "./PluginInstance";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*/
|
|
6
|
+
class Plugin implements IPlugin {
|
|
7
|
+
readonly id;
|
|
8
|
+
|
|
9
|
+
private readonly _engine;
|
|
10
|
+
|
|
11
|
+
constructor(engine: Engine) {
|
|
12
|
+
this.id = "#template#";
|
|
13
|
+
|
|
14
|
+
this._engine = engine;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
getPlugin(container: Container): PluginInstance {
|
|
18
|
+
return new PluginInstance(container, this._engine);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
loadOptions(_options: Options, _source?: ISourceOptions): void {
|
|
22
|
+
if (!this.needsPlugin()) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Load your options here
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
needsPlugin(_options?: ISourceOptions): boolean {
|
|
30
|
+
return true; // add your condition here
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param engine - The engine instance
|
|
36
|
+
*/
|
|
37
|
+
export async function loadTemplatePlugin(engine: Engine): Promise<void> {
|
|
38
|
+
await engine.addPlugin(new Plugin(engine));
|
|
39
|
+
}
|
|
@@ -40,9 +40,11 @@ A bundled script can also be used, this will include every needed plugin needed
|
|
|
40
40
|
Once the scripts are loaded you can set up `tsParticles` like this:
|
|
41
41
|
|
|
42
42
|
```javascript
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
(async () => {
|
|
44
|
+
await tsParticles.load("tsparticles", {
|
|
45
|
+
preset: "template",
|
|
46
|
+
});
|
|
47
|
+
})();
|
|
46
48
|
```
|
|
47
49
|
|
|
48
50
|
#### Customization
|
|
@@ -51,14 +53,16 @@ tsParticles.load("tsparticles", {
|
|
|
51
53
|
You can override all the options defining the properties like in any standard `tsParticles` installation.
|
|
52
54
|
|
|
53
55
|
```javascript
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
(async () => {
|
|
57
|
+
await tsParticles.load("tsparticles", {
|
|
58
|
+
particles: {
|
|
59
|
+
shape: {
|
|
60
|
+
type: "square"
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
preset: "template"
|
|
64
|
+
});
|
|
65
|
+
})();
|
|
62
66
|
```
|
|
63
67
|
|
|
64
68
|
Like in the sample above, the circles will be replaced by squares.
|
|
@@ -71,19 +75,19 @@ This sample uses the class component syntax, but you can use hooks as well (if t
|
|
|
71
75
|
|
|
72
76
|
```javascript
|
|
73
77
|
import Particles from "react-particles";
|
|
74
|
-
import {
|
|
78
|
+
import { Engine } from "tsparticles-engine";
|
|
75
79
|
import { loadTemplatePreset } from "tsparticles-preset-template";
|
|
76
80
|
|
|
77
81
|
export class ParticlesContainer extends React.PureComponent<IProps> {
|
|
78
82
|
// this customizes the component tsParticles installation
|
|
79
|
-
customInit(
|
|
83
|
+
async customInit(engine: Engine) {
|
|
80
84
|
// this adds the preset to tsParticles, you can safely use the
|
|
81
|
-
loadTemplatePreset(
|
|
85
|
+
await loadTemplatePreset(engine);
|
|
82
86
|
}
|
|
83
87
|
|
|
84
88
|
render() {
|
|
85
89
|
const options = {
|
|
86
|
-
preset: "template",
|
|
90
|
+
preset: "template",
|
|
87
91
|
};
|
|
88
92
|
|
|
89
93
|
return <Particles options={options} init={this.customInit} />;
|
|
@@ -100,25 +104,25 @@ _The syntax for `Vue.js 2.x` and `3.x` is the same_
|
|
|
100
104
|
```
|
|
101
105
|
|
|
102
106
|
```js
|
|
103
|
-
function particlesInit(
|
|
104
|
-
|
|
107
|
+
async function particlesInit(engine: Engine) {
|
|
108
|
+
await loadTemplatePreset(main);
|
|
105
109
|
}
|
|
106
110
|
```
|
|
107
111
|
|
|
108
112
|
### Angular
|
|
109
113
|
|
|
110
114
|
```html
|
|
115
|
+
|
|
111
116
|
<ng-particles
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
(particlesInit)="particlesInit($event)"
|
|
117
|
+
[id]="id"
|
|
118
|
+
[options]="particlesOptions"
|
|
119
|
+
[particlesInit]="particlesInit"
|
|
116
120
|
></ng-particles>
|
|
117
121
|
```
|
|
118
122
|
|
|
119
123
|
```ts
|
|
120
|
-
function particlesInit(
|
|
121
|
-
|
|
124
|
+
async function particlesInit(engine: Engine): Promise<void> {
|
|
125
|
+
loadTemplatePreset(engine);
|
|
122
126
|
}
|
|
123
127
|
```
|
|
124
128
|
|
|
@@ -129,12 +133,12 @@ function particlesInit(main: Main): void {
|
|
|
129
133
|
<Particles
|
|
130
134
|
id="tsparticles"
|
|
131
135
|
url="{particlesUrl}"
|
|
132
|
-
|
|
136
|
+
particlesInit="{particlesInit}"
|
|
133
137
|
/>
|
|
134
138
|
```
|
|
135
139
|
|
|
136
140
|
```js
|
|
137
|
-
let
|
|
138
|
-
|
|
141
|
+
let particlesInit = async (engine) => {
|
|
142
|
+
await loadTemplatePreset(engine);
|
|
139
143
|
};
|
|
140
144
|
```
|