Skip to main content

Getting started with Blockly

8. Generate JavaScript code

Blockly can convert blocks into strings of code in a process called code generation. Blocks on their own don't do anything, but we can make them generate code that does, and then execute that code. The code execution step is application-specific and therefore outside of Blockly's scope. It is up to you to determine if, when, and how to execute the strings of code that Blockly generates.

Code generation and execution is how you get from a list of blocks to a program that does something. But before you determine how your application will execute code, you first need to tell Blockly how to generate the code.

In this step, you'll set up code generation for the add_text block.

The language generator

A language generator defines the rules for generating a specific language (such as indentation).

By default, Blockly can generate code from blocks for five languages: Dart, JavaScript, Lua, PHP, and Python. You can also create a custom language generator to generate code in a different language, which the custom generator codelab describes.

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.

Find the javascript.js file in src/generators/. This is where you'll write the block generator function for the add_text block..

The block generator for add_text will first recursively generate the code for the input TEXT. Then, it provides the function that will add text to the output area using generator.provideFunction_. provideFunction_ is an advanced code generation feature that allows you to specify a function that will be defined just once, even if the block is used multiple times.

Finally, the block generator creates the function call that will be generated for this block.

Add the following code to src/generators/javascript.js:

import {Order} from 'blockly/javascript';

export const forBlock = Object.create(null);

forBlock['add_text'] = function (block, generator) {
// Generate the code for the input block.
const text = generator.valueToCode(block, 'TEXT', Order.NONE) || "''";
// Create the function for this block.
const addText = generator.provideFunction_(
'addText',
`function ${generator.FUNCTION_NAME_PLACEHOLDER_}(text) {

// Add text to the output area.
const outputDiv = document.getElementById('output');
const textEl = document.createElement('p');
textEl.innerText = text;
outputDiv.appendChild(textEl);
}`,
);
// Generate the function call for this block.
const code = `${addText}(${text});\n`;
return code;
};

With this translation function, the add_text block with a string input of "Hello, World!":

translates into the JavaScript code:

function addText(text) {
// Add text to the output area.
const outputDiv = document.getElementById('output');
const textEl = document.createElement('p');
textEl.innerText = text;
outputDiv.appendChild(textEl);
}

addText('Hello, World!');

Register the block code generator

Finally, you need to register the block generator for add_text with Blockly's JavaScript generator.

Add the following imports to the index.js file:

import {forBlock} from './generators/javascript';
import {javascriptGenerator} from 'blockly/javascript';

Note that the index.js file should now have 7 total import statements:

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 './index.css';

Now you can add the forBlock for add_text into Blockly's javascriptGenerator so that Blockly can generate the code for your block. The following Object.assign statement registers your block generator by adding it to the forBlock object of the javascriptGenerator. Adding this assignment means that add_text is part of the list of blocks that javascriptGenerator knows how to generate code for.

Put the following line of code into index.js, just below Blockly.common.defineBlocks(blocks);

Object.assign(javascriptGenerator.forBlock, forBlock);

For more information on block generators, read the generating code page on the developer site.