@tsparticles/rollup-plugin 3.4.14 → 4.0.0-beta.12
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/buildMap.d.ts +1 -1
- package/dist/buildMap.d.ts.map +1 -1
- package/dist/config/createConfig.d.ts.map +1 -1
- package/dist/config/createSingleConfig.d.ts +1 -0
- package/dist/config/createSingleConfig.d.ts.map +1 -1
- package/dist/config/entry.d.ts +1 -0
- package/dist/config/entry.d.ts.map +1 -1
- package/dist/config/externals.d.ts +3 -4
- package/dist/config/externals.d.ts.map +1 -1
- package/dist/config/umdPolicy.d.ts +6 -0
- package/dist/config/umdPolicy.d.ts.map +1 -0
- package/dist/createParticlesBuild.d.ts.map +1 -1
- package/dist/index.cjs +584 -16
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +584 -17
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -2
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var fs = require('node:fs');
|
|
3
4
|
var path = require('node:path');
|
|
5
|
+
var pluginNodeResolve = require('@rollup/plugin-node-resolve');
|
|
4
6
|
var replace = require('@rollup/plugin-replace');
|
|
5
7
|
var terser = require('@rollup/plugin-terser');
|
|
6
8
|
var rollupPluginVisualizer = require('rollup-plugin-visualizer');
|
|
@@ -88,19 +90,276 @@ const buildMap = {
|
|
|
88
90
|
banner: ({ version }) => `Updater v${version}`,
|
|
89
91
|
minBanner: ({ version }) => `Updater v${version}`,
|
|
90
92
|
},
|
|
93
|
+
util: {
|
|
94
|
+
format: "",
|
|
95
|
+
hasBundle: false,
|
|
96
|
+
banner: ({ version }) => `Utility v${version}`,
|
|
97
|
+
minBanner: ({ version, bundleName }) => `tsParticles ${bundleName ?? "Utility"} v${version}`,
|
|
98
|
+
},
|
|
91
99
|
};
|
|
92
100
|
|
|
93
101
|
const getEntry = (data) => {
|
|
94
|
-
const { bundle, format, lazy, min, name } = data, fileName = bundle ? "bundle" : "index", completeFileName = lazy ? `${fileName}.lazy` : fileName, fixFormat = format ? `.${format}` : "", fixName = name ? `.${name}` : "", fixMin = min ? ".min" : "", fixLazy = lazy ? ".lazy" : "";
|
|
102
|
+
const { bundle, dir, format, lazy, min, name } = data, fileName = bundle ? "bundle" : "index", browserFileName = "browser", completeFileName = lazy ? `${fileName}.lazy` : fileName, completeBrowserFileName = lazy ? `${browserFileName}.lazy` : browserFileName, browserCandidate = path.resolve(dir, "dist/browser", `${completeBrowserFileName}.js`), inputFileName = !bundle && fs.existsSync(browserCandidate) ? completeBrowserFileName : completeFileName, fixFormat = format ? `.${format}` : "", fixName = name ? `.${name}` : "", fixMin = min ? ".min" : "", fixLazy = lazy ? ".lazy" : "";
|
|
95
103
|
return {
|
|
96
104
|
name: `tsparticles${fixFormat}${fixName}${fixLazy}${fixMin}`,
|
|
97
|
-
input: `./dist/browser/${
|
|
105
|
+
input: `./dist/browser/${inputFileName}.js`,
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const internalRoot = "__tsParticlesInternals";
|
|
110
|
+
const toScopeSegment = (value) => {
|
|
111
|
+
const normalized = value
|
|
112
|
+
.replaceAll(/([a-z\d])([A-Z])/g, "$1-$2")
|
|
113
|
+
.replaceAll(/[._\s]+/g, "-")
|
|
114
|
+
.toLowerCase();
|
|
115
|
+
return normalized
|
|
116
|
+
.split("-")
|
|
117
|
+
.filter(Boolean)
|
|
118
|
+
.map((segment, index) => index === 0 ? segment : `${segment[0]?.toUpperCase() ?? ""}${segment.slice(1)}`)
|
|
119
|
+
.join("");
|
|
120
|
+
};
|
|
121
|
+
const resolveBundleScope = (moduleName) => {
|
|
122
|
+
if (!moduleName) {
|
|
123
|
+
return "full";
|
|
124
|
+
}
|
|
125
|
+
return toScopeSegment(moduleName);
|
|
126
|
+
};
|
|
127
|
+
const resolveKind = (scope) => {
|
|
128
|
+
if (scope === "pjs") {
|
|
129
|
+
return "pjs";
|
|
130
|
+
}
|
|
131
|
+
if (scope === "confetti") {
|
|
132
|
+
return "confetti";
|
|
133
|
+
}
|
|
134
|
+
if (scope === "fireworks") {
|
|
135
|
+
return "fireworks";
|
|
136
|
+
}
|
|
137
|
+
return "bundle";
|
|
138
|
+
};
|
|
139
|
+
const buildTypePrefix = {
|
|
140
|
+
effect: "effects",
|
|
141
|
+
interaction: "interactions",
|
|
142
|
+
interactionExternal: "interactions",
|
|
143
|
+
interactionParticles: "interactions",
|
|
144
|
+
palette: "palettes",
|
|
145
|
+
path: "paths",
|
|
146
|
+
plugin: "plugins",
|
|
147
|
+
pluginEasing: "plugins",
|
|
148
|
+
pluginEmittersShape: "plugins.emittersShapes",
|
|
149
|
+
pluginExport: "plugins",
|
|
150
|
+
preset: "presets",
|
|
151
|
+
shape: "shapes",
|
|
152
|
+
template: "utils",
|
|
153
|
+
updater: "updaters",
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* Qualifies a raw module-name leaf with a type-specific prefix so that
|
|
157
|
+
* `getUmdPolicyData` produces the same namespace as `getUmdGlobalForExternal`.
|
|
158
|
+
* Without this, `interactionExternal "parallax"` would land on
|
|
159
|
+
* `interactions.parallax` while the non-bundled consumer expects
|
|
160
|
+
* `interactions.externalParallax`, causing a UMD global mismatch.
|
|
161
|
+
*/
|
|
162
|
+
const leafPrefixes = {
|
|
163
|
+
interactionExternal: "external-",
|
|
164
|
+
interactionParticles: "particles-",
|
|
165
|
+
pluginEasing: "easing-",
|
|
166
|
+
};
|
|
167
|
+
const qualifyLeaf = (type, rawLeaf) => {
|
|
168
|
+
const prefix = leafPrefixes[type];
|
|
169
|
+
return prefix ? `${prefix}${rawLeaf}` : rawLeaf;
|
|
170
|
+
};
|
|
171
|
+
const getUmdPolicyData = (type, moduleName) => {
|
|
172
|
+
if (type === "engine") {
|
|
173
|
+
return {
|
|
174
|
+
kind: "engine",
|
|
175
|
+
scope: `${internalRoot}.engine`,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
if (type === "bundle") {
|
|
179
|
+
const scope = resolveBundleScope(moduleName);
|
|
180
|
+
return {
|
|
181
|
+
kind: resolveKind(scope),
|
|
182
|
+
scope: `${internalRoot}.bundles.${scope}`,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
if (type === "util") {
|
|
186
|
+
// Util packages use the moduleName as-is (dots as separators), e.g. "canvas.utils" -> "__tsParticlesInternals.canvas.utils"
|
|
187
|
+
// This must match the getUmdGlobalForExternal fallback for deps that reference these packages.
|
|
188
|
+
return {
|
|
189
|
+
kind: "package",
|
|
190
|
+
scope: `${internalRoot}.${moduleName ?? "util"}`,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
const prefix = buildTypePrefix[type], rawLeaf = moduleName ?? "default", leaf = toScopeSegment(qualifyLeaf(type, rawLeaf));
|
|
194
|
+
return {
|
|
195
|
+
kind: "package",
|
|
196
|
+
scope: `${internalRoot}.${prefix}.${leaf}`,
|
|
98
197
|
};
|
|
99
198
|
};
|
|
199
|
+
const buildScopedPath = (prefix, rawLeaf) => {
|
|
200
|
+
const leaf = toScopeSegment(rawLeaf);
|
|
201
|
+
return `${internalRoot}.${prefix}.${leaf}`;
|
|
202
|
+
};
|
|
203
|
+
const bundleLeafGlobals = new Map(["all", "basic", "confetti", "fireworks", "pjs", "slim"].map(leaf => [leaf, `${internalRoot}.bundles.${leaf}`]));
|
|
204
|
+
const scopedPrefixRules = [
|
|
205
|
+
{
|
|
206
|
+
// @tsparticles/plugin-export-image -> __tsParticlesInternals.plugins.image
|
|
207
|
+
prefix: "plugin-export-",
|
|
208
|
+
scope: "plugins",
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
prefix: "plugin-emitters-shape-",
|
|
212
|
+
scope: "plugins.emittersShapes",
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
prefix: "plugin-",
|
|
216
|
+
scope: "plugins",
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
prefix: "interaction-external-",
|
|
220
|
+
scope: "interactions",
|
|
221
|
+
transform: segment => `external-${segment}`,
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
prefix: "interaction-particles-",
|
|
225
|
+
scope: "interactions",
|
|
226
|
+
transform: segment => `particles-${segment}`,
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
prefix: "interaction-",
|
|
230
|
+
scope: "interactions",
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
prefix: "effect-",
|
|
234
|
+
scope: "effects",
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
prefix: "path-",
|
|
238
|
+
scope: "paths",
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
prefix: "shape-",
|
|
242
|
+
scope: "shapes",
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
prefix: "updater-",
|
|
246
|
+
scope: "updaters",
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
prefix: "palette-",
|
|
250
|
+
scope: "palettes",
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
prefix: "preset-",
|
|
254
|
+
scope: "presets",
|
|
255
|
+
},
|
|
256
|
+
];
|
|
257
|
+
const getScopedGlobalFromPrefix = (leaf) => {
|
|
258
|
+
for (const rule of scopedPrefixRules) {
|
|
259
|
+
if (!leaf.startsWith(rule.prefix)) {
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
const segment = leaf.slice(rule.prefix.length);
|
|
263
|
+
return buildScopedPath(rule.scope, rule.transform ? rule.transform(segment) : segment);
|
|
264
|
+
}
|
|
265
|
+
return undefined;
|
|
266
|
+
};
|
|
267
|
+
const getScopedGlobalForLeaf = (leaf) => {
|
|
268
|
+
const directLeafMap = new Map([
|
|
269
|
+
["engine", `${internalRoot}.engine`],
|
|
270
|
+
// Util packages: not "path plugins" but helper utilities; map to their actual scope
|
|
271
|
+
["path-utils", `${internalRoot}.path.utils`],
|
|
272
|
+
["canvas-utils", `${internalRoot}.canvas.utils`],
|
|
273
|
+
// Historical package name mismatch: @tsparticles/path-zig-zag exposes paths.zigzag.
|
|
274
|
+
["path-zig-zag", `${internalRoot}.paths.zigzag`],
|
|
275
|
+
// Historical package name mismatch: @tsparticles/plugin-poisson-disc exposes plugins.poisson.
|
|
276
|
+
["plugin-poisson-disc", `${internalRoot}.plugins.poisson`],
|
|
277
|
+
...bundleLeafGlobals,
|
|
278
|
+
]), bundleLeaf = directLeafMap.get(leaf);
|
|
279
|
+
if (bundleLeaf) {
|
|
280
|
+
return bundleLeaf;
|
|
281
|
+
}
|
|
282
|
+
const scopedLeaf = getScopedGlobalFromPrefix(leaf);
|
|
283
|
+
if (scopedLeaf) {
|
|
284
|
+
return scopedLeaf;
|
|
285
|
+
}
|
|
286
|
+
return `${internalRoot}.${leaf.split("-").map(toScopeSegment).join(".")}`;
|
|
287
|
+
};
|
|
288
|
+
const getUmdGlobalForExternal = (id) => {
|
|
289
|
+
if (id === "tsparticles") {
|
|
290
|
+
return `${internalRoot}.bundles.full`;
|
|
291
|
+
}
|
|
292
|
+
if (id.startsWith("tsparticles-")) {
|
|
293
|
+
return buildScopedPath("bundles", id.slice("tsparticles-".length));
|
|
294
|
+
}
|
|
295
|
+
if (!id.startsWith("@tsparticles/")) {
|
|
296
|
+
return undefined;
|
|
297
|
+
}
|
|
298
|
+
return getScopedGlobalForLeaf(id.slice("@tsparticles/".length));
|
|
299
|
+
};
|
|
300
|
+
const getUmdGlobalsBootstrap = (temporaryGlobalName) => {
|
|
301
|
+
const temporaryBootstrap = `g.${temporaryGlobalName}=g.${temporaryGlobalName}||{};`
|
|
302
|
+
;
|
|
303
|
+
// Pre-create namespaces (including nested ones) to avoid eager UMD external lookups
|
|
304
|
+
// crashing on missing branches like plugins.emittersShapes.circle.
|
|
305
|
+
const namespaces = [
|
|
306
|
+
"bundles",
|
|
307
|
+
"effects",
|
|
308
|
+
"engine",
|
|
309
|
+
"interactions",
|
|
310
|
+
"palettes",
|
|
311
|
+
"paths",
|
|
312
|
+
"plugins",
|
|
313
|
+
"plugins.emittersShapes",
|
|
314
|
+
"presets",
|
|
315
|
+
"shapes",
|
|
316
|
+
"updaters",
|
|
317
|
+
"utils",
|
|
318
|
+
"canvas",
|
|
319
|
+
"canvas.utils",
|
|
320
|
+
"path",
|
|
321
|
+
"path.utils",
|
|
322
|
+
], namespacesBootstrap = namespaces
|
|
323
|
+
.map(namespace => {
|
|
324
|
+
const segments = namespace.split(".");
|
|
325
|
+
let currentPath = "g.__tsParticlesInternals";
|
|
326
|
+
return segments
|
|
327
|
+
.map(segment => {
|
|
328
|
+
currentPath += `.${segment}`;
|
|
329
|
+
return `${currentPath}=${currentPath}||{};`;
|
|
330
|
+
})
|
|
331
|
+
.join("");
|
|
332
|
+
})
|
|
333
|
+
.join("");
|
|
334
|
+
return (`(function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};${namespacesBootstrap}` +
|
|
335
|
+
`var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};` +
|
|
336
|
+
`g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);` +
|
|
337
|
+
`g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);` +
|
|
338
|
+
`g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);` +
|
|
339
|
+
`g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);` +
|
|
340
|
+
`g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);` +
|
|
341
|
+
`g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);` +
|
|
342
|
+
`g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);` +
|
|
343
|
+
`g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);` +
|
|
344
|
+
`g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);` +
|
|
345
|
+
`g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);` +
|
|
346
|
+
`g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);` +
|
|
347
|
+
`g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);` +
|
|
348
|
+
`g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);` +
|
|
349
|
+
`${temporaryBootstrap}})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);\n`);
|
|
350
|
+
};
|
|
100
351
|
|
|
352
|
+
const defaultGlobal = "window";
|
|
353
|
+
const getRootGlobal = (external) => {
|
|
354
|
+
const root = external.data?.root;
|
|
355
|
+
if (Array.isArray(root)) {
|
|
356
|
+
return root.filter((t) => typeof t === "string").join(".") || defaultGlobal;
|
|
357
|
+
}
|
|
358
|
+
return typeof root === "string" ? root : defaultGlobal;
|
|
359
|
+
};
|
|
101
360
|
const getExternal = ({ bundle, additionalExternals = [] }) => {
|
|
102
361
|
if (bundle) {
|
|
103
|
-
return
|
|
362
|
+
return additionalExternals.filter(e => !e.bundle).map(e => e.name);
|
|
104
363
|
}
|
|
105
364
|
return [
|
|
106
365
|
...additionalExternals.map(e => e.name),
|
|
@@ -110,22 +369,302 @@ const getExternal = ({ bundle, additionalExternals = [] }) => {
|
|
|
110
369
|
];
|
|
111
370
|
};
|
|
112
371
|
const getGlobals = (additionalExternals = [], bundle) => {
|
|
113
|
-
|
|
114
|
-
|
|
372
|
+
const globalsAdditional = bundle ? additionalExternals.filter(e => !e.bundle) : additionalExternals;
|
|
373
|
+
const additionalMap = new Map(globalsAdditional.map(e => [e.name, getRootGlobal(e)]));
|
|
374
|
+
return (id) => {
|
|
375
|
+
if (additionalMap.has(id)) {
|
|
376
|
+
return additionalMap.get(id) ?? defaultGlobal;
|
|
377
|
+
}
|
|
378
|
+
const tsparticlesGlobal = getUmdGlobalForExternal(id);
|
|
379
|
+
if (tsparticlesGlobal) {
|
|
380
|
+
return tsparticlesGlobal;
|
|
381
|
+
}
|
|
382
|
+
return defaultGlobal;
|
|
383
|
+
};
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
const toJsBanner = (text) => {
|
|
387
|
+
return `/* ${text} */`;
|
|
388
|
+
};
|
|
389
|
+
const temporaryUmdGlobal = "tsparticlesInternalExports";
|
|
390
|
+
const lazyWrapperVirtualPrefix = "\0tsparticles-lazy-wrapper:";
|
|
391
|
+
// Public export predicate per kind
|
|
392
|
+
const getPublicExports = (exports$1, kind) => {
|
|
393
|
+
const fixedPublicMap = {
|
|
394
|
+
confetti: "confetti",
|
|
395
|
+
engine: "tsParticles",
|
|
396
|
+
fireworks: "fireworks",
|
|
397
|
+
pjs: "initPjs",
|
|
398
|
+
};
|
|
399
|
+
if (kind === "bundle") {
|
|
400
|
+
// Bundles expose load* functions AND the tsParticles instance (needed for bundle users)
|
|
401
|
+
return exports$1.filter(t => /^load[A-Z]/.test(t) || t === "tsParticles");
|
|
402
|
+
}
|
|
403
|
+
if (kind === "package") {
|
|
404
|
+
return exports$1.filter(t => /^load[A-Z]/.test(t));
|
|
115
405
|
}
|
|
116
|
-
|
|
406
|
+
const requiredExport = fixedPublicMap[kind];
|
|
407
|
+
if (!exports$1.includes(requiredExport)) {
|
|
408
|
+
throw new Error(`UMD public export policy violated: missing ${requiredExport}`);
|
|
409
|
+
}
|
|
410
|
+
return [requiredExport];
|
|
411
|
+
};
|
|
412
|
+
const validatePublicExports = (publicExports, allExports, kind) => {
|
|
413
|
+
const fixedPublicMap = {
|
|
414
|
+
confetti: "confetti",
|
|
415
|
+
engine: "tsParticles",
|
|
416
|
+
fireworks: "fireworks",
|
|
417
|
+
pjs: "initPjs",
|
|
418
|
+
};
|
|
419
|
+
if (kind !== "bundle" && kind !== "package") {
|
|
420
|
+
const required = fixedPublicMap[kind];
|
|
421
|
+
if (!allExports.includes(required)) {
|
|
422
|
+
throw new Error(`UMD public export policy violated: missing ${required}`);
|
|
423
|
+
}
|
|
424
|
+
if (publicExports.length !== 1 || publicExports[0] !== required) {
|
|
425
|
+
throw new Error(`UMD public export policy violated: ${kind} can expose only ${required}`);
|
|
426
|
+
}
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
// For bundle/package: only load* (and tsParticles for bundle) are allowed on window
|
|
430
|
+
const invalid = publicExports.filter(t => !/^load[A-Z]/.test(t) && t !== "tsParticles");
|
|
431
|
+
if (invalid.length > 0) {
|
|
432
|
+
throw new Error(`UMD public export policy violated: only load* exports (and tsParticles for bundles) are allowed on window, found ${invalid.join(", ")}`);
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
/**
|
|
436
|
+
* Build the namespace initialization expression to use as the UMD factory's first argument.
|
|
437
|
+
* Example: scope = "__tsParticlesInternals.engine"
|
|
438
|
+
* Result: "(global.__tsParticlesInternals = global.__tsParticlesInternals || {}, global.__tsParticlesInternals.engine = global.__tsParticlesInternals.engine || {})"
|
|
439
|
+
*
|
|
440
|
+
* This is used to REPLACE `global.window = global.tsparticlesInternalExports || {}` in the UMD wrapper,
|
|
441
|
+
* so that rollup writes all exports directly into the correct namespace object.
|
|
442
|
+
*/
|
|
443
|
+
const buildGlobalNamespaceInit = (scope) => {
|
|
444
|
+
const segments = scope.split(".");
|
|
445
|
+
const inits = [];
|
|
446
|
+
let currentPath = "global";
|
|
447
|
+
for (const segment of segments) {
|
|
448
|
+
currentPath += `.${segment}`;
|
|
449
|
+
inits.push(`${currentPath} = ${currentPath} || {}`);
|
|
450
|
+
}
|
|
451
|
+
return `(${inits.join(", ")})`;
|
|
452
|
+
};
|
|
453
|
+
/**
|
|
454
|
+
* Replace the UMD factory's exports target (global.window = ...) with the correct namespace path.
|
|
455
|
+
* This makes rollup write all `exports.X = X` directly into __tsParticlesInternals.<scope>.
|
|
456
|
+
*/
|
|
457
|
+
const redirectUmdExportsToNamespace = (code, scope) => {
|
|
458
|
+
const namespaceInit = buildGlobalNamespaceInit(scope);
|
|
459
|
+
return code
|
|
460
|
+
// multi-dependency case: factory(global.window = ..., globalDep1, ...)
|
|
461
|
+
.replaceAll(`factory(global.window = global.${temporaryUmdGlobal} || {}, `, `factory(${namespaceInit}, `)
|
|
462
|
+
.replaceAll(`factory(global.window = {}, `, `factory(${namespaceInit}, `)
|
|
463
|
+
// single case: factory(global.window = ...)
|
|
464
|
+
.replaceAll(`factory(global.window = global.${temporaryUmdGlobal} || {})`, `factory(${namespaceInit})`)
|
|
465
|
+
.replaceAll(`factory(global.window = {})`, `factory(${namespaceInit})`);
|
|
466
|
+
};
|
|
467
|
+
/**
|
|
468
|
+
* Build the code that copies public exports from the namespace to window.
|
|
469
|
+
* Reads from globalThis.__tsParticlesInternals.<scope>.<export> after the factory has run.
|
|
470
|
+
*/
|
|
471
|
+
const buildWindowExposureCode = (scope, publicExports) => {
|
|
472
|
+
if (publicExports.length === 0) {
|
|
473
|
+
return "";
|
|
474
|
+
}
|
|
475
|
+
const assignments = publicExports.map(exp => `${exp}: (globalThis.${scope} || {}).${exp}`).join(", ");
|
|
476
|
+
return `Object.assign(globalThis.window || globalThis, { ${assignments} });\n`;
|
|
477
|
+
};
|
|
478
|
+
const buildBundleEngineAliasCode = (umdPolicy) => {
|
|
479
|
+
if (umdPolicy.kind !== "bundle") {
|
|
480
|
+
return "";
|
|
481
|
+
}
|
|
482
|
+
// Keep backward compatibility for packages that still resolve engine externals from internals.engine.
|
|
483
|
+
return (`globalThis.__tsParticlesInternals = globalThis.__tsParticlesInternals || {};\n` +
|
|
484
|
+
`if (!globalThis.__tsParticlesInternals.engine || !globalThis.__tsParticlesInternals.engine.tsParticles) {\n` +
|
|
485
|
+
` globalThis.__tsParticlesInternals.engine = globalThis.${umdPolicy.scope} || {};\n` +
|
|
486
|
+
`}\n`);
|
|
487
|
+
};
|
|
488
|
+
const buildLazyRuntimePath = (name) => {
|
|
489
|
+
return `chunks/${name}.js`;
|
|
117
490
|
};
|
|
491
|
+
const getLazyRuntimeInputPath = (dir) => {
|
|
492
|
+
return path.resolve(dir, "dist/browser/index.lazy.js");
|
|
493
|
+
};
|
|
494
|
+
const parseNamedExports = (content) => {
|
|
495
|
+
const exports$1 = new Set();
|
|
496
|
+
for (const match of content.matchAll(/export\s+(?:async\s+)?(?:function|class|const|let|var)\s+([A-Za-z_$][\w$]*)/g)) {
|
|
497
|
+
exports$1.add(match[1]);
|
|
498
|
+
}
|
|
499
|
+
for (const match of content.matchAll(/export\s*{([^}]+)}(?!\s*from)/g)) {
|
|
500
|
+
const values = match[1]
|
|
501
|
+
.split(",")
|
|
502
|
+
.map(value => value.trim())
|
|
503
|
+
.filter(Boolean)
|
|
504
|
+
.map(value => value.split(/\s+as\s+/).pop()?.trim())
|
|
505
|
+
.filter((value) => Boolean(value));
|
|
506
|
+
for (const value of values) {
|
|
507
|
+
exports$1.add(value);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
return [...exports$1];
|
|
511
|
+
};
|
|
512
|
+
const resolveLazyEntryExports = (filePath, visited = new Set()) => {
|
|
513
|
+
if (visited.has(filePath) || !fs.existsSync(filePath)) {
|
|
514
|
+
return [];
|
|
515
|
+
}
|
|
516
|
+
visited.add(filePath);
|
|
517
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
518
|
+
const exports$1 = new Set(parseNamedExports(content));
|
|
519
|
+
for (const match of content.matchAll(/export\s+(?:\*|{[^}]+})\s+from\s+["'](.+?)["']/g)) {
|
|
520
|
+
const specifier = match[1];
|
|
521
|
+
if (!specifier.startsWith(".")) {
|
|
522
|
+
continue;
|
|
523
|
+
}
|
|
524
|
+
const resolvedPath = path.resolve(path.dirname(filePath), specifier);
|
|
525
|
+
const normalizedPath = path.extname(resolvedPath) ? resolvedPath : `${resolvedPath}.js`;
|
|
526
|
+
for (const value of resolveLazyEntryExports(normalizedPath, visited)) {
|
|
527
|
+
exports$1.add(value);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
return [...exports$1];
|
|
531
|
+
};
|
|
532
|
+
const createLazyWrapperEntryPlugin = (params, min) => {
|
|
533
|
+
const { dir, umdPolicy } = params;
|
|
534
|
+
const { name } = getEntry({ ...params.entry, dir, min, lazy: true });
|
|
535
|
+
const runtimePath = buildLazyRuntimePath(name);
|
|
536
|
+
const runtimeInputPath = getLazyRuntimeInputPath(dir);
|
|
537
|
+
const lazyExports = resolveLazyEntryExports(runtimeInputPath);
|
|
538
|
+
const publicExports = getPublicExports([...new Set(umdPolicy.kind === "bundle" ? [...lazyExports, "tsParticles"] : lazyExports)], umdPolicy.kind);
|
|
539
|
+
const needsEngineExports = publicExports.includes("tsParticles") || umdPolicy.kind === "bundle";
|
|
540
|
+
const exportedDeclarations = publicExports
|
|
541
|
+
.filter(exp => exp !== "tsParticles")
|
|
542
|
+
.map(exp => `const ${exp} = async (...args) => { const module = await getLazyModule(); return module.${exp}(...args); };`)
|
|
543
|
+
.join("\n");
|
|
544
|
+
const tsParticlesExport = publicExports.includes("tsParticles")
|
|
545
|
+
? "const tsParticles = engineExports.tsParticles;"
|
|
546
|
+
: "";
|
|
547
|
+
const namedExports = publicExports.join(", ");
|
|
548
|
+
const engineBootstrap = needsEngineExports
|
|
549
|
+
? [
|
|
550
|
+
"globalThis.__tsParticlesInternals = globalThis.__tsParticlesInternals || {};",
|
|
551
|
+
"globalThis.__tsParticlesInternals.engine = globalThis.__tsParticlesInternals.engine || engineExports;",
|
|
552
|
+
].join("\n")
|
|
553
|
+
: "";
|
|
554
|
+
const imports = needsEngineExports ? 'import * as engineExports from "@tsparticles/engine";\n' : "";
|
|
555
|
+
const source = `${imports}
|
|
556
|
+
const currentScript = typeof document !== "undefined" ? document.currentScript : undefined;
|
|
557
|
+
const runtimeUrl = new URL("${runtimePath}", currentScript?.src ?? globalThis.location?.href ?? "/").href;
|
|
558
|
+
let lazyModulePromise;
|
|
559
|
+
const dynamicImport = new Function("path", "return import(path);");
|
|
560
|
+
const getLazyModule = () => {
|
|
561
|
+
lazyModulePromise ??= dynamicImport(runtimeUrl);
|
|
118
562
|
|
|
563
|
+
return lazyModulePromise;
|
|
564
|
+
};
|
|
565
|
+
${engineBootstrap}
|
|
566
|
+
${tsParticlesExport}
|
|
567
|
+
${exportedDeclarations}
|
|
568
|
+
export { ${namedExports} };
|
|
569
|
+
`;
|
|
570
|
+
return {
|
|
571
|
+
name: "tsparticles-lazy-wrapper-entry",
|
|
572
|
+
resolveId(id) {
|
|
573
|
+
return id === `${lazyWrapperVirtualPrefix}${name}` ? id : null;
|
|
574
|
+
},
|
|
575
|
+
load(id) {
|
|
576
|
+
return id === `${lazyWrapperVirtualPrefix}${name}` ? source : null;
|
|
577
|
+
},
|
|
578
|
+
};
|
|
579
|
+
};
|
|
580
|
+
const exposeEntryExports = (enabled, umdPolicy) => {
|
|
581
|
+
return {
|
|
582
|
+
name: "expose-entry-exports",
|
|
583
|
+
renderChunk(code, chunk) {
|
|
584
|
+
if (!chunk.isEntry) {
|
|
585
|
+
return null;
|
|
586
|
+
}
|
|
587
|
+
const exports$1 = chunk.exports.filter(t => t !== "default");
|
|
588
|
+
// No exports at all - just bootstrap namespace and clean up
|
|
589
|
+
if (exports$1.length === 0) {
|
|
590
|
+
if (!umdPolicy) {
|
|
591
|
+
return null;
|
|
592
|
+
}
|
|
593
|
+
const umdCode = redirectUmdExportsToNamespace(code, umdPolicy.scope);
|
|
594
|
+
return {
|
|
595
|
+
code: `${getUmdGlobalsBootstrap(temporaryUmdGlobal)}${umdCode}\ndelete (globalThis.window || globalThis).${temporaryUmdGlobal};\n`,
|
|
596
|
+
map: null,
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
// No UMD policy (e.g. ESM lazy split bundles) - expose all to window (old behavior)
|
|
600
|
+
if (!umdPolicy) {
|
|
601
|
+
const assignments = exports$1.map(t => `${t}: ${t}`).join(", ");
|
|
602
|
+
return {
|
|
603
|
+
code: `${code}\nObject.assign(globalThis.window || globalThis, { ${assignments} });\n`,
|
|
604
|
+
map: null,
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
// With UMD policy:
|
|
608
|
+
// 1) Redirect factory's exports target to the internal namespace
|
|
609
|
+
// 2) After factory runs, copy public exports from namespace to window
|
|
610
|
+
const publicExports = getPublicExports(exports$1, umdPolicy.kind);
|
|
611
|
+
validatePublicExports(publicExports, exports$1, umdPolicy.kind);
|
|
612
|
+
// The key step: replace factory's first arg so rollup writes all exports to __tsParticlesInternals.<scope>
|
|
613
|
+
const umdCode = redirectUmdExportsToNamespace(code, umdPolicy.scope);
|
|
614
|
+
// Read public exports from the namespace and expose on window
|
|
615
|
+
const windowCode = buildWindowExposureCode(umdPolicy.scope, publicExports);
|
|
616
|
+
const engineAliasCode = buildBundleEngineAliasCode(umdPolicy);
|
|
617
|
+
return {
|
|
618
|
+
code: `${getUmdGlobalsBootstrap(temporaryUmdGlobal)}${umdCode}\n${windowCode}${engineAliasCode}` +
|
|
619
|
+
`delete (globalThis.window || globalThis).${temporaryUmdGlobal};\n`,
|
|
620
|
+
map: null,
|
|
621
|
+
};
|
|
622
|
+
},
|
|
623
|
+
};
|
|
624
|
+
};
|
|
119
625
|
const createSingleConfig = (params, min, lazy) => {
|
|
120
|
-
const { additionalExternals, banner, bundle, dir, entry, minBanner, version
|
|
626
|
+
const { additionalExternals, banner, bundle, dir, entry, minBanner, version } = params, { name, input } = getEntry({ ...entry, dir, min, lazy }), wrapperEntryPlugin = lazy ? createLazyWrapperEntryPlugin(params, min) : undefined;
|
|
627
|
+
if (lazy) {
|
|
628
|
+
return {
|
|
629
|
+
input: `${lazyWrapperVirtualPrefix}${name}`,
|
|
630
|
+
external: getExternal({ bundle, additionalExternals }),
|
|
631
|
+
plugins: [
|
|
632
|
+
wrapperEntryPlugin,
|
|
633
|
+
pluginNodeResolve.nodeResolve({
|
|
634
|
+
browser: true,
|
|
635
|
+
}),
|
|
636
|
+
replace({
|
|
637
|
+
preventAssignment: true,
|
|
638
|
+
__VERSION__: JSON.stringify(version),
|
|
639
|
+
}),
|
|
640
|
+
exposeEntryExports(true, params.umdPolicy),
|
|
641
|
+
min && terser(),
|
|
642
|
+
].filter(Boolean),
|
|
643
|
+
output: {
|
|
644
|
+
file: path.resolve(dir, "dist", `${name}.js`),
|
|
645
|
+
format: "umd",
|
|
646
|
+
name: temporaryUmdGlobal,
|
|
647
|
+
globals: getGlobals(additionalExternals, bundle),
|
|
648
|
+
banner: toJsBanner(min ? minBanner : banner),
|
|
649
|
+
// inlineDynamicImports must be true for UMD (Rollup doesn't support code-splitting in UMD format).
|
|
650
|
+
// The actual lazy loading is handled at runtime via `new Function("path", "return import(path)")`
|
|
651
|
+
// which Rollup cannot see/inline — so setting this to true has no effect on lazy behaviour.
|
|
652
|
+
inlineDynamicImports: true,
|
|
653
|
+
},
|
|
654
|
+
};
|
|
655
|
+
}
|
|
121
656
|
return {
|
|
122
657
|
input,
|
|
123
658
|
external: getExternal({ bundle, additionalExternals }),
|
|
124
659
|
plugins: [
|
|
660
|
+
pluginNodeResolve.nodeResolve({
|
|
661
|
+
browser: true,
|
|
662
|
+
}),
|
|
125
663
|
replace({
|
|
126
664
|
preventAssignment: true,
|
|
127
665
|
__VERSION__: JSON.stringify(version),
|
|
128
666
|
}),
|
|
667
|
+
exposeEntryExports(true, params.umdPolicy),
|
|
129
668
|
!min &&
|
|
130
669
|
rollupPluginVisualizer.visualizer({
|
|
131
670
|
filename: path.resolve(dir, "dist/report.html"),
|
|
@@ -135,21 +674,44 @@ const createSingleConfig = (params, min, lazy) => {
|
|
|
135
674
|
output: {
|
|
136
675
|
file: path.resolve(dir, "dist", `${name}.js`),
|
|
137
676
|
format: "umd",
|
|
138
|
-
name:
|
|
677
|
+
name: temporaryUmdGlobal,
|
|
139
678
|
globals: getGlobals(additionalExternals, bundle),
|
|
140
|
-
banner: min ? minBanner : banner,
|
|
679
|
+
banner: toJsBanner(min ? minBanner : banner),
|
|
141
680
|
inlineDynamicImports: true,
|
|
142
681
|
},
|
|
143
682
|
};
|
|
144
683
|
};
|
|
684
|
+
const createLazyRuntimeConfig = (params, min) => {
|
|
685
|
+
const { additionalExternals, banner, bundle, dir, entry, minBanner, version } = params, { name } = getEntry({ ...entry, dir, min, lazy: true });
|
|
686
|
+
return {
|
|
687
|
+
input: getLazyRuntimeInputPath(dir),
|
|
688
|
+
external: getExternal({ bundle, additionalExternals }),
|
|
689
|
+
plugins: [
|
|
690
|
+
pluginNodeResolve.nodeResolve({
|
|
691
|
+
browser: true,
|
|
692
|
+
}),
|
|
693
|
+
replace({
|
|
694
|
+
preventAssignment: true,
|
|
695
|
+
__VERSION__: JSON.stringify(version),
|
|
696
|
+
}),
|
|
697
|
+
min && terser(),
|
|
698
|
+
].filter(Boolean),
|
|
699
|
+
output: {
|
|
700
|
+
dir: path.resolve(dir, "dist"),
|
|
701
|
+
format: "es",
|
|
702
|
+
entryFileNames: buildLazyRuntimePath(name),
|
|
703
|
+
chunkFileNames: min ? "chunks/[name]-[hash].min.js" : "chunks/[name]-[hash].js",
|
|
704
|
+
banner: toJsBanner(min ? minBanner : banner),
|
|
705
|
+
},
|
|
706
|
+
};
|
|
707
|
+
};
|
|
145
708
|
|
|
146
709
|
const createConfig = (params) => {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
createSingleConfig(params, true,
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
];
|
|
710
|
+
const configs = [createSingleConfig(params, false, false), createSingleConfig(params, true, false)];
|
|
711
|
+
if (params.includeLazy) {
|
|
712
|
+
configs.push(createLazyRuntimeConfig(params, false), createSingleConfig(params, false, true), createLazyRuntimeConfig(params, true), createSingleConfig(params, true, true));
|
|
713
|
+
}
|
|
714
|
+
return configs;
|
|
153
715
|
};
|
|
154
716
|
|
|
155
717
|
const createParticlesBuild = (type, params) => {
|
|
@@ -157,7 +719,7 @@ const createParticlesBuild = (type, params) => {
|
|
|
157
719
|
if (!def) {
|
|
158
720
|
throw new Error(`Unknown build type: ${type}`);
|
|
159
721
|
}
|
|
160
|
-
const dir = params.dir, version = params.version, additionalExternals = params.additionalExternals, moduleName = params.moduleName, bundle = params.bundle, banner = def.banner(params), minBanner = def.minBanner(params), base = createConfig({
|
|
722
|
+
const dir = params.dir, version = params.version, additionalExternals = params.additionalExternals, moduleName = params.moduleName, bundle = params.bundle, umdPolicy = getUmdPolicyData(type, moduleName), banner = def.banner(params), minBanner = def.minBanner(params), base = createConfig({
|
|
161
723
|
entry: {
|
|
162
724
|
format: def.format,
|
|
163
725
|
name: moduleName,
|
|
@@ -168,6 +730,8 @@ const createParticlesBuild = (type, params) => {
|
|
|
168
730
|
minBanner,
|
|
169
731
|
dir,
|
|
170
732
|
bundle: false,
|
|
733
|
+
includeLazy: false,
|
|
734
|
+
umdPolicy,
|
|
171
735
|
additionalExternals,
|
|
172
736
|
});
|
|
173
737
|
if (def.hasBundle && (bundle ?? true)) {
|
|
@@ -186,6 +750,8 @@ const createParticlesBuild = (type, params) => {
|
|
|
186
750
|
minBanner,
|
|
187
751
|
dir,
|
|
188
752
|
bundle: true,
|
|
753
|
+
includeLazy: false,
|
|
754
|
+
umdPolicy,
|
|
189
755
|
additionalExternals,
|
|
190
756
|
}),
|
|
191
757
|
];
|
|
@@ -209,6 +775,7 @@ const loadParticlesPreset = (p) => createParticlesBuild("preset", p);
|
|
|
209
775
|
const loadParticlesShape = (p) => createParticlesBuild("shape", p);
|
|
210
776
|
const loadParticlesTemplate = (p) => createParticlesBuild("template", p);
|
|
211
777
|
const loadParticlesUpdater = (p) => createParticlesBuild("updater", p);
|
|
778
|
+
const loadParticlesUtil = (p) => createParticlesBuild("util", p);
|
|
212
779
|
|
|
213
780
|
exports.createParticlesBuild = createParticlesBuild;
|
|
214
781
|
exports.loadParticlesBundle = loadParticlesBundle;
|
|
@@ -227,3 +794,4 @@ exports.loadParticlesPreset = loadParticlesPreset;
|
|
|
227
794
|
exports.loadParticlesShape = loadParticlesShape;
|
|
228
795
|
exports.loadParticlesTemplate = loadParticlesTemplate;
|
|
229
796
|
exports.loadParticlesUpdater = loadParticlesUpdater;
|
|
797
|
+
exports.loadParticlesUtil = loadParticlesUtil;
|