34 | It works!
35 | Transparency is supported, so you can display the project behind the frame as long as the page doesn't explicitly set a background color.
36 | You can also use JavaScript and most other Web APIs, like this:
37 | Click me!
38 | Due to browser security measures, blocks like "mouse x" and "mouse down?" will not work while the cursor is over the frame unless you use the disable interactivity block.
39 | Many websites also block other sites from embedding them for security reasons.
40 |
41 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/website/hello.txt:
--------------------------------------------------------------------------------
1 | Hello, world!
--------------------------------------------------------------------------------
/website/hello.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TurboWarp/extensions/a73e6fd55ee6a502abe75e32adfd2c6def412f51/website/hello.zip
--------------------------------------------------------------------------------
/website/meow.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TurboWarp/extensions/a73e6fd55ee6a502abe75e32adfd2c6def412f51/website/meow.mp3
--------------------------------------------------------------------------------
/website/robot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TurboWarp/extensions/a73e6fd55ee6a502abe75e32adfd2c6def412f51/website/robot.png
--------------------------------------------------------------------------------
/website/test/README.md:
--------------------------------------------------------------------------------
1 | DO NOT use these test extensions. They WILL be deleted and modified in ways that break your project, and they don't have any blocks you would actually want to use.
2 |
--------------------------------------------------------------------------------
/website/test/bad-xml.js:
--------------------------------------------------------------------------------
1 | (function(Scratch) {
2 | 'use strict';
3 |
4 | class XMLTest {
5 | getInfo () {
6 | return {
7 | id: 'xmltest',
8 | name: `<>"'&& Name`,
9 | docsURI: `https://example.com/&''""<<>>`,
10 | menuIconURI: `data:<>&"' category icon`,
11 | blocks: [
12 | {
13 | blockType: `block type <>&"'`,
14 | opcode: `opcode <>&"'`,
15 | text: `<>&"' [string argument <>&"'] [inputMenu <"'&>] [fieldMenu <"'&>] [image <"'&>]`,
16 | blockIconURI: `'data:<>&"' block icon`,
17 | arguments: {
18 | [`string argument <>&"'`]: {
19 | type: Scratch.ArgumentType.STRING,
20 | defaultValue: `default string <>&"'`
21 | },
22 | [`inputMenu <"'&>`]: {
23 | type: Scratch.ArgumentType.STRING,
24 | menu: `input <>&"'`,
25 | defaultValue: `default input <>&"'`
26 | },
27 | [`fieldMenu <"'&>`]: {
28 | type: `argument type <>&"'`,
29 | menu: `field <>&"'`,
30 | defaultValue: `default field <>&"'`
31 | },
32 | [`image <"'&>`]: {
33 | type: Scratch.ArgumentType.IMAGE,
34 | dataURI: `data:<>&"' image input`
35 | }
36 | }
37 | },
38 | {
39 | opcode: 'button',
40 | blockType: Scratch.BlockType.BUTTON,
41 | text: `'"><& button text`,
42 | func: `'"><& func`
43 | }
44 | ],
45 | menus: {
46 | [`input <>&"'`]: {
47 | acceptReporters: true,
48 | items: [
49 | `1 <>&"`,
50 | `2 <>&"`,
51 | `3 <>&"`
52 | ]
53 | },
54 | [`field <>&"'`]: {
55 | acceptReporters: false,
56 | items: [
57 | `1 <>&"`,
58 | `2 <>&"`,
59 | `3 <>&"`
60 | ]
61 | }
62 | }
63 | };
64 | }
65 | [`opcode <>&"'`](args) {
66 | console.log(args);
67 | }
68 | }
69 | Scratch.extensions.register(new XMLTest());
70 | })(Scratch);
71 |
--------------------------------------------------------------------------------
/website/test/broken.js:
--------------------------------------------------------------------------------
1 | (function(Scratch) {
2 | 'use strict';
3 |
4 | class Broken {
5 | getInfo () {
6 | return {
7 | id: 'broken',
8 | name: 'Broken Extension',
9 | blocks: [
10 | {
11 | opcode: 'error',
12 | blockType: Scratch.BlockType.REPORTER,
13 | text: 'error'
14 | },
15 | {
16 | opcode: 'returnUndefined',
17 | blockType: Scratch.BlockType.REPORTER,
18 | text: 'return undefined'
19 | }
20 | ]
21 | };
22 | }
23 |
24 | error () {
25 | throw new Error("This is an error :(");
26 | }
27 |
28 | returnUndefined () {
29 |
30 | }
31 | }
32 |
33 | Scratch.extensions.register(new Broken());
34 | })(Scratch);
35 |
--------------------------------------------------------------------------------
/website/test/button.js:
--------------------------------------------------------------------------------
1 | (function(Scratch) {
2 | 'use strict';
3 | class Test {
4 | getInfo () {
5 | return {
6 | id: 'testbutton',
7 | name: 'test 123',
8 | docsURI: 'https://extensions.turbowarp.org',
9 | blocks: [
10 | {
11 | blockType: Scratch.BlockType.BUTTON,
12 | func: 'MAKE_A_VARIABLE',
13 | text: 'Make variable'
14 | },
15 | {
16 | blockType: Scratch.BlockType.BUTTON,
17 | text: ':)',
18 | func: 'hello'
19 | }
20 | ]
21 | };
22 | }
23 | hello () {
24 | alert('>:]');
25 | }
26 | }
27 | Scratch.extensions.register(new Test());
28 | })(Scratch);
29 |
--------------------------------------------------------------------------------
/website/test/cjk.js:
--------------------------------------------------------------------------------
1 | (function (Scratch) {
2 | 'use strict';
3 |
4 | Scratch.extensions.register({
5 | getInfo: () => ({
6 | id: 'testcjk',
7 | name: '这是一个测试',
8 | blocks: [
9 | {
10 | opcode: 'test1',
11 | text: '這是一個測試',
12 | blockType: Scratch.BlockType.COMMAND
13 | },
14 | {
15 | opcode: 'test2',
16 | text: 'これはテストです',
17 | blockType: Scratch.BlockType.COMMAND
18 | },
19 | {
20 | opcode: 'test3',
21 | text: '이것은 테스트입니다',
22 | blockType: Scratch.BlockType.COMMAND
23 | }
24 | ]
25 | })
26 | });
27 | })(Scratch);
28 |
--------------------------------------------------------------------------------
/website/test/l10n.js:
--------------------------------------------------------------------------------
1 | (function(Scratch) {
2 | 'use strict';
3 | Scratch.translate.setup({
4 | en: {
5 | test: 'EN message'
6 | },
7 | es: {
8 | test: 'ES message'
9 | }
10 | });
11 | class Test {
12 | getInfo() {
13 | return {
14 | id: 'testl10n',
15 | name: Scratch.translate('Default message'),
16 | blocks: []
17 | };
18 | }
19 | }
20 | Scratch.extensions.register(new Test());
21 | })(Scratch);
22 |
--------------------------------------------------------------------------------
/website/test/label.js:
--------------------------------------------------------------------------------
1 | (function(Scratch) {
2 | 'use strict';
3 | class Test {
4 | getInfo() {
5 | return {
6 | id: 'testlabel',
7 | name: 'Label',
8 | blocks: [
9 | {
10 | blockType: Scratch.BlockType.LABEL,
11 | text: 'test 123 :) <>&%"'
12 | }
13 | ]
14 | };
15 | }
16 | }
17 | Scratch.extensions.register(new Test());
18 | })(Scratch);
19 |
--------------------------------------------------------------------------------
/website/test/loops.js:
--------------------------------------------------------------------------------
1 | // From https://github.com/TurboWarp/scratch-vm/pull/141
2 | (function (Scratch) {
3 | "use strict";
4 |
5 | class LoopsAndThings {
6 | getInfo() {
7 | return {
8 | id: "loopsAndThings",
9 | name: "Loops and things test",
10 | blocks: [
11 | {
12 | opcode: "conditional",
13 | blockType: Scratch.BlockType.CONDITIONAL,
14 | text: "run branch [BRANCH] of",
15 | arguments: {
16 | BRANCH: {
17 | type: Scratch.ArgumentType.NUMBER,
18 | defaultValue: 1
19 | }
20 | },
21 | branchCount: 3
22 | },
23 | {
24 | opcode: "loop",
25 | blockType: Scratch.BlockType.LOOP,
26 | text: "my repeat [TIMES]",
27 | arguments: {
28 | TIMES: {
29 | type: Scratch.ArgumentType.NUMBER,
30 | defaultValue: 10
31 | }
32 | },
33 | },
34 | '---',
35 | {
36 | opcode: "testPromise",
37 | blockType: Scratch.BlockType.REPORTER,
38 | text: "return [VALUE] in a Promise",
39 | arguments: {
40 | VALUE: {
41 | type: Scratch.ArgumentType.STRING,
42 | defaultValue: ''
43 | }
44 | }
45 | }
46 | ]
47 | };
48 | }
49 |
50 | conditional({BRANCH}, util) {
51 | return Scratch.Cast.toNumber(BRANCH);
52 | }
53 |
54 | loop({TIMES}, util) {
55 | const times = Math.round(Scratch.Cast.toNumber(TIMES));
56 | if (typeof util.stackFrame.loopCounter === "undefined") {
57 | util.stackFrame.loopCounter = times;
58 | }
59 | util.stackFrame.loopCounter--;
60 | if (util.stackFrame.loopCounter >= 0) {
61 | return true;
62 | }
63 | }
64 |
65 | testPromise({VALUE}) {
66 | return Promise.resolve(VALUE);
67 | }
68 | }
69 |
70 | Scratch.extensions.register(new LoopsAndThings());
71 | })(Scratch);
--------------------------------------------------------------------------------
/website/test/scratchx.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | const ext = {};
5 |
6 | ext._getStatus = () => ({
7 | status: 2,
8 | msg: 'Ready'
9 | });
10 |
11 | ext.testReporter = () => Math.random();
12 |
13 | ext.testReporterWait = (delay, callback) => {
14 | setTimeout(() => {
15 | callback(Math.random());
16 | }, delay * 1000);
17 | };
18 |
19 | var descriptor = {
20 | blocks: [
21 | ['r', 'test reporter', 'testReporter'],
22 | ['R', 'test reporter 2 %n', 'testReporterWait', '1'],
23 | ],
24 | };
25 |
26 | ScratchExtensions.register('ScratchX Test', descriptor, ext);
27 | }());
28 |
--------------------------------------------------------------------------------