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'
-            ]
+            }
         };
     };