< User:Kenny2scratch

Writing Scratch Extensions (3.0)

Scratch Extensions make it possible to communicate with hardware or web services, thereby enhancing the functionality of Scratch. This article describes the process for creating Scratch extensions.

The process for creating the extension can be summarized into the following steps:

  1. Add boilerplate code
  2. Describe the extension
  3. Describe the blocks that the extension adds
  4. Describe any dropdown menus that the extension requires
  5. Specify the strings to use for other languages
  6. Add code implementing each block

For this article, the resulting sample extension will provide three new blocks:

  • A reporter block that returns its first argument to the power of its second argument: (() to the power of ()::extension)
  • A boolean block that returns true if exactly one of the boolean inputs is true: <<> xor <>::extension>
  • A reporter block that returns a bitwise operator (specified by its second argument) of its first and third arguments: (bitwise [or v] of () and ()::extension)
Note Note: This article assumes medium-level prior knowledge of JavaScript. See Category:JavaScript Tutorials for a tutorial about JavaScript.

Before Beginning

Before starting, make ready the following things:

Adding boilerplate code

Add the following code to the opened JavaScript file:

 1 class ExtraReporters {
 2     constructor (runtimeProxy) {
 3         /**
 4          * A proxy to communicate with the Scratch 3.0 runtime across a worker boundary.
 5          * @type {Runtime}
 6          */
 7         this.runtime = runtimeProxy;
 8     }
 9 
10     /**
11      * More info in the "Describing the Extension" section.
12      * @return {object} This extension's metadata.
13      */
14     getInfo () {
15         return {
16             // Internal name of the extension - must be valid as a variable name
17             id: 'extraReporters',
18 
19             // Optional: the displayed name of this extension as string or array.
20             // If this is not specified, the "id" value will be used.
21             // If this is an array, first element must be the name in the default language,
22             // while the second is the ID of the translation string for the name in other languages.
23             // If this is a string, it will be displayed as the name no matter what.
24             name: ['Extra Reporters', 'extraReporters'],
25 
26             // Optional: URL to an image that will be used as the extension icon. "data:" URLs
27             // can be used.
28             // If this is not specified, a generic icon will be used.
29             iconURI: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAFCAAAAACyOJm3AAAAFklEQVQYV2P4DwMMEMgAI/+DEUIMBgAEWB7i7uidhAAAAABJRU5ErkJggg==',
30 
31             // Optional: Link to a webpage documenting this extension.
32             // If this is not specified, the extension will have no documentation link.
33             docsURI: 'https://....',
34 
35             // The list of blocks that this extension adds. This must be specified.
36             // They will appear on Scratch in the same order they are specified here.
37             // More about this later in the "Describing the Blocks" section.
38             blocks: [
39             ],
40 
41             // The list of dropdown menus that this extension uses.
42             // More about this later in the "Describing Dropdown Menus" section.
43             menus: {
44             },
45             
46             // A map of strings to use for different languages.
47             // More about this later in the "Specifying Other Languages" section.
48             translation_map: {
49             }
50         };
51     }
52 }

Describing the Extension

16             // Internal name of the extension - must be valid as a variable name
17             id: 'extraReporters',

This value will be used to identify the extension within the Scratch code. It must be valid as a variable name. It is usually best to use a descriptive name.

19             // Optional: the displayed name of this extension as string or array.
20             // If this is not specified, the "id" value will be used.
21             // If this is an array, first element must be the name in the default language,
22             // while the second is the ID of the translation string for the name in other languages.
23             // If this is a string, it will be displayed as the name no matter what.
24             name: ['Extra Reporters', 'extraReporters'],

This value can be one of the following:

  • Not there at all, in which case the "id" value will be displayed as the name
  • An array with two elements:
    • The name to be displayed if no translations are available
    • The ID for the translation string to be displayed, if available. (Translating is explained in the section Specifying Other Languages.)
  • A string, which will be displayed as the name of the extension in all cases
26             // Optional: URL to an image that will be used as the extension icon. "data:" URLs
27             // can be used.
28             // If this is not specified, a generic icon will be used.
29             iconURI: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAFCAAAAACyOJm3AAAAFklEQVQYV2P4DwMMEMgAI/+DEUIMBgAEWB7i7uidhAAAAABJRU5ErkJggg==',

This is an URL to an image, which will be used as the icon for the extension. Data URIs are allowed. If this is left out, a generic icon will be used. As an example, a Wiki-related extension might use this image URL: https://en.scratch-wiki.info/w/images/Wiki_icon.png

31             // Optional: Link to a webpage documenting this extension.
32             // If this is not specified, the extension will have no documentation link.
33             docsURI: 'https://....',

This is another URL, this time to a webpage with more information about the extension. For example, a Wiki-related extension might link back to the Wiki page documenting the extension. If the extension has no documentation, this can be left out.

35             // The list of blocks that this extension adds. This must be specified.
36             // They will appear on Scratch in the same order they are specified here.
37             // More about this later in the "Describing the Blocks" section.
38             blocks: [
39             ],

This is where the blocks that the extension adds must be described. What should go in here will be explained in the Describing the Blocks section.

41             // The list of dropdown menus that this extension uses.
42             // More about this later in the "Describing Dropdown Menus" section.
43             menus: {
44             },

This is where the dropdown menus that the extension adds can be described. What should go in here will be explained in the section Describing Dropdown Menus.

46             // A map of strings to use for different languages.
47             // More about this later in the "Specifying Other Languages" section.
48             translation_map: {
49             }

This is where strings to use for different languages will be specified. What should go in here will be explained in the section Specifying Other Languages.

Describing the Blocks

Below is some sample code to add for the new "power" block.

38             blocks: [
39                 {
40                     // Internal name of the block - must be valid as a variable name.
41                     opcode: 'power',
42 
43                     // The type of block being defined. Explained in more detail below.
44                     blockType: 'reporter',
45 
46                     // The number of branches this block includes.
47                     // This should be left out for blocks that are not C or E-shaped.
48                     branchCount: 0,
49 
50                     // Whether this is a cap block. False if left out.
51                     terminal: false,
52 
53                     // What actually appears on the block. Explained in more detail below.
54                     text: ['{BASE} to the power of {EXPONENT}', 'power_text']
55 
56                     // Default values for each block input. If left out, inputs will be blank.
57                     defaults: {
58                         BASE: 2,
59                         EXPONENT: 3
60                     }
61 
62                     // The code for the block.
63                     func: this.power,
64 
65                     // List of places where the block is allowed to appear.
66                     // For example, the "switch costume" block has this set to ['sprite'].
67                     filter: ['sprite', 'stage']
68                 }
69             ],

Explained part by part:

40                     // Internal name of the block - must be valid as a variable name.
41                     opcode: 'power',

This is the internal name for the block. It has the same restrictions as the internal name for the extension.

43                     // The type of block being defined. Explained in more detail below.
44                     blockType: 'reporter',

This is the type of block that this block should be. The available block types include:

  • 'command', the result of which is an ordinary Stack Block
  • 'reporter', the result of which is a normal Reporter Block
  • 'Boolean', the result of which is a Boolean Block
  • 'hat', the result of which is a Hat Block. These blocks are, in essence, Boolean blocks that have the extra task of starting a stack of blocks whenever they are true.
  • 'conditional', the result of which is a C Block, an E block, a € block, or so on.
  • 'loop', the result of which is always a C block. These blocks differ from normal C blocks in that when the stack they encapsulate is finished running, the "loop" block is run again to determine whether to run the stack again.
46                     // The number of branches this block includes.
47                     // This should be left out for blocks that are not C or E-shaped.
48                     branchCount: 0,
This is the number of branches that a 'conditional' block has. For example, for an if <> then block this is set to 1, or for an
if <> then
else
block it is set to 2. If the block is not a "conditional" block, this should not be specified.
50                     // Whether this is a cap block. False if left out.
51                     terminal: false,

This controls whether the block is a Cap Block. If it is not specified, the block is assumed not to be a cap block. Examples of blocks where this is true include the stop [all v] and forever blocks.

52                     // What actually appears on the block. Explained in more detail below.
53                     text: ['{BASE} to the power of {EXPONENT}', 'power_text']