scratch4js 1.0.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/README.md ADDED
@@ -0,0 +1,118 @@
1
+ # scratch4js
2
+
3
+ Read and edit Scratch **`.sb3`** projects with a small, declarative API.
4
+
5
+ An `.sb3` file is just a zip containing a `project.json` (the stage, the
6
+ sprites, their scripts) plus the costume and sound files it references.
7
+ scratch4js wraps that with plain objects you can read and mutate, then zip back
8
+ up. It uses [`@turbowarp/jszip`](https://github.com/TurboWarp/jszip) for fast
9
+ (de)compression and pure JSON for everything else — no Scratch VM, no DOM.
10
+
11
+ Works in Node and the browser. Written in plain JS with JSDoc types.
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ pnpm add scratch4js
17
+ ```
18
+
19
+ ## Quick start
20
+
21
+ ```js
22
+ import { Project } from 'scratch4js';
23
+ import { readFile, writeFile } from 'node:fs/promises';
24
+
25
+ // Load an .sb3 from its bytes.
26
+ const project = await Project.load(await readFile('game.sb3'));
27
+
28
+ // Edit sprites declaratively.
29
+ const cat = project.sprite('Sprite1');
30
+ cat.x = 0;
31
+ cat.y = -20;
32
+ cat.size = 150;
33
+ cat.visible = true;
34
+
35
+ // Variables, lists and broadcasts.
36
+ project.stage.setVariable('score', 0);
37
+ project.stage.setList('inventory', ['sword', 'shield']);
38
+ project.stage.addBroadcast('game over');
39
+
40
+ // Save back to .sb3 bytes.
41
+ await writeFile('game.edited.sb3', await project.save());
42
+ ```
43
+
44
+ In the browser, `Project.load` accepts an `ArrayBuffer`/`Uint8Array` (e.g. from a
45
+ file input) and `save()` returns a `Uint8Array` you can wrap in a `Blob`.
46
+
47
+ ## API
48
+
49
+ ### `Project`
50
+
51
+ | Member | Description |
52
+ | ----------------------------------------------- | ------------------------------------------------------ |
53
+ | `await Project.load(bytes)` | Parse an `.sb3` (`Uint8Array`/`ArrayBuffer`/`Buffer`). |
54
+ | `Project.create()` | A new, empty project with a bare stage. |
55
+ | `project.stage` | The `Stage` target. |
56
+ | `project.sprites` | Array of `Sprite` targets. |
57
+ | `project.targets` | Every target, stage included. |
58
+ | `project.sprite(name)` / `project.target(name)` | Look up by name. |
59
+ | `project.addSprite(name, props?)` | Add a sprite (give it a costume before use). |
60
+ | `project.removeSprite(name)` | Remove a sprite; drops assets it solely owned. |
61
+ | `project.meta` / `monitors` / `extensions` | Raw project-level fields. |
62
+ | `await project.save({ compressionLevel })` | Serialize to `.sb3` bytes. |
63
+
64
+ ### `Sprite` / `Stage` (extend `Target`)
65
+
66
+ Shared `Target` accessors: `name`, `volume`, `costumes`, `currentCostume`,
67
+ `sounds`, and the raw `blocks` object.
68
+
69
+ - **Costumes & sounds:** `getCostume(name)`, `addCostume(name, bytes, opts?)`,
70
+ `removeCostume(nameOrIndex)`, and the matching `getSound` / `addSound` /
71
+ `removeSound`. Asset bytes are stored under their MD5 automatically, and the
72
+ file type is sniffed from the bytes (override with `opts.dataFormat`).
73
+ - **Variables & lists:** `getVariable(name)`, `setVariable(name, value)`,
74
+ `deleteVariable(name)`, `variableNames`, plus `getList` / `setList` /
75
+ `deleteList` / `listNames`.
76
+
77
+ `Sprite` adds: `x`, `y`, `size`, `direction`, `visible`, `draggable`,
78
+ `rotationStyle`, `layerOrder`.
79
+
80
+ `Stage` adds: `tempo`, `videoState`, `videoTransparency`, `broadcastNames`, and
81
+ `addBroadcast(name)`.
82
+
83
+ ### `Costume` / `Sound`
84
+
85
+ `name`, `dataFormat`, `md5ext`, and `data` (the raw bytes). Assigning to `data`
86
+ re-hashes and rewrites `assetId`/`md5ext`. Costumes also expose
87
+ `rotationCenterX/Y` and `bitmapResolution`; sounds expose `rate` and
88
+ `sampleCount`.
89
+
90
+ ### Utilities
91
+
92
+ `md5(bytes)`, `uid()` (Scratch-style id), and `sniffFormat(bytes)` are exported
93
+ for convenience.
94
+
95
+ ## Example: swap a costume's image
96
+
97
+ ```js
98
+ import { Project } from 'scratch4js';
99
+ import { readFile, writeFile } from 'node:fs/promises';
100
+
101
+ const project = await Project.load(await readFile('game.sb3'));
102
+
103
+ const cat = project.sprite('Sprite1');
104
+ cat.getCostume('costume1').data = await readFile('new-cat.png');
105
+ cat.addSound('boop', await readFile('boop.wav'));
106
+
107
+ await writeFile('game.edited.sb3', await project.save());
108
+ ```
109
+
110
+ ## Develop
111
+
112
+ ```bash
113
+ pnpm install
114
+ pnpm run build # bundle to dist/ (esm, cjs, umd)
115
+ pnpm run dev # watch mode
116
+ pnpm run lint
117
+ pnpm run format
118
+ ```
package/dist/LICENSE ADDED
@@ -0,0 +1,373 @@
1
+ Mozilla Public License Version 2.0
2
+ ==================================
3
+
4
+ 1. Definitions
5
+ --------------
6
+
7
+ 1.1. "Contributor"
8
+ means each individual or legal entity that creates, contributes to
9
+ the creation of, or owns Covered Software.
10
+
11
+ 1.2. "Contributor Version"
12
+ means the combination of the Contributions of others (if any) used
13
+ by a Contributor and that particular Contributor's Contribution.
14
+
15
+ 1.3. "Contribution"
16
+ means Covered Software of a particular Contributor.
17
+
18
+ 1.4. "Covered Software"
19
+ means Source Code Form to which the initial Contributor has attached
20
+ the notice in Exhibit A, the Executable Form of such Source Code
21
+ Form, and Modifications of such Source Code Form, in each case
22
+ including portions thereof.
23
+
24
+ 1.5. "Incompatible With Secondary Licenses"
25
+ means
26
+
27
+ (a) that the initial Contributor has attached the notice described
28
+ in Exhibit B to the Covered Software; or
29
+
30
+ (b) that the Covered Software was made available under the terms of
31
+ version 1.1 or earlier of the License, but not also under the
32
+ terms of a Secondary License.
33
+
34
+ 1.6. "Executable Form"
35
+ means any form of the work other than Source Code Form.
36
+
37
+ 1.7. "Larger Work"
38
+ means a work that combines Covered Software with other material, in
39
+ a separate file or files, that is not Covered Software.
40
+
41
+ 1.8. "License"
42
+ means this document.
43
+
44
+ 1.9. "Licensable"
45
+ means having the right to grant, to the maximum extent possible,
46
+ whether at the time of the initial grant or subsequently, any and
47
+ all of the rights conveyed by this License.
48
+
49
+ 1.10. "Modifications"
50
+ means any of the following:
51
+
52
+ (a) any file in Source Code Form that results from an addition to,
53
+ deletion from, or modification of the contents of Covered
54
+ Software; or
55
+
56
+ (b) any new file in Source Code Form that contains any Covered
57
+ Software.
58
+
59
+ 1.11. "Patent Claims" of a Contributor
60
+ means any patent claim(s), including without limitation, method,
61
+ process, and apparatus claims, in any patent Licensable by such
62
+ Contributor that would be infringed, but for the grant of the
63
+ License, by the making, using, selling, offering for sale, having
64
+ made, import, or transfer of either its Contributions or its
65
+ Contributor Version.
66
+
67
+ 1.12. "Secondary License"
68
+ means either the GNU General Public License, Version 2.0, the GNU
69
+ Lesser General Public License, Version 2.1, the GNU Affero General
70
+ Public License, Version 3.0, or any later versions of those
71
+ licenses.
72
+
73
+ 1.13. "Source Code Form"
74
+ means the form of the work preferred for making modifications.
75
+
76
+ 1.14. "You" (or "Your")
77
+ means an individual or a legal entity exercising rights under this
78
+ License. For legal entities, "You" includes any entity that
79
+ controls, is controlled by, or is under common control with You. For
80
+ purposes of this definition, "control" means (a) the power, direct
81
+ or indirect, to cause the direction or management of such entity,
82
+ whether by contract or otherwise, or (b) ownership of more than
83
+ fifty percent (50%) of the outstanding shares or beneficial
84
+ ownership of such entity.
85
+
86
+ 2. License Grants and Conditions
87
+ --------------------------------
88
+
89
+ 2.1. Grants
90
+
91
+ Each Contributor hereby grants You a world-wide, royalty-free,
92
+ non-exclusive license:
93
+
94
+ (a) under intellectual property rights (other than patent or trademark)
95
+ Licensable by such Contributor to use, reproduce, make available,
96
+ modify, display, perform, distribute, and otherwise exploit its
97
+ Contributions, either on an unmodified basis, with Modifications, or
98
+ as part of a Larger Work; and
99
+
100
+ (b) under Patent Claims of such Contributor to make, use, sell, offer
101
+ for sale, have made, import, and otherwise transfer either its
102
+ Contributions or its Contributor Version.
103
+
104
+ 2.2. Effective Date
105
+
106
+ The licenses granted in Section 2.1 with respect to any Contribution
107
+ become effective for each Contribution on the date the Contributor first
108
+ distributes such Contribution.
109
+
110
+ 2.3. Limitations on Grant Scope
111
+
112
+ The licenses granted in this Section 2 are the only rights granted under
113
+ this License. No additional rights or licenses will be implied from the
114
+ distribution or licensing of Covered Software under this License.
115
+ Notwithstanding Section 2.1(b) above, no patent license is granted by a
116
+ Contributor:
117
+
118
+ (a) for any code that a Contributor has removed from Covered Software;
119
+ or
120
+
121
+ (b) for infringements caused by: (i) Your and any other third party's
122
+ modifications of Covered Software, or (ii) the combination of its
123
+ Contributions with other software (except as part of its Contributor
124
+ Version); or
125
+
126
+ (c) under Patent Claims infringed by Covered Software in the absence of
127
+ its Contributions.
128
+
129
+ This License does not grant any rights in the trademarks, service marks,
130
+ or logos of any Contributor (except as may be necessary to comply with
131
+ the notice requirements in Section 3.4).
132
+
133
+ 2.4. Subsequent Licenses
134
+
135
+ No Contributor makes additional grants as a result of Your choice to
136
+ distribute the Covered Software under a subsequent version of this
137
+ License (see Section 10.2) or under the terms of a Secondary License (if
138
+ permitted under the terms of Section 3.3).
139
+
140
+ 2.5. Representation
141
+
142
+ Each Contributor represents that the Contributor believes its
143
+ Contributions are its original creation(s) or it has sufficient rights
144
+ to grant the rights to its Contributions conveyed by this License.
145
+
146
+ 2.6. Fair Use
147
+
148
+ This License is not intended to limit any rights You have under
149
+ applicable copyright doctrines of fair use, fair dealing, or other
150
+ equivalents.
151
+
152
+ 2.7. Conditions
153
+
154
+ Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
155
+ in Section 2.1.
156
+
157
+ 3. Responsibilities
158
+ -------------------
159
+
160
+ 3.1. Distribution of Source Form
161
+
162
+ All distribution of Covered Software in Source Code Form, including any
163
+ Modifications that You create or to which You contribute, must be under
164
+ the terms of this License. You must inform recipients that the Source
165
+ Code Form of the Covered Software is governed by the terms of this
166
+ License, and how they can obtain a copy of this License. You may not
167
+ attempt to alter or restrict the recipients' rights in the Source Code
168
+ Form.
169
+
170
+ 3.2. Distribution of Executable Form
171
+
172
+ If You distribute Covered Software in Executable Form then:
173
+
174
+ (a) such Covered Software must also be made available in Source Code
175
+ Form, as described in Section 3.1, and You must inform recipients of
176
+ the Executable Form how they can obtain a copy of such Source Code
177
+ Form by reasonable means in a timely manner, at a charge no more
178
+ than the cost of distribution to the recipient; and
179
+
180
+ (b) You may distribute such Executable Form under the terms of this
181
+ License, or sublicense it under different terms, provided that the
182
+ license for the Executable Form does not attempt to limit or alter
183
+ the recipients' rights in the Source Code Form under this License.
184
+
185
+ 3.3. Distribution of a Larger Work
186
+
187
+ You may create and distribute a Larger Work under terms of Your choice,
188
+ provided that You also comply with the requirements of this License for
189
+ the Covered Software. If the Larger Work is a combination of Covered
190
+ Software with a work governed by one or more Secondary Licenses, and the
191
+ Covered Software is not Incompatible With Secondary Licenses, this
192
+ License permits You to additionally distribute such Covered Software
193
+ under the terms of such Secondary License(s), so that the recipient of
194
+ the Larger Work may, at their option, further distribute the Covered
195
+ Software under the terms of either this License or such Secondary
196
+ License(s).
197
+
198
+ 3.4. Notices
199
+
200
+ You may not remove or alter the substance of any license notices
201
+ (including copyright notices, patent notices, disclaimers of warranty,
202
+ or limitations of liability) contained within the Source Code Form of
203
+ the Covered Software, except that You may alter any license notices to
204
+ the extent required to remedy known factual inaccuracies.
205
+
206
+ 3.5. Application of Additional Terms
207
+
208
+ You may choose to offer, and to charge a fee for, warranty, support,
209
+ indemnity or liability obligations to one or more recipients of Covered
210
+ Software. However, You may do so only on Your own behalf, and not on
211
+ behalf of any Contributor. You must make it absolutely clear that any
212
+ such warranty, support, indemnity, or liability obligation is offered by
213
+ You alone, and You hereby agree to indemnify every Contributor for any
214
+ liability incurred by such Contributor as a result of warranty, support,
215
+ indemnity or liability terms You offer. You may include additional
216
+ disclaimers of warranty and limitations of liability specific to any
217
+ jurisdiction.
218
+
219
+ 4. Inability to Comply Due to Statute or Regulation
220
+ ---------------------------------------------------
221
+
222
+ If it is impossible for You to comply with any of the terms of this
223
+ License with respect to some or all of the Covered Software due to
224
+ statute, judicial order, or regulation then You must: (a) comply with
225
+ the terms of this License to the maximum extent possible; and (b)
226
+ describe the limitations and the code they affect. Such description must
227
+ be placed in a text file included with all distributions of the Covered
228
+ Software under this License. Except to the extent prohibited by statute
229
+ or regulation, such description must be sufficiently detailed for a
230
+ recipient of ordinary skill to be able to understand it.
231
+
232
+ 5. Termination
233
+ --------------
234
+
235
+ 5.1. The rights granted under this License will terminate automatically
236
+ if You fail to comply with any of its terms. However, if You become
237
+ compliant, then the rights granted under this License from a particular
238
+ Contributor are reinstated (a) provisionally, unless and until such
239
+ Contributor explicitly and finally terminates Your grants, and (b) on an
240
+ ongoing basis, if such Contributor fails to notify You of the
241
+ non-compliance by some reasonable means prior to 60 days after You have
242
+ come back into compliance. Moreover, Your grants from a particular
243
+ Contributor are reinstated on an ongoing basis if such Contributor
244
+ notifies You of the non-compliance by some reasonable means, this is the
245
+ first time You have received notice of non-compliance with this License
246
+ from such Contributor, and You become compliant prior to 30 days after
247
+ Your receipt of the notice.
248
+
249
+ 5.2. If You initiate litigation against any entity by asserting a patent
250
+ infringement claim (excluding declaratory judgment actions,
251
+ counter-claims, and cross-claims) alleging that a Contributor Version
252
+ directly or indirectly infringes any patent, then the rights granted to
253
+ You by any and all Contributors for the Covered Software under Section
254
+ 2.1 of this License shall terminate.
255
+
256
+ 5.3. In the event of termination under Sections 5.1 or 5.2 above, all
257
+ end user license agreements (excluding distributors and resellers) which
258
+ have been validly granted by You or Your distributors under this License
259
+ prior to termination shall survive termination.
260
+
261
+ ************************************************************************
262
+ * *
263
+ * 6. Disclaimer of Warranty *
264
+ * ------------------------- *
265
+ * *
266
+ * Covered Software is provided under this License on an "as is" *
267
+ * basis, without warranty of any kind, either expressed, implied, or *
268
+ * statutory, including, without limitation, warranties that the *
269
+ * Covered Software is free of defects, merchantable, fit for a *
270
+ * particular purpose or non-infringing. The entire risk as to the *
271
+ * quality and performance of the Covered Software is with You. *
272
+ * Should any Covered Software prove defective in any respect, You *
273
+ * (not any Contributor) assume the cost of any necessary servicing, *
274
+ * repair, or correction. This disclaimer of warranty constitutes an *
275
+ * essential part of this License. No use of any Covered Software is *
276
+ * authorized under this License except under this disclaimer. *
277
+ * *
278
+ ************************************************************************
279
+
280
+ ************************************************************************
281
+ * *
282
+ * 7. Limitation of Liability *
283
+ * -------------------------- *
284
+ * *
285
+ * Under no circumstances and under no legal theory, whether tort *
286
+ * (including negligence), contract, or otherwise, shall any *
287
+ * Contributor, or anyone who distributes Covered Software as *
288
+ * permitted above, be liable to You for any direct, indirect, *
289
+ * special, incidental, or consequential damages of any character *
290
+ * including, without limitation, damages for lost profits, loss of *
291
+ * goodwill, work stoppage, computer failure or malfunction, or any *
292
+ * and all other commercial damages or losses, even if such party *
293
+ * shall have been informed of the possibility of such damages. This *
294
+ * limitation of liability shall not apply to liability for death or *
295
+ * personal injury resulting from such party's negligence to the *
296
+ * extent applicable law prohibits such limitation. Some *
297
+ * jurisdictions do not allow the exclusion or limitation of *
298
+ * incidental or consequential damages, so this exclusion and *
299
+ * limitation may not apply to You. *
300
+ * *
301
+ ************************************************************************
302
+
303
+ 8. Litigation
304
+ -------------
305
+
306
+ Any litigation relating to this License may be brought only in the
307
+ courts of a jurisdiction where the defendant maintains its principal
308
+ place of business and such litigation shall be governed by laws of that
309
+ jurisdiction, without reference to its conflict-of-law provisions.
310
+ Nothing in this Section shall prevent a party's ability to bring
311
+ cross-claims or counter-claims.
312
+
313
+ 9. Miscellaneous
314
+ ----------------
315
+
316
+ This License represents the complete agreement concerning the subject
317
+ matter hereof. If any provision of this License is held to be
318
+ unenforceable, such provision shall be reformed only to the extent
319
+ necessary to make it enforceable. Any law or regulation which provides
320
+ that the language of a contract shall be construed against the drafter
321
+ shall not be used to construe this License against a Contributor.
322
+
323
+ 10. Versions of the License
324
+ ---------------------------
325
+
326
+ 10.1. New Versions
327
+
328
+ Mozilla Foundation is the license steward. Except as provided in Section
329
+ 10.3, no one other than the license steward has the right to modify or
330
+ publish new versions of this License. Each version will be given a
331
+ distinguishing version number.
332
+
333
+ 10.2. Effect of New Versions
334
+
335
+ You may distribute the Covered Software under the terms of the version
336
+ of the License under which You originally received the Covered Software,
337
+ or under the terms of any subsequent version published by the license
338
+ steward.
339
+
340
+ 10.3. Modified Versions
341
+
342
+ If you create software not governed by this License, and you want to
343
+ create a new license for such software, you may create and use a
344
+ modified version of this License if you rename the license and remove
345
+ any references to the name of the license steward (except to note that
346
+ such modified license differs from this License).
347
+
348
+ 10.4. Distributing Source Code Form that is Incompatible With Secondary
349
+ Licenses
350
+
351
+ If You choose to distribute Source Code Form that is Incompatible With
352
+ Secondary Licenses under the terms of this version of the License, the
353
+ notice described in Exhibit B of this License must be attached.
354
+
355
+ Exhibit A - Source Code Form License Notice
356
+ -------------------------------------------
357
+
358
+ This Source Code Form is subject to the terms of the Mozilla Public
359
+ License, v. 2.0. If a copy of the MPL was not distributed with this
360
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
361
+
362
+ If it is not possible or desirable to put the notice in a particular
363
+ file, then You may include the notice in a location (such as a LICENSE
364
+ file in a relevant directory) where a recipient would be likely to look
365
+ for such a notice.
366
+
367
+ You may add additional accurate notices of copyright ownership.
368
+
369
+ Exhibit B - "Incompatible With Secondary Licenses" Notice
370
+ ---------------------------------------------------------
371
+
372
+ This Source Code Form is "Incompatible With Secondary Licenses", as
373
+ defined by the Mozilla Public License, v. 2.0.
@@ -0,0 +1,2 @@
1
+ "use strict";const __rslib_import_meta_url__="u"<typeof document?new(require("url".replace("",""))).URL("file:"+__filename).href:document.currentScript&&document.currentScript.src||new URL("main.js",document.baseURI).href;var __webpack_require__={};__webpack_require__.d=(e,t,s)=>{var r=(t,s)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,[s]:t[r]})};r(t,"get"),r(s,"value")},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__={};__webpack_require__.r(__webpack_exports__),__webpack_require__.d(__webpack_exports__,{Costume:()=>Costume,Project:()=>Project,Sound:()=>Sound,Sprite:()=>Sprite,Stage:()=>Stage,Target:()=>Target,md5:()=>md5,sniffFormat:()=>sniffFormat,uid:()=>uid});const jszip_namespaceObject=require("@turbowarp/jszip"),K=new Int32Array([0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,0xa679438e,0x49b40821,0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa,0xd62f105d,0x2441453,0xd8a1e681,0xe7d3fbc8,0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a,0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70,0x289b7ec6,0xeaa127fa,0xd4ef3085,0x4881d05,0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,0xf4292244,0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391]),S=[7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21],rotl=(e,t)=>e<<t|e>>>32-t,HEX=[];for(let i=0;i<256;i++)HEX[i]=(i<16?"0":"")+i.toString(16);const hexLE=e=>HEX[255&e]+HEX[e>>>8&255]+HEX[e>>>16&255]+HEX[e>>>24&255];function md5(e){let t=e instanceof Uint8Array?e:new Uint8Array(e),s=t.length,r=s+1,n=r+(r%64<=56?56-r%64:120-r%64)+8,o=new Uint8Array(n);o.set(t),o[s]=128;let a=s<<3>>>0,u=s>>>29>>>0;o[n-8]=255&a,o[n-7]=a>>>8&255,o[n-6]=a>>>16&255,o[n-5]=a>>>24&255,o[n-4]=255&u,o[n-3]=u>>>8&255,o[n-2]=u>>>16&255,o[n-1]=u>>>24&255;let c=0x67452301,d=0xefcdab89,m=0x98badcfe,l=0x10325476,p=new Int32Array(16);for(let e=0;e<n;e+=64){for(let t=0;t<16;t++){let s=e+4*t;p[t]=o[s]|o[s+1]<<8|o[s+2]<<16|o[s+3]<<24}let t=c,s=d,r=m,n=l;for(let e=0;e<64;e++){let o,a;e<16?(o=s&r|~s&n,a=e):e<32?(o=n&s|~n&r,a=(5*e+1)%16):e<48?(o=s^r^n,a=(3*e+5)%16):(o=r^(s|~n),a=7*e%16),o=o+t+K[e]+p[a]|0,t=n,n=r,r=s,s=s+rotl(o,S[e])|0}c=c+t|0,d=d+s|0,m=m+r|0,l=l+n|0}return hexLE(c)+hexLE(d)+hexLE(m)+hexLE(l)}class Asset{constructor(e,t){this.json=e,this.project=t}get name(){return this.json.name}set name(e){this.json.name=String(e)}get dataFormat(){return this.json.dataFormat}get md5ext(){return this.json.md5ext}get data(){return this.project.assets.get(this.json.md5ext)}set data(e){let t=e instanceof Uint8Array?e:new Uint8Array(e),s=this.json.md5ext,r=md5(t);this.json.assetId=r,this.json.md5ext=`${r}.${this.json.dataFormat}`,this.project.assets.set(this.json.md5ext,t),s&&s!==this.json.md5ext&&this.project._maybeDropAsset(s)}}class Costume extends Asset{get bitmapResolution(){return this.json.bitmapResolution??1}set bitmapResolution(e){this.json.bitmapResolution=Number(e)}get rotationCenterX(){return this.json.rotationCenterX??0}set rotationCenterX(e){this.json.rotationCenterX=Number(e)}get rotationCenterY(){return this.json.rotationCenterY??0}set rotationCenterY(e){this.json.rotationCenterY=Number(e)}}class Sound extends Asset{get rate(){return this.json.rate}set rate(e){this.json.rate=Number(e)}get sampleCount(){return this.json.sampleCount}set sampleCount(e){this.json.sampleCount=Number(e)}}const startsWith=(e,t)=>t.every((t,s)=>e[s]===t),ascii=e=>[...e].map(e=>e.charCodeAt(0));function sniffFormat(e){if(!e||e.length<4)return;if(startsWith(e,[137,80,78,71]))return"png";if(startsWith(e,[255,216,255]))return"jpg";if(startsWith(e,ascii("GIF")))return"gif";if(startsWith(e,ascii("RIFF")))return"wav";if(startsWith(e,ascii("ID3"))||255===e[0]&&(224&e[1])==224)return"mp3";let t=String.fromCharCode(...e.slice(0,256)).trimStart();if(t.startsWith("<?xml")||t.startsWith("<svg")||t.includes("<svg"))return"svg"}const SOUP="!#%()*+,-./:;=?@[]^_`{|}~ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";function uid(){let e="";for(let t=0;t<20;t++)e+=SOUP[Math.floor(Math.random()*SOUP.length)];return e}class Target{constructor(e,t){this.json=e,this.project=t}get isStage(){return!!this.json.isStage}get name(){return this.json.name}set name(e){this.json.name=String(e)}get volume(){return this.json.volume??100}set volume(e){this.json.volume=Number(e)}get costumes(){return this.json.costumes.map(e=>new Costume(e,this.project))}get currentCostume(){return this.json.currentCostume??0}set currentCostume(e){this.json.currentCostume=Number(e)}getCostume(e){let t=this.json.costumes.find(t=>t.name===e);return t?new Costume(t,this.project):void 0}addCostume(e,t,s={}){let r=t instanceof Uint8Array?t:new Uint8Array(t),n=s.dataFormat??sniffFormat(r)??"png",o=md5(r),a={name:String(e),bitmapResolution:s.bitmapResolution??("svg"===n?1:2),dataFormat:n,assetId:o,md5ext:`${o}.${n}`,rotationCenterX:s.rotationCenterX??0,rotationCenterY:s.rotationCenterY??0};return this.project.assets.set(a.md5ext,r),this.json.costumes.push(a),new Costume(a,this.project)}removeCostume(e){return this._removeMedia("costumes",e)}get sounds(){return this.json.sounds.map(e=>new Sound(e,this.project))}getSound(e){let t=this.json.sounds.find(t=>t.name===e);return t?new Sound(t,this.project):void 0}addSound(e,t,s={}){let r=t instanceof Uint8Array?t:new Uint8Array(t),n=s.dataFormat??sniffFormat(r)??"wav",o=md5(r),a={name:String(e),assetId:o,dataFormat:n,format:"",rate:s.rate??48e3,sampleCount:s.sampleCount??0,md5ext:`${o}.${n}`};return this.project.assets.set(a.md5ext,r),this.json.sounds.push(a),new Sound(a,this.project)}removeSound(e){return this._removeMedia("sounds",e)}_removeMedia(e,t){let s=this.json[e],r="number"==typeof t?t:s.findIndex(e=>e.name===t);if(r<0||r>=s.length)return!1;let[n]=s.splice(r,1);return"costumes"===e&&this.json.currentCostume>=s.length&&(this.json.currentCostume=Math.max(0,s.length-1)),this.project._maybeDropAsset(n.md5ext),!0}get variableNames(){return Object.values(this.json.variables).map(([e])=>e)}getVariable(e){let t=Object.values(this.json.variables).find(([t])=>t===e);return t?t[1]:void 0}setVariable(e,t){for(let[s,r]of Object.entries(this.json.variables))if(r[0]===e)return r[1]=t,s;let s=uid();return this.json.variables[s]=[e,t],s}deleteVariable(e){for(let[t,s]of Object.entries(this.json.variables))if(s[0]===e)return delete this.json.variables[t],!0;return!1}get listNames(){return Object.values(this.json.lists).map(([e])=>e)}getList(e){let t=Object.values(this.json.lists).find(([t])=>t===e);return t?t[1]:void 0}setList(e,t=[]){for(let[s,r]of Object.entries(this.json.lists))if(r[0]===e)return r[1]=t,s;let s=uid();return this.json.lists[s]=[e,t],s}deleteList(e){for(let[t,s]of Object.entries(this.json.lists))if(s[0]===e)return delete this.json.lists[t],!0;return!1}get blocks(){return this.json.blocks}}class Stage extends Target{get isStage(){return!0}get tempo(){return this.json.tempo??60}set tempo(e){this.json.tempo=Number(e)}get videoState(){return this.json.videoState??"off"}set videoState(e){this.json.videoState=String(e)}get videoTransparency(){return this.json.videoTransparency??50}set videoTransparency(e){this.json.videoTransparency=Number(e)}get broadcastNames(){return Object.values(this.json.broadcasts)}addBroadcast(e){for(let[t,s]of Object.entries(this.json.broadcasts))if(s===e)return t;let t=`broadcastMsgId-${e}`;return this.json.broadcasts[t]=e,t}}class Sprite extends Target{get isStage(){return!1}get x(){return this.json.x??0}set x(e){this.json.x=Number(e)}get y(){return this.json.y??0}set y(e){this.json.y=Number(e)}get size(){return this.json.size??100}set size(e){this.json.size=Number(e)}get direction(){return this.json.direction??90}set direction(e){this.json.direction=Number(e)}get visible(){return this.json.visible??!0}set visible(e){this.json.visible=!!e}get draggable(){return this.json.draggable??!1}set draggable(e){this.json.draggable=!!e}get rotationStyle(){return this.json.rotationStyle??"all around"}set rotationStyle(e){this.json.rotationStyle=String(e)}get layerOrder(){return this.json.layerOrder??0}set layerOrder(e){this.json.layerOrder=Number(e)}}const DEFAULT_META={semver:"3.0.0",vm:"14.0.0",agent:""};class Project{constructor(e,t=new Map){this.json=e,this.assets=t}static async load(e){let t=await jszip_namespaceObject.loadAsync(e),s=t.file("project.json");if(!s)throw Error("Not a valid sb3: project.json is missing.");let r=JSON.parse(await s.async("string")),n=new Map,o=[];return t.forEach((e,t)=>{t.dir||"project.json"===e||o.push(t.async("uint8array").then(t=>n.set(e,t)))}),await Promise.all(o),new Project(r,n)}static create(){return new Project({targets:[{isStage:!0,name:"Stage",variables:{},lists:{},broadcasts:{},blocks:{},comments:{},currentCostume:0,costumes:[],sounds:[],volume:100,layerOrder:0,tempo:60,videoTransparency:50,videoState:"on",textToSpeechLanguage:null}],monitors:[],extensions:[],meta:{...DEFAULT_META}})}get stage(){return new Stage(this.json.targets.find(e=>e.isStage),this)}get sprites(){return this.json.targets.filter(e=>!e.isStage).map(e=>new Sprite(e,this))}get targets(){return this.json.targets.map(e=>e.isStage?new Stage(e,this):new Sprite(e,this))}get meta(){return this.json.meta}get monitors(){return this.json.monitors}get extensions(){return this.json.extensions}sprite(e){let t=this.json.targets.find(t=>!t.isStage&&t.name===e);return t?new Sprite(t,this):void 0}target(e){let t=this.json.targets.find(t=>t.name===e);if(t)return t.isStage?new Stage(t,this):new Sprite(t,this)}addSprite(e,t={}){if(this.sprite(e))throw Error(`A sprite named "${e}" already exists.`);let s=Math.max(0,...this.json.targets.map(e=>e.layerOrder??0)),r={isStage:!1,name:String(e),variables:{},lists:{},broadcasts:{},blocks:{},comments:{},currentCostume:0,costumes:[],sounds:[],volume:100,layerOrder:s+1,visible:!0,x:0,y:0,size:100,direction:90,draggable:!1,rotationStyle:"all around",...t};return this.json.targets.push(r),new Sprite(r,this)}removeSprite(e){let t="string"==typeof e?e:e.name,s=this.json.targets.findIndex(e=>!e.isStage&&e.name===t);if(s<0)return!1;let[r]=this.json.targets.splice(s,1);for(let e of[...r.costumes,...r.sounds])this._maybeDropAsset(e.md5ext);return!0}_maybeDropAsset(e){!e||this.json.targets.some(t=>t.costumes.some(t=>t.md5ext===e)||t.sounds.some(t=>t.md5ext===e))||this.assets.delete(e)}async save({compressionLevel:e=6}={}){let t=new jszip_namespaceObject;for(let[e,s]of(t.file("project.json",JSON.stringify(this.json)),this.assets))t.file(e,s);return t.generateAsync({type:"uint8array",compression:"DEFLATE",compressionOptions:{level:e}})}}for(var __rspack_i in exports.Costume=__webpack_exports__.Costume,exports.Project=__webpack_exports__.Project,exports.Sound=__webpack_exports__.Sound,exports.Sprite=__webpack_exports__.Sprite,exports.Stage=__webpack_exports__.Stage,exports.Target=__webpack_exports__.Target,exports.md5=__webpack_exports__.md5,exports.sniffFormat=__webpack_exports__.sniffFormat,exports.uid=__webpack_exports__.uid,__webpack_exports__)-1===["Costume","Project","Sound","Sprite","Stage","Target","md5","sniffFormat","uid"].indexOf(__rspack_i)&&(exports[__rspack_i]=__webpack_exports__[__rspack_i]);Object.defineProperty(exports,"__esModule",{value:!0});
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["webpack://webpack/runtime/define_property_getters","webpack://webpack/runtime/has_own_property","webpack://webpack/runtime/make_namespace_object","../../src/md5.js","../../src/assets.js","../../src/format.js","../../src/ids.js","../../src/target.js","../../src/project.js"],"sourcesContent":["__webpack_require__.d = (exports, getters, values) => {\n\tvar define = (defs, kind) => {\n\t\tfor(var key in defs) {\n\t\t\tif(__webpack_require__.o(defs, key) && !__webpack_require__.o(exports, key)) {\n\t\t\t\tObject.defineProperty(exports, key, { enumerable: true, [kind]: defs[key] });\n\t\t\t}\n\t\t}\n\t};\n\tdefine(getters, \"get\");\n\tdefine(values, \"value\");\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","// Pure-JS MD5 (RFC 1321). Scratch names asset files by the MD5 hash of their\n// bytes, so we need a hash that runs in both Node and the browser without\n// pulling in a dependency.\n\n// prettier-ignore\nconst K = new Int32Array([\n 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a,\n 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,\n 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340,\n 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,\n 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8,\n 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,\n 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa,\n 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,\n 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92,\n 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,\n 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,\n]);\n\n// prettier-ignore\nconst S = [\n 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,\n 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,\n 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,\n 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21,\n];\n\nconst rotl = (x, c) => (x << c) | (x >>> (32 - c));\n\nconst HEX = [];\nfor (let i = 0; i < 256; i++) HEX[i] = (i < 16 ? '0' : '') + i.toString(16);\nconst hexLE = (x) =>\n HEX[x & 0xff] +\n HEX[(x >>> 8) & 0xff] +\n HEX[(x >>> 16) & 0xff] +\n HEX[(x >>> 24) & 0xff];\n\n/**\n * Compute the lowercase hex MD5 digest of some bytes.\n *\n * @param {Uint8Array | ArrayBuffer} input - Bytes to hash.\n * @returns {string} 32-character lowercase hex digest.\n */\nexport function md5(input) {\n const msg = input instanceof Uint8Array ? input : new Uint8Array(input);\n const n = msg.length;\n\n // Pad: 0x80, zeros, then the original bit length as a 64-bit little-endian int.\n const withOne = n + 1;\n const padZeros =\n withOne % 64 <= 56 ? 56 - (withOne % 64) : 120 - (withOne % 64);\n const total = withOne + padZeros + 8;\n const buf = new Uint8Array(total);\n buf.set(msg);\n buf[n] = 0x80;\n const bitsLo = (n << 3) >>> 0;\n const bitsHi = (n >>> 29) >>> 0;\n buf[total - 8] = bitsLo & 0xff;\n buf[total - 7] = (bitsLo >>> 8) & 0xff;\n buf[total - 6] = (bitsLo >>> 16) & 0xff;\n buf[total - 5] = (bitsLo >>> 24) & 0xff;\n buf[total - 4] = bitsHi & 0xff;\n buf[total - 3] = (bitsHi >>> 8) & 0xff;\n buf[total - 2] = (bitsHi >>> 16) & 0xff;\n buf[total - 1] = (bitsHi >>> 24) & 0xff;\n\n let a0 = 0x67452301;\n let b0 = 0xefcdab89;\n let c0 = 0x98badcfe;\n let d0 = 0x10325476;\n\n const M = new Int32Array(16);\n for (let off = 0; off < total; off += 64) {\n for (let i = 0; i < 16; i++) {\n const j = off + i * 4;\n M[i] =\n buf[j] | (buf[j + 1] << 8) | (buf[j + 2] << 16) | (buf[j + 3] << 24);\n }\n\n let A = a0;\n let B = b0;\n let C = c0;\n let D = d0;\n\n for (let i = 0; i < 64; i++) {\n let F;\n let g;\n if (i < 16) {\n F = (B & C) | (~B & D);\n g = i;\n } else if (i < 32) {\n F = (D & B) | (~D & C);\n g = (5 * i + 1) % 16;\n } else if (i < 48) {\n F = B ^ C ^ D;\n g = (3 * i + 5) % 16;\n } else {\n F = C ^ (B | ~D);\n g = (7 * i) % 16;\n }\n F = (F + A + K[i] + M[g]) | 0;\n A = D;\n D = C;\n C = B;\n B = (B + rotl(F, S[i])) | 0;\n }\n\n a0 = (a0 + A) | 0;\n b0 = (b0 + B) | 0;\n c0 = (c0 + C) | 0;\n d0 = (d0 + D) | 0;\n }\n\n return hexLE(a0) + hexLE(b0) + hexLE(c0) + hexLE(d0);\n}\n","import { md5 } from './md5.js';\n\n/**\n * Base class for the two kinds of media a target can own: costumes and sounds.\n * Each asset wraps its raw entry in `project.json` plus the bytes stored in the\n * surrounding zip, keyed by `md5ext` (e.g. `b7f1cf69….wav`).\n *\n * @abstract\n */\nclass Asset {\n /**\n * @param {object} json - The raw costume/sound entry from project.json.\n * @param {import('./project.js').Project} project - Owning project (holds the bytes).\n */\n constructor(json, project) {\n /** @type {object} The underlying JSON; mutate via the accessors below. */\n this.json = json;\n /** @type {import('./project.js').Project} */\n this.project = project;\n }\n\n /** @returns {string} Display name shown in the editor. */\n get name() {\n return this.json.name;\n }\n set name(value) {\n this.json.name = String(value);\n }\n\n /** @returns {string} File extension/type, e.g. `png`, `svg`, `wav`, `mp3`. */\n get dataFormat() {\n return this.json.dataFormat;\n }\n\n /** @returns {string} The `<md5>.<ext>` filename of this asset inside the zip. */\n get md5ext() {\n return this.json.md5ext;\n }\n\n /**\n * The raw bytes of this asset, read from / written to the project's zip.\n *\n * Assigning new bytes recomputes the MD5 and rewrites `assetId`/`md5ext`, so\n * the file is always addressed by the hash of its current contents.\n *\n * @returns {Uint8Array | undefined}\n */\n get data() {\n return this.project.assets.get(this.json.md5ext);\n }\n set data(bytes) {\n const buf = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);\n const old = this.json.md5ext;\n const hash = md5(buf);\n this.json.assetId = hash;\n this.json.md5ext = `${hash}.${this.json.dataFormat}`;\n this.project.assets.set(this.json.md5ext, buf);\n if (old && old !== this.json.md5ext) this.project._maybeDropAsset(old);\n }\n}\n\n/**\n * A costume: an image (bitmap or SVG) a target can display.\n */\nexport class Costume extends Asset {\n /** @returns {number} Pixels per unit for bitmaps (1 for SVG, 2 for HD bitmaps). */\n get bitmapResolution() {\n return this.json.bitmapResolution ?? 1;\n }\n set bitmapResolution(value) {\n this.json.bitmapResolution = Number(value);\n }\n\n /** @returns {number} X of the rotation/anchor center, in costume pixels. */\n get rotationCenterX() {\n return this.json.rotationCenterX ?? 0;\n }\n set rotationCenterX(value) {\n this.json.rotationCenterX = Number(value);\n }\n\n /** @returns {number} Y of the rotation/anchor center, in costume pixels. */\n get rotationCenterY() {\n return this.json.rotationCenterY ?? 0;\n }\n set rotationCenterY(value) {\n this.json.rotationCenterY = Number(value);\n }\n}\n\n/**\n * A sound a target can play.\n */\nexport class Sound extends Asset {\n /** @returns {number} Sample rate in Hz. */\n get rate() {\n return this.json.rate;\n }\n set rate(value) {\n this.json.rate = Number(value);\n }\n\n /** @returns {number} Number of samples in the clip. */\n get sampleCount() {\n return this.json.sampleCount;\n }\n set sampleCount(value) {\n this.json.sampleCount = Number(value);\n }\n}\n","// Best-effort detection of an asset's type from its leading bytes, so callers\n// can drop in a buffer without spelling out `dataFormat` every time.\n\nconst startsWith = (bytes, sig) => sig.every((b, i) => bytes[i] === b);\nconst ascii = (s) => [...s].map((c) => c.charCodeAt(0));\n\n/**\n * Guess a Scratch `dataFormat` (file extension) from raw asset bytes.\n *\n * @param {Uint8Array} bytes - The asset contents.\n * @returns {string | undefined} The detected format, or undefined if unknown.\n */\nexport function sniffFormat(bytes) {\n if (!bytes || bytes.length < 4) return undefined;\n if (startsWith(bytes, [0x89, 0x50, 0x4e, 0x47])) return 'png';\n if (startsWith(bytes, [0xff, 0xd8, 0xff])) return 'jpg';\n if (startsWith(bytes, ascii('GIF'))) return 'gif';\n if (startsWith(bytes, ascii('RIFF'))) return 'wav';\n if (\n startsWith(bytes, ascii('ID3')) ||\n (bytes[0] === 0xff && (bytes[1] & 0xe0) === 0xe0)\n )\n return 'mp3';\n // Text-based: SVG documents start with an XML prolog or the root tag.\n const head = String.fromCharCode(...bytes.slice(0, 256)).trimStart();\n if (\n head.startsWith('<?xml') ||\n head.startsWith('<svg') ||\n head.includes('<svg')\n )\n return 'svg';\n return undefined;\n}\n","// Scratch generates the keys used for blocks, variables, lists and broadcasts\n// from a fixed \"soup\" of characters. We mirror that here so generated IDs look\n// native and stay clear of JSON-unsafe characters.\nconst SOUP =\n '!#%()*+,-./:;=?@[]^_`{|}~' +\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +\n 'abcdefghijklmnopqrstuvwxyz' +\n '0123456789';\n\n/**\n * Generate a fresh 20-character Scratch-style unique id.\n *\n * @returns {string} A new id.\n */\nexport function uid() {\n let id = '';\n for (let i = 0; i < 20; i++) {\n id += SOUP[Math.floor(Math.random() * SOUP.length)];\n }\n return id;\n}\n","import { Costume, Sound } from './assets.js';\nimport { sniffFormat } from './format.js';\nimport { md5 } from './md5.js';\nimport { uid } from './ids.js';\n\n/**\n * A target is anything that lives in the project's `targets` array: either the\n * single {@link Stage} or a {@link Sprite}. This base class covers everything\n * the two share — name, costumes, sounds, variables, lists and raw blocks.\n *\n * @abstract\n */\nexport class Target {\n /**\n * @param {object} json - The raw target entry from project.json.\n * @param {import('./project.js').Project} project - Owning project.\n */\n constructor(json, project) {\n /** @type {object} The underlying JSON; the accessors below keep it in sync. */\n this.json = json;\n /** @type {import('./project.js').Project} */\n this.project = project;\n }\n\n /** @returns {boolean} True for the stage, false for sprites. */\n get isStage() {\n return Boolean(this.json.isStage);\n }\n\n /** @returns {string} The target's name. */\n get name() {\n return this.json.name;\n }\n set name(value) {\n this.json.name = String(value);\n }\n\n /** @returns {number} Output volume, 0–100. */\n get volume() {\n return this.json.volume ?? 100;\n }\n set volume(value) {\n this.json.volume = Number(value);\n }\n\n // --- Costumes -------------------------------------------------------------\n\n /** @returns {Costume[]} The target's costumes, in order. */\n get costumes() {\n return this.json.costumes.map((c) => new Costume(c, this.project));\n }\n\n /** @returns {number} Index of the currently selected costume. */\n get currentCostume() {\n return this.json.currentCostume ?? 0;\n }\n set currentCostume(value) {\n this.json.currentCostume = Number(value);\n }\n\n /**\n * Find a costume by name.\n *\n * @param {string} name\n * @returns {Costume | undefined}\n */\n getCostume(name) {\n const entry = this.json.costumes.find((c) => c.name === name);\n return entry ? new Costume(entry, this.project) : undefined;\n }\n\n /**\n * Add a costume from raw image bytes. The asset is stored in the zip keyed by\n * its MD5, and a costume entry pointing at it is appended.\n *\n * @param {string} name - Costume name.\n * @param {Uint8Array | ArrayBuffer} data - Image bytes (PNG/SVG/JPG/…).\n * @param {object} [options]\n * @param {string} [options.dataFormat] - Override the detected file type.\n * @param {number} [options.rotationCenterX] - Anchor X (defaults to 0).\n * @param {number} [options.rotationCenterY] - Anchor Y (defaults to 0).\n * @param {number} [options.bitmapResolution] - 1 for SVG, 2 for HD bitmaps.\n * @returns {Costume} The newly added costume.\n */\n addCostume(name, data, options = {}) {\n const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);\n const dataFormat = options.dataFormat ?? sniffFormat(bytes) ?? 'png';\n const hash = md5(bytes);\n const entry = {\n name: String(name),\n bitmapResolution:\n options.bitmapResolution ?? (dataFormat === 'svg' ? 1 : 2),\n dataFormat,\n assetId: hash,\n md5ext: `${hash}.${dataFormat}`,\n rotationCenterX: options.rotationCenterX ?? 0,\n rotationCenterY: options.rotationCenterY ?? 0,\n };\n this.project.assets.set(entry.md5ext, bytes);\n this.json.costumes.push(entry);\n return new Costume(entry, this.project);\n }\n\n /**\n * Remove a costume by name or index.\n *\n * @param {string | number} nameOrIndex\n * @returns {boolean} True if a costume was removed.\n */\n removeCostume(nameOrIndex) {\n return this._removeMedia('costumes', nameOrIndex);\n }\n\n // --- Sounds ---------------------------------------------------------------\n\n /** @returns {Sound[]} The target's sounds, in order. */\n get sounds() {\n return this.json.sounds.map((s) => new Sound(s, this.project));\n }\n\n /**\n * Find a sound by name.\n *\n * @param {string} name\n * @returns {Sound | undefined}\n */\n getSound(name) {\n const entry = this.json.sounds.find((s) => s.name === name);\n return entry ? new Sound(entry, this.project) : undefined;\n }\n\n /**\n * Add a sound from raw audio bytes.\n *\n * @param {string} name - Sound name.\n * @param {Uint8Array | ArrayBuffer} data - Audio bytes (WAV/MP3).\n * @param {object} [options]\n * @param {string} [options.dataFormat] - Override the detected file type.\n * @param {number} [options.rate] - Sample rate in Hz (default 48000).\n * @param {number} [options.sampleCount] - Number of samples (default 0).\n * @returns {Sound} The newly added sound.\n */\n addSound(name, data, options = {}) {\n const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);\n const dataFormat = options.dataFormat ?? sniffFormat(bytes) ?? 'wav';\n const hash = md5(bytes);\n const entry = {\n name: String(name),\n assetId: hash,\n dataFormat,\n format: '',\n rate: options.rate ?? 48000,\n sampleCount: options.sampleCount ?? 0,\n md5ext: `${hash}.${dataFormat}`,\n };\n this.project.assets.set(entry.md5ext, bytes);\n this.json.sounds.push(entry);\n return new Sound(entry, this.project);\n }\n\n /**\n * Remove a sound by name or index.\n *\n * @param {string | number} nameOrIndex\n * @returns {boolean} True if a sound was removed.\n */\n removeSound(nameOrIndex) {\n return this._removeMedia('sounds', nameOrIndex);\n }\n\n /**\n * @param {'costumes' | 'sounds'} kind\n * @param {string | number} nameOrIndex\n * @returns {boolean}\n * @private\n */\n _removeMedia(kind, nameOrIndex) {\n const list = this.json[kind];\n const index =\n typeof nameOrIndex === 'number'\n ? nameOrIndex\n : list.findIndex((m) => m.name === nameOrIndex);\n if (index < 0 || index >= list.length) return false;\n const [removed] = list.splice(index, 1);\n if (kind === 'costumes' && this.json.currentCostume >= list.length) {\n this.json.currentCostume = Math.max(0, list.length - 1);\n }\n this.project._maybeDropAsset(removed.md5ext);\n return true;\n }\n\n // --- Variables & lists ----------------------------------------------------\n\n /** @returns {string[]} Names of this target's variables. */\n get variableNames() {\n return Object.values(this.json.variables).map(([name]) => name);\n }\n\n /**\n * Read a variable's value by name.\n *\n * @param {string} name\n * @returns {string | number | boolean | undefined}\n */\n getVariable(name) {\n const found = Object.values(this.json.variables).find(([n]) => n === name);\n return found ? found[1] : undefined;\n }\n\n /**\n * Create or update a variable by name.\n *\n * @param {string} name\n * @param {string | number | boolean} value\n * @returns {string} The variable's id.\n */\n setVariable(name, value) {\n for (const [id, entry] of Object.entries(this.json.variables)) {\n if (entry[0] === name) {\n entry[1] = value;\n return id;\n }\n }\n const id = uid();\n this.json.variables[id] = [name, value];\n return id;\n }\n\n /**\n * Delete a variable by name.\n *\n * @param {string} name\n * @returns {boolean} True if a variable was deleted.\n */\n deleteVariable(name) {\n for (const [id, entry] of Object.entries(this.json.variables)) {\n if (entry[0] === name) {\n delete this.json.variables[id];\n return true;\n }\n }\n return false;\n }\n\n /** @returns {string[]} Names of this target's lists. */\n get listNames() {\n return Object.values(this.json.lists).map(([name]) => name);\n }\n\n /**\n * Read a list's contents by name.\n *\n * @param {string} name\n * @returns {Array<string | number> | undefined}\n */\n getList(name) {\n const found = Object.values(this.json.lists).find(([n]) => n === name);\n return found ? found[1] : undefined;\n }\n\n /**\n * Create or replace a list by name.\n *\n * @param {string} name\n * @param {Array<string | number>} items\n * @returns {string} The list's id.\n */\n setList(name, items = []) {\n for (const [id, entry] of Object.entries(this.json.lists)) {\n if (entry[0] === name) {\n entry[1] = items;\n return id;\n }\n }\n const id = uid();\n this.json.lists[id] = [name, items];\n return id;\n }\n\n /**\n * Delete a list by name.\n *\n * @param {string} name\n * @returns {boolean} True if a list was deleted.\n */\n deleteList(name) {\n for (const [id, entry] of Object.entries(this.json.lists)) {\n if (entry[0] === name) {\n delete this.json.lists[id];\n return true;\n }\n }\n return false;\n }\n\n /**\n * The raw `blocks` object for advanced scripting edits. Keys are block ids;\n * values are the block definitions. Mutate directly for low-level changes.\n *\n * @returns {object}\n */\n get blocks() {\n return this.json.blocks;\n }\n}\n\n/**\n * The stage: the single backdrop-bearing target that also owns the project's\n * broadcasts.\n */\nexport class Stage extends Target {\n /** @returns {true} Always the stage. Discriminates {@link Stage} from {@link Sprite}. */\n get isStage() {\n return true;\n }\n\n /** @returns {number} Tempo for music blocks, in BPM. */\n get tempo() {\n return this.json.tempo ?? 60;\n }\n set tempo(value) {\n this.json.tempo = Number(value);\n }\n\n /** @returns {string} Video input state: `on`, `off`, or `on-flipped`. */\n get videoState() {\n return this.json.videoState ?? 'off';\n }\n set videoState(value) {\n this.json.videoState = String(value);\n }\n\n /** @returns {number} Video transparency, 0–100. */\n get videoTransparency() {\n return this.json.videoTransparency ?? 50;\n }\n set videoTransparency(value) {\n this.json.videoTransparency = Number(value);\n }\n\n /** @returns {string[]} Names of all broadcast messages in the project. */\n get broadcastNames() {\n return Object.values(this.json.broadcasts);\n }\n\n /**\n * Add a broadcast message if it does not already exist.\n *\n * @param {string} name\n * @returns {string} The broadcast's id.\n */\n addBroadcast(name) {\n for (const [id, n] of Object.entries(this.json.broadcasts)) {\n if (n === name) return id;\n }\n const id = `broadcastMsgId-${name}`;\n this.json.broadcasts[id] = name;\n return id;\n }\n}\n\n/**\n * A sprite: a movable target with a position, size and orientation.\n */\nexport class Sprite extends Target {\n /** @returns {false} Never the stage. Discriminates {@link Sprite} from {@link Stage}. */\n get isStage() {\n return false;\n }\n\n /** @returns {number} X position on the stage (−240…240). */\n get x() {\n return this.json.x ?? 0;\n }\n set x(value) {\n this.json.x = Number(value);\n }\n\n /** @returns {number} Y position on the stage (−180…180). */\n get y() {\n return this.json.y ?? 0;\n }\n set y(value) {\n this.json.y = Number(value);\n }\n\n /** @returns {number} Size as a percentage (100 = original). */\n get size() {\n return this.json.size ?? 100;\n }\n set size(value) {\n this.json.size = Number(value);\n }\n\n /** @returns {number} Direction in degrees (90 = pointing right). */\n get direction() {\n return this.json.direction ?? 90;\n }\n set direction(value) {\n this.json.direction = Number(value);\n }\n\n /** @returns {boolean} Whether the sprite is shown. */\n get visible() {\n return this.json.visible ?? true;\n }\n set visible(value) {\n this.json.visible = Boolean(value);\n }\n\n /** @returns {boolean} Whether the sprite can be dragged in the player. */\n get draggable() {\n return this.json.draggable ?? false;\n }\n set draggable(value) {\n this.json.draggable = Boolean(value);\n }\n\n /** @returns {string} Rotation style: `all around`, `left-right`, `don't rotate`. */\n get rotationStyle() {\n return this.json.rotationStyle ?? 'all around';\n }\n set rotationStyle(value) {\n this.json.rotationStyle = String(value);\n }\n\n /** @returns {number} Stacking order; higher draws on top. */\n get layerOrder() {\n return this.json.layerOrder ?? 0;\n }\n set layerOrder(value) {\n this.json.layerOrder = Number(value);\n }\n}\n","import JSZip from '@turbowarp/jszip';\nimport { Sprite, Stage } from './target.js';\n\n/**\n * The project's `meta` block.\n *\n * @typedef {object} ProjectMeta\n * @property {string} semver - Scratch project schema version (e.g. `3.0.0`).\n * @property {string} vm - VM version that wrote the project.\n * @property {string} agent - User-agent string of the editor, if any.\n */\n\nconst DEFAULT_META = {\n semver: '3.0.0',\n vm: '14.0.0',\n agent: '',\n};\n\n/**\n * A loaded Scratch project (`.sb3`). An sb3 is a zip holding a `project.json`\n * description plus the costume/sound asset files it references. This class is\n * the entry point: load bytes, edit declaratively through {@link Stage} and\n * {@link Sprite}, then save back to bytes.\n *\n * @example\n * import { Project } from 'scratch4js';\n * import { readFile, writeFile } from 'node:fs/promises';\n *\n * const project = await Project.load(await readFile('game.sb3'));\n * const cat = project.sprite('Sprite1');\n * cat.x = 0;\n * cat.size = 150;\n * project.stage.setVariable('score', 0);\n * await writeFile('game.edited.sb3', await project.save());\n */\nexport class Project {\n /**\n * Prefer {@link Project.load}. Construct directly only when you already hold a\n * parsed `project.json` and its asset bytes.\n *\n * @param {object} json - Parsed project.json.\n * @param {Map<string, Uint8Array>} [assets] - Asset bytes keyed by `md5ext`.\n */\n constructor(json, assets = new Map()) {\n /** @type {object} The parsed project.json. */\n this.json = json;\n /** @type {Map<string, Uint8Array>} Asset bytes keyed by `<md5>.<ext>`. */\n this.assets = assets;\n }\n\n /**\n * Load a project from the raw bytes of an `.sb3` file.\n *\n * @param {Uint8Array | ArrayBuffer | Buffer} data - The sb3 zip bytes.\n * @returns {Promise<Project>}\n */\n static async load(data) {\n const zip = await JSZip.loadAsync(data);\n const projectFile = zip.file('project.json');\n if (!projectFile)\n throw new Error('Not a valid sb3: project.json is missing.');\n const json = JSON.parse(await projectFile.async('string'));\n\n const assets = new Map();\n const reads = [];\n zip.forEach((path, file) => {\n if (file.dir || path === 'project.json') return;\n reads.push(\n file.async('uint8array').then((bytes) => assets.set(path, bytes)),\n );\n });\n await Promise.all(reads);\n\n return new Project(json, assets);\n }\n\n /**\n * Create a new, empty project containing just a bare stage.\n *\n * @returns {Project}\n */\n static create() {\n const json = {\n targets: [\n {\n isStage: true,\n name: 'Stage',\n variables: {},\n lists: {},\n broadcasts: {},\n blocks: {},\n comments: {},\n currentCostume: 0,\n costumes: [],\n sounds: [],\n volume: 100,\n layerOrder: 0,\n tempo: 60,\n videoTransparency: 50,\n videoState: 'on',\n textToSpeechLanguage: null,\n },\n ],\n monitors: [],\n extensions: [],\n meta: { ...DEFAULT_META },\n };\n return new Project(json);\n }\n\n /** @returns {Stage} The project's single stage. */\n get stage() {\n const json = this.json.targets.find((t) => t.isStage);\n return new Stage(json, this);\n }\n\n /** @returns {Sprite[]} All non-stage targets, in array order. */\n get sprites() {\n return this.json.targets\n .filter((t) => !t.isStage)\n .map((t) => new Sprite(t, this));\n }\n\n /** @returns {Array<Stage | Sprite>} Every target, stage included. */\n get targets() {\n return this.json.targets.map((t) =>\n t.isStage ? new Stage(t, this) : new Sprite(t, this),\n );\n }\n\n /** @returns {ProjectMeta} The project's `meta` block (semver, vm, agent). */\n get meta() {\n return this.json.meta;\n }\n\n /** @returns {object[]} The raw `monitors` (variable/list watchers) array. */\n get monitors() {\n return this.json.monitors;\n }\n\n /** @returns {string[]} Ids of enabled extensions (e.g. `pen`, `music`). */\n get extensions() {\n return this.json.extensions;\n }\n\n /**\n * Find a sprite by name.\n *\n * @param {string} name\n * @returns {Sprite | undefined}\n */\n sprite(name) {\n const json = this.json.targets.find((t) => !t.isStage && t.name === name);\n return json ? new Sprite(json, this) : undefined;\n }\n\n /**\n * Find any target (sprite or stage) by name.\n *\n * @param {string} name\n * @returns {Stage | Sprite | undefined}\n */\n target(name) {\n const json = this.json.targets.find((t) => t.name === name);\n if (!json) return undefined;\n return json.isStage ? new Stage(json, this) : new Sprite(json, this);\n }\n\n /**\n * Add a new, empty sprite. It starts with no costumes, so add at least one\n * with {@link Sprite#addCostume} before opening the project in the editor.\n *\n * @param {string} name - Sprite name (must be unique among sprites).\n * @param {object} [props] - Initial property overrides (`x`, `y`, `size`, …).\n * @returns {Sprite} The new sprite.\n */\n addSprite(name, props = {}) {\n if (this.sprite(name))\n throw new Error(`A sprite named \"${name}\" already exists.`);\n const maxLayer = Math.max(\n 0,\n ...this.json.targets.map((t) => t.layerOrder ?? 0),\n );\n const json = {\n isStage: false,\n name: String(name),\n variables: {},\n lists: {},\n broadcasts: {},\n blocks: {},\n comments: {},\n currentCostume: 0,\n costumes: [],\n sounds: [],\n volume: 100,\n layerOrder: maxLayer + 1,\n visible: true,\n x: 0,\n y: 0,\n size: 100,\n direction: 90,\n draggable: false,\n rotationStyle: 'all around',\n ...props,\n };\n this.json.targets.push(json);\n return new Sprite(json, this);\n }\n\n /**\n * Remove a sprite by name or instance. Assets it solely owned are dropped.\n *\n * @param {string | Sprite} nameOrSprite\n * @returns {boolean} True if a sprite was removed.\n */\n removeSprite(nameOrSprite) {\n const name =\n typeof nameOrSprite === 'string' ? nameOrSprite : nameOrSprite.name;\n const index = this.json.targets.findIndex(\n (t) => !t.isStage && t.name === name,\n );\n if (index < 0) return false;\n const [removed] = this.json.targets.splice(index, 1);\n for (const media of [...removed.costumes, ...removed.sounds]) {\n this._maybeDropAsset(media.md5ext);\n }\n return true;\n }\n\n /**\n * Drop an asset's bytes if no costume or sound anywhere still references it.\n * Called automatically when media is removed or its bytes are replaced.\n *\n * @param {string} md5ext\n * @private\n */\n _maybeDropAsset(md5ext) {\n if (!md5ext) return;\n const stillUsed = this.json.targets.some(\n (t) =>\n t.costumes.some((c) => c.md5ext === md5ext) ||\n t.sounds.some((s) => s.md5ext === md5ext),\n );\n if (!stillUsed) this.assets.delete(md5ext);\n }\n\n /**\n * Serialize the project back into `.sb3` bytes.\n *\n * @param {object} [options]\n * @param {number} [options.compressionLevel=6] - DEFLATE level, 1–9.\n * @returns {Promise<Uint8Array>} The sb3 zip bytes.\n */\n async save({ compressionLevel = 6 } = {}) {\n const zip = new JSZip();\n zip.file('project.json', JSON.stringify(this.json));\n for (const [path, bytes] of this.assets) {\n zip.file(path, bytes);\n }\n return zip.generateAsync({\n type: 'uint8array',\n compression: 'DEFLATE',\n compressionOptions: { level: compressionLevel },\n });\n }\n}\n"],"names":["__webpack_require__","e","Object","Symbol","K","Int32Array","S","rotl","x","c","HEX","i","hexLE","md5","input","msg","Uint8Array","n","withOne","total","buf","bitsLo","bitsHi","a0","b0","c0","d0","M","off","j","A","B","C","D","F","g","Asset","json","project","value","String","bytes","old","hash","Costume","Number","Sound","startsWith","sig","b","ascii","s","sniffFormat","head","SOUP","uid","id","Math","Target","Boolean","name","entry","undefined","data","options","dataFormat","nameOrIndex","kind","list","index","m","removed","found","items","Stage","Sprite","DEFAULT_META","Project","assets","Map","zip","JSZip","projectFile","Error","JSON","reads","path","file","Promise","t","props","maxLayer","nameOrSprite","media","md5ext","compressionLevel"],"mappings":"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"}