diff --git a/packages/docs/README.md b/packages/docs/README.md index 0488b6f7d..d1ecacb4e 100644 --- a/packages/docs/README.md +++ b/packages/docs/README.md @@ -35,6 +35,15 @@ npm run serve The build folder is now served at http://localhost:3000/. +## Linting + +```bash +# check formatting: +npm run format:check +# fix formatting: +npm run format +``` + ## Generating reference docs The API reference pages are auto-generated from the Blockly TypeScript source using `@microsoft/api-extractor` and `@microsoft/api-documenter`. This is a separate step from the Docusaurus build and must be run from the `packages/blockly` directory: diff --git a/packages/docs/docs/codelabs/context-menu-option/add-a-context-menu-item.mdx b/packages/docs/docs/codelabs/context-menu-option/add-a-context-menu-item.mdx index 0fa0b9a7b..5dbcc8578 100644 --- a/packages/docs/docs/codelabs/context-menu-option/add-a-context-menu-item.mdx +++ b/packages/docs/docs/codelabs/context-menu-option/add-a-context-menu-item.mdx @@ -33,11 +33,10 @@ Add a function to `index.js` named `registerHelloWorldItem`. Create a new regist function registerHelloWorldItem() { const helloWorldItem = { displayText: 'Hello World', - preconditionFn: function(scope) { + preconditionFn: function (scope) { return 'enabled'; }, - callback: function(scope) { - }, + callback: function (scope) {}, id: 'hello_world', weight: 100, }; @@ -52,10 +51,9 @@ function start() { Blockly.ContextMenuItems.registerCommentOptions(); // Create main workspace. - workspace = Blockly.inject('blocklyDiv', - { - toolbox: toolboxSimple, - }); + workspace = Blockly.inject('blocklyDiv', { + toolbox: toolboxSimple, + }); } ``` @@ -80,6 +78,10 @@ you will never need to make a new `ContextMenuRegistry`. Always use the singleto Reload your web page and open a context menu on the workspace (right-click with a mouse, or press `Ctrl+Enter` (Windows) or `Command+Enter` (Mac) if you are navigating Blockly with the keyboard). You should see a new option labeled "Hello World" at the bottom of the context menu. - ![A context menu. The last option says "Hello World".](../../../static/images/codelabs/context-menu-option/hello_world.png) + + {' '} + ![A context menu. The last option says "Hello + World".](../../../static/images/codelabs/context-menu-option/hello_world.png){' '} + Next, drag a block onto the workspace and open a context menu on the block. You'll see "Hello World" at the bottom of the block's context menu. Finally, open a context menu on the workspace and create a comment, then open a context menu on the comment's header. "Hello World" should be at the bottom of the context menu. diff --git a/packages/docs/docs/codelabs/context-menu-option/callback.mdx b/packages/docs/docs/codelabs/context-menu-option/callback.mdx index 938204646..a3e063591 100644 --- a/packages/docs/docs/codelabs/context-menu-option/callback.mdx +++ b/packages/docs/docs/codelabs/context-menu-option/callback.mdx @@ -30,5 +30,4 @@ As an example, update the help item's `callback` to add a block to the workspace - Select the **Help** option. - A text block should appear in the top left of the workspace. - -![A text block containing the text "Now there is a block".](../../../static/images/codelabs/context-menu-option/there_is_a_block.png) \ No newline at end of file +![A text block containing the text "Now there is a block".](../../../static/images/codelabs/context-menu-option/there_is_a_block.png) diff --git a/packages/docs/docs/codelabs/context-menu-option/codelab-overview.mdx b/packages/docs/docs/codelabs/context-menu-option/codelab-overview.mdx index 92b43bbed..486ed67f6 100644 --- a/packages/docs/docs/codelabs/context-menu-option/codelab-overview.mdx +++ b/packages/docs/docs/codelabs/context-menu-option/codelab-overview.mdx @@ -11,6 +11,7 @@ description: Overview of the "Customizing context menus" codelab. ### What you'll learn In this codelab you will learn how to: + - Add a context menu option to the workspace. - Add a context menu option to all blocks. - Use precondition functions to hide or disable context menu options. @@ -18,11 +19,13 @@ In this codelab you will learn how to: - Customize ordering and display text for context menu options. ### What you'll build + A very simple Blockly workspace with a few new context menu options. ### What you'll need + - A browser. - A text editor. - Basic knowledge of HTML, CSS, and JavaScript. -This codelab is focused on Blockly's context menus. Non-relevant concepts and code are glossed over and are provided for you to simply copy and paste. \ No newline at end of file +This codelab is focused on Blockly's context menus. Non-relevant concepts and code are glossed over and are provided for you to simply copy and paste. diff --git a/packages/docs/docs/codelabs/context-menu-option/display-text.mdx b/packages/docs/docs/codelabs/context-menu-option/display-text.mdx index 76eea7404..d25b2fec1 100644 --- a/packages/docs/docs/codelabs/context-menu-option/display-text.mdx +++ b/packages/docs/docs/codelabs/context-menu-option/display-text.mdx @@ -16,7 +16,7 @@ As an example, add this registry item. The display text depends on the block typ ```js function registerDisplayItem() { const displayItem = { - displayText: function(scope) { + displayText: function (scope) { if (scope.focusedNode.type.startsWith('text')) { return 'Text block'; } else if (scope.focusedNode.type.startsWith('controls')) { @@ -25,13 +25,12 @@ function registerDisplayItem() { return 'Some other block'; } }, - preconditionFn: function(scope) { + preconditionFn: function (scope) { return scope.focusedNode instanceof Blockly.BlockSvg ? 'enabled' : 'hidden'; }, - callback: function(scope) { - }, + callback: function (scope) {}, id: 'display_text_example', weight: 100, }; @@ -44,4 +43,4 @@ As usual, remember to call `registerDisplayItem()` from your `start` function. ### Test it - Reload the workspace and open context menus on various blocks. -- The last context menu option's text should vary based on the block type. \ No newline at end of file +- The last context menu option's text should vary based on the block type. diff --git a/packages/docs/docs/codelabs/context-menu-option/precondition-blockly-state.mdx b/packages/docs/docs/codelabs/context-menu-option/precondition-blockly-state.mdx index 36f947c08..8b81edb7b 100644 --- a/packages/docs/docs/codelabs/context-menu-option/precondition-blockly-state.mdx +++ b/packages/docs/docs/codelabs/context-menu-option/precondition-blockly-state.mdx @@ -13,15 +13,14 @@ Disabling your context menu options half of the time is not useful, but you may function registerHelpItem() { const helpItem = { displayText: 'Help! There are no blocks', - preconditionFn: function(scope) { + preconditionFn: function (scope) { if (!(scope.focusedNode instanceof Blockly.WorkspaceSvg)) return 'hidden'; if (!scope.focusedNode.getTopBlocks().length) { return 'enabled'; } return 'hidden'; }, - callback: function(scope) { - }, + callback: function (scope) {}, id: 'help_no_blocks', weight: 100, }; @@ -34,4 +33,4 @@ Don't forget to call `registerHelpItem` from your `start` function. ### Test it - Reload your page and open a context menu on the workspace. You should see an option labeled "Help! There are no blocks". -- Add a block to the workspace and open a context menu on the workspace again. The **Help** option should be gone. \ No newline at end of file +- Add a block to the workspace and open a context menu on the workspace again. The **Help** option should be gone. diff --git a/packages/docs/docs/codelabs/context-menu-option/precondition-external-state.mdx b/packages/docs/docs/codelabs/context-menu-option/precondition-external-state.mdx index 6347c8203..1b8dcd272 100644 --- a/packages/docs/docs/codelabs/context-menu-option/precondition-external-state.mdx +++ b/packages/docs/docs/codelabs/context-menu-option/precondition-external-state.mdx @@ -29,4 +29,4 @@ Use of the `preconditionFn` is not limited to checking the type of the Blockly c Reload your workspace, check your watch, and open a context menu on the workspace to confirm the timing. The option will always be in the menu, but will sometimes be greyed out. -![A context menu. The last option says "Hello World" but the text is grey, indicating that it cannot be selected.](../../../static/images/codelabs/context-menu-option/hello_world_grey.png) \ No newline at end of file +![A context menu. The last option says "Hello World" but the text is grey, indicating that it cannot be selected.](../../../static/images/codelabs/context-menu-option/hello_world_grey.png) diff --git a/packages/docs/docs/codelabs/context-menu-option/precondition-node-type.mdx b/packages/docs/docs/codelabs/context-menu-option/precondition-node-type.mdx index a8c1f2a7f..f98c21bc4 100644 --- a/packages/docs/docs/codelabs/context-menu-option/precondition-node-type.mdx +++ b/packages/docs/docs/codelabs/context-menu-option/precondition-node-type.mdx @@ -17,7 +17,7 @@ The `scope` argument is an object that is passed to `preconditionFn`. You'll use The return value of `preconditionFn` is `'enabled'`, `'disabled'`, or `'hidden'`. An **enabled** option is shown with black text and is selectable. A **disabled** option is shown with grey text and is not selectable. A **hidden** option is not included in the context menu at all. -### Write the function +### Write the function You can now test `scope.focusedNode` to display the "Hello World" option in workspace and block context menus, but not on any others. Change `preconditionFn` to: diff --git a/packages/docs/docs/codelabs/context-menu-option/separators.mdx b/packages/docs/docs/codelabs/context-menu-option/separators.mdx index 140a7b92a..999ce8f26 100644 --- a/packages/docs/docs/codelabs/context-menu-option/separators.mdx +++ b/packages/docs/docs/codelabs/context-menu-option/separators.mdx @@ -22,7 +22,7 @@ function registerSeparators() { scopeType: Blockly.ContextMenuRegistry.ScopeType.WORKSPACE, weight: 99, separator: true, - } + }; Blockly.ContextMenuRegistry.registry.register(workspaceSeparator); const blockSeparator = { @@ -30,7 +30,7 @@ function registerSeparators() { scopeType: Blockly.ContextMenuRegistry.ScopeType.BLOCK, weight: 99, separator: true, - } + }; Blockly.ContextMenuRegistry.registry.register(blockSeparator); } ``` diff --git a/packages/docs/docs/codelabs/context-menu-option/setup.mdx b/packages/docs/docs/codelabs/context-menu-option/setup.mdx index 880e6b20b..fc9e4359e 100644 --- a/packages/docs/docs/codelabs/context-menu-option/setup.mdx +++ b/packages/docs/docs/codelabs/context-menu-option/setup.mdx @@ -24,13 +24,18 @@ git clone https://github.com/RaspberryPiFoundation/blockly.git If you downloaded the source as a zip, unpacking it should give you a root folder named `blockly-main`. The relevant files are in `docs/docs/codelabs/context-menu-option`. There are two versions of the app: + - `starter-code/`: The starter code that you'll build upon in this codelab. - `complete-code/`: The code after completing the codelab, in case you get lost or want to compare to your version. Each folder contains: + - `index.js` - The codelab's logic. To start, it just injects a simple workspace. - `index.html` - A web page containing a simple blockly workspace. To run the code, simple open `starter-code/index.html` in a browser. You should see a Blockly workspace with an always-open flyout. -![A web page with the text "Context Menu Codelab" and a simple Blockly workspace.](../../../static/images/codelabs/context-menu-option/starter_workspace.png) \ No newline at end of file + + ![A web page with the text "Context Menu Codelab" and a simple Blockly + workspace.](../../../static/images/codelabs/context-menu-option/starter_workspace.png) + diff --git a/packages/docs/docs/codelabs/context-menu-option/summary.mdx b/packages/docs/docs/codelabs/context-menu-option/summary.mdx index dc3ff7440..2a7fcb99c 100644 --- a/packages/docs/docs/codelabs/context-menu-option/summary.mdx +++ b/packages/docs/docs/codelabs/context-menu-option/summary.mdx @@ -4,7 +4,6 @@ slug: /codelabs/context-menu-option/summary/index.html description: Summary of the "Customizing context menus" codelab. --- - # Customizing context menus ## 11. Summary @@ -15,4 +14,4 @@ In this codelab you have learned how to create and modify context menu options. - [Context menu documentation](/guides/configure/web/context-menus) -- You can also define [block context menus](/guides/configure/web/context-menus#customize-per-block) directly on a block definition, which is equivalent to adding a precondition based on the type of the block. \ No newline at end of file +- You can also define [block context menus](/guides/configure/web/context-menus#customize-per-block) directly on a block definition, which is equivalent to adding a precondition based on the type of the block. diff --git a/packages/docs/docs/codelabs/context-menu-option/weight-and-id.mdx b/packages/docs/docs/codelabs/context-menu-option/weight-and-id.mdx index cfeb35de5..8b586eb07 100644 --- a/packages/docs/docs/codelabs/context-menu-option/weight-and-id.mdx +++ b/packages/docs/docs/codelabs/context-menu-option/weight-and-id.mdx @@ -24,7 +24,7 @@ Every registry item has an `id` that can be used to unregister it. You can use t For instance, you can remove the item that deletes all blocks on the workspace: ```js - Blockly.ContextMenuRegistry.registry.unregister('workspaceDelete'); +Blockly.ContextMenuRegistry.registry.unregister('workspaceDelete'); ``` ### Default items diff --git a/packages/docs/docs/codelabs/css/blocks.mdx b/packages/docs/docs/codelabs/css/blocks.mdx index b5db9a440..d71f33572 100644 --- a/packages/docs/docs/codelabs/css/blocks.mdx +++ b/packages/docs/docs/codelabs/css/blocks.mdx @@ -46,6 +46,7 @@ Note that different renderers use different numbers of `` elements to draw a block: Thrasos uses a single `` element, Geras uses three `` elements, and Zelos uses one `` for the outside of the block and one `` for each inline input. + #### Choose colours The last step before writing your colour rules is to decide what colours to use. The Halloween theme in the themes codelab sets three colours: @@ -62,6 +63,7 @@ How these colours are used depends on the renderer. The Thrasos renderer uses the primary colour as the `fill` of the block, the tertiary colour as the `stroke`, and the secondary colour as the `fill` when the block is a [shadow block](/guides/configure/web/toolboxes/preset#shadow-blocks). + #### Add your rules You're now ready to add your rules to set the `fill` and `stroke` of the logic blocks: @@ -204,7 +206,7 @@ Your last step is to add similar rules for the loop, text, and list blocks: } .list_blocks:not(.blocklyDisabledPattern).blocklyShadow > .blocklyPath { - fill: #ad7Be9; + fill: #ad7be9; stroke: none; } diff --git a/packages/docs/docs/codelabs/css/categories.mdx b/packages/docs/docs/codelabs/css/categories.mdx index cd5871794..0575518de 100644 --- a/packages/docs/docs/codelabs/css/categories.mdx +++ b/packages/docs/docs/codelabs/css/categories.mdx @@ -29,6 +29,7 @@ Unfortunately, the only thing that distinguishes this `
` from other categor To solve this problem, you'll need to add a class to the `blocklyToolboxCategory` `
` for the **Logic** category. Open the `toolbox.js` file and find the definition of the **Logic** category: + ```js { kind: 'category', @@ -44,6 +45,7 @@ you're not using themes to assign category colours, you don't need the classes to the **Logic** category's `
`: `logic_category` uniquely identifies the `
` and `blocklyToolboxCategory` is used by Blockly's CSS to define rules that apply to all categories. + ```js { kind: 'category', diff --git a/packages/docs/docs/codelabs/css/components.mdx b/packages/docs/docs/codelabs/css/components.mdx index 54cf3f416..8d2801877 100644 --- a/packages/docs/docs/codelabs/css/components.mdx +++ b/packages/docs/docs/codelabs/css/components.mdx @@ -13,9 +13,9 @@ In this section, you will create CSS rules to assign the colours used by the [co To start, create a file named `halloween.css` and add it to your `index.html` file: ```html - ... - - +... + + ``` ### Main workspace colour @@ -142,6 +142,7 @@ apply to HTML elements, like the `
` used by the toolbox, and `fill` and `stroke` apply to most SVG elements, like the `` used by the flyout background. (An exception to this is the top-level `` element that contains Blockly, which uses `background-color` and `color`.) + ### The !important declaration You might have also noticed that some rules use an `!important` declaration while others don't. This is because Blockly sets colours in several different ways, some of which are easily overridden and some of which aren't. diff --git a/packages/docs/docs/codelabs/custom-generator/array-block-generator.mdx b/packages/docs/docs/codelabs/custom-generator/array-block-generator.mdx index 2c52cf9f3..b0115f4ea 100644 --- a/packages/docs/docs/codelabs/custom-generator/array-block-generator.mdx +++ b/packages/docs/docs/codelabs/custom-generator/array-block-generator.mdx @@ -16,12 +16,7 @@ The array block uses a mutator to dynamically change the number of inputs it has The generated code looks like: ```json -[ - 1, - "two", - false, - true -] +[1, "two", false, true] ``` As with member blocks, there are no restrictions on the types of blocks connected to inputs. @@ -33,8 +28,7 @@ Each value input on the block has a name: `ADD0`, `ADD1`, etc. Use `valueToCode` ```js const values = []; for (let i = 0; i < block.itemCount_; i++) { - const valueCode = generator.valueToCode(block, 'ADD' + i, - Order.ATOMIC); + const valueCode = generator.valueToCode(block, 'ADD' + i, Order.ATOMIC); if (valueCode) { values.push(valueCode); } @@ -48,8 +42,8 @@ To include empty inputs, use the string `'null'` as the value: ```js const values = []; for (let i = 0; i < block.itemCount_; i++) { - const valueCode = generator.valueToCode(block, 'ADD' + i, - Order.ATOMIC) || 'null'; + const valueCode = + generator.valueToCode(block, 'ADD' + i, Order.ATOMIC) || 'null'; values.push(valueCode); } ``` @@ -67,8 +61,10 @@ const valueString = values.join(',\n'); Next, use `prefixLines` to add indentation at the beginning of each line: ```js -const indentedValueString = - generator.prefixLines(valueString, generator.INDENT); +const indentedValueString = generator.prefixLines( + valueString, + generator.INDENT, +); ``` `INDENT` is a property on the generator. It defaults to two spaces, but language generators may override it to increase indent or change to tabs. @@ -85,18 +81,19 @@ return [codeString, Order.ATOMIC]; Here is the final array block generator: ```js -jsonGenerator.forBlock['lists_create_with'] = function(block, generator) { +jsonGenerator.forBlock['lists_create_with'] = function (block, generator) { const values = []; for (let i = 0; i < block.itemCount_; i++) { - const valueCode = generator.valueToCode(block, 'ADD' + i, - Order.ATOMIC); + const valueCode = generator.valueToCode(block, 'ADD' + i, Order.ATOMIC); if (valueCode) { values.push(valueCode); } } const valueString = values.join(',\n'); - const indentedValueString = - generator.prefixLines(valueString, generator.INDENT); + const indentedValueString = generator.prefixLines( + valueString, + generator.INDENT, + ); const codeString = '[\n' + indentedValueString + '\n]'; return [codeString, Order.ATOMIC]; }; @@ -108,4 +105,4 @@ Test the block generator by adding an array to the onscreen blocks and populatin What code does it generate if there are no inputs? -What if there are five inputs, one of which is empty? \ No newline at end of file +What if there are five inputs, one of which is empty? diff --git a/packages/docs/docs/codelabs/custom-generator/block-generator-overview.mdx b/packages/docs/docs/codelabs/custom-generator/block-generator-overview.mdx index a28b0c5d5..5cc462aff 100644 --- a/packages/docs/docs/codelabs/custom-generator/block-generator-overview.mdx +++ b/packages/docs/docs/codelabs/custom-generator/block-generator-overview.mdx @@ -12,7 +12,7 @@ At its core, a block generator is a function that takes in a block (and optional Each language generator has a property called `forBlock`, which is a dictionary object where all block generator functions must be placed. For instance, here is the code to add a block generator for blocks of type `sample_block` on a language generator object (`sampleGenerator`). ```js -sampleGenerator.forBlock['sample_block'] = function(block, generator) { +sampleGenerator.forBlock['sample_block'] = function (block, generator) { return 'my code string'; }; ``` @@ -26,7 +26,7 @@ A statement block's generator simply returns a string. For example, this code defines a block generator that always returns the same function call. ```js -sampleGenerator.forBlock['left_turn_block'] = function(block, generator) { +sampleGenerator.forBlock['left_turn_block'] = function (block, generator) { return 'turnLeft()'; }; ``` @@ -40,7 +40,7 @@ A value block's generator returns an array containing a string and a [precedence This code defines a block generator that always returns `1 + 1`: ```js -sampleGenerator.forBlock['two_block'] = function(block, generator) { +sampleGenerator.forBlock['two_block'] = function (block, generator) { return ['1 + 1', Order.ADDITION]; }; ``` @@ -61,4 +61,4 @@ In `src/generators/json.js`, declare a new enum called `Order` and add the `ATOM const Order = { ATOMIC: 0, }; -``` \ No newline at end of file +``` diff --git a/packages/docs/docs/codelabs/custom-generator/codelab-overview.mdx b/packages/docs/docs/codelabs/custom-generator/codelab-overview.mdx index 094310448..58b1f6b94 100644 --- a/packages/docs/docs/codelabs/custom-generator/codelab-overview.mdx +++ b/packages/docs/docs/codelabs/custom-generator/codelab-overview.mdx @@ -21,11 +21,15 @@ import CodelabImage from '@site/src/components/CodelabImage'; You will build a JSON generator that implements the [JSON language spec](https://www.json.org/json-en.html). -![Screenshot of the toolbox and workspace built in this codelab. It contains blocks that implement the JSON spec, like member, object, lists, strings, and numbers.](../../../static/images/codelabs/custom-generator/json_workspace.png) + + ![Screenshot of the toolbox and workspace built in this codelab. It contains + blocks that implement the JSON spec, like member, object, lists, strings, and + numbers.](../../../static/images/codelabs/custom-generator/json_workspace.png) + ### What you'll need - Familiarity with JSON and the JSON specification. - Basic understanding of blocks and toolboxes in Blockly. - NPM installed ([instructions](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)). -- Comfort using the command line/terminal. \ No newline at end of file +- Comfort using the command line/terminal. diff --git a/packages/docs/docs/codelabs/custom-generator/complete-code/src/index.js b/packages/docs/docs/codelabs/custom-generator/complete-code/src/index.js index 175127a43..a21768aa9 100644 --- a/packages/docs/docs/codelabs/custom-generator/complete-code/src/index.js +++ b/packages/docs/docs/codelabs/custom-generator/complete-code/src/index.js @@ -5,10 +5,10 @@ */ import * as Blockly from 'blockly'; -import {blocks} from './blocks/json'; -import {jsonGenerator} from './generators/json'; -import {save, load} from './serialization'; -import {toolbox} from './toolbox'; +import { blocks } from './blocks/json'; +import { jsonGenerator } from './generators/json'; +import { save, load } from './serialization'; +import { toolbox } from './toolbox'; import './index.css'; // Register the blocks with Blockly @@ -17,7 +17,7 @@ Blockly.common.defineBlocks(blocks); // Set up UI elements and inject Blockly const codeDiv = document.getElementById('generatedCode').firstChild; const blocklyDiv = document.getElementById('blocklyDiv'); -const ws = Blockly.inject(blocklyDiv, {toolbox}); +const ws = Blockly.inject(blocklyDiv, { toolbox }); // This function resets the code div and shows the // generated code from the workspace. diff --git a/packages/docs/docs/codelabs/custom-generator/generating-a-stack.mdx b/packages/docs/docs/codelabs/custom-generator/generating-a-stack.mdx index ed798442c..6d1a49cfd 100644 --- a/packages/docs/docs/codelabs/custom-generator/generating-a-stack.mdx +++ b/packages/docs/docs/codelabs/custom-generator/generating-a-stack.mdx @@ -7,9 +7,10 @@ description: How to generate code for the blocks in a stack. ## 9. Generating a stack -### The scrub_ function +### The scrub\_ function The `scrub_` function is called on every block from `blockToCode`. It takes in three arguments: + - `block` is the current block. - `code` is the code generated for this block, which includes code from all attached value blocks. - `opt_thisOnly` is an optional `boolean`. If true, code should be generated for this block but no subsequent blocks. @@ -17,9 +18,8 @@ The `scrub_` function is called on every block from `blockToCode`. It takes in t By default, `scrub_` simply returns the passed-in code. A common pattern is to override the function to also generate code for any blocks that follow the current block in a stack. In this case, the code will add commas and newlines between object members: ```js -jsonGenerator.scrub_ = function(block, code, thisOnly) { - const nextBlock = - block.nextConnection && block.nextConnection.targetBlock(); +jsonGenerator.scrub_ = function (block, code, thisOnly) { + const nextBlock = block.nextConnection && block.nextConnection.targetBlock(); if (nextBlock && !thisOnly) { return code + ',\n' + jsonGenerator.blockToCode(nextBlock); } @@ -27,8 +27,8 @@ jsonGenerator.scrub_ = function(block, code, thisOnly) { }; ``` -### Testing scrub_ +### Testing scrub\_ Create a stack of `member` blocks on the workspace. There should be generated code for all of the blocks, not just the first one. -Next, add an `object` block and drag the `member` blocks into it. This case tests `statementToCode`, and should generate code for all of of the blocks. \ No newline at end of file +Next, add an `object` block and drag the `member` blocks into it. This case tests `statementToCode`, and should generate code for all of of the blocks. diff --git a/packages/docs/docs/codelabs/custom-generator/member-block-generator.mdx b/packages/docs/docs/codelabs/custom-generator/member-block-generator.mdx index 59be1af66..20e118578 100644 --- a/packages/docs/docs/codelabs/custom-generator/member-block-generator.mdx +++ b/packages/docs/docs/codelabs/custom-generator/member-block-generator.mdx @@ -27,14 +27,14 @@ Recall: the name of the value being fetched is `MEMBER_NAME` because that is how ### Input value -The **property value** is whatever is attached to the value input. A variety of blocks could be attached there: `logic_null`, `text`, `math_number`, `logic_boolean`, or even an array (`lists_create_with`). Use `valueToCode` to get the correct value: +The **property value** is whatever is attached to the value input. A variety of blocks could be attached there: `logic_null`, `text`, `math_number`, `logic_boolean`, or even an array (`lists_create_with`). Use `valueToCode` to get the correct value: ```js -const value = generator.valueToCode(block, 'MEMBER_VALUE', - Order.ATOMIC); +const value = generator.valueToCode(block, 'MEMBER_VALUE', Order.ATOMIC); ``` `valueToCode` does three things: + - Finds the blocks connected to the named value input (the second argument) - Generates the code for that block - Returns the code as a string @@ -56,11 +56,10 @@ const code = `"${name}": ${value}`; All together, here is block generator for the member block: ```js -jsonGenerator.forBlock['member'] = function(block, generator) { +jsonGenerator.forBlock['member'] = function (block, generator) { const name = block.getFieldValue('MEMBER_NAME'); - const value = generator.valueToCode( - block, 'MEMBER_VALUE', Order.ATOMIC); + const value = generator.valueToCode(block, 'MEMBER_VALUE', Order.ATOMIC); const code = `"${name}": ${value}`; return code; }; -``` \ No newline at end of file +``` diff --git a/packages/docs/docs/codelabs/custom-generator/object-block-generator.mdx b/packages/docs/docs/codelabs/custom-generator/object-block-generator.mdx index 4a82d9ec8..c3e17e49a 100644 --- a/packages/docs/docs/codelabs/custom-generator/object-block-generator.mdx +++ b/packages/docs/docs/codelabs/custom-generator/object-block-generator.mdx @@ -28,6 +28,7 @@ The generated code looks like this: We'll use `statementToCode` to get the code for the blocks attached to the statement input of the `object` block. `statementToCode` does three things: + - Finds the first block connected to the named statement input (the second argument) - Generates the code for that block - Returns the code as a string @@ -35,8 +36,7 @@ We'll use `statementToCode` to get the code for the blocks attached to the state In this case the input name is `'MEMBERS'`. ```js -const statement_members = - generator.statementToCode(block, 'MEMBERS'); +const statement_members = generator.statementToCode(block, 'MEMBERS'); ``` ### Format and return @@ -47,6 +47,7 @@ Wrap the statements in curly brackets and return the code, using the default pre const code = '{\n' + statement_members + '\n}'; return [code, Order.ATOMIC]; ``` + Note that `statementToCode` handles the indentation automatically. ### Test it @@ -54,9 +55,8 @@ Note that `statementToCode` handles the indentation automatically. Here is the full block generator: ```js -jsonGenerator.forBlock['object'] = function(block, generator) { - const statementMembers = - generator.statementToCode(block, 'MEMBERS'); +jsonGenerator.forBlock['object'] = function (block, generator) { + const statementMembers = generator.statementToCode(block, 'MEMBERS'); const code = '{\n' + statementMembers + '\n}'; return [code, Order.ATOMIC]; }; @@ -70,4 +70,4 @@ Test it by generating code for an `object` block containing a single `member` bl } ``` -Next, add a second member block and rerun the generator. Did the resulting code change? Let's look at the next section to find out why not. \ No newline at end of file +Next, add a second member block and rerun the generator. Did the resulting code change? Let's look at the next section to find out why not. diff --git a/packages/docs/docs/codelabs/custom-generator/setup.mdx b/packages/docs/docs/codelabs/custom-generator/setup.mdx index 3cd557e18..48582bcfd 100644 --- a/packages/docs/docs/codelabs/custom-generator/setup.mdx +++ b/packages/docs/docs/codelabs/custom-generator/setup.mdx @@ -14,10 +14,11 @@ This codelab will demonstrate how to add code to the Blockly sample app to creat ### The application Use the [`npx @blockly/create-package app`](https://www.npmjs.com/package/@blockly/create-package) command to create a standalone application that contains a sample setup of Blockly, including custom blocks and a display of the generated code and output. - 1. Run `npx @blockly/create-package app custom-generator-codelab`. This will create a blockly application in the folder `custom-generator-codelab`. - 1. `cd` into the new directory: `cd custom-generator-codelab`. - 1. Run `npm start` to start the server and run the sample application. - 1. The sample app will automatically run in the browser window that opens. + +1. Run `npx @blockly/create-package app custom-generator-codelab`. This will create a blockly application in the folder `custom-generator-codelab`. +1. `cd` into the new directory: `cd custom-generator-codelab`. +1. Run `npm start` to start the server and run the sample application. +1. The sample app will automatically run in the browser window that opens. The initial application has one custom block and includes JavaScript generator definitions for that block. Since this codelab will be creating a JSON generator instead, it will remove that custom block and add its own. @@ -34,9 +35,10 @@ const storageKey = 'jsonGeneratorWorkspace'; This codelab will use two custom blocks, as well as five blocks from Blockly's standard set. -The custom blocks represent the *Object* and *Member* sections of the JSON specification. +The custom blocks represent the _Object_ and _Member_ sections of the JSON specification. The blocks are: + - `object` - `member` - `math_number` @@ -52,44 +54,46 @@ Create a new file in the `src/blocks/` directory called `json.js`. This will hol ```js import * as Blockly from 'blockly'; -export const blocks = Blockly.common.createBlockDefinitionsFromJsonArray([{ - "type": "object", - "message0": "{ %1 %2 }", - "args0": [ - { - "type": "input_dummy" - }, - { - "type": "input_statement", - "name": "MEMBERS" - } - ], - "output": null, - "colour": 230, -}, -{ - "type": "member", - "message0": "%1 %2 %3", - "args0": [ - { - "type": "field_input", - "name": "MEMBER_NAME", - "text": "" - }, - { - "type": "field_label", - "name": "COLON", - "text": ":" - }, - { - "type": "input_value", - "name": "MEMBER_VALUE" - } - ], - "previousStatement": null, - "nextStatement": null, - "colour": 230, -}]); +export const blocks = Blockly.common.createBlockDefinitionsFromJsonArray([ + { + type: 'object', + message0: '{ %1 %2 }', + args0: [ + { + type: 'input_dummy', + }, + { + type: 'input_statement', + name: 'MEMBERS', + }, + ], + output: null, + colour: 230, + }, + { + type: 'member', + message0: '%1 %2 %3', + args0: [ + { + type: 'field_input', + name: 'MEMBER_NAME', + text: '', + }, + { + type: 'field_label', + name: 'COLON', + text: ':', + }, + { + type: 'input_value', + name: 'MEMBER_VALUE', + }, + ], + previousStatement: null, + nextStatement: null, + colour: 230, + }, +]); ``` This code creates the block definitions, but it doesn't register the definitions with Blockly to make the blocks usable. We'll do that in `src/index.js`. @@ -97,13 +101,13 @@ Currently, the app imports `blocks` from the original sample file, `text.js`. In ```js // Remove this! -import {blocks} from './blocks/text'; +import { blocks } from './blocks/text'; ``` and add the import for the new blocks: ```js -import {blocks} from './blocks/json'; +import { blocks } from './blocks/json'; ``` Later in the file the block definitions are registered with Blockly (this code is already present and does not need to be added): @@ -120,44 +124,48 @@ The file `src/toolbox.js` contains the original sample toolbox. Replace the enti ```js export const toolbox = { - 'kind': 'flyoutToolbox', - 'contents': [ + kind: 'flyoutToolbox', + contents: [ { - 'kind': 'block', - 'type': 'object' + kind: 'block', + type: 'object', }, { - 'kind': 'block', - 'type': 'member' + kind: 'block', + type: 'member', }, { - 'kind': 'block', - 'type': 'math_number' + kind: 'block', + type: 'math_number', }, { - 'kind': 'block', - 'type': 'text' + kind: 'block', + type: 'text', }, { - 'kind': 'block', - 'type': 'logic_boolean' + kind: 'block', + type: 'logic_boolean', }, { - 'kind': 'block', - 'type': 'logic_null' + kind: 'block', + type: 'logic_null', }, { - 'kind': 'block', - 'type': 'lists_create_with' + kind: 'block', + type: 'lists_create_with', }, - ] -} + ], +}; ``` Our `index.js` file already handles importing the toolbox and using it in Blockly. If the server is already running, refresh the page to see changes. Otherwise, run `npm start` to start the server. New blocks should now exist in the toolbox, like this: -![Screenshot of toolbox showing the added blocks, including the new member and object blocks, plus the built-in number, text, boolean, null, and list blocks.](../../../static/images/codelabs/custom-generator/toolbox_blocks.png) + + ![Screenshot of toolbox showing the added blocks, including the new member and + object blocks, plus the built-in number, text, boolean, null, and list + blocks.](../../../static/images/codelabs/custom-generator/toolbox_blocks.png) + -The app is still trying to generate and run JavaScript for the workspace, instead of JSON. We will change that soon. \ No newline at end of file +The app is still trying to generate and run JavaScript for the workspace, instead of JSON. We will change that soon. diff --git a/packages/docs/docs/codelabs/custom-generator/summary.mdx b/packages/docs/docs/codelabs/custom-generator/summary.mdx index 427408180..db769d92b 100644 --- a/packages/docs/docs/codelabs/custom-generator/summary.mdx +++ b/packages/docs/docs/codelabs/custom-generator/summary.mdx @@ -9,6 +9,7 @@ description: Summary of the "Build a custom generator" codelab. ## 10. Summary In this codelab you learned: + - How to build a custom language generator to generate JSON. - How to define block generators for built in blocks and for custom blocks. - How to use a custom generator in a sample app. @@ -16,6 +17,7 @@ In this codelab you learned: - How to generate code for stacks of blocks. JSON is a simple language, and there are many additional features that could be implemented in a custom generator. Blockly's built-in language generators are a good place to learn more about some additional features: + - Variable definition and use. - Function definition and use. - Initialization and cleanup. @@ -23,4 +25,4 @@ JSON is a simple language, and there are many additional features that could be - Handling comments. - Handling parentheses with operator precedence. -Blockly ships with five language generators: Python, Dart, JavaScript, PHP, and Lua. The language generators and block generators can be found in the [generators directory](https://github.com/RaspberryPiFoundation/blockly/tree/main/generators). \ No newline at end of file +Blockly ships with five language generators: Python, Dart, JavaScript, PHP, and Lua. The language generators and block generators can be found in the [generators directory](https://github.com/RaspberryPiFoundation/blockly/tree/main/generators). diff --git a/packages/docs/docs/codelabs/custom-generator/the-basics.mdx b/packages/docs/docs/codelabs/custom-generator/the-basics.mdx index 8652a58ab..d03d72a03 100644 --- a/packages/docs/docs/codelabs/custom-generator/the-basics.mdx +++ b/packages/docs/docs/codelabs/custom-generator/the-basics.mdx @@ -7,9 +7,10 @@ description: How to define and call a language generator. ## 3. The basics -A *language generator* defines the basic properties of a language, such as how indentation works. *Block generators* define how individual blocks are turned into code, and must be defined for every block used. +A _language generator_ defines the basic properties of a language, such as how indentation works. _Block generators_ define how individual blocks are turned into code, and must be defined for every block used. A language generator has a single entry point: `workspaceToCode`. This function takes in a workspace and: + - Initializes the generator and any necessary state by calling `init`. - Walks the list of top blocks on the workspace and calls `blockToCode` on each top block. - Cleans up any leftover state by calling `finish`. @@ -33,8 +34,8 @@ Next, hook up the new generator with the sample app. First, remove the old code ```js // Remove these lines! -import {forBlock} from './generators/javascript'; -import {javascriptGenerator} from 'blockly/javascript'; +import { forBlock } from './generators/javascript'; +import { javascriptGenerator } from 'blockly/javascript'; // Also remove this line! (further down) Object.assign(javascriptGenerator.forBlock, forBlock); @@ -43,7 +44,7 @@ Object.assign(javascriptGenerator.forBlock, forBlock); Now import the new generator: ```js -import {jsonGenerator} from './generators/json'; +import { jsonGenerator } from './generators/json'; ``` Currently, there are two panels in the app next to the workspace. One shows the generated JavaScript code, and one executes it. The one panel showing the generated Javascript code will be changed to show the generated JSON code instead. Since JSON can't be directly executed, the panel that shows the execution will be left blank. Change the `runCode` function to the following: @@ -74,4 +75,4 @@ Put a number block on the workspace and check the generator output area. It's em Language "JSON" does not know how to generate code for block type "math_number". ``` -This error occurs because there has to be a block generator for each type of block. Read the next section for more details. \ No newline at end of file +This error occurs because there has to be a block generator for each type of block. Read the next section for more details. diff --git a/packages/docs/docs/codelabs/custom-generator/value-block-generators.mdx b/packages/docs/docs/codelabs/custom-generator/value-block-generators.mdx index 2d33ac323..e7102456e 100644 --- a/packages/docs/docs/codelabs/custom-generator/value-block-generators.mdx +++ b/packages/docs/docs/codelabs/custom-generator/value-block-generators.mdx @@ -17,14 +17,16 @@ It will use `getFieldValue` on several types of fields. The simplest block in this example is the `logic_null` block. -![The null block simply returns "null".](../../../static/images/codelabs/custom-generator/null_block.png) + + ![The null block simply returns + "null".](../../../static/images/codelabs/custom-generator/null_block.png) + No matter what, it generates the code `'null'`. Notice that this is a string, because all generated code is a string. Add the following code to `src/generators/json.js`: - ```js -jsonGenerator.forBlock['logic_null'] = function(block) { +jsonGenerator.forBlock['logic_null'] = function (block) { return ['null', Order.ATOMIC]; }; ``` @@ -33,7 +35,10 @@ jsonGenerator.forBlock['logic_null'] = function(block) { Next is the `text` block. -![The text block has an input for the user to type text into.](../../../static/images/codelabs/custom-generator/text_block.png) + + ![The text block has an input for the user to type text + into.](../../../static/images/codelabs/custom-generator/text_block.png) + Unlike `logic_null`, there is a single text input field on this block. Use `getFieldValue`: @@ -44,7 +49,7 @@ const textValue = block.getFieldValue('TEXT'); Since this is a string in the generated code, wrap the value in quotation marks and return it: ```js -jsonGenerator.forBlock['text'] = function(block) { +jsonGenerator.forBlock['text'] = function (block) { const textValue = block.getFieldValue('TEXT'); const code = `"${textValue}"`; return [code, Order.ATOMIC]; @@ -55,14 +60,17 @@ jsonGenerator.forBlock['text'] = function(block) { The `math_number` block has a number field. -![The number block has an input for a user to type a number](../../../static/images/codelabs/custom-generator/number_block.png) + + ![The number block has an input for a user to type a + number](../../../static/images/codelabs/custom-generator/number_block.png) + Like the `text` block, the `math_number` block can use `getFieldValue`. Unlike the text block, the function doesn't need to wrap it in additional quotation marks, because in the JSON code, it won't be a string. However, like all generated code and as with `null` above, the function needs to return the code as a string from the generator. ```js -jsonGenerator.forBlock['math_number'] = function(block) { +jsonGenerator.forBlock['math_number'] = function (block) { const code = String(block.getFieldValue('NUM')); return [code, Order.ATOMIC]; }; @@ -72,13 +80,16 @@ jsonGenerator.forBlock['math_number'] = function(block) { The `logic_boolean` block has a dropdown field named `BOOL`. -![The boolean block lets the user select 'true' or 'false' from a dropdown menu.](../../../static/images/codelabs/custom-generator/boolean_block.png) + + ![The boolean block lets the user select 'true' or 'false' from a dropdown + menu.](../../../static/images/codelabs/custom-generator/boolean_block.png) + Calling `getFieldValue` on a dropdown field returns the value of the selected option, which may not be the same as the display text. In this case the dropdown has two possible values: `TRUE` and `FALSE`. ```js -jsonGenerator.forBlock['logic_boolean'] = function(block) { - const code = (block.getFieldValue('BOOL') === 'TRUE') ? 'true' : 'false'; +jsonGenerator.forBlock['logic_boolean'] = function (block) { + const code = block.getFieldValue('BOOL') === 'TRUE' ? 'true' : 'false'; return [code, Order.ATOMIC]; }; ``` @@ -88,4 +99,4 @@ jsonGenerator.forBlock['logic_boolean'] = function(block) { - Value blocks return an array containing the value as a string and the precedence. - `getFieldValue` finds the field with the specified name and returns its value. - The type of the return value from `getFieldValue` depends on the type of the field. -- Each field type must document what its value represents. \ No newline at end of file +- Each field type must document what its value represents. diff --git a/packages/docs/docs/codelabs/custom-renderer/change-connection-shapes.mdx b/packages/docs/docs/codelabs/custom-renderer/change-connection-shapes.mdx index 30a32e410..e46cbbfba 100644 --- a/packages/docs/docs/codelabs/custom-renderer/change-connection-shapes.mdx +++ b/packages/docs/docs/codelabs/custom-renderer/change-connection-shapes.mdx @@ -8,6 +8,7 @@ description: How to change connection shapes. ## 7. Change connection shapes This step will define and use new shapes for previous/next connections and input/output connections. This takes three steps: + 1. Define new shape objects. 1. Override `init()` to store the new shape objects. 1. Override `shapeFor(connection)` to return the new objects. @@ -17,6 +18,7 @@ This step will define and use new shapes for previous/next connections and input An outline path is drawn clockwise around the block, starting at the top left. As a result the previous connection is drawn from left-to-right, while the next connection is drawn from right-to-left. Previous and next connections are defined by the same object. The object has four properties: + - `width`: The width of the connection. - `height`: The height of the connection. - `pathLeft`: The sub-path that describes the connection when drawn from left-to-right. @@ -64,6 +66,7 @@ Define a new function called `makeRectangularPreviousConn()` and put it inside t Just as previous/next connection shapes are drawn from left-to-right and right-to-left, input/output connection shapes are drawn from top-to-bottom and bottom-to-top. Input and output connections are defined by the same object. The object has four properties: + - `width`: The width of the connection. - `height`: The height of the connection. - `pathUp`: The sub-path that describes the connection when drawn from top-to-bottom. @@ -148,6 +151,6 @@ Next, override the `shapeFor(connection)` function in the `CustomConstantProvide ### The result -Return to the browser, click on the `Loops` entry, and drag out a repeat block. The resulting block should have rectangular connections for all four connection types. +Return to the browser, click on the `Loops` entry, and drag out a repeat block. The resulting block should have rectangular connections for all four connection types. -![[Screenshot of a custom renderer with notches, corners, and tabs with fundamentally different shapes than the defaults.]](../../../static/images/codelabs/custom-renderer/custom_notches.png) \ No newline at end of file +![[Screenshot of a custom renderer with notches, corners, and tabs with fundamentally different shapes than the defaults.]](../../../static/images/codelabs/custom-renderer/custom_notches.png) diff --git a/packages/docs/docs/codelabs/custom-renderer/codelab-overview.mdx b/packages/docs/docs/codelabs/custom-renderer/codelab-overview.mdx index 111eaa671..a17137c0e 100644 --- a/packages/docs/docs/codelabs/custom-renderer/codelab-overview.mdx +++ b/packages/docs/docs/codelabs/custom-renderer/codelab-overview.mdx @@ -20,16 +20,16 @@ description: Overview of the "Build custom renderers" codelab. This codelab builds and uses four renderers: 1. A minimal custom renderer that extends `Blockly.blockRendering.Renderer` but makes no modifications. -![Screenshot of a renderer with an appearance matching the base renderer.](../../../static/images/codelabs/custom-renderer/custom_renderer.png) + ![Screenshot of a renderer with an appearance matching the base renderer.](../../../static/images/codelabs/custom-renderer/custom_renderer.png) 1. A custom renderer which sets new values for the rendering-related constants `NOTCH_WIDTH`, `NOTCH_HEIGHT`,`CORNER_RADIUS`, and `TAB_HEIGHT` found in `Blockly.blockRendering.ConstantProvider`. -![Screenshot of a custom renderer with notches, corners, and tabs that have similar shapes as the default but with different widths, heights, and radiuses.](../../../static/images/codelabs/custom-renderer/custom_constants.png) + ![Screenshot of a custom renderer with notches, corners, and tabs that have similar shapes as the default but with different widths, heights, and radiuses.](../../../static/images/codelabs/custom-renderer/custom_constants.png) 1. A custom renderer which overrides the functions `Blockly.blockRendering.ConstantProvider.init()` and `Blockly.blockRendering.ConstantProvider.shapeFor(connection)` to define and return custom [SVG paths](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/path). -![Screenshot of a custom renderer with notches, corners, and tabs with fundamentally different shapes than the defaults.](../../../static/images/codelabs/custom-renderer/custom_notches.png) + ![Screenshot of a custom renderer with notches, corners, and tabs with fundamentally different shapes than the defaults.](../../../static/images/codelabs/custom-renderer/custom_notches.png) 1. A custom renderer which overrides the function `Blockly.blockRendering.ConstantProvider.shapeFor(connection)` to return different shapes for the input/output connections depending on whether the their type is a `Number`, `String`, or `Boolean`. -![Screenshot of a custom renderer with rectangles for the Number input/outputs and a puzzle tab for the Boolean input/output attached to an "if" block](../../../static/images/codelabs/custom-renderer/typed_connection_shapes.png) + ![Screenshot of a custom renderer with rectangles for the Number input/outputs and a puzzle tab for the Boolean input/output attached to an "if" block](../../../static/images/codelabs/custom-renderer/typed_connection_shapes.png) ### What you'll need - Basic understanding of renderers and toolboxes in Blockly. - NPM installed ([instructions](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)). -- Comfort using the command line/terminal. \ No newline at end of file +- Comfort using the command line/terminal. diff --git a/packages/docs/docs/codelabs/custom-renderer/complete-code/src/generators/javascript.js b/packages/docs/docs/codelabs/custom-renderer/complete-code/src/generators/javascript.js index 1ee6bc236..f7508e36e 100644 --- a/packages/docs/docs/codelabs/custom-renderer/complete-code/src/generators/javascript.js +++ b/packages/docs/docs/codelabs/custom-renderer/complete-code/src/generators/javascript.js @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {Order} from 'blockly/javascript'; +import { Order } from 'blockly/javascript'; // Export all the code generators for our custom blocks, // but don't register them with Blockly yet. diff --git a/packages/docs/docs/codelabs/custom-renderer/complete-code/src/index.js b/packages/docs/docs/codelabs/custom-renderer/complete-code/src/index.js index fe5c3ebf8..7694e44a4 100644 --- a/packages/docs/docs/codelabs/custom-renderer/complete-code/src/index.js +++ b/packages/docs/docs/codelabs/custom-renderer/complete-code/src/index.js @@ -5,11 +5,11 @@ */ import * as Blockly from 'blockly'; -import {blocks} from './blocks/text'; -import {forBlock} from './generators/javascript'; -import {javascriptGenerator} from 'blockly/javascript'; -import {save, load} from './serialization'; -import {toolbox} from './toolbox'; +import { blocks } from './blocks/text'; +import { forBlock } from './generators/javascript'; +import { javascriptGenerator } from 'blockly/javascript'; +import { save, load } from './serialization'; +import { toolbox } from './toolbox'; import './renderers/custom'; import './index.css'; diff --git a/packages/docs/docs/codelabs/custom-renderer/define-and-register-a-custom-renderer.mdx b/packages/docs/docs/codelabs/custom-renderer/define-and-register-a-custom-renderer.mdx index 6d6d98c53..d3d9cecee 100644 --- a/packages/docs/docs/codelabs/custom-renderer/define-and-register-a-custom-renderer.mdx +++ b/packages/docs/docs/codelabs/custom-renderer/define-and-register-a-custom-renderer.mdx @@ -52,4 +52,4 @@ const ws = Blockly.inject(blocklyDiv, { If the server is already running, refresh the page to see the new changes. Otherwise, run `npm start` to start the server. Once the server is running, click on the `Loops` entry in the browser and drag out a repeat block. The resulting block will use the same values already defined in the base `Blockly.blockRendering.Renderer`. -![Screenshot of a renderer with an appearance matching the base renderer.](../../../static/images/codelabs/custom-renderer/custom_renderer.png) \ No newline at end of file +![Screenshot of a renderer with an appearance matching the base renderer.](../../../static/images/codelabs/custom-renderer/custom_renderer.png) diff --git a/packages/docs/docs/codelabs/custom-renderer/observe-the-built-in-renderers.mdx b/packages/docs/docs/codelabs/custom-renderer/observe-the-built-in-renderers.mdx index 2ec48bd41..4f5afcf11 100644 --- a/packages/docs/docs/codelabs/custom-renderer/observe-the-built-in-renderers.mdx +++ b/packages/docs/docs/codelabs/custom-renderer/observe-the-built-in-renderers.mdx @@ -9,4 +9,4 @@ description: Introduction to the built-in renderers. First, visit [the advanced playground](https://blockly-demo.appspot.com/static/tests/playgrounds/advanced_playground.html) to observe what the built-in renderers look like. -Click on the "Loops" entry and drag out a repeat block. Now, change the selection in the "renderer" drop down to observe the look of each built-in renderer. By default, the renderer named "Geras" is used. \ No newline at end of file +Click on the "Loops" entry and drag out a repeat block. Now, change the selection in the "renderer" drop down to observe the look of each built-in renderer. By default, the renderer named "Geras" is used. diff --git a/packages/docs/docs/codelabs/custom-renderer/override-constants.mdx b/packages/docs/docs/codelabs/custom-renderer/override-constants.mdx index 0e5c84d66..d08d596cb 100644 --- a/packages/docs/docs/codelabs/custom-renderer/override-constants.mdx +++ b/packages/docs/docs/codelabs/custom-renderer/override-constants.mdx @@ -7,11 +7,12 @@ description: How to override the constants in a renderer. ## 5. Override constants -A **ConstantsProvider** holds all rendering-related constants. This includes sizing information and colours. Blockly provides a base **ConstantsProvider** with all required fields set to default values. +A **ConstantsProvider** holds all rendering-related constants. This includes sizing information and colours. Blockly provides a base **ConstantsProvider** with all required fields set to default values. The **ConstantsProvider** `constructor()` sets all static properties, such as `NOTCH_WIDTH` and `NOTCH_HEIGHT`. For a full list of properties, see [constants.ts](https://github.com/RaspberryPiFoundation/blockly/blob/main/core/renderers/common/constants.ts). Only override the necessary subset of the constants, rather than all of them. To do so: + - Define a constants provider that extends the base `ConstantProvider`. - Call the superclass `super()` in the `constructor()`. - Set individual properties. @@ -69,6 +70,6 @@ To use the new **CustomConstantProvider**, override `makeConstants_()` inside th ### The result -Return to the browser, click on the `Loops` entry, and drag out a repeat block. The resulting block should have triangular previous and next connections, and skinny input and output connections. Note that the general shapes of the connections have not changed--only parameters such as width and height. +Return to the browser, click on the `Loops` entry, and drag out a repeat block. The resulting block should have triangular previous and next connections, and skinny input and output connections. Note that the general shapes of the connections have not changed--only parameters such as width and height. -![Screenshot of a custom renderer with notches, corners, and tabs that have similar shapes as the default but with different widths, heights, and radiuses.](../../../static/images/codelabs/custom-renderer/custom_constants.png) \ No newline at end of file +![Screenshot of a custom renderer with notches, corners, and tabs that have similar shapes as the default but with different widths, heights, and radiuses.](../../../static/images/codelabs/custom-renderer/custom_constants.png) diff --git a/packages/docs/docs/codelabs/custom-renderer/setup.mdx b/packages/docs/docs/codelabs/custom-renderer/setup.mdx index 48b6f65a0..e97707fcf 100644 --- a/packages/docs/docs/codelabs/custom-renderer/setup.mdx +++ b/packages/docs/docs/codelabs/custom-renderer/setup.mdx @@ -12,10 +12,11 @@ This codelab will add code to the Blockly sample app to create and use a new cus ### The application Use the Use the [`npx @blockly/create-package`](https://www.npmjs.com/package/@blockly/create-package) command to create a standalone application that contains a sample setup of Blockly, including custom blocks and a display of the generated code and output. - 1. Run `npx @blockly/create-package app custom-renderer-codelab`. This will create a blockly application in the folder `custom-renderer-codelab`. - 1. `cd` into the new directory: `cd custom-renderer-codelab`. - 1. Run `npm start` to start the server and run the sample application. - 1. The sample app will automatically run in the browser window that opens. + +1. Run `npx @blockly/create-package app custom-renderer-codelab`. This will create a blockly application in the folder `custom-renderer-codelab`. +1. `cd` into the new directory: `cd custom-renderer-codelab`. +1. Run `npm start` to start the server and run the sample application. +1. The sample app will automatically run in the browser window that opens. The initial application uses the default renderer and contains no code or definitions for a custom renderer. @@ -26,4 +27,4 @@ Before setting up the rest of the application, change the storage key used for t ```js // Use a unique storage key for this codelab const storageKey = 'customRenderersWorkspace'; -``` \ No newline at end of file +``` diff --git a/packages/docs/docs/codelabs/custom-renderer/summary.mdx b/packages/docs/docs/codelabs/custom-renderer/summary.mdx index 0a314e5de..e39709289 100644 --- a/packages/docs/docs/codelabs/custom-renderer/summary.mdx +++ b/packages/docs/docs/codelabs/custom-renderer/summary.mdx @@ -4,13 +4,13 @@ slug: /codelabs/custom-renderer/summary/index.html description: Summary of the "Build custom renderers" codelab. --- - # Build custom renderers ## 9. Summary -Custom renderers are a powerful way to change the look and feel of Blockly. In this codelab you learned: +Custom renderers are a powerful way to change the look and feel of Blockly. In this codelab you learned: + - How to declare and register a custom renderer by extending `Blockly.blockRendering.Renderer`. - How to override renderer constants such as `NOTCH_HEIGHT` in `Blockly.blockRendering.ConstantProvider`. - How to modify connection shapes by creating custom [SVG paths](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/path), storing them in `init()`, and finally returning them in `shapeFor(connection)`. -- How to update the mapping from connection to connection shape by adding logic in `shapeFor(connection)`. \ No newline at end of file +- How to update the mapping from connection to connection shape by adding logic in `shapeFor(connection)`. diff --git a/packages/docs/docs/codelabs/custom-renderer/typed-connection-shapes.mdx b/packages/docs/docs/codelabs/custom-renderer/typed-connection-shapes.mdx index 9e0fdc084..8c575c3b6 100644 --- a/packages/docs/docs/codelabs/custom-renderer/typed-connection-shapes.mdx +++ b/packages/docs/docs/codelabs/custom-renderer/typed-connection-shapes.mdx @@ -14,6 +14,7 @@ This step will create a renderer that sets connection shapes at runtime based on Override the `shapeFor(connection)` function in the `CustomConstantProvider` class definition to return a different connection shape based on the `checks` returned from `connection.getCheck()`. Note the previous definition of `shapeFor(connection)` created in previous steps will need to be deleted. The new definition of `shapeFor(connection)` will: + - Return a rectangular tab for inputs and outputs that accept `Number`s and `String`s. - Return the default puzzle tab for all other inputs and outputs. - Return the normal notch for all previous and next connections. @@ -45,8 +46,9 @@ shapeFor(connection) { ### The result Take these steps to fully test this change in the browser: + 1. Click on the `Loops` entry and drag out a repeat block. 1. Click on the `Logic` entry and drag the conditional `if` block into the repeat block that was placed on the workspace in the previous step. There should be an entry similar to the screenshot below, in which the `Number` inputs and outputs are rectangular, but the boolean input on the `if` block is a puzzle tab. -![Screenshot of a custom renderer with rectangles for the Number input/outputs and a puzzle tab for the Boolean input/output attached to an "if" block](../../../static/images/codelabs/custom-renderer/typed_connection_shapes.png) \ No newline at end of file +![Screenshot of a custom renderer with rectangles for the Number input/outputs and a puzzle tab for the Boolean input/output attached to an "if" block](../../../static/images/codelabs/custom-renderer/typed_connection_shapes.png) diff --git a/packages/docs/docs/codelabs/custom-renderer/understand-connection-shapes.mdx b/packages/docs/docs/codelabs/custom-renderer/understand-connection-shapes.mdx index 20a130712..552974026 100644 --- a/packages/docs/docs/codelabs/custom-renderer/understand-connection-shapes.mdx +++ b/packages/docs/docs/codelabs/custom-renderer/understand-connection-shapes.mdx @@ -65,4 +65,4 @@ shapeFor(connection: RenderedConnection): Shape { throw Error('Unknown connection type'); } } -``` \ No newline at end of file +``` diff --git a/packages/docs/docs/codelabs/custom-toolbox/add-an-icon-to-your-category.mdx b/packages/docs/docs/codelabs/custom-toolbox/add-an-icon-to-your-category.mdx index 7a58bef61..9a58f7dcb 100644 --- a/packages/docs/docs/codelabs/custom-toolbox/add-an-icon-to-your-category.mdx +++ b/packages/docs/docs/codelabs/custom-toolbox/add-an-icon-to-your-category.mdx @@ -10,33 +10,41 @@ import CodelabImage from '@site/src/components/CodelabImage'; ## 5. Add an icon to your category We are going to add an icon to our "Logic" category by adding an icon library to -our `index.html` file, and setting the appropriate CSS class on our category definition. +our `index.html` file, and setting the appropriate CSS class on our category definition. To start, we are going to grab an icon library and add it to `index.html`: + ``` ``` + We are going to add a cog icon from this library to the "Logic" category. To do this, we will add the appropriate CSS classes to our category definition. In `index.html` scroll down to your toolbox definition and change the below line: + ```xml ``` + to be: + ```xml ``` + All the classes used to create a category can be set similar to how we set the icon class above. See the [Blockly toolbox documentation](/guides/configure/web/toolboxes/appearance#category-css) for more information. ### Add some CSS + If you open `index.html` you will notice that the gear icon is positioned incorrectly and is a bit difficult to see. We will use the `customIcon` class to change the color of the icon and use the `blocklyTreeRowContentContainer` class to position the icon above the text. In your `toolbox_style.css` file add: + ```css /* Changes color of the icon to white. */ .customIcon { @@ -54,6 +62,7 @@ In your `toolbox_style.css` file add: ``` ### Update setSelected + If you open `index.html` and click on the "Logic" category you will notice that the white icon now blends into the white background. @@ -68,11 +77,13 @@ this.iconDom_.style.color = this.colour_; ``` Add the below line to `setSelected` if the category has not been selected: + ```js this.iconDom_.style.color = 'white'; ``` Your `setSelected` method should look similar to below: + ```js /** @override */ setSelected(isSelected){ @@ -96,10 +107,20 @@ Your `setSelected` method should look similar to below: Blockly.utils.aria.State.SELECTED, isSelected); } ``` + ### The result + If you open your `index.html` file, you should see a white gear above your "Logic" label, and it should change to blue when the category has been selected. - ![A white gear above the word "Logic" on a blue background.](../../../static/images/codelabs/custom-toolbox/category_gear.png) + + {' '} + ![A white gear above the word "Logic" on a blue + background.](../../../static/images/codelabs/custom-toolbox/category_gear.png){' '} + - ![A blue gear above the word "Logic" on a white background.](../../../static/images/codelabs/custom-toolbox/category_gear_selected.png) \ No newline at end of file + + {' '} + ![A blue gear above the word "Logic" on a white + background.](../../../static/images/codelabs/custom-toolbox/category_gear_selected.png){' '} + diff --git a/packages/docs/docs/codelabs/custom-toolbox/adding-a-custom-toolbox-item.mdx b/packages/docs/docs/codelabs/custom-toolbox/adding-a-custom-toolbox-item.mdx index 0cb7ef202..03e2034c1 100644 --- a/packages/docs/docs/codelabs/custom-toolbox/adding-a-custom-toolbox-item.mdx +++ b/packages/docs/docs/codelabs/custom-toolbox/adding-a-custom-toolbox-item.mdx @@ -8,15 +8,18 @@ import CodelabImage from '@site/src/components/CodelabImage'; # Customizing a Blockly toolbox ## 7. Adding a custom toolbox item + In the previous sections we modified the toolbox by extending the base category class. In this section we will make a completely new toolbox item and add it to our toolbox. For this example, we are going to create a toolbox label. ### Setup + In the same directory as `index.html` create a new file named `toolbox_label.js`. Include this file in `index.html`: + ```html ``` @@ -32,20 +35,24 @@ class ToolboxLabel extends Blockly.ToolboxItem { } Blockly.registry.register( - Blockly.registry.Type.TOOLBOX_ITEM, - 'toolboxlabel', - ToolboxLabel); + Blockly.registry.Type.TOOLBOX_ITEM, + 'toolboxlabel', + ToolboxLabel, +); ``` + By registering this toolbox item with the name "toolboxlabel" we can now use this name in our toolbox definition to add our custom item to the toolbox. Navigate to `index.html`, and scroll down to the toolbox definition. Add a `` element as the first item in your toolbox definition: + ```xml ``` Your toolbox definition should now look something like: + ```xml ` to our category by overriding the `createIconDom_` method. ### Change the element for our icon + By default, the `createIconDom_` method adds a `` element for the category icon. We can override this to return an `` element. Add the following methods to `custom_category.js`: + ```js /** @override */ createIconDom_() { @@ -31,7 +34,12 @@ createIconDom_() { ``` ### The result + If you open `index.html` you should now see the blockly logo on top of all your categories - ![A toolbox with the blockly logo on top of the category label.](../../../static/images/codelabs/custom-toolbox/image_toolbox.png) \ No newline at end of file + + {' '} + ![A toolbox with the blockly logo on top of the category + label.](../../../static/images/codelabs/custom-toolbox/image_toolbox.png){' '} + diff --git a/packages/docs/docs/codelabs/custom-toolbox/change-the-look-of-a-category.mdx b/packages/docs/docs/codelabs/custom-toolbox/change-the-look-of-a-category.mdx index 8029f9209..921b56d50 100644 --- a/packages/docs/docs/codelabs/custom-toolbox/change-the-look-of-a-category.mdx +++ b/packages/docs/docs/codelabs/custom-toolbox/change-the-look-of-a-category.mdx @@ -15,16 +15,19 @@ In the default `ToolboxCategory` class, the `addColourBorder_` method adds a str to the category name. We can override this method in order to add colour to the entire category div. Add the following code to your `CustomCategory` class. + ```js /** @override */ addColourBorder_(colour){ this.rowDiv_.style.backgroundColor = colour; } ``` + The `colour` passed in is calculated from either the `categorystyle` or the `colour` attribute set on the category definition. For example, the "Logic" category definition looks like: + ```xml ... @@ -38,6 +41,7 @@ The logic_category style looks like: "colour": "210" } ``` + For more information on Blockly styles please visit the [themes documentation](/guides/configure/web/appearance/themes#category-style). ### Add some CSS @@ -45,7 +49,11 @@ For more information on Blockly styles please visit the [themes documentation](/ Open `index.html` to see your updated toolbox. Your toolbox should look similar to the below toolbox. - ![A toolbox with colors that expand the across the entire category.](../../../static/images/codelabs/custom-toolbox/colored_toolbox.png) + + {' '} + ![A toolbox with colors that expand the across the entire + category.](../../../static/images/codelabs/custom-toolbox/colored_toolbox.png){' '} + We are going to add some CSS to make it easier to read, and to space out our categories. @@ -57,6 +65,7 @@ and include it in `index.html`: ``` Copy and paste the following CSS into your `toolbox_style.css` file. + ```css /* Makes our label white. */ .blocklyToolboxCategoryLabel { @@ -78,4 +87,8 @@ Copy and paste the following CSS into your `toolbox_style.css` file. Open `index.html` to see your toolbox. - ![Toolbox with category corners that are rounded and white text.](../../../static/images/codelabs/custom-toolbox/styled_toolbox.png) \ No newline at end of file + + {' '} + ![Toolbox with category corners that are rounded and white + text.](../../../static/images/codelabs/custom-toolbox/styled_toolbox.png){' '} + diff --git a/packages/docs/docs/codelabs/custom-toolbox/change-the-look-of-a-selected-category.mdx b/packages/docs/docs/codelabs/custom-toolbox/change-the-look-of-a-selected-category.mdx index 96d9572ee..f63cbf3d4 100644 --- a/packages/docs/docs/codelabs/custom-toolbox/change-the-look-of-a-selected-category.mdx +++ b/packages/docs/docs/codelabs/custom-toolbox/change-the-look-of-a-selected-category.mdx @@ -21,6 +21,7 @@ color of the div to white, and the text to the color of the category when it has been selected. Add the following code to `custom_category.js`: + ```js /** @override */ setSelected(isSelected){ @@ -44,7 +45,13 @@ setSelected(isSelected){ ``` ### The result + Open `index.html` and click on the "Logic" category. You should now see a white category with a colored label. - ![A toolbox with all categories colored except for the first category that has a white background.](../../../static/images/codelabs/custom-toolbox/category_selected.png) \ No newline at end of file + + {' '} + ![A toolbox with all categories colored except for the first category that has + a white + background.](../../../static/images/codelabs/custom-toolbox/category_selected.png){' '} + diff --git a/packages/docs/docs/codelabs/custom-toolbox/codelab-overview.mdx b/packages/docs/docs/codelabs/custom-toolbox/codelab-overview.mdx index 810ff4986..5e668c88b 100644 --- a/packages/docs/docs/codelabs/custom-toolbox/codelab-overview.mdx +++ b/packages/docs/docs/codelabs/custom-toolbox/codelab-overview.mdx @@ -11,9 +11,11 @@ import CodelabImage from '@site/src/components/CodelabImage'; ## 1. Codelab overview ### What you'll learn + This codelab will focus on customizing the Blockly toolbox. In this codelab you will learn: + 1. How to add a background color to a toolbox category. 1. How to change the look of a selected category. 1. How to add a custom CSS classes to a toolbox category. @@ -26,11 +28,16 @@ Over the course of this codelab you will customize your toolbox categories as we as create a custom toolbox item. The resulting toolbox is shown below. - ![A toolbox with colored background and the blockly label above the category text.](../../../static/images/codelabs/custom-toolbox/final_toolbox.png) + + {' '} + ![A toolbox with colored background and the blockly label above the category + text.](../../../static/images/codelabs/custom-toolbox/final_toolbox.png){' '} + The code samples are written in ES6 syntax. You can find the code for the [completed custom toolbox](https://github.com/RaspberryPiFoundation/blockly/docs/docs/codelabs/custom-toolbox/complete-code) on GitHub. ### What you'll need + - A browser. - A text editor. - Basic knowledge of HTML, CSS, and JavaScript. @@ -38,4 +45,4 @@ The code samples are written in ES6 syntax. You can find the code for the [compl Throughout various parts of this codelab we will be talking about [toolbox definitions](/guides/configure/web/toolboxes/category?tab=xml). The toolbox definition can be written in XML or JSON. We will be using an XML -toolbox definition that can be found in the provided code. \ No newline at end of file +toolbox definition that can be found in the provided code. diff --git a/packages/docs/docs/codelabs/custom-toolbox/setup.mdx b/packages/docs/docs/codelabs/custom-toolbox/setup.mdx index 864dbcd41..e24003bde 100644 --- a/packages/docs/docs/codelabs/custom-toolbox/setup.mdx +++ b/packages/docs/docs/codelabs/custom-toolbox/setup.mdx @@ -10,6 +10,7 @@ import CodelabImage from '@site/src/components/CodelabImage'; ## 2. Setup ### Download the sample code + You can get the sample code for this codelab by either downloading the zip here: [Download zip](https://github.com/RaspberryPiFoundation/blockly/archive/main.zip) @@ -23,10 +24,12 @@ git clone https://github.com/RaspberryPiFoundation/blockly.git If you downloaded the source as a zip, unpacking it should give you a root folder named `blockly-main`. The relevant files are in `docs/docs/codelabs/custom-toolbox`. There are two versions of the app: + - `starter-code/`: The starter code that you'll build upon in this codelab. - `complete-code/`: The code after completing the codelab, in case you get lost or want to compare to your version. Each folder contains: + - `index.js` - The codelab's logic. To start, it just injects a simple workspace. - `index.html` - A web page containing a simple blockly workspace. @@ -35,6 +38,7 @@ To run the code, simply open `starter-code/index.html` in a browser. You should ![A web page with the text "Toolbox Customization Codelab" and a Blockly workspace.](../../../static/images/codelabs/custom-toolbox/starter_workspace.png) ### Define and register a custom category + To start, create a file named `custom_category.js` in the `starter-code` directory. Include your new file by adding a script tag to `index.html`. @@ -45,6 +49,7 @@ directory. Include your new file by adding a script tag to `index.html`. In order to create a custom category we will create a new category that extends the default `Blockly.ToolboxCategory` class. Add the following code to your `custom_category.js` file. + ```js class CustomCategory extends Blockly.ToolboxCategory { /** @@ -59,12 +64,16 @@ class CustomCategory extends Blockly.ToolboxCategory { After defining your category you need to tell Blockly that it exists. Register your category by adding the below code to the end of `custom_category.js`. + ```js Blockly.registry.register( - Blockly.registry.Type.TOOLBOX_ITEM, - Blockly.ToolboxCategory.registrationName, - CustomCategory, true); + Blockly.registry.Type.TOOLBOX_ITEM, + Blockly.ToolboxCategory.registrationName, + CustomCategory, + true, +); ``` + By registering our `CustomCategory` with `Blockly.ToolboxCategory.registrationName` we are overriding the default category in Blockly. Because we are overriding a toolbox item instead of adding a new one, we must pass in `true` as the last @@ -76,7 +85,11 @@ an error because we are overriding an existing class. To test, open `index.html` in a browser. Your toolbox should look the same as it did before. - ![The default toolbox. A list of categories with a strip of colour to the left.](../../../static/images/codelabs/custom-toolbox/base_toolbox.png) + + {' '} + ![The default toolbox. A list of categories with a strip of colour to the + left.](../../../static/images/codelabs/custom-toolbox/base_toolbox.png){' '} + However, if you run the below commands in your console you will see that your toolbox is now using the `CustomCategory` class. @@ -84,4 +97,4 @@ your toolbox is now using the `CustomCategory` class. ```js var toolbox = Blockly.common.getMainWorkspace().getToolbox(); toolbox.getToolboxItems()[0]; -``` \ No newline at end of file +``` diff --git a/packages/docs/docs/codelabs/custom-toolbox/summary.mdx b/packages/docs/docs/codelabs/custom-toolbox/summary.mdx index 3d31e36a6..19c454f28 100644 --- a/packages/docs/docs/codelabs/custom-toolbox/summary.mdx +++ b/packages/docs/docs/codelabs/custom-toolbox/summary.mdx @@ -4,16 +4,16 @@ slug: /codelabs/custom-toolbox/summary/index.html description: Summary of the "Customizing a Blockly toolbox" codelab. --- - # Customizing a Blockly toolbox ## 8. Summary The toolbox can be customized in a variety of ways to make it work for your application. In this codelab you learned: -* How to create a custom category. -* What method to override to change how the colour of the category is applied. -* What method to override to change the look of the category when selected. -* How to add an icon by adding a custom CSS class to the icon div. -* How to change what HTML Elements are used for different parts of a category. -* How to create a custom toolbox item. -You can find the code for the [completed custom toolbox](https://github.com/RaspberryPiFoundation/blockly/docs/docs/codelabs/custom-toolbox/complete-code) on GitHub. \ No newline at end of file + +- How to create a custom category. +- What method to override to change how the colour of the category is applied. +- What method to override to change the look of the category when selected. +- How to add an icon by adding a custom CSS class to the icon div. +- How to change what HTML Elements are used for different parts of a category. +- How to create a custom toolbox item. + You can find the code for the [completed custom toolbox](https://github.com/RaspberryPiFoundation/blockly/docs/docs/codelabs/custom-toolbox/complete-code) on GitHub. diff --git a/packages/docs/docs/codelabs/getting-started/add-blockly-libraries.mdx b/packages/docs/docs/codelabs/getting-started/add-blockly-libraries.mdx index 3e4c4d997..04664a3d0 100644 --- a/packages/docs/docs/codelabs/getting-started/add-blockly-libraries.mdx +++ b/packages/docs/docs/codelabs/getting-started/add-blockly-libraries.mdx @@ -9,7 +9,7 @@ description: How to add Blockly libraries to an app. Now that you know what you'll be building, you need to add Blockly dependencies to your app. -Blockly releases are [published on npm](https://www.npmjs.com/package/blockly) on a quarterly basis. For this codelab you will import blockly using [unpkg](https://unpkg.com), which lets you import all of the files you need with a single script tag. +Blockly releases are [published on npm](https://www.npmjs.com/package/blockly) on a quarterly basis. For this codelab you will import blockly using [unpkg](https://unpkg.com), which lets you import all of the files you need with a single script tag. ### Add the script tag @@ -20,7 +20,7 @@ Open `starter-code/index.html` in a text editor and scroll to the end. You can s ``` -Add Blockly just before these two scripts. The order is important, because you will use Blockly objects later in `main.js`. Your imports should now look like this: +Add Blockly just before these two scripts. The order is important, because you will use Blockly objects later in `main.js`. Your imports should now look like this: ```html @@ -34,6 +34,7 @@ Add Blockly just before these two scripts. The order is important, because you w ### Default imports Importing Blockly this way loads four default modules. + - Blockly core: The main Blockly library, which defines the basic Blockly UI and logic. - Built-in block definitions: Common blocks such as loops, logic, math, and string manipulation. - The JavaScript generator: Converts blocks into JavaScript, and contains block generators for all built-in blocks. diff --git a/packages/docs/docs/codelabs/getting-started/codelab-overview.mdx b/packages/docs/docs/codelabs/getting-started/codelab-overview.mdx index aceb71e52..f55fe04cf 100644 --- a/packages/docs/docs/codelabs/getting-started/codelab-overview.mdx +++ b/packages/docs/docs/codelabs/getting-started/codelab-overview.mdx @@ -26,14 +26,20 @@ Blockly includes everything you need for defining and rendering blocks in a drag MusicMaker, a web app where you can program buttons to play different sounds, using Blockly. - ![image](../../../static/images/codelabs/getting-started/play_mode.png) + + {' '} + ![image](../../../static/images/codelabs/getting-started/play_mode.png){' '} + - ![image](../../../static/images/codelabs/getting-started/d4_three_times.png) + + {' '} + ![image](../../../static/images/codelabs/getting-started/d4_three_times.png){' '} + ### What you'll need -- A browser -- A text editor -- Basic knowledge of HTML, CSS and JavaScript +- A browser +- A text editor +- Basic knowledge of HTML, CSS and JavaScript This codelab is focused on Blockly. The app structure, non-relevant concepts and code are glossed over and are provided for you to simply copy and paste. diff --git a/packages/docs/docs/codelabs/getting-started/create-a-blockly-workspace.mdx b/packages/docs/docs/codelabs/getting-started/create-a-blockly-workspace.mdx index 121de27ee..89ee19212 100644 --- a/packages/docs/docs/codelabs/getting-started/create-a-blockly-workspace.mdx +++ b/packages/docs/docs/codelabs/getting-started/create-a-blockly-workspace.mdx @@ -14,10 +14,14 @@ In this section you will learn how to add a workspace to your app, including how ### Parts of Blockly A Blockly workspace has two main components: + - The area where the user assembles their blocks (the white area). - A toolbox that contains all blocks that are available to the user (the grey area). - ![image](../../../static/images/codelabs/getting-started/d4_three_times.png) + + {' '} + ![image](../../../static/images/codelabs/getting-started/d4_three_times.png){' '} + The toolbox may be organized into categories, and may contain both single blocks and groups of blocks. A well-organized toolbox helps the user to explore the available blocks and understand the capabilities of the underlying system. @@ -31,23 +35,23 @@ Open up `scripts/main.js` and scroll down to the end of the file. Then add the c ```js const toolbox = { - 'kind': 'flyoutToolbox', - 'contents': [ + kind: 'flyoutToolbox', + contents: [ { - 'kind': 'block', - 'type': 'controls_repeat_ext', - 'inputs': { - 'TIMES': { - 'shadow': { - 'type': 'math_number', - 'fields': { - 'NUM': 5 - } - } - } - } - } - ] + kind: 'block', + type: 'controls_repeat_ext', + inputs: { + TIMES: { + shadow: { + type: 'math_number', + fields: { + NUM: 5, + }, + }, + }, + }, + }, + ], }; ``` @@ -55,9 +59,10 @@ This JavaScript object defines a toolbox with a single "repeat loop" block. ### Injection -Adding a Blockly workspace to a page is called *injection*, because the workspace is injected into a `div` that already exists on the page. +Adding a Blockly workspace to a page is called _injection_, because the workspace is injected into a `div` that already exists on the page. To do this you call the function `Blockly.inject(container, options)`, which takes two arguments: + - `container` is where the Blockly workspace should be placed on the page. It can be an `Element`, an ID string, or a CSS selector. - `options` is a dictionary of configuration options. @@ -76,7 +81,7 @@ Blockly.inject('blocklyDiv', { toolbox: toolbox, scrollbars: false, horizontalLayout: true, - toolboxPosition: "end", + toolboxPosition: 'end', }); ``` @@ -93,6 +98,9 @@ The `options` struct gives you significant control over your Blockly instance. Y Now refresh the page. Select the EDIT mode, then tap on one of the buttons. You should see a Blockly editor: - ![image](../../../static/images/codelabs/getting-started/workspace_with_loop.png) + + {' '} + ![image](../../../static/images/codelabs/getting-started/workspace_with_loop.png){' '} + -Drag and drop the available loop block to the workspace to test it out. \ No newline at end of file +Drag and drop the available loop block to the workspace to test it out. diff --git a/packages/docs/docs/codelabs/getting-started/create-a-custom-block.mdx b/packages/docs/docs/codelabs/getting-started/create-a-custom-block.mdx index e31c83416..9effdeba9 100644 --- a/packages/docs/docs/codelabs/getting-started/create-a-custom-block.mdx +++ b/packages/docs/docs/codelabs/getting-started/create-a-custom-block.mdx @@ -11,9 +11,12 @@ import CodelabImage from '@site/src/components/CodelabImage'; Since this is a music maker app, we want a block that plays sounds. We could create one block per sound, but instead we will create a single block with a dropdown to select which note to play: - ![image](../../../static/images/codelabs/getting-started/play_sound_block.png) + + {' '} + ![image](../../../static/images/codelabs/getting-started/play_sound_block.png){' '} + -In Blockly, a *block definition* describes how a block looks and behaves. This includes its text, colour, and shape. It may also include which other blocks it can connect to. +In Blockly, a _block definition_ describes how a block looks and behaves. This includes its text, colour, and shape. It may also include which other blocks it can connect to. Blocks can be defined in either JavaScript or JSON. The developer site has a full article on [how to define a block](/guides/create-custom-blocks/define/block-definitions#how-to-create-block-definitions). @@ -29,25 +32,25 @@ Create a JS file to define a new "play sound" block: ```js Blockly.common.defineBlocksWithJsonArray([ { - "type": "play_sound", - "message0": "Play %1", - "args0": [ + type: 'play_sound', + message0: 'Play %1', + args0: [ { - "type": "field_dropdown", - "name": "VALUE", - "options": [ - ["C4", "sounds/c4.m4a"], - ["D4", "sounds/d4.m4a"], - ["E4", "sounds/e4.m4a"], - ["F4", "sounds/f4.m4a"], - ["G4", "sounds/g4.m4a"] - ] - } + type: 'field_dropdown', + name: 'VALUE', + options: [ + ['C4', 'sounds/c4.m4a'], + ['D4', 'sounds/d4.m4a'], + ['E4', 'sounds/e4.m4a'], + ['F4', 'sounds/f4.m4a'], + ['G4', 'sounds/g4.m4a'], + ], + }, ], - "previousStatement": null, - "nextStatement": null, - "colour": 355 - } + previousStatement: null, + nextStatement: null, + colour: 355, + }, ]); ``` @@ -57,7 +60,7 @@ Add a script tag to `index.html` to include your new block definition: ``` -Your sound block definitions must come after importing Blockly and before the other imports, since you will use Blockly functions in this file, and you will be using functions from this file in later files. Your imports should now look like this: +Your sound block definitions must come after importing Blockly and before the other imports, since you will use Blockly functions in this file, and you will be using functions from this file in later files. Your imports should now look like this: ```html @@ -72,34 +75,37 @@ Now we can update the toolbox to include the new sound block, by adding `{'kind' ```js const toolbox = { - 'kind': 'flyoutToolbox', - 'contents': [ + kind: 'flyoutToolbox', + contents: [ { - 'kind': 'block', - 'type': 'controls_repeat_ext', - 'inputs': { - 'TIMES': { - 'shadow': { - 'type': 'math_number', - 'fields': { - 'NUM': 5 - } - } - } - } + kind: 'block', + type: 'controls_repeat_ext', + inputs: { + TIMES: { + shadow: { + type: 'math_number', + fields: { + NUM: 5, + }, + }, + }, + }, }, { - 'kind': 'block', - 'type': 'play_sound' - } - ] + kind: 'block', + type: 'play_sound', + }, + ], }; ``` Run the app one more time, and play around with the new `Play (sound)` block. It should look like this: - ![image](../../../static/images/codelabs/getting-started/workspace_with_toolbox.png) + + {' '} + ![image](../../../static/images/codelabs/getting-started/workspace_with_toolbox.png){' '} + ### The block factory -This step discussed how to manually define custom blocks in Blockly. Once you've completed the entire codelab, we recommend that you check out our [block factory tool](/guides/create-custom-blocks/blockly-developer-tools), which helps automate part of this process. \ No newline at end of file +This step discussed how to manually define custom blocks in Blockly. Once you've completed the entire codelab, we recommend that you check out our [block factory tool](/guides/create-custom-blocks/blockly-developer-tools), which helps automate part of this process. diff --git a/packages/docs/docs/codelabs/getting-started/explore-the-app.mdx b/packages/docs/docs/codelabs/getting-started/explore-the-app.mdx index d9f3193cc..b2302c063 100644 --- a/packages/docs/docs/codelabs/getting-started/explore-the-app.mdx +++ b/packages/docs/docs/codelabs/getting-started/explore-the-app.mdx @@ -15,13 +15,18 @@ To run the app, simply open `starter-code/index.html` in a browser. By default, the app launches in "**Play Mode**". In this mode, you can see 9 buttons. None of them can do anything yet. The idea is to let the user define custom behaviors for each button, using Blockly. - ![image](../../../static/images/codelabs/getting-started/play_mode.png) + + {' '} + ![image](../../../static/images/codelabs/getting-started/play_mode.png){' '} + ### Edit mode By tapping the **EDIT** button, you can switch to edit mode. In this mode, tapping a button will display an editor, which is where you can program how sounds should play for that button. For now, the editor screen is empty. - ![image](../../../static/images/codelabs/getting-started/edit_mode_unimplemented.png) + + {' '} + ![image](../../../static/images/codelabs/getting-started/edit_mode_unimplemented.png){' '} + You can go back to the play mode by tapping **SAVE** and then **DONE** buttons. - diff --git a/packages/docs/docs/codelabs/getting-started/generate-javaScript-code.mdx b/packages/docs/docs/codelabs/getting-started/generate-javaScript-code.mdx index 31fdf479e..bf8f9e7d6 100644 --- a/packages/docs/docs/codelabs/getting-started/generate-javaScript-code.mdx +++ b/packages/docs/docs/codelabs/getting-started/generate-javaScript-code.mdx @@ -17,26 +17,29 @@ This generated code will be run by the browser, effectively executing the blocks Blockly can generate code from blocks for different languages, e.g. JavaScript, Python, or PHP. -A *language generator* defines the rules for generating a specific language (such as indentation). Because we are using the default imports, we don't need to add any new code to get the JavaScript generator. +A _language generator_ defines the rules for generating a specific language (such as indentation). Because we are using the default imports, we don't need to add any new code to get the JavaScript generator. As previously mentioned, you can define your imports more carefully to get a [different generator](https://www.npmjs.com/package/blockly#blockly-generators). ### Add a block generator -When Blockly generates JavaScript code for blocks in a workspace, it translates each block into code. By default, it knows how to translate all library-provided default blocks into JavaScript code. However, for any custom blocks, we need to specify our own translation functions. These are called *block generators*. +When Blockly generates JavaScript code for blocks in a workspace, it translates each block into code. By default, it knows how to translate all library-provided default blocks into JavaScript code. However, for any custom blocks, we need to specify our own translation functions. These are called _block generators_. Add the following code to the bottom of `scripts/sound_blocks.js`: ```js -javascript.javascriptGenerator.forBlock['play_sound'] = function(block) { - let value = '\'' + block.getFieldValue('VALUE') + '\''; +javascript.javascriptGenerator.forBlock['play_sound'] = function (block) { + let value = "'" + block.getFieldValue('VALUE') + "'"; return 'MusicMaker.queueSound(' + value + ');\n'; }; ``` With this translation function, the following `play_sound` block: - ![image](../../../static/images/codelabs/getting-started/play_sound_block.png) + + {' '} + ![image](../../../static/images/codelabs/getting-started/play_sound_block.png){' '} + translates into the JavaScript code: @@ -44,4 +47,4 @@ translates into the JavaScript code: MusicMaker.queueSound('Sounds/c4.m4a'); ``` -For more information on block generators, read the [generating code](/guides/create-custom-blocks/code-generation/overview#block-code-generators) page on the developer site. \ No newline at end of file +For more information on block generators, read the [generating code](/guides/create-custom-blocks/code-generation/overview#block-code-generators) page on the developer site. diff --git a/packages/docs/docs/codelabs/getting-started/run-generated-code.mdx b/packages/docs/docs/codelabs/getting-started/run-generated-code.mdx index 67cbdb39d..a3b8000ff 100644 --- a/packages/docs/docs/codelabs/getting-started/run-generated-code.mdx +++ b/packages/docs/docs/codelabs/getting-started/run-generated-code.mdx @@ -22,7 +22,9 @@ Next, you need to generate the code out of that workspace, which you can do with The user's code will consist of many `MusicMaker.queueSound` calls. At the end of our generated script, add a call to `MusicMaker.play` to play all the sounds added to the queue: ```js -let code = javascript.javascriptGenerator.workspaceToCode(Blockly.getMainWorkspace()); +let code = javascript.javascriptGenerator.workspaceToCode( + Blockly.getMainWorkspace(), +); code += 'MusicMaker.play();'; ``` @@ -43,7 +45,9 @@ The end result should look like this: ```js function handlePlay(event) { loadWorkspace(event.target); - let code = javascript.javascriptGenerator.workspaceToCode(Blockly.getMainWorkspace()); + let code = javascript.javascriptGenerator.workspaceToCode( + Blockly.getMainWorkspace(), + ); code += 'MusicMaker.play();'; try { eval(code); @@ -54,12 +58,16 @@ function handlePlay(event) { ``` ### A note on eval + Executing scripts with eval is not always the safest option - we use it here for simplicity. If you intend to run the user's blocks in production, check out the JS Interpreter project. This project is separate from Blockly, but was specifically written for Blockly. ### Test it Run the app and try it out! Edit one of the buttons to play a D4 sound 3 times: - ![image](../../../static/images/codelabs/getting-started/d4_three_times.png) + + {' '} + ![image](../../../static/images/codelabs/getting-started/d4_three_times.png){' '} + -Save and exit the edit mode. Now if you tap this button, you should hear the D4 sound played 3 times. \ No newline at end of file +Save and exit the edit mode. Now if you tap this button, you should hear the D4 sound played 3 times. diff --git a/packages/docs/docs/codelabs/getting-started/save-load-workspace.mdx b/packages/docs/docs/codelabs/getting-started/save-load-workspace.mdx index da211c20d..89fe52540 100644 --- a/packages/docs/docs/codelabs/getting-started/save-load-workspace.mdx +++ b/packages/docs/docs/codelabs/getting-started/save-load-workspace.mdx @@ -17,7 +17,8 @@ Open `scripts/main.js`. Add the following code to the `save()` method: ```js button.blocklySave = Blockly.serialization.workspaces.save( - Blockly.getMainWorkspace()); + Blockly.getMainWorkspace(), +); ``` `workspaces.save` takes the Blockly workspace, exports its state to a JavaScript object and stores it in a `blocklySave` property on the button. This way the exported state for the block sequence gets associated with a particular button. @@ -50,4 +51,4 @@ function enableBlocklyMode(e) { } ``` -Now, test the code. Edit the workspace for one of the buttons, add some blocks, save it, and reopen it. The workspace should still contain the blocks you added. \ No newline at end of file +Now, test the code. Edit the workspace for one of the buttons, add some blocks, save it, and reopen it. The workspace should still contain the blocks you added. diff --git a/packages/docs/docs/codelabs/getting-started/setup.mdx b/packages/docs/docs/codelabs/getting-started/setup.mdx index c34968c85..d07921bac 100644 --- a/packages/docs/docs/codelabs/getting-started/setup.mdx +++ b/packages/docs/docs/codelabs/getting-started/setup.mdx @@ -22,10 +22,12 @@ git clone https://github.com/RaspberryPiFoundation/blockly.git If you downloaded the source as a zip, unpacking it should give you a root folder named `blockly-main`. The relevant files are in `docs/docs/codelabs/getting-started`. There are two versions of the app: + - `starter-code/`: The starter code that you'll build upon in this codelab. - `complete-code/`: The code after completing the codelab, in case you get lost or want to compare to your version. Each folder contains: + - `scripts/` - `main.js` - The main logic for the app. In the starter project it has all the code needed to navigate and switch between views in the basic app. - `music_maker.js` - A small library to play sounds. We will use it to actually play sounds in the browser. diff --git a/packages/docs/docs/codelabs/getting-started/the-end.mdx b/packages/docs/docs/codelabs/getting-started/the-end.mdx index e1f6508d0..10e5305ce 100644 --- a/packages/docs/docs/codelabs/getting-started/the-end.mdx +++ b/packages/docs/docs/codelabs/getting-started/the-end.mdx @@ -12,4 +12,4 @@ And with that, you're done with the Blockly codelab! If you'd like to continue p For more documentation, visit the [Blockly developer site](/guides/get-started/what-is-blockly). -Additionally, Blockly has an active [developer forum](https://groups.google.com/g/blockly). Please drop by and say hello. We're happy to answer any questions or give advice on best practices for building an app with Blockly. Feel free to show us your prototypes early; collectively we have a lot of experience and can offer hints which will save you time. \ No newline at end of file +Additionally, Blockly has an active [developer forum](https://groups.google.com/g/blockly). Please drop by and say hello. We're happy to answer any questions or give advice on best practices for building an app with Blockly. Feel free to show us your prototypes early; collectively we have a lot of experience and can offer hints which will save you time. diff --git a/packages/docs/docs/codelabs/index.mdx b/packages/docs/docs/codelabs/index.mdx index b2dc45051..cda1d7a1a 100644 --- a/packages/docs/docs/codelabs/index.mdx +++ b/packages/docs/docs/codelabs/index.mdx @@ -5,7 +5,6 @@ pagination_prev: null slug: /codelabs/index --- - import { CodelabGrid, CodelabCard } from '@site/src/components/CodelabCards'; import Image from '@site/src/components/Image'; @@ -13,51 +12,83 @@ Blockly Codelabs provide a guided, tutorial, hands-on coding experience of Block - Blockly icon + level="beginner" + title="Getting started with Blockly" + href="/codelabs/getting-started/codelab-overview"> + Blockly icon - Blockly icon + level="beginner" + title="Customizing a Blockly toolbox" + href="/codelabs/custom-toolbox/codelab-overview"> + Blockly icon - Blockly icon + level="beginner" + title="Customizing your themes" + href="/codelabs/theme-extension-identifier/codelab-overview"> + Blockly icon - Blockly icon + level="Intermediate" + title="Customizing context menus" + href="/codelabs/context-menu-option/codelab-overview"> + Blockly icon - Blockly icon + level="Intermediate" + title="Block validation and warnings" + href="/codelabs/validation-and-warnings/codelab-overview"> + Blockly icon - Blockly icon + level="Intermediate" + title="Use CSS in Blockly" + href="/codelabs/css/codelab-overview"> + Blockly icon - Blockly icon + level="Advanced" + title="Build a custom generator" + href="/codelabs/custom-generator/codelab-overview"> + Blockly icon - Blockly icon + level="Advanced" + title="Build custom renderers" + href="/codelabs/custom-renderer/codelab-overview"> + Blockly icon diff --git a/packages/docs/docs/codelabs/theme-extension-identifier/codelab-overview.mdx b/packages/docs/docs/codelabs/theme-extension-identifier/codelab-overview.mdx index 1ce3f8870..630615778 100644 --- a/packages/docs/docs/codelabs/theme-extension-identifier/codelab-overview.mdx +++ b/packages/docs/docs/codelabs/theme-extension-identifier/codelab-overview.mdx @@ -4,7 +4,6 @@ slug: /codelabs/theme-extension-identifier/codelab-overview/index.html description: Overview of the "Customizing your themes" codelab. --- - # Customizing your themes ## 1. Codelab overview @@ -12,17 +11,19 @@ description: Overview of the "Customizing your themes" codelab. ### What you'll learn In this codelab you will learn how to: + - Add component styles. - Add a category style. - Add a block style. - ### What you'll build + A very simple Blockly workspace with customized themes. ### What you'll need + - A browser - Basic knowledge of HTML, CSS, and JavaScript. This codelab is focused on Blockly's theme extension. Non-relevant concepts -are glossed over and provided for you to simple copy and paste. \ No newline at end of file +are glossed over and provided for you to simple copy and paste. diff --git a/packages/docs/docs/codelabs/theme-extension-identifier/customize-block-styles.mdx b/packages/docs/docs/codelabs/theme-extension-identifier/customize-block-styles.mdx index ac873f723..b90c3852b 100644 --- a/packages/docs/docs/codelabs/theme-extension-identifier/customize-block-styles.mdx +++ b/packages/docs/docs/codelabs/theme-extension-identifier/customize-block-styles.mdx @@ -13,60 +13,59 @@ For more information on block styles visit our themes [documentation](/guides/co Update the Theme definition to have the block styles as below. - ```js Blockly.Themes.Halloween = Blockly.Theme.defineTheme('halloween', { - 'base': Blockly.Themes.Classic, - 'categoryStyles': { - 'list_category': { - 'colour': "#4a148c" + base: Blockly.Themes.Classic, + categoryStyles: { + list_category: { + colour: '#4a148c', }, - 'logic_category': { - 'colour': "#8b4513", + logic_category: { + colour: '#8b4513', }, - 'loop_category': { - 'colour': "#85E21F", + loop_category: { + colour: '#85E21F', }, - 'text_category': { - 'colour': "#FE9B13", + text_category: { + colour: '#FE9B13', }, }, - 'blockStyles': { - 'list_blocks': { - 'colourPrimary': "#4a148c", - 'colourSecondary':"#AD7BE9", - 'colourTertiary':"#CDB6E9", + blockStyles: { + list_blocks: { + colourPrimary: '#4a148c', + colourSecondary: '#AD7BE9', + colourTertiary: '#CDB6E9', }, - 'logic_blocks': { - 'colourPrimary': "#8b4513", - 'colourSecondary':"#ff0000", - 'colourTertiary':"#C5EAFF" + logic_blocks: { + colourPrimary: '#8b4513', + colourSecondary: '#ff0000', + colourTertiary: '#C5EAFF', }, - 'loop_blocks': { - 'colourPrimary': "#85E21F", - 'colourSecondary':"#ff0000", - 'colourTertiary':"#C5EAFF" + loop_blocks: { + colourPrimary: '#85E21F', + colourSecondary: '#ff0000', + colourTertiary: '#C5EAFF', }, - 'text_blocks': { - 'colourPrimary': "#FE9B13", - 'colourSecondary':"#ff0000", - 'colourTertiary':"#C5EAFF" + text_blocks: { + colourPrimary: '#FE9B13', + colourSecondary: '#ff0000', + colourTertiary: '#C5EAFF', }, }, - 'componentStyles': { - 'workspaceBackgroundColour': '#ff7518', - 'toolboxBackgroundColour': '#F9C10E', - 'toolboxForegroundColour': '#fff', - 'flyoutBackgroundColour': '#252526', - 'flyoutForegroundColour': '#ccc', - 'flyoutOpacity': 1, - 'scrollbarColour': '#ff0000', - 'insertionMarkerColour': '#fff', - 'insertionMarkerOpacity': 0.3, - 'scrollbarOpacity': 0.4, - 'cursorColour': '#d0d0d0', - 'blackBackground': '#333' - } + componentStyles: { + workspaceBackgroundColour: '#ff7518', + toolboxBackgroundColour: '#F9C10E', + toolboxForegroundColour: '#fff', + flyoutBackgroundColour: '#252526', + flyoutForegroundColour: '#ccc', + flyoutOpacity: 1, + scrollbarColour: '#ff0000', + insertionMarkerColour: '#fff', + insertionMarkerOpacity: 0.3, + scrollbarOpacity: 0.4, + cursorColour: '#d0d0d0', + blackBackground: '#333', + }, }); ``` @@ -74,4 +73,4 @@ Blockly.Themes.Halloween = Blockly.Theme.defineTheme('halloween', { Click on different blocks in the component and you should see the colours that you applied show up. -![Customized Block colors on the components](../../../static/images/codelabs/theme-extension/block_styles.png) \ No newline at end of file +![Customized Block colors on the components](../../../static/images/codelabs/theme-extension/block_styles.png) diff --git a/packages/docs/docs/codelabs/theme-extension-identifier/customize-category-styles.mdx b/packages/docs/docs/codelabs/theme-extension-identifier/customize-category-styles.mdx index 3cc624af5..724850842 100644 --- a/packages/docs/docs/codelabs/theme-extension-identifier/customize-category-styles.mdx +++ b/packages/docs/docs/codelabs/theme-extension-identifier/customize-category-styles.mdx @@ -16,37 +16,36 @@ Update the Theme definition to have the category styles as below. ```js Blockly.Themes.Halloween = Blockly.Theme.defineTheme('halloween', { - 'base': Blockly.Themes.Classic, - 'categoryStyles': { - 'list_category': { - 'colour': "#4a148c" + base: Blockly.Themes.Classic, + categoryStyles: { + list_category: { + colour: '#4a148c', }, - 'logic_category': { - 'colour': "#8b4513", + logic_category: { + colour: '#8b4513', }, - 'loop_category': { - 'colour': "#85E21F", + loop_category: { + colour: '#85E21F', + }, + text_category: { + colour: '#FE9B13', }, - 'text_category': { - 'colour': "#FE9B13", - } }, - 'componentStyles': { - 'workspaceBackgroundColour': '#ff7518', - 'toolboxBackgroundColour': '#F9C10E', - 'toolboxForegroundColour': '#fff', - 'flyoutBackgroundColour': '#252526', - 'flyoutForegroundColour': '#ccc', - 'flyoutOpacity': 1, - 'scrollbarColour': '#ff0000', - 'insertionMarkerColour': '#fff', - 'insertionMarkerOpacity': 0.3, - 'scrollbarOpacity': 0.4, - 'cursorColour': '#d0d0d0', - 'blackBackground': '#333' - } + componentStyles: { + workspaceBackgroundColour: '#ff7518', + toolboxBackgroundColour: '#F9C10E', + toolboxForegroundColour: '#fff', + flyoutBackgroundColour: '#252526', + flyoutForegroundColour: '#ccc', + flyoutOpacity: 1, + scrollbarColour: '#ff0000', + insertionMarkerColour: '#fff', + insertionMarkerOpacity: 0.3, + scrollbarOpacity: 0.4, + cursorColour: '#d0d0d0', + blackBackground: '#333', + }, }); - ``` ### Test it diff --git a/packages/docs/docs/codelabs/theme-extension-identifier/customize-components.mdx b/packages/docs/docs/codelabs/theme-extension-identifier/customize-components.mdx index a451841d4..752be022e 100644 --- a/packages/docs/docs/codelabs/theme-extension-identifier/customize-components.mdx +++ b/packages/docs/docs/codelabs/theme-extension-identifier/customize-components.mdx @@ -11,21 +11,21 @@ Within the Halloween theme definition, you can customize the colours of multiple ```js Blockly.Themes.Halloween = Blockly.Theme.defineTheme('halloween', { - 'base': Blockly.Themes.Classic, - 'componentStyles': { - 'workspaceBackgroundColour': '#ff7518', - 'toolboxBackgroundColour': '#F9C10E', - 'toolboxForegroundColour': '#fff', - 'flyoutBackgroundColour': '#252526', - 'flyoutForegroundColour': '#ccc', - 'flyoutOpacity': 1, - 'scrollbarColour': '#ff0000', - 'insertionMarkerColour': '#fff', - 'insertionMarkerOpacity': 0.3, - 'scrollbarOpacity': 0.4, - 'cursorColour': '#d0d0d0', - 'blackBackground': '#333' - } + base: Blockly.Themes.Classic, + componentStyles: { + workspaceBackgroundColour: '#ff7518', + toolboxBackgroundColour: '#F9C10E', + toolboxForegroundColour: '#fff', + flyoutBackgroundColour: '#252526', + flyoutForegroundColour: '#ccc', + flyoutOpacity: 1, + scrollbarColour: '#ff0000', + insertionMarkerColour: '#fff', + insertionMarkerOpacity: 0.3, + scrollbarOpacity: 0.4, + cursorColour: '#d0d0d0', + blackBackground: '#333', + }, }); ``` @@ -33,4 +33,4 @@ Blockly.Themes.Halloween = Blockly.Theme.defineTheme('halloween', { Reload your web page. You should see a themed workspace! -![Fun with colours.](../../../static/images/codelabs/theme-extension/theme_components_workspace.png) \ No newline at end of file +![Fun with colours.](../../../static/images/codelabs/theme-extension/theme_components_workspace.png) diff --git a/packages/docs/docs/codelabs/theme-extension-identifier/setup.mdx b/packages/docs/docs/codelabs/theme-extension-identifier/setup.mdx index dedf7a32e..36e4dc1c6 100644 --- a/packages/docs/docs/codelabs/theme-extension-identifier/setup.mdx +++ b/packages/docs/docs/codelabs/theme-extension-identifier/setup.mdx @@ -22,13 +22,15 @@ git clone https://github.com/RaspberryPiFoundation/blockly.git If you downloaded the source as a zip, unpacking it should give you a root folder named `blockly-main`. The relevant files are in `docs/docs/codelabs/theme-extension-identifier`. There are two versions of the app: + - `starter-code/`: The starter code that you'll build upon in this codelab. - `complete-code/`: The code after completing the codelab, in case you get lost or want to compare to your version. Each folder contains: + - `index.js` - The codelab's logic. To start, it just injects a simple workspace. - `index.html` - A web page containing a simple blockly workspace. To run the code, simple open `starter-code/index.html` in a browser. You should see a Blockly workspace with a flyout. -![A web page with the text "Theme Extension Codelab" and a Blockly workspace.](../../../static/images/codelabs/theme-extension/starter_workspace.png) \ No newline at end of file +![A web page with the text "Theme Extension Codelab" and a Blockly workspace.](../../../static/images/codelabs/theme-extension/starter_workspace.png) diff --git a/packages/docs/docs/codelabs/theme-extension-identifier/summary.mdx b/packages/docs/docs/codelabs/theme-extension-identifier/summary.mdx index 7aa6ba0ff..c07901a62 100644 --- a/packages/docs/docs/codelabs/theme-extension-identifier/summary.mdx +++ b/packages/docs/docs/codelabs/theme-extension-identifier/summary.mdx @@ -4,7 +4,6 @@ slug: /codelabs/theme-extension-identifier/summary/index.html description: Summary of the "Customizing your themes" codelab. --- - # Customizing your themes ## 7. Summary @@ -15,4 +14,4 @@ In this codelab you have learned how to extend and customize themes for the bloc - [Themes documentation](/guides/configure/web/appearance/themes) -- You can also customize the font styles. Details are available in the [documentation](/guides/configure/web/appearance/themes#font-styles). \ No newline at end of file +- You can also customize the font styles. Details are available in the [documentation](/guides/configure/web/appearance/themes#font-styles). diff --git a/packages/docs/docs/codelabs/theme-extension-identifier/workspace-theme.mdx b/packages/docs/docs/codelabs/theme-extension-identifier/workspace-theme.mdx index 8d11f89ef..5d86693c2 100644 --- a/packages/docs/docs/codelabs/theme-extension-identifier/workspace-theme.mdx +++ b/packages/docs/docs/codelabs/theme-extension-identifier/workspace-theme.mdx @@ -16,22 +16,23 @@ Themes are a way to customize the look and feel of Blockly. Currently, we suppor A theme can be created using the constructor or by using defineTheme. Using `defineTheme` makes it easy to extend a pre existing theme and set all values with a single object. Add the below code in `index.js` right before function start() + ```js Blockly.Themes.Halloween = Blockly.Theme.defineTheme('halloween', { - 'base': Blockly.Themes.Classic, + base: Blockly.Themes.Classic, }); ``` And then add a line to inject this theme in function start() in `index.js` + ```js function start() { - // Create main workspace. - workspace = Blockly.inject('blocklyDiv', - { - toolbox: toolboxCategories, - theme: Blockly.Themes.Halloween, - }); - } + // Create main workspace. + workspace = Blockly.inject('blocklyDiv', { + toolbox: toolboxCategories, + theme: Blockly.Themes.Halloween, + }); +} ``` :::note diff --git a/packages/docs/docs/codelabs/validation-and-warnings/codelab-overview.mdx b/packages/docs/docs/codelabs/validation-and-warnings/codelab-overview.mdx index a94204958..9144ad971 100644 --- a/packages/docs/docs/codelabs/validation-and-warnings/codelab-overview.mdx +++ b/packages/docs/docs/codelabs/validation-and-warnings/codelab-overview.mdx @@ -11,20 +11,27 @@ import CodelabImage from '@site/src/components/CodelabImage'; ## 1. Codelab overview ### What you'll learn + This codelab will show you how to ensure that custom blocks either: + 1. have everything they need to be able to generate valid code, or 1. display a visual warning to the user that the block is currently invalid. ### What you'll build + In this codelab, you'll create a new custom block type that generates a list of numbers counting up within a given range. The block will validate itself and display a warning if the first number in the range is greater than the last number: -![Two instances of a custom block, one with a validation warning.](../../../static/images/codelabs/validation-and-warnings/final_range_blocks.png) + + ![Two instances of a custom block, one with a validation + warning.](../../../static/images/codelabs/validation-and-warnings/final_range_blocks.png) + You can find the code for the [completed custom block](https://github.com/RaspberryPiFoundation/blockly/docs/docs/codelabs/validation-and-warnings/complete-code/index.js) on GitHub. ### What you'll need + - A browser. - A text editor. - Basic knowledge of JavaScript. - Basic understanding of the [Blockly toolbox](/guides/configure/web/toolboxes/toolbox). -- Basic understanding of [using JSON to define custom blocks](/guides/create-custom-blocks/define/structure-json). \ No newline at end of file +- Basic understanding of [using JSON to define custom blocks](/guides/create-custom-blocks/define/structure-json). diff --git a/packages/docs/docs/codelabs/validation-and-warnings/displaying-warnings.mdx b/packages/docs/docs/codelabs/validation-and-warnings/displaying-warnings.mdx index 416eadc65..1d5d60415 100644 --- a/packages/docs/docs/codelabs/validation-and-warnings/displaying-warnings.mdx +++ b/packages/docs/docs/codelabs/validation-and-warnings/displaying-warnings.mdx @@ -14,16 +14,18 @@ However, there may be invalid conditions that can't be corrected automatically b In the case of our custom block, we want our extension to be notified whenever either field is updated, so that it can check both of the fields to determine whether the block is currently valid. We can set that up with a general change listener by adding this code inside the extension function after the custom validator: ```js - // Validate the entire block whenever any part of it changes, - // and display a warning if the block cannot be made valid. - this.setOnChange(function(event) { - const first = this.getFieldValue('FIRST'); - const last = this.getFieldValue('LAST'); - const valid = (first < last); - this.setWarningText(valid +// Validate the entire block whenever any part of it changes, +// and display a warning if the block cannot be made valid. +this.setOnChange(function (event) { + const first = this.getFieldValue('FIRST'); + const last = this.getFieldValue('LAST'); + const valid = first < last; + this.setWarningText( + valid ? null - : `The first number (${first}) must be smaller than the last number (${last}).`); - }); + : `The first number (${first}) must be smaller than the last number (${last}).`, + ); +}); ``` This change listener function will get called whenever any part of the block is updated. It has access to all of the block's current field values, as well as the block's parents and children, if any. In this case, it reads both field values and compares them to determine whether the block is valid. Then it calls `this.setWarningText(...)`, which can accept either `null` indicating that there is nothing wrong or a string describing the problem. @@ -39,17 +41,17 @@ Depending on the severity of the issue, this might be sufficient for your custom You can disable a block using `this.setDisabledReason(true, 'reason')`, although there are some caveats: disabled blocks can't be dragged out of the toolbox flyout, and the act of disabling a block usually adds an event to Blockly's undo history. That's probably not the behavior you want when validating a block, so you can avoid both of these effects with the following code, which you should put inside the change listener function after setting the warning text: ```js - // Disable invalid blocks (unless it's in a toolbox flyout, - // since you can't drag disabled blocks to your workspace). - if (!this.isInFlyout) { - const initialGroup = Blockly.Events.getGroup(); - // Make it so the move and the disable event get undone together. - Blockly.Events.setGroup(event.group); - this.setDisabledReason(!valid, 'Invalid range'); - Blockly.Events.setGroup(initialGroup); - } +// Disable invalid blocks (unless it's in a toolbox flyout, +// since you can't drag disabled blocks to your workspace). +if (!this.isInFlyout) { + const initialGroup = Blockly.Events.getGroup(); + // Make it so the move and the disable event get undone together. + Blockly.Events.setGroup(event.group); + this.setDisabledReason(!valid, 'Invalid range'); + Blockly.Events.setGroup(initialGroup); +} ``` Reload `index.html` one last time, drag out the custom block, and edit the fields to make the `FIRST` field greater than the `LAST` field again. This time, the block should be disabled, and it won't generate code even if it is combined with other blocks: -![A Blockly workspace with disabled custom blocks.](../../../static/images/codelabs/validation-and-warnings/disabled_block.png) \ No newline at end of file +![A Blockly workspace with disabled custom blocks.](../../../static/images/codelabs/validation-and-warnings/disabled_block.png) diff --git a/packages/docs/docs/codelabs/validation-and-warnings/setup.mdx b/packages/docs/docs/codelabs/validation-and-warnings/setup.mdx index fc1724eaa..2711ebe24 100644 --- a/packages/docs/docs/codelabs/validation-and-warnings/setup.mdx +++ b/packages/docs/docs/codelabs/validation-and-warnings/setup.mdx @@ -10,6 +10,7 @@ import CodelabImage from '@site/src/components/CodelabImage'; ## 2. Setup ### Download the sample code + You can get the sample code for this codelab by either downloading the zip here: [Download zip](https://github.com/RaspberryPiFoundation/blockly/archive/main.zip) @@ -23,10 +24,12 @@ git clone https://github.com/RaspberryPiFoundation/blockly.git If you downloaded the source as a zip, unpacking it should give you a root folder named `blockly-main`. The relevant files are in `docs/docs/codelabs/validation-and-warnings`. There are two versions of the app: + - `starter-code/`: The starter code that you'll build upon in this codelab. - `complete-code/`: The code after completing the codelab, in case you get lost or want to compare to your version. Each folder contains: + - `index.js` - The codelab's logic. To start, it just injects a simple workspace. - `index.html` - A web page containing a simple blockly workspace, an empty space where generated code will be displayed, and a button to execute the generated code. @@ -35,33 +38,35 @@ Open the file `starter-code/index.html` in a browser to see what it looks like. ![A web page with the text "Validation and Warnings Codelab" and a Blockly workspace.](../../../static/images/codelabs/validation-and-warnings/starter_workspace.png) Next, open the file `starter-code/index.js` in a text editor. You will be making changes to this file, but first let's take a look at the contents. The code in this file already does a few things: + 1. It uses Blockly's toolbox JSON API to define a toolbox containing a few built-in blocks that will be useful for testing our custom block. 1. In a function called `start()`, it initializes a Blockly workspace with the above toolbox, and adds a change event listener that displays the generated JavaScript code whenever a block is moved or updated in the workspace. 1. In a function called `executeCode()`, it executes the generated JavaScript code. ### Define a custom block type + To prepare for adding validation, let's define a new custom block type named `list_range` with two number fields called `FIRST` and `LAST`. Copy the following code to the beginning of `index.js`: ```js // Use Blockly's custom block JSON API to define a new block type. Blockly.common.defineBlocksWithJsonArray([ { - 'type': 'list_range', - 'message0': 'create list of numbers from %1 up to %2', - 'args0': [ + type: 'list_range', + message0: 'create list of numbers from %1 up to %2', + args0: [ { - 'type': 'field_number', - 'name': 'FIRST', - 'value': 0, + type: 'field_number', + name: 'FIRST', + value: 0, }, { - 'type': 'field_number', - 'name': 'LAST', - 'value': 5, + type: 'field_number', + name: 'LAST', + value: 5, }, ], - 'output': 'Array', - 'style': 'list_blocks', + output: 'Array', + style: 'list_blocks', }, ]); ``` @@ -77,14 +82,18 @@ Then, to make this block available from the toolbox, find the toolbox definition Now, if you reload `index.html` and open the toolbox, you should see the new block at the top: -![A Blockly toolbox containing range, for-each, sum, print, and break blocks.](../../../static/images/codelabs/validation-and-warnings/completed_toolbox.png) + + ![A Blockly toolbox containing range, for-each, sum, print, and break + blocks.](../../../static/images/codelabs/validation-and-warnings/completed_toolbox.png) + ### Generating JavaScript code for the custom block + You can drag this block out from the toolbox into the workspace, but if you try to use it, you'll find that Blockly doesn't know how to generate JavaScript code from this block yet and error messages will appear in the browser console when it tries to update the display of the generated code. To fix this, add the following code below the custom block definition: ```js // Define how to generate JavaScript from the custom block. -javascript.javascriptGenerator['list_range'] = function(block) { +javascript.javascriptGenerator['list_range'] = function (block) { const first = this.getFieldValue('FIRST'); const last = this.getFieldValue('LAST'); const numbers = []; @@ -100,4 +109,4 @@ Reload `index.html` once again and try adding the new block to the workspace. Yo ![A Blockly workspace with some blocks, the generated code, and the output.](../../../static/images/codelabs/validation-and-warnings/generated_javascript.png) -Now we are ready to start adding validation! \ No newline at end of file +Now we are ready to start adding validation! diff --git a/packages/docs/docs/codelabs/validation-and-warnings/summary.mdx b/packages/docs/docs/codelabs/validation-and-warnings/summary.mdx index e7a720055..2973ca752 100644 --- a/packages/docs/docs/codelabs/validation-and-warnings/summary.mdx +++ b/packages/docs/docs/codelabs/validation-and-warnings/summary.mdx @@ -9,21 +9,24 @@ description: Summary of the "Block validation and warnings" codelab. ## 5. Summary In this codelab, you learned: -* How to use the field validators in Blockly's JSON API. -* How to create an extension that adds functionality to a block. -* How to create custom field validators. -* How to validate the entire block when any part of it changes. -* How to display a warning message on the block. -* How to disable a block (without adding an event to the undo history). + +- How to use the field validators in Blockly's JSON API. +- How to create an extension that adds functionality to a block. +- How to create custom field validators. +- How to validate the entire block when any part of it changes. +- How to display a warning message on the block. +- How to disable a block (without adding an event to the undo history). You can find the code for the [completed custom block](https://github.com/RaspberryPiFoundation/blockly/docs/docs/codelabs/validation-and-warnings/complete-code/index.js) on GitHub. ### Resources + For more information related topics, check out the documentation: -* [Defining the toolbox](/guides/configure/web/toolboxes/toolbox) -* [Defining custom blocks](/guides/create-custom-blocks/overview) -* [Generating code from blocks](/guides/create-custom-blocks/code-generation/overview) -* [Creating extensions](/guides/create-custom-blocks/define/extensions#extensions) -* [Listening for change events](/guides/configure/web/events) -* [Custom validators](/guides/create-custom-blocks/fields/validators) -* [Custom block style guide](/guides/design/blocks) \ No newline at end of file + +- [Defining the toolbox](/guides/configure/web/toolboxes/toolbox) +- [Defining custom blocks](/guides/create-custom-blocks/overview) +- [Generating code from blocks](/guides/create-custom-blocks/code-generation/overview) +- [Creating extensions](/guides/create-custom-blocks/define/extensions#extensions) +- [Listening for change events](/guides/configure/web/events) +- [Custom validators](/guides/create-custom-blocks/fields/validators) +- [Custom block style guide](/guides/design/blocks) diff --git a/packages/docs/docs/codelabs/validation-and-warnings/validating-blocks.mdx b/packages/docs/docs/codelabs/validation-and-warnings/validating-blocks.mdx index 4c0cc6e17..c656d6778 100644 --- a/packages/docs/docs/codelabs/validation-and-warnings/validating-blocks.mdx +++ b/packages/docs/docs/codelabs/validation-and-warnings/validating-blocks.mdx @@ -6,9 +6,11 @@ description: How to validate the fields in a block. # Block validation and warnings ## 3. Validating blocks + When you're designing custom blocks, you may find that it doesn't make sense to use the block in certain ways. Depending on the intended purpose of your block, you may want to add constraints on the possible values that can be assigned to its fields, or on where it is used. ### Basic field constraints + Blockly generally allows users to enter negative values and decimal values for number fields, but for this custom block, let's make sure that only positive whole numbers are allowed. Add `'min': 0` and `'precision': 1` to the fields in the custom block definition so that they look like this: ```js @@ -35,6 +37,7 @@ Then reload `index.html`, drag the custom block to your workspace, and try enter If you want, you can also add a `'max'` constraint to a number field. ### Adding custom validation to a field + The built-in constraints are very convenient, but sometimes you might need to add custom constraints. For example, let's say that our custom block needs the first number of the range to be even, and the last number to be odd. We can easily implement the even constraint by setting the `'precision'` constraint of the `FIRST` field to `2`, but the odd constraint requires a custom validator. So far, we've been using Blockly's JSON API for defining custom blocks, but Blockly also has a JavaScript API with more advanced features, and one of those features is defining custom validators. Fortunately, we don't have to convert our entire custom block definition to the JavaScript API in order to take advantage of these advanced features, because Blockly has a system for adding JavaScript extensions to blocks that were defined with the JSON API. @@ -57,7 +60,7 @@ Blockly.common.defineBlocksWithJsonArray([ Then copy the following code to `index.js` underneath the custom block definition to register an implementation of that extension: ```js -Blockly.Extensions.register('list_range_validation', function() { +Blockly.Extensions.register('list_range_validation', function () { // Validation code to be added here... }); ``` @@ -65,27 +68,27 @@ Blockly.Extensions.register('list_range_validation', function() { The extension's function will be executed every time the custom block is instantiated, and the block instance itself will be implicitly available inside the function using JavaScript's `this` keyword. We can use it to access Blockly's JavaScript API for blocks, including validators. To add a validator on the `LAST` field, put the following code inside the extension function: ```js - this.getField('LAST').setValidator(function(newValue) { - // Validation of newValue for LAST field to be added here... - }); +this.getField('LAST').setValidator(function (newValue) { + // Validation of newValue for LAST field to be added here... +}); ``` Blockly validator functions are called whenever the user enters a new value for that field, and the new value is passed to the function as a parameter. The parameter might be an invalid value, but validator function can return a valid value to override the user input. To force the `LAST` field to be an odd number, put the following code inside the validator function: ```js - return Math.round((newValue - 1) / 2) * 2 + 1; +return Math.round((newValue - 1) / 2) * 2 + 1; ``` Afterwards, your extension code should look something like this: ```js -Blockly.Extensions.register('list_range_validation', function() { +Blockly.Extensions.register('list_range_validation', function () { // Add custom validation. - this.getField('LAST').setValidator(function(newValue) { + this.getField('LAST').setValidator(function (newValue) { // Force an odd number. return Math.round((newValue - 1) / 2) * 2 + 1; }); }); ``` -Reload `index.html` now, then drag the custom block to your workspace and try setting the `LAST` field to various values. Notice how it always turns into an odd number! \ No newline at end of file +Reload `index.html` now, then drag the custom block to your workspace and try setting the `LAST` field to various values. Notice how it always turns into an odd number! diff --git a/packages/docs/docs/guides/app-integration/attribution.mdx b/packages/docs/docs/guides/app-integration/attribution.mdx index 22d52504f..4f7df2e81 100644 --- a/packages/docs/docs/guides/app-integration/attribution.mdx +++ b/packages/docs/docs/guides/app-integration/attribution.mdx @@ -7,7 +7,10 @@ image: images/blockly_banner.png import Image from '@site/src/components/Image'; - + # Attribute Blockly @@ -19,8 +22,12 @@ product in their website, app, or product. This page describes the best practices for referring to Blockly and attributing it as well as appropriate uses of the logo. -Download all assets + + Download all assets + ## How to refer to Blockly @@ -29,7 +36,7 @@ uses of the logo. Upon first reference in a paragraph, use the primary one-line description: > Blockly is an open-source developer library from the Raspberry Pi Foundation, originally developed at Google. -It creates a visual programming interface that uses drag-and-drop blocks. +> It creates a visual programming interface that uses drag-and-drop blocks. When referring to Blockly in the context of another app which uses Blockly you should use the phrase "Built with Blockly". @@ -39,13 +46,18 @@ press interviews, the app, and on your website. ### Reference do's and don'ts -

Do — Call Blockly "beginner friendly" +

+ Do — Call Blockly "beginner friendly" instead of "kid friendly." Blockly is used for a variety of applications, not - all of which are kid focused.

+ all of which are kid focused. +

-

Don't — Refer to Blockly as a language +

+ Don't — Refer to Blockly as a language (for example, as a "block-based programming language"). Blockly is not a - language, it's a library that developers use to make a block-based visual programming interface.

+ language, it's a library that developers use to make a block-based visual + programming interface. +

## How to visually represent Blockly @@ -57,27 +69,59 @@ following logos, depending on background color: - - - + - - + +
- Built on Blockly white + + Built on Blockly white - Built on Blockly black + + Built on Blockly black
For light backgrounds with overlapping shapes or varied patterns, and for solid dark backgrounds (no shapes or patterns) with high contrast. + For light backgrounds with overlapping shapes or varied patterns, and + for solid dark backgrounds (no shapes or patterns) with high contrast. + For dark backgrounds with overlapping shapes or varied patterns.
PNG - SVGPNG - SVG + + PNG + + + SVG + + + + PNG + + + SVG + +
@@ -86,15 +130,28 @@ Please hyperlink the badge to Blockly's home page: [https://www.blockly.com](htt ### Badge sizing and spacing -
-
-

To ensure legibility, badges should not be used with a height smaller than 24px.

-

For lockups, provide at least x-height and width x1 white space around the - logo. Never crowd or overlap the logo with other elements.

+
+
+

+ To ensure legibility, badges should not be used with a height smaller than + 24px. +

+

+ For lockups, provide at least x-height and width x1 white space around the + logo. Never crowd or overlap the logo with other elements. +

-
- Blockly Badge - Blockly Badge +
+ Blockly Badge + Blockly Badge
@@ -109,66 +166,134 @@ element on your page. -
- Standard Blockly logo + + Standard Blockly logo

Standard lockup

The standard lockup can be used in slide decks and blog posts.

-

Whenever possible, the logo should be represented as a horizontal lockup with a full color logomark and neutral 700 (#5F6368) or solid white logotype.

- PNG - SVG +

+ Whenever possible, the logo should be represented as a horizontal lockup + with a full color logomark and neutral 700 (#5F6368) or solid white + logotype. +

+ + PNG + + + SVG +
- +
- - - - - - + + + - - - + + +
- Blockly vertical logo + + Blockly vertical logo - Blockly logomark + + Blockly logomark - Blockly knockout logo + + Blockly knockout logo
When there is limited horizontal space, a vertical lockup can be used with the full color logomark and neutral 700 (#5F6368) or solid white logotype.When there is limited vertical and horizontal space, the logomark can be used by itself without the logotype.When the color of the logomark has poor contrast with the background, a solid white knockout version can be used. + When there is limited horizontal space, a vertical lockup can be used + with the full color logomark and neutral 700 (#5F6368) or solid white + logotype. + + When there is limited vertical and horizontal space, the logomark can be + used by itself without the logotype. + + When the color of the logomark has poor contrast with the background, a + solid white knockout version can be used. +
PNG - SVGPNG - SVGPNG - SVG + + PNG + + + SVG + + + + PNG + + + SVG + + + + PNG + + + SVG + +
### Logo colours - +
- - - + + +
- - -
@@ -187,13 +312,17 @@ element on your page.
-
-
+
+

Sizing and spacing

-

To ensure legibility, the logo should not be used with a height - smaller than 24px.

-

For lockups, provide at least x-height x2 white space around the - logo. Never crowd or overlap the logo with other elements.

+

+ To ensure legibility, the logo should not be used with a height smaller + than 24px. +

+

+ For lockups, provide at least x-height x2 white space around the logo. + Never crowd or overlap the logo with other elements. +

Common errors

Do not...
    @@ -203,14 +332,23 @@ element on your page.
  • Rotate or flip in any direction
  • Alter proportions, positioning, or placement
  • Replace the logotype with a different typeface
  • -
  • Use the old Blockly logo (existing uses should be updated when convenient)
  • -
  • Use the logo on a poorly contrasting background (e.g. the knockout logo on a light gray background)
  • +
  • + Use the old Blockly logo (existing uses should be updated when + convenient) +
  • +
  • + Use the logo on a poorly contrasting background (e.g. the knockout logo + on a light gray background) +
  • Overlap or crowd the logo with other elements
  • Redraw the logo
-
- Height references for padding the logo +
+ Height references for padding the logo
diff --git a/packages/docs/docs/guides/app-integration/run-code.mdx b/packages/docs/docs/guides/app-integration/run-code.mdx index a13e75dd1..df06fc372 100644 --- a/packages/docs/docs/guides/app-integration/run-code.mdx +++ b/packages/docs/docs/guides/app-integration/run-code.mdx @@ -22,62 +22,46 @@ code generators with any of the following methods. - ```js - import {javascriptGenerator} from 'blockly/javascript'; - import {pythonGenerator} from 'blockly/python'; - import {phpGenerator} from 'blockly/php'; - import {luaGenerator} from 'blockly/lua'; - import {dartGenerator} from 'blockly/dart'; - - // Generate code for all the blocks in the workspace. - const jsCode = javascriptGenerator.workspaceToCode(workspace); - const pythonCode = pythonGenerator.workspaceToCode(workspace); - const phpCode = phpGenerator.workspaceToCode(workspace); - const luaCode = luaGenerator.workspaceToCode(workspace); - const dartCode = dartGenerator.workspaceToCode(workspace); - ``` + ```js import {javascriptGenerator} from 'blockly/javascript'; import{' '} + {pythonGenerator} from 'blockly/python'; import {phpGenerator} from + 'blockly/php'; import {luaGenerator} from 'blockly/lua'; import{' '} + {dartGenerator} from 'blockly/dart'; // Generate code for all the blocks in + the workspace. const jsCode = + javascriptGenerator.workspaceToCode(workspace); const pythonCode = + pythonGenerator.workspaceToCode(workspace); const phpCode = + phpGenerator.workspaceToCode(workspace); const luaCode = + luaGenerator.workspaceToCode(workspace); const dartCode = + dartGenerator.workspaceToCode(workspace); ``` - You must include the generator after you include Blockly. - - ```html - - - - - - - ``` - - ```js - // Generate code for all the blocks in the workspace. - const jsCode = javascript.javascriptGenerator.workspaceToCode(workspace); - const pythonCode = python.pythonGenerator.workspaceToCode(workspace); - const phpCode = php.phpGenerator.workspaceToCode(workspace); - const luaCode = lua.luaGenerator.workspaceToCode(workspace); - const dartCode = dart.dartGenerator.workspaceToCode(workspace); - ``` + You must include the generator after you include Blockly. ```html + + + + + + + ``` ```js // Generate code for all the blocks in the workspace. const jsCode + = javascript.javascriptGenerator.workspaceToCode(workspace); const + pythonCode = python.pythonGenerator.workspaceToCode(workspace); const + phpCode = php.phpGenerator.workspaceToCode(workspace); const luaCode = + lua.luaGenerator.workspaceToCode(workspace); const dartCode = + dart.dartGenerator.workspaceToCode(workspace); ``` - You must include the generator after you include Blockly. - - ```html - - - - - - - ``` - - ```js - // Generate code for all the blocks in the workspace. - const jsCode = javascript.javascriptGenerator.workspaceToCode(workspace); - const pythonCode = python.pythonGenerator.workspaceToCode(workspace); - const phpCode = php.phpGenerator.workspaceToCode(workspace); - const luaCode = lua.luaGenerator.workspaceToCode(workspace); - const dartCode = dart.dartGenerator.workspaceToCode(workspace); - ``` + You must include the generator after you include Blockly. ```html + + + + + + + ``` ```js // Generate code for all the blocks in the workspace. const jsCode + = javascript.javascriptGenerator.workspaceToCode(workspace); const + pythonCode = python.pythonGenerator.workspaceToCode(workspace); const + phpCode = php.phpGenerator.workspaceToCode(workspace); const luaCode = + lua.luaGenerator.workspaceToCode(workspace); const dartCode = + dart.dartGenerator.workspaceToCode(workspace); ``` ## Generate code @@ -121,7 +105,7 @@ start or after the end of the generated code. ```js let code = javascriptGenerator.workspaceToCode(workspace); // Add a preamble and a postscript to the code. -const preamble = 'import {MyLibrary} from \'/path/to/my/library\';\n' +const preamble = "import {MyLibrary} from '/path/to/my/library';\n"; const postscript = 'MyLibrary.myKickoffFunction();\n'; code = preamble + code + postscript; ``` diff --git a/packages/docs/docs/guides/app-integration/running-javascript.mdx b/packages/docs/docs/guides/app-integration/running-javascript.mdx index 91e997b9e..dfec8d90c 100644 --- a/packages/docs/docs/guides/app-integration/running-javascript.mdx +++ b/packages/docs/docs/guides/app-integration/running-javascript.mdx @@ -11,7 +11,7 @@ generally to run within a web page (possibly the same, or a embedded WebView). Like any generator, the first step is to include the JavaScript generator. ```js -import {javascriptGenerator} from 'blockly/javascript'; +import { javascriptGenerator } from 'blockly/javascript'; ``` To generate JavaScript from the workspace, call: @@ -73,7 +73,7 @@ highlighted. ## Infinite Loops Although the resulting code is guaranteed to be syntactically correct at all -times, it may contain infinite loops. Since solving the +times, it may contain infinite loops. Since solving the [Halting problem](https://en.wikipedia.org/wiki/Halting_problem) is beyond Blockly's scope (!) the best approach for dealing with these cases is to maintain a counter and decrement it every time an iteration is performed. @@ -83,7 +83,8 @@ example: ```js window.LoopTrap = 1000; -javascriptGenerator.INFINITE_LOOP_TRAP = 'if(--window.LoopTrap == 0) throw "Infinite loop.";\n'; +javascriptGenerator.INFINITE_LOOP_TRAP = + 'if(--window.LoopTrap == 0) throw "Infinite loop.";\n'; var code = javascriptGenerator.workspaceToCode(workspace); ``` @@ -99,18 +100,18 @@ If you are serious about running the user's blocks properly, then the [JS-Interpreter project](https://github.com/NeilFraser/JS-Interpreter) is the way to go. This project is separate from Blockly, but was specifically written for Blockly. - * Execute code at any speed. - * Pause/resume/step-through execution. - * Highlight blocks as they execute. - * Completely isolated from browser's JavaScript. +- Execute code at any speed. +- Pause/resume/step-through execution. +- Highlight blocks as they execute. +- Completely isolated from browser's JavaScript. ### Run the Interpreter First, download the JS-Interpreter from GitHub: -* [Download zip file](https://github.com/NeilFraser/JS-Interpreter/zipball/master) -* [Download tar file](https://github.com/NeilFraser/JS-Interpreter/tarball/master) -* [View on GitHub](https://github.com/NeilFraser/JS-Interpreter) +- [Download zip file](https://github.com/NeilFraser/JS-Interpreter/zipball/master) +- [Download tar file](https://github.com/NeilFraser/JS-Interpreter/tarball/master) +- [View on GitHub](https://github.com/NeilFraser/JS-Interpreter) Then add it to your page: @@ -155,18 +156,24 @@ But to start with, here is the API needed to support the alert and prompt blocks ```js function initApi(interpreter, globalObject) { // Add an API function for the alert() block. - var wrapper = function(text) { + var wrapper = function (text) { return alert(arguments.length ? text : ''); }; - interpreter.setProperty(globalObject, 'alert', - interpreter.createNativeFunction(wrapper)); + interpreter.setProperty( + globalObject, + 'alert', + interpreter.createNativeFunction(wrapper), + ); // Add an API function for the prompt() block. - wrapper = function(text) { + wrapper = function (text) { return prompt(text); }; - interpreter.setProperty(globalObject, 'prompt', - interpreter.createNativeFunction(wrapper)); + interpreter.setProperty( + globalObject, + 'prompt', + interpreter.createNativeFunction(wrapper), + ); } ``` @@ -189,11 +196,14 @@ argument, and register it as a native function. ```js function initApi(interpreter, globalObject) { // Add an API function for highlighting blocks. - var wrapper = function(id) { + var wrapper = function (id) { return workspace.highlightBlock(id); }; - interpreter.setProperty(globalObject, 'highlightBlock', - interpreter.createNativeFunction(wrapper)); + interpreter.setProperty( + globalObject, + 'highlightBlock', + interpreter.createNativeFunction(wrapper), + ); } ``` diff --git a/packages/docs/docs/guides/configure/web/appearance/colour-formats.mdx b/packages/docs/docs/guides/configure/web/appearance/colour-formats.mdx index 958bfec61..49025227d 100644 --- a/packages/docs/docs/guides/configure/web/appearance/colour-formats.mdx +++ b/packages/docs/docs/guides/configure/web/appearance/colour-formats.mdx @@ -24,8 +24,8 @@ The saturation and values can be adapted for each application by calling the following functions: ```js -Blockly.utils.colour.setHsvSaturation(0.45) // 0 (inclusive) to 1 (exclusive), defaulting to 0.45 -Blockly.utils.colour.setHsvValue(0.65) // 0 (inclusive) to 1 (exclusive), defaulting to 0.65 +Blockly.utils.colour.setHsvSaturation(0.45); // 0 (inclusive) to 1 (exclusive), defaulting to 0.45 +Blockly.utils.colour.setHsvValue(0.65); // 0 (inclusive) to 1 (exclusive), defaulting to 0.65 ``` Several colour pickers offer the HSV colour space, such as [HSV @@ -65,15 +65,15 @@ Blockly includes nine colour constants in the string table, corresponding to the toolbox categories, plus a distinct colour for dynamic variables: ```js -'%{BKY_LOGIC_HUE}' -'%{BKY_LOOPS_HUE}' -'%{BKY_MATH_HUE}' -'%{BKY_TEXTS_HUE}' -'%{BKY_LISTS_HUE}' -'%{BKY_COLOUR_HUE}' -'%{BKY_VARIABLES_HUE}' -'%{BKY_VARIABLES_DYNAMIC_HUE}' -'%{BKY_PROCEDURES_HUE}' +'%{BKY_LOGIC_HUE}'; +'%{BKY_LOOPS_HUE}'; +'%{BKY_MATH_HUE}'; +'%{BKY_TEXTS_HUE}'; +'%{BKY_LISTS_HUE}'; +'%{BKY_COLOUR_HUE}'; +'%{BKY_VARIABLES_HUE}'; +'%{BKY_VARIABLES_DYNAMIC_HUE}'; +'%{BKY_PROCEDURES_HUE}'; ``` These string values can be used in both the JSON definitions and diff --git a/packages/docs/docs/guides/configure/web/appearance/css.mdx b/packages/docs/docs/guides/configure/web/appearance/css.mdx index 1c5feaa1d..e729f134d 100644 --- a/packages/docs/docs/guides/configure/web/appearance/css.mdx +++ b/packages/docs/docs/guides/configure/web/appearance/css.mdx @@ -13,9 +13,9 @@ are labeled with CSS classes that identify what they represent (e.g. You can use CSS to style your application: -* Override Blockly's CSS rules with your own rules. -* Add your own CSS classes to Blockly components for additional specificity. -* Use CSS classes and rules to style custom components. +- Override Blockly's CSS rules with your own rules. +- Add your own CSS classes to Blockly components for additional specificity. +- Use CSS classes and rules to style custom components. For a practical introduction to using CSS in blockly, see the [Use CSS in Blockly](/codelabs/css/codelab-overview/index.html) @@ -33,22 +33,22 @@ provides finer-grained control than type (element) selectors. Blockly uses CSS classes to provide the following kinds of information about the HTML and SVG elements it uses. -* **Type.** Most Blockly CSS classes identify what an element represents. For - example, the root element of a block is labeled `blocklyBlock`. Some - elements are labeled with multiple classes, each more specific than the - last. For example, the root element of a text input field is labeled - `blocklyField`, `blocklyInputField`, and `blocklyTextInputField`. Type - classes remain the same for the life of a component. +- **Type.** Most Blockly CSS classes identify what an element represents. For + example, the root element of a block is labeled `blocklyBlock`. Some + elements are labeled with multiple classes, each more specific than the + last. For example, the root element of a text input field is labeled + `blocklyField`, `blocklyInputField`, and `blocklyTextInputField`. Type + classes remain the same for the life of a component. -* **State.** Blockly also uses CSS classes to specify the state of a - component. For example, when the cursor is on a text input field, its root - element is labeled with the `blocklyEditing` class. When the cursor is moved - away, this class is removed. +- **State.** Blockly also uses CSS classes to specify the state of a + component. For example, when the cursor is on a text input field, its root + element is labeled with the `blocklyEditing` class. When the cursor is moved + away, this class is removed. -* **Additional information.** Blockly uses a few CSS classes to provide - additional information. For example, the injection `
` has classes that - provide the name of the workspace's current renderer and theme. These - classes generally remain the same for the life of the application. +- **Additional information.** Blockly uses a few CSS classes to provide + additional information. For example, the injection `
` has classes that + provide the name of the workspace's current renderer and theme. These + classes generally remain the same for the life of the application. The easiest way to discover what CSS classes Blockly uses is to open your browser's developer tools and inspect the elements used by your application. @@ -80,20 +80,22 @@ To add CSS classes to a custom block, pass a string or array of strings to the `classes` key. ```js -Blockly.common.defineBlocksWithJsonArray([{ - "type": "string_length", - "message0": 'length of %1', - "args0": [ - { - "type": "input_value", - "name": "VALUE", - "check": "String", - } - ], - "classes": "myStringLengthBlock", - "output": "Number", - "colour": 160, -}]); +Blockly.common.defineBlocksWithJsonArray([ + { + type: 'string_length', + message0: 'length of %1', + args0: [ + { + type: 'input_value', + name: 'VALUE', + check: 'String', + }, + ], + classes: 'myStringLengthBlock', + output: 'Number', + colour: 160, + }, +]); ``` You can also add or remove a CSS class from a block's `` element by calling @@ -110,42 +112,44 @@ name to the label's constructor. When constructing a custom component, use one of the following methods to add custom CSS classes: -* If your component is a subclass of `Field` or `Icon`, override the - `initView` method. For example: +- If your component is a subclass of `Field` or `Icon`, override the + `initView` method. For example: - ```js - class MyCustomField extends Blockly.FieldTextInput { - ... + ```js + class MyCustomField extends Blockly.FieldTextInput { + ... - initView() { - super.initView(); + initView() { + super.initView(); - // Add custom CSS class so we can style the field. - if (this.fieldGroup_) { - Blockly.utils.dom.addClass(this.fieldGroup_, 'myCustomField'); - } + // Add custom CSS class so we can style the field. + if (this.fieldGroup_) { + Blockly.utils.dom.addClass(this.fieldGroup_, 'myCustomField'); } } - ``` + } + ``` - For more information, see [Customizing fields with - CSS](/guides/create-custom-blocks/fields/customizing-fields/creating#customizing-with-css) - or [Create the icon's - view](/guides/create-custom-blocks/icons/creating-custom-icons/basic-implementation#create-the-icons-view). + For more information, see [Customizing fields with + CSS](/guides/create-custom-blocks/fields/customizing-fields/creating#customizing-with-css) + or [Create the icon's + view](/guides/create-custom-blocks/icons/creating-custom-icons/basic-implementation#create-the-icons-view). -* When constructing an SVG element, pass your class to - `Blockly.utils.dom.createSvgElement`: +- When constructing an SVG element, pass your class to + `Blockly.utils.dom.createSvgElement`: - ```js - this.svgRoot = Blockly.utils.dom.createSvgElement(Svg.G, {'class': 'myCustomComponent'}); - ``` + ```js + this.svgRoot = Blockly.utils.dom.createSvgElement(Svg.G, { + class: 'myCustomComponent', + }); + ``` -* When constructing an HTML element, use `Blockly.utils.dom.addClass`: +- When constructing an HTML element, use `Blockly.utils.dom.addClass`: - ```js - const myDiv = document.createElement('div'); - Blockly.utils.dom.addClass(myDiv, 'myInformation'); - ``` + ```js + const myDiv = document.createElement('div'); + Blockly.utils.dom.addClass(myDiv, 'myInformation'); + ``` To add or remove classes after construction, use `Blockly.utils.dom.addClass` or `Blockly.utils.dom.removeClass`. @@ -193,7 +197,9 @@ attributes**) or in CSS rules. Thus, all of the following do the same thing. ```css /* External CSS file.*/ -circle {fill:red;} +circle { + fill: red; +} ``` ```svg @@ -204,14 +210,14 @@ circle {fill:red;} The list of SVG styling properties is related to but different from the list of CSS properties: -* **Same concept, same name.** For example, both SVG and CSS use `direction` - to specify whether text is LTR or RTL. -* **Same concept, different name.** For example, SVG uses `fill` to specify - fill color; CSS uses `background-color`. -* **CSS only.** CSS has many properties that are not in SVG, such as `margin` - and `padding`. -* **SVG only.** SVG has a few properties that are not in CSS, such as `x` and - `y`. +- **Same concept, same name.** For example, both SVG and CSS use `direction` + to specify whether text is LTR or RTL. +- **Same concept, different name.** For example, SVG uses `fill` to specify + fill color; CSS uses `background-color`. +- **CSS only.** CSS has many properties that are not in SVG, such as `margin` + and `padding`. +- **SVG only.** SVG has a few properties that are not in CSS, such as `x` and + `y`. Thus, if you're styling an SVG element, use [SVG styling properties](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute#presentation_attributes). @@ -237,25 +243,24 @@ these steps and stop when only one rule remains: have an `!important` annotation. 1. Choose the rules with the highest [specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_cascade/Specificity). - - * [SVG presentation attributes](#svg-style) have a specificity of zero. - * Rules in a `