From 99f6c7b6a093d6d54bc764234c96ececaac42076 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford <cwillisf@media.mit.edu> Date: Fri, 5 Apr 2019 16:05:42 -0700 Subject: [PATCH] Update extension docs to reflect current implementation state --- docs/extensions.md | 72 ++++++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/docs/extensions.md b/docs/extensions.md index d55071c99..7e500b03b 100644 --- a/docs/extensions.md +++ b/docs/extensions.md @@ -41,7 +41,8 @@ for translation. **All extensions** may additionally define a `translation_map` object within the `getInfo` function which can provide translations within an extension itself. The "Annotated Example" below provides a more complete illustration of how -translation within an extension can be managed. +translation within an extension can be managed. **WARNING:** the `translation_map` feature is currently in the +proposal phase and may change before implementation. ## Backwards Compatibility @@ -118,6 +119,16 @@ class SomeBlocks { ## Annotated Example ```js +// Core, Team, and Official extensions can `require` VM code: +const ArgumentType = require('../../extension-support/argument-type'); +const BlockType = require('../../extension-support/block-type'); +const TargetType = require('../../extension-support/target-type'); + +// ...or VM dependencies: +const formatMessage = require('format-message'); + +// Core, Team, and Official extension classes should be registered statically with the Extension Manager. +// See: scratch-vm/src/extension-support/extension-manager.js class SomeBlocks { constructor (runtime) { /** @@ -150,7 +161,7 @@ class SomeBlocks { name: formatMessage({ id: 'extensionName', defaultMessage: 'Some Blocks', - description: 'Extension name' + description: 'The name of the "Some Blocks" extension' }), // Optional: URI for a block icon, to display at the edge of each block for this @@ -177,21 +188,25 @@ class SomeBlocks { // This will appear in project JSON. 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 "if {} else {}" - // A 'conditional' block may return the one-based index of a branch to - // run, or it may return zero/falsy to run no branch. - // 'loop' - control flow, like "repeat {} {}" or "forever {}" - // A 'loop' block is like a conditional block with two differences: - // - the block is assumed to have exactly one child branch, and - // - each time a child branch finishes, the loop block is called again. - blockType: 'reporter', + // Required: the kind of block we're defining, from a predefined list. + // Fully supported block types: + // BlockType.BOOLEAN - same as REPORTER but returns a Boolean value + // BlockType.COMMAND - a normal command block, like "move {} steps" + // BlockType.HAT - starts a stack if its value changes from falsy to truthy ("edge triggered") + // BlockType.REPORTER - returns a value, like "direction" + // Block types in development or for internal use only: + // BlockType.BUTTON - place a button in the block palette + // BlockType.CONDITIONAL - control flow, like "if {}" or "if {} else {}" + // A CONDITIONAL block may return the one-based index of a branch to + // run, or it may return zero/falsy to run no branch. + // BlockType.EVENT - starts a stack in response to an event (full spec TBD) + // BlockType.LOOP - control flow, like "repeat {} {}" or "forever {}" + // A LOOP block is like a CONDITIONAL block with two differences: + // - the block is assumed to have exactly one child branch, and + // - each time a child branch finishes, the loop block is called again. + blockType: BlockType.REPORTER, - // Required for conditional blocks, ignored for others: the number of + // 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. @@ -228,7 +243,7 @@ class SomeBlocks { // args object passed to the implementation function. LETTER_NUM: { // Required: type of the argument / shape of the block input - type: 'number', + type: ArgumentType.NUMBER, // Optional: the default value of the argument default: 1 @@ -238,24 +253,25 @@ class SomeBlocks { // args object passed to the implementation function. TEXT: { // Required: type of the argument / shape of the block input - type: 'string', + type: ArgumentType.STRING, // Optional: the default value of the argument default: formatMessage({ id: 'myReporter.TEXT_default', defaultMessage: 'text', - description: 'Default for "TEXT" argument of "myReporter"' + description: 'Default for "TEXT" argument of "someBlocks.myReporter"' }) } }, - // Required: the function implementing this block. + // Optional: the function implementing this block. + // If absent, assume `func` is the same as `opcode`. 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'] + // [TargetType.SPRITE, TargetType.STAGE] + filter: [TargetType.SPRITE] }, { // Another block... @@ -276,7 +292,7 @@ class SomeBlocks { text: formatMessage({ id: 'menuA_item1', defaultMessage: 'Item One', - description: 'Label for item 1 of menu A' + description: 'Label for item 1 of menu A in "Some Blocks" extension' }) }, @@ -290,7 +306,7 @@ class SomeBlocks { menuB: 'getItemsForMenuB' }, - // Optional: translations + // Optional: translations (UNSTABLE - NOT YET SUPPORTED) translation_map: { de: { 'extensionName': 'Einige Blöcke', @@ -307,13 +323,7 @@ class SomeBlocks { it: { // ... } - }, - - // Optional: list new target type(s) provided by this extension. - targetTypes: [ - 'wedo2', // automatically transformed to 'someBlocks.wedo2' - 'speech' // automatically transformed to 'someBlocks.speech' - ] + } }; };