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