Update extension docs to reflect current implementation state

This commit is contained in:
Christopher Willis-Ford 2019-04-05 16:05:42 -07:00
parent 18f3307ed0
commit 99f6c7b6a0

View file

@ -41,7 +41,8 @@ for translation.
**All extensions** may additionally define a `translation_map` object within the `getInfo` function which can provide **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 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 ## Backwards Compatibility
@ -118,6 +119,16 @@ class SomeBlocks {
## Annotated Example ## Annotated Example
```js ```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 { class SomeBlocks {
constructor (runtime) { constructor (runtime) {
/** /**
@ -150,7 +161,7 @@ class SomeBlocks {
name: formatMessage({ name: formatMessage({
id: 'extensionName', id: 'extensionName',
defaultMessage: 'Some Blocks', 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 // 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. // This will appear in project JSON.
opcode: 'myReporter', // becomes 'someBlocks.myReporter' opcode: 'myReporter', // becomes 'someBlocks.myReporter'
// Required: the kind of block we're defining, from a predefined list: // Required: the kind of block we're defining, from a predefined list.
// 'command' - a normal command block, like "move {} steps" // Fully supported block types:
// 'reporter' - returns a value, like "direction" // BlockType.BOOLEAN - same as REPORTER but returns a Boolean value
// 'Boolean' - same as 'reporter' but returns a Boolean value // BlockType.COMMAND - a normal command block, like "move {} steps"
// 'hat' - starts a stack if its value is truthy // BlockType.HAT - starts a stack if its value changes from falsy to truthy ("edge triggered")
// 'conditional' - control flow, like "if {}" or "if {} else {}" // BlockType.REPORTER - returns a value, like "direction"
// A 'conditional' block may return the one-based index of a branch to // Block types in development or for internal use only:
// run, or it may return zero/falsy to run no branch. // BlockType.BUTTON - place a button in the block palette
// 'loop' - control flow, like "repeat {} {}" or "forever {}" // BlockType.CONDITIONAL - control flow, like "if {}" or "if {} else {}"
// A 'loop' block is like a conditional block with two differences: // A CONDITIONAL block may return the one-based index of a branch to
// - the block is assumed to have exactly one child branch, and // run, or it may return zero/falsy to run no branch.
// - each time a child branch finishes, the loop block is called again. // BlockType.EVENT - starts a stack in response to an event (full spec TBD)
blockType: 'reporter', // 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 // child branches this block controls. An "if" or "repeat" block would
// specify a branch count of 1; an "if-else" block would specify a // specify a branch count of 1; an "if-else" block would specify a
// branch count of 2. // branch count of 2.
@ -228,7 +243,7 @@ class SomeBlocks {
// args object passed to the implementation function. // args object passed to the implementation function.
LETTER_NUM: { LETTER_NUM: {
// Required: type of the argument / shape of the block input // Required: type of the argument / shape of the block input
type: 'number', type: ArgumentType.NUMBER,
// Optional: the default value of the argument // Optional: the default value of the argument
default: 1 default: 1
@ -238,24 +253,25 @@ class SomeBlocks {
// args object passed to the implementation function. // args object passed to the implementation function.
TEXT: { TEXT: {
// Required: type of the argument / shape of the block input // Required: type of the argument / shape of the block input
type: 'string', type: ArgumentType.STRING,
// Optional: the default value of the argument // Optional: the default value of the argument
default: formatMessage({ default: formatMessage({
id: 'myReporter.TEXT_default', id: 'myReporter.TEXT_default',
defaultMessage: 'text', 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', func: 'myReporter',
// Optional: list of target types for which this block should appear. // Optional: list of target types for which this block should appear.
// If absent, assume it applies to all builtin targets -- that is: // If absent, assume it applies to all builtin targets -- that is:
// ['sprite', 'stage'] // [TargetType.SPRITE, TargetType.STAGE]
filter: ['someBlocks.wedo2', 'sprite', 'stage'] filter: [TargetType.SPRITE]
}, },
{ {
// Another block... // Another block...
@ -276,7 +292,7 @@ class SomeBlocks {
text: formatMessage({ text: formatMessage({
id: 'menuA_item1', id: 'menuA_item1',
defaultMessage: 'Item One', 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' menuB: 'getItemsForMenuB'
}, },
// Optional: translations // Optional: translations (UNSTABLE - NOT YET SUPPORTED)
translation_map: { translation_map: {
de: { de: {
'extensionName': 'Einige Blöcke', 'extensionName': 'Einige Blöcke',
@ -307,13 +323,7 @@ class SomeBlocks {
it: { it: {
// ... // ...
} }
}, }
// Optional: list new target type(s) provided by this extension.
targetTypes: [
'wedo2', // automatically transformed to 'someBlocks.wedo2'
'speech' // automatically transformed to 'someBlocks.speech'
]
}; };
}; };