@tsparticles/cli-create-utils 4.0.0-beta.12 → 4.0.0-beta.16
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/CHANGELOG.md +12 -0
- package/LICENSE +21 -0
- package/README.md +36 -35
- package/dist/create-project.d.ts +18 -0
- package/dist/create-project.js +1022 -0
- package/dist/file-utils.d.ts +7 -0
- package/dist/file-utils.js +13 -3
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/prompt-utils.d.ts +27 -0
- package/dist/prompt-utils.js +50 -0
- package/dist/template-utils.d.ts +11 -18
- package/dist/template-utils.js +52 -82
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/files/empty-project/package.dist.json +1 -1
- package/files/empty-project/package.json +5 -5
- package/package.json +34 -31
- package/src/create-project.ts +1154 -0
- package/src/file-utils.ts +19 -4
- package/src/index.ts +2 -0
- package/src/prompt-utils.ts +89 -0
- package/src/template-utils.ts +66 -102
- package/.cache/eslint/.eslintcache +0 -1
|
@@ -0,0 +1,1022 @@
|
|
|
1
|
+
/* eslint-disable sort-imports */
|
|
2
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { camelize, capitalize, dash } from "./string-utils.js";
|
|
5
|
+
import { copyEmptyTemplateFiles, runBuild, runInstall, updatePackageDistFile, updatePackageFile, } from "./template-utils.js";
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @param name
|
|
9
|
+
* @param destination
|
|
10
|
+
*/
|
|
11
|
+
function getNameData(name, destination) {
|
|
12
|
+
const pascalName = capitalize(name.trim(), "-", "_", " "), camelName = camelize(pascalName), dashedName = dash(camelName), folderName = path.basename(destination);
|
|
13
|
+
return {
|
|
14
|
+
camelName,
|
|
15
|
+
dashedName,
|
|
16
|
+
folderName,
|
|
17
|
+
pascalName,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
*
|
|
22
|
+
* @param loadFunction
|
|
23
|
+
*/
|
|
24
|
+
function getNoopLazyIndex(loadFunction) {
|
|
25
|
+
return `import type { Engine } from "@tsparticles/engine/lazy";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param engine - The engine instance
|
|
29
|
+
*/
|
|
30
|
+
export async function ${loadFunction}(engine: Engine): Promise<void> {
|
|
31
|
+
const { ${loadFunction}: load } = await import("./index.js");
|
|
32
|
+
|
|
33
|
+
await load(engine);
|
|
34
|
+
}
|
|
35
|
+
`;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
*
|
|
39
|
+
* @param loadFunction
|
|
40
|
+
*/
|
|
41
|
+
function getBrowserFile(loadFunction) {
|
|
42
|
+
return `import { ${loadFunction} } from "./index.js";
|
|
43
|
+
|
|
44
|
+
const globalObject = globalThis as typeof globalThis & {
|
|
45
|
+
__tsParticlesInternals?: Record<string, unknown>;
|
|
46
|
+
${loadFunction}?: typeof ${loadFunction};
|
|
47
|
+
};
|
|
48
|
+
globalObject.__tsParticlesInternals = globalObject.__tsParticlesInternals ?? {};
|
|
49
|
+
globalObject.${loadFunction} = ${loadFunction};
|
|
50
|
+
|
|
51
|
+
export * from "./index.js";
|
|
52
|
+
`;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
*
|
|
56
|
+
* @param loadFunction
|
|
57
|
+
* @param reexportEngine
|
|
58
|
+
*/
|
|
59
|
+
function getBundleFile(loadFunction, reexportEngine) {
|
|
60
|
+
return `import { ${loadFunction} } from "./index.js";
|
|
61
|
+
|
|
62
|
+
${reexportEngine ? 'export { tsParticles } from "@tsparticles/engine";' : ""}
|
|
63
|
+
export { ${loadFunction} } from "./index.js";
|
|
64
|
+
|
|
65
|
+
const globalObject = globalThis as typeof globalThis & {
|
|
66
|
+
__tsParticlesInternals?: Record<string, unknown>;
|
|
67
|
+
${loadFunction}?: typeof ${loadFunction};
|
|
68
|
+
};
|
|
69
|
+
globalObject.__tsParticlesInternals = globalObject.__tsParticlesInternals ?? {};
|
|
70
|
+
|
|
71
|
+
globalObject.${loadFunction} = ${loadFunction};
|
|
72
|
+
`;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
*
|
|
76
|
+
* @param kindLabel
|
|
77
|
+
* @param description
|
|
78
|
+
*/
|
|
79
|
+
function getProjectDescription(kindLabel, description) {
|
|
80
|
+
return `tsParticles ${description} ${kindLabel}`;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
*
|
|
84
|
+
* @param repositoryUrl
|
|
85
|
+
* @param packageSuffix
|
|
86
|
+
*/
|
|
87
|
+
function getRepoUrl(repositoryUrl, packageSuffix) {
|
|
88
|
+
if (repositoryUrl) {
|
|
89
|
+
return repositoryUrl;
|
|
90
|
+
}
|
|
91
|
+
return `https://github.com/tsparticles/${packageSuffix}.git`;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
*
|
|
95
|
+
* @param config
|
|
96
|
+
*/
|
|
97
|
+
function getRollupConfig(config) {
|
|
98
|
+
return `import { ${config.rollupFactory} } from "@tsparticles/rollup-plugin";
|
|
99
|
+
import { fileURLToPath } from "node:url";
|
|
100
|
+
import { readFile } from "node:fs/promises";
|
|
101
|
+
import path from "node:path";
|
|
102
|
+
|
|
103
|
+
const __filename = fileURLToPath(import.meta.url),
|
|
104
|
+
__dirname = path.dirname(__filename),
|
|
105
|
+
rootPkgPath = path.join(__dirname, "package.json"),
|
|
106
|
+
pkg = JSON.parse(await readFile(rootPkgPath, "utf-8"));
|
|
107
|
+
|
|
108
|
+
export default ${config.rollupFactory}({
|
|
109
|
+
moduleName: "${config.moduleName}",
|
|
110
|
+
${config.rollupNameKey}: "${config.rollupNameValue}",
|
|
111
|
+
version: pkg.version,
|
|
112
|
+
dir: __dirname,
|
|
113
|
+
});
|
|
114
|
+
`;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
*
|
|
118
|
+
* @param config
|
|
119
|
+
*/
|
|
120
|
+
function getReadme(config) {
|
|
121
|
+
return `[](https://particles.js.org)
|
|
122
|
+
|
|
123
|
+
# ${config.description}
|
|
124
|
+
|
|
125
|
+
[](https://www.jsdelivr.com/package/npm/${config.packageSuffix})
|
|
126
|
+
[](https://www.npmjs.com/package/${config.packageSuffix})
|
|
127
|
+
|
|
128
|
+
## Installation
|
|
129
|
+
|
|
130
|
+
\`\`\`bash
|
|
131
|
+
npm install ${config.packageSuffix}
|
|
132
|
+
\`\`\`
|
|
133
|
+
|
|
134
|
+
## Usage
|
|
135
|
+
|
|
136
|
+
\`\`\`ts
|
|
137
|
+
import { tsParticles } from "@tsparticles/engine";
|
|
138
|
+
import { ${config.loadFunction} } from "${config.packageSuffix}";
|
|
139
|
+
|
|
140
|
+
await ${config.loadFunction}(tsParticles);
|
|
141
|
+
\`\`\`
|
|
142
|
+
`;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
*
|
|
146
|
+
* @param nameData
|
|
147
|
+
* @param description
|
|
148
|
+
*/
|
|
149
|
+
function createBundleConfig(nameData, description) {
|
|
150
|
+
const loadFunction = `load${nameData.pascalName}`;
|
|
151
|
+
return {
|
|
152
|
+
description: getProjectDescription("bundle", description),
|
|
153
|
+
fileName: `tsparticles.${nameData.camelName}.bundle.min.js`,
|
|
154
|
+
jsDelivrFileName: `tsparticles.${nameData.camelName}.bundle.min.js`,
|
|
155
|
+
kindLabel: "Bundle",
|
|
156
|
+
loadFunction,
|
|
157
|
+
moduleName: nameData.dashedName,
|
|
158
|
+
packageName: `@tsparticles/${nameData.dashedName}`,
|
|
159
|
+
packageSuffix: `@tsparticles/${nameData.dashedName}`,
|
|
160
|
+
registerName: nameData.pascalName,
|
|
161
|
+
rollupFactory: "loadParticlesBundle",
|
|
162
|
+
rollupNameKey: "bundleName",
|
|
163
|
+
rollupNameValue: nameData.pascalName,
|
|
164
|
+
srcFiles: {
|
|
165
|
+
"src/index.ts": `import { type Engine } from "@tsparticles/engine";
|
|
166
|
+
|
|
167
|
+
declare const __VERSION__: string;
|
|
168
|
+
|
|
169
|
+
export async function ${loadFunction}(engine: Engine): Promise<void> {
|
|
170
|
+
engine.checkVersion(__VERSION__);
|
|
171
|
+
|
|
172
|
+
await engine.pluginManager.register(async () => {
|
|
173
|
+
// TODO: load dependencies for this bundle
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
`,
|
|
177
|
+
"src/index.lazy.ts": getNoopLazyIndex(loadFunction),
|
|
178
|
+
"src/browser.ts": getBrowserFile(loadFunction),
|
|
179
|
+
"src/bundle.ts": getBundleFile(loadFunction, true),
|
|
180
|
+
},
|
|
181
|
+
withBundleFile: true,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
*
|
|
186
|
+
* @param nameData
|
|
187
|
+
* @param description
|
|
188
|
+
*/
|
|
189
|
+
function createEffectConfig(nameData, description) {
|
|
190
|
+
const loadFunction = `load${nameData.pascalName}Effect`, drawerName = `${nameData.pascalName}EffectDrawer`;
|
|
191
|
+
return {
|
|
192
|
+
description: getProjectDescription("effect", description),
|
|
193
|
+
fileName: `tsparticles.effect.${nameData.camelName}.min.js`,
|
|
194
|
+
jsDelivrFileName: `tsparticles.effect.${nameData.camelName}.min.js`,
|
|
195
|
+
kindLabel: "Effect",
|
|
196
|
+
loadFunction,
|
|
197
|
+
moduleName: nameData.dashedName,
|
|
198
|
+
packageName: `@tsparticles/effect-${nameData.dashedName}`,
|
|
199
|
+
packageSuffix: `@tsparticles/effect-${nameData.dashedName}`,
|
|
200
|
+
registerName: nameData.camelName,
|
|
201
|
+
rollupFactory: "loadParticlesEffect",
|
|
202
|
+
rollupNameKey: "effectName",
|
|
203
|
+
rollupNameValue: nameData.pascalName,
|
|
204
|
+
srcFiles: {
|
|
205
|
+
"src/index.ts": `import { type Engine, type IEffectDrawer, type IShapeDrawData, type Particle } from "@tsparticles/engine";
|
|
206
|
+
|
|
207
|
+
declare const __VERSION__: string;
|
|
208
|
+
|
|
209
|
+
class ${drawerName} implements IEffectDrawer<Particle> {
|
|
210
|
+
drawAfter(_data: IShapeDrawData<Particle>): void {
|
|
211
|
+
// TODO: implement drawAfter
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export async function ${loadFunction}(engine: Engine): Promise<void> {
|
|
216
|
+
engine.checkVersion(__VERSION__);
|
|
217
|
+
|
|
218
|
+
await engine.pluginManager.register(e => {
|
|
219
|
+
e.pluginManager.addEffect("${nameData.camelName}", () => {
|
|
220
|
+
return Promise.resolve(new ${drawerName}());
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
`,
|
|
225
|
+
"src/index.lazy.ts": getNoopLazyIndex(loadFunction),
|
|
226
|
+
"src/browser.ts": getBrowserFile(loadFunction),
|
|
227
|
+
},
|
|
228
|
+
withBundleFile: false,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
*
|
|
233
|
+
* @param nameData
|
|
234
|
+
* @param description
|
|
235
|
+
* @param type
|
|
236
|
+
*/
|
|
237
|
+
function createInteractionConfig(nameData, description, type) {
|
|
238
|
+
const isExternal = type === "external" || type === "generic", isParticles = type === "particles" || type === "generic";
|
|
239
|
+
let loadFunction = `load${nameData.pascalName}Interaction`, packageName = `@tsparticles/interaction-${nameData.dashedName}`, fileName = `tsparticles.interaction.${nameData.camelName}.min.js`, rollupFactory = "loadParticlesInteraction";
|
|
240
|
+
if (type === "external") {
|
|
241
|
+
loadFunction = `loadExternal${nameData.pascalName}Interaction`;
|
|
242
|
+
packageName = `@tsparticles/interaction-external-${nameData.dashedName}`;
|
|
243
|
+
fileName = `tsparticles.interaction.external.${nameData.camelName}.min.js`;
|
|
244
|
+
rollupFactory = "loadParticlesInteractionExternal";
|
|
245
|
+
}
|
|
246
|
+
else if (type === "particles") {
|
|
247
|
+
loadFunction = `loadParticles${nameData.pascalName}Interaction`;
|
|
248
|
+
packageName = `@tsparticles/interaction-particles-${nameData.dashedName}`;
|
|
249
|
+
fileName = `tsparticles.interaction.particles.${nameData.camelName}.min.js`;
|
|
250
|
+
rollupFactory = "loadParticlesInteractionParticles";
|
|
251
|
+
}
|
|
252
|
+
return {
|
|
253
|
+
description: getProjectDescription("interaction", description),
|
|
254
|
+
fileName,
|
|
255
|
+
jsDelivrFileName: fileName,
|
|
256
|
+
kindLabel: "Interaction",
|
|
257
|
+
loadFunction,
|
|
258
|
+
moduleName: nameData.dashedName,
|
|
259
|
+
packageName,
|
|
260
|
+
packageSuffix: packageName,
|
|
261
|
+
registerName: nameData.camelName,
|
|
262
|
+
rollupFactory,
|
|
263
|
+
rollupNameKey: "pluginName",
|
|
264
|
+
rollupNameValue: nameData.pascalName,
|
|
265
|
+
srcFiles: {
|
|
266
|
+
"src/index.ts": `import { type Engine, type IDelta, type Particle } from "@tsparticles/engine";
|
|
267
|
+
|
|
268
|
+
declare const __VERSION__: string;
|
|
269
|
+
|
|
270
|
+
interface IInteractivityData {
|
|
271
|
+
type?: string;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
interface IInteractor {
|
|
275
|
+
clear(): void;
|
|
276
|
+
init(): void;
|
|
277
|
+
interact(..._args: unknown[]): void;
|
|
278
|
+
isEnabled(..._args: unknown[]): boolean;
|
|
279
|
+
reset(): void;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
type InteractorFactory = (container: unknown) => Promise<IInteractor>;
|
|
283
|
+
|
|
284
|
+
type PluginManagerWithInteractors = Engine["pluginManager"] & {
|
|
285
|
+
addInteractor?: (name: string, interactor: InteractorFactory) => void;
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
${isExternal
|
|
289
|
+
? `class External${nameData.pascalName}Interactor implements IInteractor {
|
|
290
|
+
clear(): void {
|
|
291
|
+
// TODO: implement clear
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
init(): void {
|
|
295
|
+
// TODO: implement init
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
interact(_data: IInteractivityData, _delta: IDelta): void {
|
|
299
|
+
// TODO: implement interact
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
isEnabled(_data: IInteractivityData, _particle?: Particle): boolean {
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
reset(): void {
|
|
307
|
+
// TODO: implement reset
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
`
|
|
312
|
+
: ""}${isParticles
|
|
313
|
+
? `class Particles${nameData.pascalName}Interactor implements IInteractor {
|
|
314
|
+
clear(): void {
|
|
315
|
+
// TODO: implement clear
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
init(): void {
|
|
319
|
+
// TODO: implement init
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
interact(_particle: Particle, _data: IInteractivityData, _delta: IDelta): void {
|
|
323
|
+
// TODO: implement interact
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
isEnabled(_particle: Particle, _data: IInteractivityData): boolean {
|
|
327
|
+
return false;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
reset(): void {
|
|
331
|
+
// TODO: implement reset
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
`
|
|
336
|
+
: ""}export async function ${loadFunction}(engine: Engine): Promise<void> {
|
|
337
|
+
engine.checkVersion(__VERSION__);
|
|
338
|
+
|
|
339
|
+
await engine.pluginManager.register(e => {
|
|
340
|
+
const pluginManager = e.pluginManager as PluginManagerWithInteractors;
|
|
341
|
+
|
|
342
|
+
${isExternal
|
|
343
|
+
? ` pluginManager.addInteractor?.("external${nameData.pascalName}", () => {
|
|
344
|
+
return Promise.resolve(new External${nameData.pascalName}Interactor());
|
|
345
|
+
});
|
|
346
|
+
`
|
|
347
|
+
: ""}${isParticles
|
|
348
|
+
? ` pluginManager.addInteractor?.("particles${nameData.pascalName}", () => {
|
|
349
|
+
return Promise.resolve(new Particles${nameData.pascalName}Interactor());
|
|
350
|
+
});
|
|
351
|
+
`
|
|
352
|
+
: ""} });
|
|
353
|
+
}
|
|
354
|
+
`,
|
|
355
|
+
"src/index.lazy.ts": getNoopLazyIndex(loadFunction),
|
|
356
|
+
"src/browser.ts": getBrowserFile(loadFunction),
|
|
357
|
+
},
|
|
358
|
+
withBundleFile: false,
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
*
|
|
363
|
+
* @param nameData
|
|
364
|
+
* @param description
|
|
365
|
+
*/
|
|
366
|
+
function createPaletteConfig(nameData, description) {
|
|
367
|
+
const loadFunction = `load${nameData.pascalName}Palette`;
|
|
368
|
+
return {
|
|
369
|
+
description: getProjectDescription("palette", description),
|
|
370
|
+
fileName: `tsparticles.palette.${nameData.camelName}.min.js`,
|
|
371
|
+
jsDelivrFileName: `tsparticles.palette.${nameData.camelName}.min.js`,
|
|
372
|
+
kindLabel: "Palette",
|
|
373
|
+
loadFunction,
|
|
374
|
+
moduleName: `palette-${nameData.dashedName}`,
|
|
375
|
+
packageName: `@tsparticles/palette-${nameData.dashedName}`,
|
|
376
|
+
packageSuffix: `@tsparticles/palette-${nameData.dashedName}`,
|
|
377
|
+
registerName: nameData.dashedName,
|
|
378
|
+
rollupFactory: "loadParticlesPalette",
|
|
379
|
+
rollupNameKey: "paletteName",
|
|
380
|
+
rollupNameValue: `${nameData.pascalName} Palette`,
|
|
381
|
+
srcFiles: {
|
|
382
|
+
"src/options.ts": `import type { ISourceOptions } from "@tsparticles/engine";
|
|
383
|
+
|
|
384
|
+
export const options: ISourceOptions = {
|
|
385
|
+
// TODO: palette options
|
|
386
|
+
};
|
|
387
|
+
`,
|
|
388
|
+
"src/index.ts": `import { type Engine } from "@tsparticles/engine";
|
|
389
|
+
import { options } from "./options.js";
|
|
390
|
+
|
|
391
|
+
export const paletteName = "${nameData.dashedName}";
|
|
392
|
+
|
|
393
|
+
export async function ${loadFunction}(engine: Engine): Promise<void> {
|
|
394
|
+
await engine.pluginManager.register(e => {
|
|
395
|
+
e.pluginManager.addPalette(paletteName, options);
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
`,
|
|
399
|
+
"src/index.lazy.ts": getNoopLazyIndex(loadFunction),
|
|
400
|
+
"src/browser.ts": getBrowserFile(loadFunction),
|
|
401
|
+
},
|
|
402
|
+
withBundleFile: false,
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
*
|
|
407
|
+
* @param nameData
|
|
408
|
+
* @param description
|
|
409
|
+
*/
|
|
410
|
+
function createPathConfig(nameData, description) {
|
|
411
|
+
const loadFunction = `load${nameData.pascalName}Path`, generatorName = `${nameData.pascalName}PathGenerator`;
|
|
412
|
+
return {
|
|
413
|
+
description: getProjectDescription("path", description),
|
|
414
|
+
fileName: `tsparticles.path.${nameData.camelName}.min.js`,
|
|
415
|
+
jsDelivrFileName: `tsparticles.path.${nameData.camelName}.min.js`,
|
|
416
|
+
kindLabel: "Path",
|
|
417
|
+
loadFunction,
|
|
418
|
+
moduleName: nameData.dashedName,
|
|
419
|
+
packageName: `@tsparticles/path-${nameData.dashedName}`,
|
|
420
|
+
packageSuffix: `@tsparticles/path-${nameData.dashedName}`,
|
|
421
|
+
registerName: nameData.camelName,
|
|
422
|
+
rollupFactory: "loadParticlesPath",
|
|
423
|
+
rollupNameKey: "pluginName",
|
|
424
|
+
rollupNameValue: nameData.pascalName,
|
|
425
|
+
srcFiles: {
|
|
426
|
+
"src/index.ts": `import { type Engine, type IDelta, type Particle, Vector } from "@tsparticles/engine";
|
|
427
|
+
|
|
428
|
+
declare const __VERSION__: string;
|
|
429
|
+
|
|
430
|
+
interface IPathGenerator {
|
|
431
|
+
generate(particle: Particle, delta: IDelta): Vector;
|
|
432
|
+
init(): void;
|
|
433
|
+
reset(): void;
|
|
434
|
+
update(): void;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
type PluginManagerWithPath = Engine["pluginManager"] & {
|
|
438
|
+
addPathGenerator?: (name: string, initializer: (container: unknown) => Promise<IPathGenerator>) => void;
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
class ${generatorName} implements IPathGenerator {
|
|
442
|
+
generate(_particle: Particle, _delta: IDelta): Vector {
|
|
443
|
+
return Vector.origin;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
init(): void {
|
|
447
|
+
// TODO: initialize generator
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
reset(): void {
|
|
451
|
+
// TODO: reset state
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
update(): void {
|
|
455
|
+
// TODO: update state
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
export async function ${loadFunction}(engine: Engine): Promise<void> {
|
|
460
|
+
engine.checkVersion(__VERSION__);
|
|
461
|
+
|
|
462
|
+
await engine.pluginManager.register(e => {
|
|
463
|
+
const pluginManager = e.pluginManager as PluginManagerWithPath;
|
|
464
|
+
|
|
465
|
+
pluginManager.addPathGenerator?.("${nameData.camelName}PathGenerator", () => {
|
|
466
|
+
return Promise.resolve(new ${generatorName}());
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
`,
|
|
471
|
+
"src/index.lazy.ts": getNoopLazyIndex(loadFunction),
|
|
472
|
+
"src/browser.ts": getBrowserFile(loadFunction),
|
|
473
|
+
},
|
|
474
|
+
withBundleFile: false,
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
*
|
|
479
|
+
* @param nameData
|
|
480
|
+
* @param loadFunction
|
|
481
|
+
* @param pluginClass
|
|
482
|
+
*/
|
|
483
|
+
function createGenericPluginIndex(loadFunction, pluginClass) {
|
|
484
|
+
return `import { type Engine } from "@tsparticles/engine";
|
|
485
|
+
import { ${pluginClass} } from "./${pluginClass}.js";
|
|
486
|
+
|
|
487
|
+
declare const __VERSION__: string;
|
|
488
|
+
|
|
489
|
+
export async function ${loadFunction}(engine: Engine): Promise<void> {
|
|
490
|
+
engine.checkVersion(__VERSION__);
|
|
491
|
+
|
|
492
|
+
await engine.pluginManager.register(e => {
|
|
493
|
+
e.pluginManager.addPlugin(new ${pluginClass}());
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
`;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
*
|
|
500
|
+
* @param nameData
|
|
501
|
+
* @param description
|
|
502
|
+
* @param type
|
|
503
|
+
*/
|
|
504
|
+
function createPluginConfig(nameData, description, type) {
|
|
505
|
+
if (type === "generic") {
|
|
506
|
+
const loadFunction = `load${nameData.pascalName}Plugin`, pluginClass = `${nameData.pascalName}Plugin`;
|
|
507
|
+
return {
|
|
508
|
+
description: getProjectDescription("plugin", description),
|
|
509
|
+
fileName: `tsparticles.plugin.${nameData.camelName}.min.js`,
|
|
510
|
+
jsDelivrFileName: `tsparticles.plugin.${nameData.camelName}.min.js`,
|
|
511
|
+
kindLabel: "Plugin",
|
|
512
|
+
loadFunction,
|
|
513
|
+
moduleName: nameData.dashedName,
|
|
514
|
+
packageName: `@tsparticles/plugin-${nameData.dashedName}`,
|
|
515
|
+
packageSuffix: `@tsparticles/plugin-${nameData.dashedName}`,
|
|
516
|
+
registerName: nameData.camelName,
|
|
517
|
+
rollupFactory: "loadParticlesPlugin",
|
|
518
|
+
rollupNameKey: "pluginName",
|
|
519
|
+
rollupNameValue: nameData.pascalName,
|
|
520
|
+
srcFiles: {
|
|
521
|
+
"src/PluginInstance.ts": `import { type Container, type IContainerPlugin } from "@tsparticles/engine";
|
|
522
|
+
|
|
523
|
+
export class PluginInstance implements IContainerPlugin {
|
|
524
|
+
constructor(private readonly _container: Container) {}
|
|
525
|
+
|
|
526
|
+
get pluginContainer(): Container {
|
|
527
|
+
return this._container;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
draw(): void {
|
|
531
|
+
// TODO: draw plugin content
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
init(): void {
|
|
535
|
+
// TODO: init plugin instance
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
particleBounce(): void {
|
|
539
|
+
// TODO: handle bounce
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
reset(): void {
|
|
543
|
+
// TODO: reset plugin instance
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
stop(): void {
|
|
547
|
+
// TODO: stop plugin instance
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
`,
|
|
551
|
+
"src/Plugin.ts": `import { type Container, type IPlugin, type ISourceOptions, type Options } from "@tsparticles/engine";
|
|
552
|
+
import type { PluginInstance } from "./PluginInstance.js";
|
|
553
|
+
|
|
554
|
+
export class ${pluginClass} implements IPlugin {
|
|
555
|
+
readonly id = "${nameData.camelName}";
|
|
556
|
+
|
|
557
|
+
async getPlugin(container: Container): Promise<PluginInstance> {
|
|
558
|
+
const { PluginInstance } = await import("./PluginInstance.js");
|
|
559
|
+
|
|
560
|
+
return new PluginInstance(container);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
loadOptions(_container: Container, _options: Options, _source?: ISourceOptions): void {
|
|
564
|
+
// TODO: load plugin options
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
needsPlugin(_options?: ISourceOptions): boolean {
|
|
568
|
+
return true;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
`,
|
|
572
|
+
"src/index.ts": createGenericPluginIndex(loadFunction, pluginClass),
|
|
573
|
+
"src/index.lazy.ts": getNoopLazyIndex(loadFunction),
|
|
574
|
+
"src/browser.ts": getBrowserFile(loadFunction),
|
|
575
|
+
},
|
|
576
|
+
withBundleFile: false,
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
if (type === "emitters-shape") {
|
|
580
|
+
const loadFunction = `loadEmittersShape${nameData.pascalName}`, className = `${nameData.pascalName}EmittersShapeGenerator`;
|
|
581
|
+
return {
|
|
582
|
+
description: getProjectDescription("emitters shape plugin", description),
|
|
583
|
+
fileName: `tsparticles.plugin.emitters.shape.${nameData.camelName}.min.js`,
|
|
584
|
+
jsDelivrFileName: `tsparticles.plugin.emitters.shape.${nameData.camelName}.min.js`,
|
|
585
|
+
kindLabel: "Plugin",
|
|
586
|
+
loadFunction,
|
|
587
|
+
moduleName: nameData.dashedName,
|
|
588
|
+
packageName: `@tsparticles/plugin-emitters-shape-${nameData.dashedName}`,
|
|
589
|
+
packageSuffix: `@tsparticles/plugin-emitters-shape-${nameData.dashedName}`,
|
|
590
|
+
registerName: nameData.dashedName,
|
|
591
|
+
rollupFactory: "loadParticlesPluginEmittersShape",
|
|
592
|
+
rollupNameKey: "pluginName",
|
|
593
|
+
rollupNameValue: nameData.pascalName,
|
|
594
|
+
srcFiles: {
|
|
595
|
+
"src/index.ts": `import { type Engine, type ICoordinates, type IDimension } from "@tsparticles/engine";
|
|
596
|
+
|
|
597
|
+
declare const __VERSION__: string;
|
|
598
|
+
|
|
599
|
+
interface IEmitterShape {
|
|
600
|
+
init(): Promise<void>;
|
|
601
|
+
randomPosition(): { offset: ICoordinates } | null;
|
|
602
|
+
resize(position: ICoordinates, size: IDimension): void;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
interface IEmitterShapeGenerator {
|
|
606
|
+
generate(container: unknown, position: ICoordinates, size: IDimension, fill: boolean, options: unknown): IEmitterShape;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
type PluginManagerWithEmitterShapes = Engine["pluginManager"] & {
|
|
610
|
+
addEmitterShapeGenerator?: (name: string, generator: IEmitterShapeGenerator) => void;
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
class ${className} implements IEmitterShapeGenerator {
|
|
614
|
+
generate(_container: unknown, position: ICoordinates): IEmitterShape {
|
|
615
|
+
return {
|
|
616
|
+
init: () => Promise.resolve(),
|
|
617
|
+
randomPosition: () => ({ offset: position }),
|
|
618
|
+
resize: () => {
|
|
619
|
+
// TODO: resize emitter shape
|
|
620
|
+
},
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
export async function ${loadFunction}(engine: Engine): Promise<void> {
|
|
626
|
+
engine.checkVersion(__VERSION__);
|
|
627
|
+
|
|
628
|
+
await engine.pluginManager.register(e => {
|
|
629
|
+
const pluginManager = e.pluginManager as PluginManagerWithEmitterShapes;
|
|
630
|
+
|
|
631
|
+
pluginManager.addEmitterShapeGenerator?.("${nameData.dashedName}", new ${className}());
|
|
632
|
+
});
|
|
633
|
+
}
|
|
634
|
+
`,
|
|
635
|
+
"src/index.lazy.ts": getNoopLazyIndex(loadFunction),
|
|
636
|
+
"src/browser.ts": getBrowserFile(loadFunction),
|
|
637
|
+
},
|
|
638
|
+
withBundleFile: false,
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
if (type === "easing") {
|
|
642
|
+
const loadFunction = `loadEasing${nameData.pascalName}Plugin`;
|
|
643
|
+
return {
|
|
644
|
+
description: getProjectDescription("easing plugin", description),
|
|
645
|
+
fileName: `tsparticles.plugin.easing.${nameData.camelName}.min.js`,
|
|
646
|
+
jsDelivrFileName: `tsparticles.plugin.easing.${nameData.camelName}.min.js`,
|
|
647
|
+
kindLabel: "Plugin",
|
|
648
|
+
loadFunction,
|
|
649
|
+
moduleName: nameData.dashedName,
|
|
650
|
+
packageName: `@tsparticles/plugin-easing-${nameData.dashedName}`,
|
|
651
|
+
packageSuffix: `@tsparticles/plugin-easing-${nameData.dashedName}`,
|
|
652
|
+
registerName: nameData.dashedName,
|
|
653
|
+
rollupFactory: "loadParticlesPluginEasing",
|
|
654
|
+
rollupNameKey: "pluginName",
|
|
655
|
+
rollupNameValue: nameData.pascalName,
|
|
656
|
+
srcFiles: {
|
|
657
|
+
"src/index.ts": `import { type Engine } from "@tsparticles/engine";
|
|
658
|
+
|
|
659
|
+
declare const __VERSION__: string;
|
|
660
|
+
|
|
661
|
+
const easingName = "${nameData.camelName}";
|
|
662
|
+
|
|
663
|
+
function easing(value: number): number {
|
|
664
|
+
return value;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
export async function ${loadFunction}(engine: Engine): Promise<void> {
|
|
668
|
+
engine.checkVersion(__VERSION__);
|
|
669
|
+
|
|
670
|
+
await engine.pluginManager.register(e => {
|
|
671
|
+
e.pluginManager.addEasing(easingName, easing);
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
`,
|
|
675
|
+
"src/index.lazy.ts": getNoopLazyIndex(loadFunction),
|
|
676
|
+
"src/browser.ts": getBrowserFile(loadFunction),
|
|
677
|
+
},
|
|
678
|
+
withBundleFile: false,
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
if (type === "export") {
|
|
682
|
+
const loadFunction = `loadExport${nameData.pascalName}Plugin`, pluginClass = `${nameData.pascalName}ExportPlugin`;
|
|
683
|
+
return {
|
|
684
|
+
description: getProjectDescription("export plugin", description),
|
|
685
|
+
fileName: `tsparticles.plugin.export.${nameData.camelName}.min.js`,
|
|
686
|
+
jsDelivrFileName: `tsparticles.plugin.export.${nameData.camelName}.min.js`,
|
|
687
|
+
kindLabel: "Plugin",
|
|
688
|
+
loadFunction,
|
|
689
|
+
moduleName: nameData.dashedName,
|
|
690
|
+
packageName: `@tsparticles/plugin-export-${nameData.dashedName}`,
|
|
691
|
+
packageSuffix: `@tsparticles/plugin-export-${nameData.dashedName}`,
|
|
692
|
+
registerName: nameData.camelName,
|
|
693
|
+
rollupFactory: "loadParticlesPluginExport",
|
|
694
|
+
rollupNameKey: "pluginName",
|
|
695
|
+
rollupNameValue: nameData.pascalName,
|
|
696
|
+
srcFiles: {
|
|
697
|
+
"src/ExportPlugin.ts": `import { type Container, type IContainerPlugin, type IPlugin, type ISourceOptions, type Options } from "@tsparticles/engine";
|
|
698
|
+
|
|
699
|
+
class ${nameData.pascalName}ExportPluginInstance implements IContainerPlugin {
|
|
700
|
+
constructor(private readonly _container: Container) {}
|
|
701
|
+
|
|
702
|
+
get pluginContainer(): Container {
|
|
703
|
+
return this._container;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
draw(): void {
|
|
707
|
+
// TODO: export draw
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
init(): void {
|
|
711
|
+
// TODO: export init
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
particleBounce(): void {
|
|
715
|
+
// TODO: export bounce
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
reset(): void {
|
|
719
|
+
// TODO: export reset
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
stop(): void {
|
|
723
|
+
// TODO: export stop
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
export class ${pluginClass} implements IPlugin {
|
|
728
|
+
readonly id = "export-${nameData.camelName}";
|
|
729
|
+
|
|
730
|
+
async getPlugin(container: Container): Promise<IContainerPlugin> {
|
|
731
|
+
return new ${nameData.pascalName}ExportPluginInstance(container);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
loadOptions(_container: Container, _options: Options, _source?: ISourceOptions): void {
|
|
735
|
+
// TODO: load export options
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
needsPlugin(_options?: ISourceOptions): boolean {
|
|
739
|
+
return true;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
`,
|
|
743
|
+
"src/index.ts": createGenericPluginIndex(loadFunction, pluginClass),
|
|
744
|
+
"src/index.lazy.ts": getNoopLazyIndex(loadFunction),
|
|
745
|
+
"src/browser.ts": getBrowserFile(loadFunction),
|
|
746
|
+
},
|
|
747
|
+
withBundleFile: false,
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
const loadFunction = `load${nameData.pascalName}ColorPlugin`, managerClass = `${nameData.pascalName}ColorManager`;
|
|
751
|
+
return {
|
|
752
|
+
description: getProjectDescription("color manager plugin", description),
|
|
753
|
+
fileName: `tsparticles.plugin.${nameData.camelName}Color.min.js`,
|
|
754
|
+
jsDelivrFileName: `tsparticles.plugin.${nameData.camelName}Color.min.js`,
|
|
755
|
+
kindLabel: "Plugin",
|
|
756
|
+
loadFunction,
|
|
757
|
+
moduleName: `${nameData.camelName}Color`,
|
|
758
|
+
packageName: `@tsparticles/plugin-${nameData.dashedName}-color`,
|
|
759
|
+
packageSuffix: `@tsparticles/plugin-${nameData.dashedName}-color`,
|
|
760
|
+
registerName: nameData.dashedName,
|
|
761
|
+
rollupFactory: "loadParticlesPlugin",
|
|
762
|
+
rollupNameKey: "pluginName",
|
|
763
|
+
rollupNameValue: `${nameData.pascalName} Color`,
|
|
764
|
+
srcFiles: {
|
|
765
|
+
"src/ColorManager.ts": `import { type IColor, type IColorManager, type IRangeColor, type IRgb, type IRgba } from "@tsparticles/engine";
|
|
766
|
+
|
|
767
|
+
export class ${managerClass} implements IColorManager {
|
|
768
|
+
accepts(input: string): boolean {
|
|
769
|
+
return input.startsWith("${nameData.camelName}(");
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
handleColor(_color: IColor): IRgb | undefined {
|
|
773
|
+
return undefined;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
handleRangeColor(_color: IRangeColor): IRgb | undefined {
|
|
777
|
+
return undefined;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
parseString(_input: string): IRgba | undefined {
|
|
781
|
+
return undefined;
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
`,
|
|
785
|
+
"src/index.ts": `import { type Engine } from "@tsparticles/engine";
|
|
786
|
+
import { ${managerClass} } from "./ColorManager.js";
|
|
787
|
+
|
|
788
|
+
declare const __VERSION__: string;
|
|
789
|
+
|
|
790
|
+
export async function ${loadFunction}(engine: Engine): Promise<void> {
|
|
791
|
+
engine.checkVersion(__VERSION__);
|
|
792
|
+
|
|
793
|
+
await engine.pluginManager.register(e => {
|
|
794
|
+
e.pluginManager.addColorManager("${nameData.camelName}", new ${managerClass}());
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
`,
|
|
798
|
+
"src/index.lazy.ts": getNoopLazyIndex(loadFunction),
|
|
799
|
+
"src/browser.ts": getBrowserFile(loadFunction),
|
|
800
|
+
},
|
|
801
|
+
withBundleFile: false,
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
*
|
|
806
|
+
* @param nameData
|
|
807
|
+
* @param description
|
|
808
|
+
*/
|
|
809
|
+
function createPresetConfig(nameData, description) {
|
|
810
|
+
const loadFunction = `load${nameData.pascalName}Preset`;
|
|
811
|
+
return {
|
|
812
|
+
description: getProjectDescription("preset", description),
|
|
813
|
+
fileName: `tsparticles.preset.${nameData.camelName}.min.js`,
|
|
814
|
+
jsDelivrFileName: `tsparticles.preset.${nameData.camelName}.min.js`,
|
|
815
|
+
kindLabel: "Preset",
|
|
816
|
+
loadFunction,
|
|
817
|
+
moduleName: nameData.dashedName,
|
|
818
|
+
packageName: `@tsparticles/preset-${nameData.dashedName}`,
|
|
819
|
+
packageSuffix: `@tsparticles/preset-${nameData.dashedName}`,
|
|
820
|
+
registerName: nameData.camelName,
|
|
821
|
+
rollupFactory: "loadParticlesPreset",
|
|
822
|
+
rollupNameKey: "presetName",
|
|
823
|
+
rollupNameValue: nameData.pascalName,
|
|
824
|
+
srcFiles: {
|
|
825
|
+
"src/options.ts": `import type { ISourceOptions } from "@tsparticles/engine";
|
|
826
|
+
|
|
827
|
+
export const options: ISourceOptions = {
|
|
828
|
+
// TODO: preset options
|
|
829
|
+
};
|
|
830
|
+
`,
|
|
831
|
+
"src/index.ts": `import { type Engine } from "@tsparticles/engine";
|
|
832
|
+
import { options } from "./options.js";
|
|
833
|
+
|
|
834
|
+
declare const __VERSION__: string;
|
|
835
|
+
|
|
836
|
+
export async function ${loadFunction}(engine: Engine): Promise<void> {
|
|
837
|
+
engine.checkVersion(__VERSION__);
|
|
838
|
+
|
|
839
|
+
await engine.pluginManager.register(e => {
|
|
840
|
+
e.pluginManager.addPreset("${nameData.camelName}", options);
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
`,
|
|
844
|
+
"src/index.lazy.ts": getNoopLazyIndex(loadFunction),
|
|
845
|
+
"src/browser.ts": getBrowserFile(loadFunction),
|
|
846
|
+
"src/bundle.ts": getBundleFile(loadFunction, false),
|
|
847
|
+
},
|
|
848
|
+
withBundleFile: true,
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
/**
|
|
852
|
+
*
|
|
853
|
+
* @param nameData
|
|
854
|
+
* @param description
|
|
855
|
+
*/
|
|
856
|
+
function createShapeConfig(nameData, description) {
|
|
857
|
+
const loadFunction = `load${nameData.pascalName}Shape`, className = `${nameData.pascalName}ShapeDrawer`;
|
|
858
|
+
return {
|
|
859
|
+
description: getProjectDescription("shape", description),
|
|
860
|
+
fileName: `tsparticles.shape.${nameData.camelName}.min.js`,
|
|
861
|
+
jsDelivrFileName: `tsparticles.shape.${nameData.camelName}.min.js`,
|
|
862
|
+
kindLabel: "Shape",
|
|
863
|
+
loadFunction,
|
|
864
|
+
moduleName: nameData.dashedName,
|
|
865
|
+
packageName: `@tsparticles/shape-${nameData.dashedName}`,
|
|
866
|
+
packageSuffix: `@tsparticles/shape-${nameData.dashedName}`,
|
|
867
|
+
registerName: nameData.camelName,
|
|
868
|
+
rollupFactory: "loadParticlesShape",
|
|
869
|
+
rollupNameKey: "shapeName",
|
|
870
|
+
rollupNameValue: nameData.pascalName,
|
|
871
|
+
srcFiles: {
|
|
872
|
+
"src/ShapeDrawer.ts": `import { type IShapeDrawData, type IShapeDrawer } from "@tsparticles/engine";
|
|
873
|
+
|
|
874
|
+
export class ${className} implements IShapeDrawer {
|
|
875
|
+
readonly validTypes = ["${nameData.camelName}"] as const;
|
|
876
|
+
|
|
877
|
+
draw(_data: IShapeDrawData): void {
|
|
878
|
+
// TODO: draw shape
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
`,
|
|
882
|
+
"src/index.ts": `import { type Engine } from "@tsparticles/engine";
|
|
883
|
+
import { ${className} } from "./ShapeDrawer.js";
|
|
884
|
+
|
|
885
|
+
declare const __VERSION__: string;
|
|
886
|
+
|
|
887
|
+
export async function ${loadFunction}(engine: Engine): Promise<void> {
|
|
888
|
+
engine.checkVersion(__VERSION__);
|
|
889
|
+
|
|
890
|
+
await engine.pluginManager.register(e => {
|
|
891
|
+
e.pluginManager.addShape(["${nameData.camelName}"], () => {
|
|
892
|
+
return Promise.resolve(new ${className}());
|
|
893
|
+
});
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
`,
|
|
897
|
+
"src/index.lazy.ts": getNoopLazyIndex(loadFunction),
|
|
898
|
+
"src/browser.ts": getBrowserFile(loadFunction),
|
|
899
|
+
},
|
|
900
|
+
withBundleFile: false,
|
|
901
|
+
};
|
|
902
|
+
}
|
|
903
|
+
/**
|
|
904
|
+
*
|
|
905
|
+
* @param nameData
|
|
906
|
+
* @param description
|
|
907
|
+
*/
|
|
908
|
+
function createUpdaterConfig(nameData, description) {
|
|
909
|
+
const loadFunction = `load${nameData.pascalName}Updater`, className = `${nameData.pascalName}Updater`;
|
|
910
|
+
return {
|
|
911
|
+
description: getProjectDescription("updater", description),
|
|
912
|
+
fileName: `tsparticles.updater.${nameData.camelName}.min.js`,
|
|
913
|
+
jsDelivrFileName: `tsparticles.updater.${nameData.camelName}.min.js`,
|
|
914
|
+
kindLabel: "Updater",
|
|
915
|
+
loadFunction,
|
|
916
|
+
moduleName: nameData.dashedName,
|
|
917
|
+
packageName: `@tsparticles/updater-${nameData.dashedName}`,
|
|
918
|
+
packageSuffix: `@tsparticles/updater-${nameData.dashedName}`,
|
|
919
|
+
registerName: nameData.camelName,
|
|
920
|
+
rollupFactory: "loadParticlesUpdater",
|
|
921
|
+
rollupNameKey: "updaterName",
|
|
922
|
+
rollupNameValue: nameData.pascalName,
|
|
923
|
+
srcFiles: {
|
|
924
|
+
"src/Updater.ts": `import { type IDelta, type IParticleUpdater, type Particle } from "@tsparticles/engine";
|
|
925
|
+
|
|
926
|
+
export class ${className} implements IParticleUpdater {
|
|
927
|
+
init(_particle: Particle): void {
|
|
928
|
+
// TODO: init updater
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
isEnabled(_particle: Particle): boolean {
|
|
932
|
+
return true;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
update(_particle: Particle, _delta: IDelta): void {
|
|
936
|
+
// TODO: update particle
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
`,
|
|
940
|
+
"src/index.ts": `import { type Engine } from "@tsparticles/engine";
|
|
941
|
+
import { ${className} } from "./Updater.js";
|
|
942
|
+
|
|
943
|
+
declare const __VERSION__: string;
|
|
944
|
+
|
|
945
|
+
export async function ${loadFunction}(engine: Engine): Promise<void> {
|
|
946
|
+
engine.checkVersion(__VERSION__);
|
|
947
|
+
|
|
948
|
+
await engine.pluginManager.register(e => {
|
|
949
|
+
e.pluginManager.addParticleUpdater("${nameData.camelName}", () => {
|
|
950
|
+
return Promise.resolve(new ${className}());
|
|
951
|
+
});
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
`,
|
|
955
|
+
"src/index.lazy.ts": getNoopLazyIndex(loadFunction),
|
|
956
|
+
"src/browser.ts": getBrowserFile(loadFunction),
|
|
957
|
+
},
|
|
958
|
+
withBundleFile: false,
|
|
959
|
+
};
|
|
960
|
+
}
|
|
961
|
+
/**
|
|
962
|
+
*
|
|
963
|
+
* @param options
|
|
964
|
+
* @param nameData
|
|
965
|
+
*/
|
|
966
|
+
function resolveProjectConfig(options, nameData) {
|
|
967
|
+
switch (options.kind) {
|
|
968
|
+
case "bundle":
|
|
969
|
+
return createBundleConfig(nameData, options.description);
|
|
970
|
+
case "effect":
|
|
971
|
+
return createEffectConfig(nameData, options.description);
|
|
972
|
+
case "interaction":
|
|
973
|
+
return createInteractionConfig(nameData, options.description, options.type ?? "generic");
|
|
974
|
+
case "palette":
|
|
975
|
+
return createPaletteConfig(nameData, options.description);
|
|
976
|
+
case "path":
|
|
977
|
+
return createPathConfig(nameData, options.description);
|
|
978
|
+
case "plugin":
|
|
979
|
+
return createPluginConfig(nameData, options.description, options.type ?? "generic");
|
|
980
|
+
case "preset":
|
|
981
|
+
return createPresetConfig(nameData, options.description);
|
|
982
|
+
case "shape":
|
|
983
|
+
return createShapeConfig(nameData, options.description);
|
|
984
|
+
case "updater":
|
|
985
|
+
return createUpdaterConfig(nameData, options.description);
|
|
986
|
+
default:
|
|
987
|
+
throw new Error(`Unsupported kind: ${String(options.kind)}`);
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
*
|
|
992
|
+
* @param destination
|
|
993
|
+
* @param srcFiles
|
|
994
|
+
*/
|
|
995
|
+
async function writeSourceFiles(destination, srcFiles) {
|
|
996
|
+
for (const [filePath, content] of Object.entries(srcFiles)) {
|
|
997
|
+
const targetPath = path.join(destination, filePath), folderPath = path.dirname(targetPath);
|
|
998
|
+
await mkdir(folderPath, { recursive: true });
|
|
999
|
+
await writeFile(targetPath, content);
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
/**
|
|
1003
|
+
*
|
|
1004
|
+
* @param options
|
|
1005
|
+
*/
|
|
1006
|
+
export async function createProjectTemplate(options) {
|
|
1007
|
+
const nameData = getNameData(options.name, options.destination), config = resolveProjectConfig(options, nameData), repoUrl = getRepoUrl(options.repositoryUrl, config.packageSuffix), metadata = {
|
|
1008
|
+
description: config.description,
|
|
1009
|
+
directory: nameData.folderName,
|
|
1010
|
+
packageName: config.packageName,
|
|
1011
|
+
repoUrl,
|
|
1012
|
+
unpkgFileName: config.jsDelivrFileName,
|
|
1013
|
+
};
|
|
1014
|
+
await copyEmptyTemplateFiles(options.destination);
|
|
1015
|
+
await writeSourceFiles(options.destination, config.srcFiles);
|
|
1016
|
+
await writeFile(path.join(options.destination, "rollup.config.js"), getRollupConfig(config));
|
|
1017
|
+
await writeFile(path.join(options.destination, "README.md"), getReadme(config));
|
|
1018
|
+
await updatePackageFile(options.destination, metadata);
|
|
1019
|
+
await updatePackageDistFile(options.destination, metadata);
|
|
1020
|
+
await runInstall(options.destination);
|
|
1021
|
+
await runBuild(options.destination);
|
|
1022
|
+
}
|