|
|
- var ExampleExtension = function () {
- };
-
- /**
- * @return {object} This extension's metadata.
- */
- ExampleExtension.prototype.getInfo = function () {
- return {
- // Required: the machine-readable name of this extension.
- // Will be used as the extension's namespace. Must not contain a '.' character.
- id: 'someBlocks',
-
- // Optional: the human-readable name of this extension as string.
- // This and any other string to be displayed in the Scratch UI may either be
- // a string or a call to `intlDefineMessage`; a plain string will not be
- // translated whereas a call to `intlDefineMessage` will connect the string
- // to the translation map (see below). The `intlDefineMessage` call is
- // similar to `defineMessages` from `react-intl` in form, but will actually
- // call some extension support code to do its magic. For example, we will
- // internally namespace the messages such that two extensions could have
- // messages with the same ID without colliding.
- // See also: https://github.com/yahoo/react-intl/wiki/API#definemessages
- name: 'Some Blocks',
-
- // Optional: URI for an icon for this extension. Data URI OK.
- // If not present, use a generic icon.
- // TODO: what file types are OK? All web images? Just PNG?
- iconURI: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAFCAAAAACyOJm3AAAAFklEQVQYV2P4DwMMEMgAI/+DE' +
- 'UIMBgAEWB7i7uidhAAAAABJRU5ErkJggg==',
-
- // Optional: Link to documentation content for this extension.
- // If not present, offer no link.
- docsURI: 'https://....',
-
- // Required: the list of blocks implemented by this extension,
- // in the order intended for display.
- blocks: [
- {
- opcode: 'example-noop',
- blockType: Scratch.BlockType.COMMAND,
- blockAllThreads: false,
- text: 'do nothing',
- func: 'noop'
- },
- {
- opcode: 'example-conditional',
- blockType: Scratch.BlockType.CONDITIONAL,
- branchCount: 4,
- isTerminal: true,
- blockAllThreads: false,
- text: 'choose [BRANCH]',
- arguments: {
- BRANCH: {
- type: Scratch.ArgumentType.NUMBER,
- defaultValue: 1
- }
- },
- func: 'noop'
- },
- {
- // Required: the machine-readable name of this operation.
- // This will appear in project JSON. Must not contain a '.' character.
- opcode: 'myReporter', // becomes 'someBlocks.myReporter'
-
- // Required: the kind of block we're defining, from a predefined list:
- // 'command' - a normal command block, like "move {} steps"
- // 'reporter' - returns a value, like "direction"
- // 'Boolean' - same as 'reporter' but returns a Boolean value
- // 'hat' - starts a stack if its value is truthy
- // 'conditional' - control flow, like "if {}" or "repeat {}"
- // A 'conditional' block may return the one-based index of a branch
- // to run, or it may return zero/falsy to run no branch. Each time a
- // child branch finishes, the block is called again. This is only a
- // slight change to the current model for control flow blocks, and is
- // also compatible with returning true/false for an "if" or "repeat"
- // block.
- // TODO: Consider Blockly-like nextStatement, previousStatement, and
- // output attributes as an alternative. Those are more flexible, but
- // allow bad combinations.
- blockType: Scratch.BlockType.REPORTER,
-
- // Required for conditional blocks, ignored for others: the number of
- // child branches this block controls. An "if" or "repeat" block would
- // specify a branch count of 1; an "if-else" block would specify a
- // branch count of 2.
- // TODO: should we support dynamic branch count for "switch"-likes?
- branchCount: 0,
-
- // Optional, default false: whether or not this block ends a stack.
- // The "forever" and "stop all" blocks would specify true here.
- isTerminal: true,
-
- // Optional, default false: whether or not to block all threads while
- // this block is busy. This is for things like the "touching color"
- // block in compatibility mode, and is only needed if the VM runs in a
- // worker. We might even consider omitting it from extension docs...
- blockAllThreads: false,
-
- // Required: the human-readable text on this block, including argument
- // placeholders. Argument placeholders should be in [MACRO_CASE] and
- // must be [ENCLOSED_WITHIN_SQUARE_BRACKETS].
- text: 'letter [LETTER_NUM] of [TEXT]',
-
- // Required: describe each argument.
- // Note that this is an array: the order of arguments will be used
- arguments: {
- // Required: the ID of the argument, which will be the name in the
- // args object passed to the implementation function.
- LETTER_NUM: {
- // Required: type of the argument / shape of the block input
- type: Scratch.ArgumentType.NUMBER,
-
- // Optional: the default value of the argument
- defaultValue: 1
- },
-
- // Required: the ID of the argument, which will be the name in the
- // args object passed to the implementation function.
- TEXT: {
- // Required: type of the argument / shape of the block input
- type: Scratch.ArgumentType.STRING,
-
- // Optional: the default value of the argument
- defaultValue: 'text'
- }
- },
-
- // Optional: a string naming the function implementing this block.
- // If this is omitted, use the opcode string.
- func: 'myReporter',
-
- // Optional: list of target types for which this block should appear.
- // If absent, assume it applies to all builtin targets -- that is:
- // ['sprite', 'stage']
- filter: ['someBlocks.wedo2', 'sprite', 'stage']
- },
- {
- opcode: 'example-Boolean',
- blockType: Scratch.BlockType.BOOLEAN,
- text: 'return true',
- func: 'returnTrue'
- },
- {
- opcode: 'example-hat',
- blockType: Scratch.BlockType.HAT,
- text: 'after forever',
- func: 'returnFalse'
- },
- {
- // Another block...
- }
- ],
-
- // Optional: define extension-specific menus here.
- menus: {
- // Required: an identifier for this menu, unique within this extension.
- menuA: [
- // Static menu: list items which should appear in the menu.
- {
- // Required: the value of the menu item when it is chosen.
- value: 'itemId1',
-
- // Optional: the human-readable label for this item.
- // Use `value` as the text if this is absent.
- text: 'Item One'
- },
-
- // The simplest form of a list item is a string which will be used as
- // both value and text.
- 'itemId2'
- ],
-
- // Dynamic menu: a string naming a function which returns an array as above.
- // Called each time the menu is opened.
- menuB: 'getItemsForMenuB'
- },
-
- // Optional: translations
- translation_map: {
- de: {
- 'extensionName': 'Einige Blöcke',
- 'myReporter': 'Buchstabe [LETTER_NUM] von [TEXT]',
- 'myReporter.TEXT_default': 'Text',
- 'menuA_item1': 'Artikel eins',
-
- // Dynamic menus can be translated too
- 'menuB_example': 'Beispiel',
-
- // This message contains ICU placeholders (see `myReporter()` below)
- 'myReporter.result': 'Buchstabe {LETTER_NUM} von {TEXT} ist {LETTER}.'
- },
- it: {
- // ...
- }
- },
-
- // Optional: list new target type(s) provided by this extension.
- targetTypes: [
- 'wedo2', // automatically transformed to 'someBlocks.wedo2'
- 'speech' // automatically transformed to 'someBlocks.speech'
- ]
- };
- };
-
- /**
- * Implement myReporter.
- * @param {object} args - the block's arguments.
- * @property {number} LETTER_NUM - the string value of the argument.
- * @property {string} TEXT - the string value of the argument.
- * @returns {string} a string which includes the block argument value.
- */
- ExampleExtension.prototype.myReporter = function (args) {
- // Note: this implementation is not Unicode-clean; it's just here as an example.
- const result = args.TEXT.charAt(args.LETTER_NUM);
-
- return ['Letter ', args.LETTER_NUM, ' of ', args.TEXT, ' is ', result, '.'].join('');
- };
-
- ExampleExtension.prototype.noop = function () {
- };
-
- ExampleExtension.prototype.returnTrue = function () {
- return true;
- };
-
- ExampleExtension.prototype.returnFalse = function () {
- return false;
- };
-
- Scratch.extensions.register(new ExampleExtension());
|