workspaceToCode 管線、forBlock、value/statement 生成器
Blockly 不能「直接執行」積木——它把積木轉成文字程式碼字串,再由你的應用決定如何執行(eval、送後端、燒進硬體)。整條管線:
// 一次生成整個工作區的程式碼
const code = Blockly.JavaScript.workspaceToCode(workspace);
// 只生成某一塊積木(與其內嵌積木)
const block = workspace.getBlockById('abc123');
const code2 = Blockly.JavaScript.blockToCode(block);
| 積木類型 | 有無 output 連接 | 對應語言概念 | 生成器回傳 |
|---|---|---|---|
| Value block | 有(回傳值) | 表達式(expression) | [code, order] 陣列 |
| Statement block | 無(執行指令) | 陳述句(statement) | code 字串 |
generator.valueToCode(block, 'NAME', order);statement 輸入用 generator.statementToCode(block, 'NAME')。[code, order];statement block 回傳 code。import {javascriptGenerator, Order} from 'blockly/javascript';
// 定義積木:LEFT (value) OPERATOR (dropdown) RIGHT (number)
Blockly.common.defineBlocksWithJsonArray([{
type: 'custom_compare',
message0: '%1 %2 %3',
args0: [
{type: 'input_value', name: 'LEFT', check: 'Number'},
{type: 'field_dropdown', name: 'OPERATOR',
options: [['=', 'EQUALS'], ['<', 'LESS'], ['>', 'GREATER']]},
{type: 'input_value', name: 'RIGHT', check: 'Number'}
],
output: 'Boolean',
colour: 210
}]);
// 生成器:把 dropdown 的語言中立值轉成 JS 運算子
javascriptGenerator.forBlock['custom_compare'] = function(block, generator) {
const OPERATORS = {EQUALS: '==', LESS: '<', GREATER: '>'};
const operator = OPERATORS[block.getFieldValue('OPERATOR')];
const order = operator === '==' ? Order.EQUALITY : Order.RELATIONAL;
const left = generator.valueToCode(block, 'LEFT', order);
const right = generator.valueToCode(block, 'RIGHT', order);
const code = left + ' ' + operator + ' ' + right;
return [code, order]; // ← value block 必須回傳 [code, order]
};
import {javascriptGenerator, Order} from 'blockly/javascript';
Blockly.common.defineBlocksWithJsonArray([{
type: 'custom_if',
message0: 'if %1 (negate: %2) then %3',
args0: [
{type: 'input_value', name: 'CONDITION', check: 'Boolean'},
{type: 'field_checkbox', name: 'NOT', checked: false},
{type: 'input_statement', name: 'THEN'}
],
previousStatement: null,
nextStatement: null,
colour: 120
}]);
javascriptGenerator.forBlock['custom_if'] = function(block, generator) {
const negate = block.getFieldValue('NOT') === 'TRUE' ? '!' : '';
const order = negate ? Order.LOGICAL_NOT : Order.NONE;
const condition = generator.valueToCode(block, 'CONDITION', order) || 'false';
const statements = generator.statementToCode(block, 'THEN');
const code = 'if (' + negate + condition + ') {\n' + statements + '}\n';
return code; // ← statement block 只回傳字串
};
generator.statementToCode(block, 'THEN') 不只呼叫內嵌積木的生成器,還會自動縮排每一行、並串起「next」連接的後續積木——你不需要自己處理縮排。
// 使用者拼:custom_if → (custom_compare → 內嵌 show_number)
if (x < 10) {
console.log(x);
}