@turbowarp/sb3fix 0.3.2 → 0.3.4
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/package.json +3 -3
- package/src/sb3fix.js +63 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@turbowarp/sb3fix",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "Fix corrupted Scratch projects",
|
|
5
5
|
"main": "src/sb3fix.js",
|
|
6
6
|
"scripts": {
|
|
@@ -21,11 +21,11 @@
|
|
|
21
21
|
},
|
|
22
22
|
"homepage": "https://github.com/TurboWarp/sb3fix#readme",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@turbowarp/jszip": "^3.11.
|
|
24
|
+
"@turbowarp/jszip": "^3.11.1"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"copy-webpack-plugin": "^12.0.2",
|
|
28
|
-
"webpack": "^5.
|
|
28
|
+
"webpack": "^5.96.1",
|
|
29
29
|
"webpack-cli": "^5.1.4"
|
|
30
30
|
}
|
|
31
31
|
}
|
package/src/sb3fix.js
CHANGED
|
@@ -199,6 +199,29 @@ const fixJSON = (data, options = {}) => {
|
|
|
199
199
|
}
|
|
200
200
|
};
|
|
201
201
|
|
|
202
|
+
/**
|
|
203
|
+
* @param {string} id
|
|
204
|
+
* @param {unknown} comment
|
|
205
|
+
*/
|
|
206
|
+
const fixCommentInPlace = (id, comment) => {
|
|
207
|
+
if (!isObject(comment)) {
|
|
208
|
+
throw new Error('comment is not an object');
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (typeof comment.text !== 'string') {
|
|
212
|
+
throw new Error('comment text is not a string');
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Scratch requires comments to not exceed 8000 characters.
|
|
216
|
+
// We'll store the excess in .extraText so the text won't be truncated if opened in TurboWarp.
|
|
217
|
+
const MAX_LENGTH = 8000;
|
|
218
|
+
if (comment.text.length > MAX_LENGTH) {
|
|
219
|
+
log(`comment ${id} had length ${comment.text.length}`);
|
|
220
|
+
comment.extraText = comment.text.substring(MAX_LENGTH);
|
|
221
|
+
comment.text = comment.text.substring(0, MAX_LENGTH);
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
|
|
202
225
|
/**
|
|
203
226
|
* @param {unknown} target
|
|
204
227
|
*/
|
|
@@ -287,6 +310,14 @@ const fixJSON = (data, options = {}) => {
|
|
|
287
310
|
fixBlockInPlace(blockId, block);
|
|
288
311
|
}
|
|
289
312
|
|
|
313
|
+
// Comments are not required
|
|
314
|
+
const comments = target.comments;
|
|
315
|
+
if (comments) {
|
|
316
|
+
for (const [commentId, comment] of Object.entries(comments)) {
|
|
317
|
+
fixCommentInPlace(commentId, comment);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
290
321
|
const variables = target.variables;
|
|
291
322
|
if (!isObject(variables)) {
|
|
292
323
|
throw new Error('variables is not an object');
|
|
@@ -314,6 +345,16 @@ const fixJSON = (data, options = {}) => {
|
|
|
314
345
|
target.layerOrder = 1;
|
|
315
346
|
}
|
|
316
347
|
}
|
|
348
|
+
|
|
349
|
+
const ROTATION_STYLES = [
|
|
350
|
+
'all around',
|
|
351
|
+
'don\'t rotate',
|
|
352
|
+
'left-right'
|
|
353
|
+
];
|
|
354
|
+
if (!target.isStage && !ROTATION_STYLES.includes(target.rotationStyle)) {
|
|
355
|
+
log(`sprite had invalid rotation style ${target.rotationStyle}`);
|
|
356
|
+
target.rotationStyle = 'all around';
|
|
357
|
+
}
|
|
317
358
|
};
|
|
318
359
|
|
|
319
360
|
/**
|
|
@@ -351,11 +392,10 @@ const fixJSON = (data, options = {}) => {
|
|
|
351
392
|
fixTargetInPlace(target);
|
|
352
393
|
}
|
|
353
394
|
|
|
354
|
-
let stage;
|
|
355
395
|
const allStages = targets.filter((target) => target.isStage);
|
|
356
396
|
if (allStages.length === 0) {
|
|
357
397
|
log('stage is missing; adding an empty one');
|
|
358
|
-
|
|
398
|
+
targets.unshift({
|
|
359
399
|
isStage: true,
|
|
360
400
|
name: 'Stage',
|
|
361
401
|
variables: {},
|
|
@@ -380,22 +420,31 @@ const fixJSON = (data, options = {}) => {
|
|
|
380
420
|
videoTransparency: 50,
|
|
381
421
|
videoState: "on",
|
|
382
422
|
textToSpeechLanguage: null
|
|
383
|
-
};
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
const
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
targets.splice(
|
|
423
|
+
});
|
|
424
|
+
} else {
|
|
425
|
+
// We will accept the first stage in targets as the real stage
|
|
426
|
+
const firstStageIndex = targets.findIndex((target) => target.isStage);
|
|
427
|
+
|
|
428
|
+
// Stage must be the first target
|
|
429
|
+
if (firstStageIndex !== 0) {
|
|
430
|
+
log(`stage was at wrong index: ${firstStageIndex}`);
|
|
431
|
+
const stage = targets[firstStageIndex];
|
|
432
|
+
targets.splice(firstStageIndex, 1);
|
|
393
433
|
targets.unshift(stage);
|
|
394
434
|
}
|
|
395
|
-
|
|
396
|
-
|
|
435
|
+
|
|
436
|
+
// Remove all the other stages
|
|
437
|
+
for (let i = targets.length - 1; i > 0; i--) {
|
|
438
|
+
if (targets[i].isStage) {
|
|
439
|
+
log(`removing extra stage at index ${i}`);
|
|
440
|
+
targets.splice(i, 1);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
397
443
|
}
|
|
398
444
|
|
|
445
|
+
// Above checks ensure this invariant holds
|
|
446
|
+
const stage = targets[0];
|
|
447
|
+
|
|
399
448
|
// stage's name must match exactly
|
|
400
449
|
if (stage.name !== 'Stage') {
|
|
401
450
|
log(`stage had wrong name: ${stage.name}`);
|