Skip to content

Commit e75cc08

Browse files
Added Both Revoke and Read function to the Blob Extension (#439)
* Added Both Revoke and Read function TheShovel, what's up pookie ;P * Fixed Unsafe stuff * Switched to DataView [and more small fixes] I couldn't remove that one loop and I spent a long time trying to do so, if you have any more stuff you would like me to change I would be more than happy to do so * Update Blobs.js * Use encoding types instead of just using plaintext. Here's some bullet points on what this does: * Allow extension users to choose what they want to be outputted, rather than deciding automatically based on the MIME. * Correct base64 encoding: encoding through first writing it to a string is not only a relatively slow way of doing such, but is also not safe, due to the potential for data loss. * Added 4 encoding types, available in both the read and write blocks for blob URLs: base 64, data URL, plain text, byte array. * Base 64 reads it as base 64; note: not a string encoded to base 64, but as binary data that was base 64 encoded. * Data URL resolves the data URL and uses its content to write to the object URL. * Plaintext just takes in the input as plaintext, just as it was done before. * Byte array takes in an array of numbers that are between 0 and 255 and reads it as a string of bytes. Outputted as a JSON string so as to be compatible with other extensions such as Arrays. --------- Co-authored-by: Steve0Greatness <steve0greatnessiscool@gmail.com>
1 parent aaf9b5a commit e75cc08

File tree

1 file changed

+104
-5
lines changed

1 file changed

+104
-5
lines changed

static/extensions/Faunks/Blobs.js

Lines changed: 104 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
{
2222
opcode: "toBlob",
2323
blockType: Scratch.BlockType.REPORTER,
24-
text: "Turn [DATA] to a [TYPE] blob",
24+
text: "Turn [DATA] from [ENCODING] to a [TYPE] blob",
2525
arguments: {
2626
DATA: {
2727
type: Scratch.ArgumentType.STRING
@@ -31,10 +31,49 @@
3131
defaultValue: "text/plain",
3232
menu: "types"
3333
},
34+
ENCODING: {
35+
type: Scratch.ArgumentType.STRING,
36+
defaultValue: "b64",
37+
menu: "encodings",
38+
}
39+
},
40+
},
41+
{
42+
opcode: "readBlob",
43+
blockType: Scratch.BlockType.REPORTER,
44+
text: "Read blob [URL] as [ENCODING]",
45+
arguments: {
46+
URL: {
47+
type: Scratch.ArgumentType.STRING
48+
},
49+
ENCODING: {
50+
type: Scratch.ArgumentType.STRING,
51+
defaultValue: "b64",
52+
menu: "encodings",
53+
}
54+
},
55+
},
56+
{
57+
opcode: "revokeBlob",
58+
blockType: Scratch.BlockType.COMMAND,
59+
text: "Revoke blob with the URL of [URL]",
60+
arguments: {
61+
URL: {
62+
type: Scratch.ArgumentType.STRING
63+
}
3464
},
3565
},
3666
]
3767
,menus: {
68+
encodings: {
69+
acceptReporters: true,
70+
items: [
71+
{ text: "Base64", value: "b64" },
72+
{ text: "Data URL", value: "dataurl" },
73+
{ text: "Plain Text", value: "plain" },
74+
{ text: "Byte Array", value: "array" }
75+
]
76+
},
3877
types: {
3978
acceptReporters: true,
4079
items: [
@@ -102,11 +141,71 @@
102141
}
103142
}
104143

105-
toBlob(args, util) {
106-
const text = String(args.DATA); // ensure it's a string (why can't it be just like python or smth)
107-
const blob = new Blob([text], { type: args.TYPE });
144+
async toBlob(args, util) {
145+
var part = args.DATA;
146+
const encoding = args.ENCODING;
147+
148+
switch (encoding) {
149+
case "array":
150+
part = JSON.parse(args.DATA);
151+
break;
152+
case "b64":
153+
var url = `data:application/octet-stream;base64,` + args.DATA;
154+
case "dataurl":
155+
var url = url ?? args.DATA;
156+
157+
if (!url.startsWith("data:")) throw new URIError("only data URLs are allowed to be resolved");
158+
159+
part = await (await fetch(url)).bytes();
160+
break;
161+
default:
162+
// Plain text used to be default behavior. I would've made it throw, otherwise.
163+
break;
164+
}
165+
166+
const blob = new Blob([part], { type: args.TYPE });
108167
return URL.createObjectURL(blob);
109-
}
168+
}
169+
170+
revokeBlob(args, util){
171+
URL.revokeObjectURL(args.URL);
172+
}
173+
174+
async readBlob(args, util) {
175+
const url = args.URL;
176+
const encoding = args.ENCODING;
177+
178+
if (!url.startsWith("blob:")) throw new URIError("must be a blob url");
179+
180+
const response = await fetch(url);
181+
const blob = await response.blob();
182+
183+
if (blob.size === 0) switch (encoding) {
184+
case "array": return "[]";
185+
case "dataurl": return `data:${blob.type},`;
186+
default: return "";
187+
}
188+
189+
190+
switch (encoding) {
191+
case "plain": return await blob.text();
192+
case "array": return JSON.stringify(Array.from(await blob.bytes()));
193+
default:
194+
const dataURL = await readBlobToDataURL(blob);
195+
196+
if (encoding == "dataurl") return dataURL;
197+
return dataURL.slice(dataURL.indexOf(",") + 1);
198+
}
199+
}
110200
}
201+
202+
function readBlobToDataURL(blob) {
203+
return new Promise(res => {
204+
const reader = new FileReader();
205+
reader.onload = e => res(e.target.result);
206+
reader.readAsDataURL(blob);
207+
});
208+
}
209+
111210
Scratch.extensions.register(new faunks_Blobs());
112211
})(Scratch);

0 commit comments

Comments
 (0)