Open ajskateboarder opened 7 months ago
The reason why this example code doesn't work is unrelated to empty C blocks - it's trying to find a "when green flag clicked" block in the stage but the code is in a sprite. The following works correctly:
import {toScratchblocks} from "./parse-sb3-blocks.mjs"
let projectJSON = {"targets":[{"isStage":true,"name":"Stage","variables":{"`jEk@4|i[#Fk?(8x)AV.-my variable":["my variable",0]},"lists":{},"broadcasts":{},"blocks":{},"comments":{},"currentCostume":0,"costumes":[{"name":"backdrop1","dataFormat":"svg","assetId":"cd21514d0531fdffb22204e0ec5ed84a","md5ext":"cd21514d0531fdffb22204e0ec5ed84a.svg","rotationCenterX":240,"rotationCenterY":180}],"sounds":[],"volume":100,"layerOrder":0,"tempo":60,"videoTransparency":50,"videoState":"on","textToSpeechLanguage":null},{"isStage":false,"name":"Sprite1","variables":{},"lists":{},"broadcasts":{},"blocks":{"a":{"opcode":"event_whenflagclicked","next":"b","parent":null,"inputs":{},"fields":{},"shadow":false,"topLevel":true,"x":34,"y":152},"b":{"opcode":"control_forever","next":null,"parent":"a","inputs":{},"fields":{},"shadow":false,"topLevel":false}},"comments":{},"currentCostume":0,"costumes":[{"name":"costume1","bitmapResolution":1,"dataFormat":"svg","assetId":"592bae6f8bb9c8d88401b54ac431f7b6","md5ext":"592bae6f8bb9c8d88401b54ac431f7b6.svg","rotationCenterX":44,"rotationCenterY":44}],"sounds":[],"volume":100,"layerOrder":1,"visible":true,"x":0,"y":0,"size":100,"direction":90,"draggable":false,"rotationStyle":"all around"}],"monitors":[],"extensions":[],"meta":{"semver":"3.0.0","vm":"0.2.0","agent":""}};
const sprite = projectJSON.targets.filter(t => !t.isStage)[0];
const whenGreenflag = Object.keys(sprite.blocks).filter(key => sprite.blocks[key].opcode === 'event_whenflagclicked')[0];
console.log(toScratchblocks(whenGreenflag, sprite.blocks, "en", {tab: " "}));
The library parses an empty C block correctly in this project: https://apple502j.github.io/parse-sb3-blocks/demo?pid=1007401022&locale=en&sprite=%20Player
Whoops, I was being too general (and also less attentive) when making this issue. So far, I have only had issues trying to parse if statements that have no inner blocks. Here's what I believe is a bug from looking at issues in my use case:
import { toScratchblocks } from "./parse-sb3-blocks.module.js";
let script = {
"(": {
fields: {},
inputs: {},
next: ")",
opcode: "event_whenflagclicked",
parent: null,
shadow: false,
topLevel: true,
x: 416,
y: 846,
id: "(",
},
")": {
fields: {},
inputs: {
SUBSTACK: [1, null],
},
next: null,
opcode: "control_if",
parent: "(",
shadow: false,
topLevel: false,
id: ")",
},
};
console.log(toScratchblocks("(", script, "en", { tab: " " }));
Which throws:
TypeError: Cannot set properties of undefined (setting 'id')
at se (parse-sb3-blocks.module.js:1:1616164)
at parse-sb3-blocks.module.js:1:1614024
at Array.forEach (<anonymous>)
at ae (parse-sb3-blocks.module.js:1:1613930)
at se (parse-sb3-blocks.module.js:1:1616392)
at ne (parse-sb3-blocks.module.js:1:1616636)
at index.js:30:13
at ModuleJob.run (node:internal/modules/esm/module_job:193:25)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:526:24)
I received this error on the latest build of parse-sb3-blocks here. The demo also seems to fail to parse it as well: https://apple502j.github.io/parse-sb3-blocks/demo?pid=1009824086&locale=en&sprite=Sprite1
How was this project made? When saving it using Scratch, "inputs": {"SUBSTACK": [1, null]}
, becomes "inputs": {}
, which parses correctly.
The project I made for the demo was made using plain Scratch. The JSON I provided was through TurboWarp though
I will try replacing {"SUBSTACK": [1, null]}
with {}
before passing it to parseSB3Blocks
edit: This works:
import { toScratchblocks } from "./parse-sb3-blocks.module.js";
let script = {
"(": {
fields: {},
inputs: {},
next: ")",
opcode: "event_whenflagclicked",
parent: null,
shadow: false,
topLevel: true,
x: 416,
y: 846,
id: "(",
},
")": {
fields: {},
inputs: {
SUBSTACK: [1, null],
},
next: null,
opcode: "control_if",
parent: "(",
shadow: false,
topLevel: false,
id: ")",
},
};
let script = JSON.parse(
JSON.stringify(script)
.replaceAll('{"SUBSTACK":[1,null]}', "{}")
.replaceAll(',"SUBSTACK":[1,null]', "")
)
console.log(toScratchblocks("(", script, "en", { tab: " " }));
Thanks so much for this workaround, this bug was driving me nuts. As for a proper fix, I don't think the project author would need to do much other than adding documentation somewhere on how to handle it.
Here's a minimal reproducable example:
This will throw the following: