6

I know that I can use

Blockly.JavaScript['my_code'] = function() {  ... }

But how can I add another language support like JSON? I tried ..

Blockly.Json['my_code'] = function() {  ... }

It fails when I try to recover

Blockly.Json.workspaceToCode(this.workspace)

workspaceToCode is not a function.

I need to add a new language to Blockly

I will not display this new language (JSON), it will just be used to send instructions to the robots.


I try to

Blockly.Json = new Blockly.Generator('Json');
Blockly.Json['my_code'] = function() {  ... }

But an error occurs in

Blockly.Json.workspaceToCode(this.workspace)

Error ..

Uncaught TypeError: this.init is not a function
    at js.ou3v.module.exports.Blockly.Generator.workspaceToCode
Kresten
  • 100
  • 2
  • 9
ridermansb
  • 10,779
  • 24
  • 115
  • 226

2 Answers2

8

Creating a new language generator for Blockly is a fairly large undertaking, and with that in mind the documentation doesn't seem to offer much in terms of help with creating one.

From my experience the best way to build a generator is to take a look at the existing ones in generators/, I have used the JavaScript generator as a template for a project of mine where I wanted to generate C++ code.

It's also worth noting that the Block Factory generates JSON for use in other Blockly applications, however when I took a look at the code for that there isn't an actual generator defined for it.

I think the error you're getting is caused because Blockly.Json doesn't have an init function. This is something defined in the existing generator files, for example, from the JavaScript generator:

/**
* Initialise the database of variable names.
* @param {!Blockly.Workspace} workspace Workspace to generate code from.
*/
Blockly.JavaScript.init = function(workspace) {
  ....
};

With this in mind, your function would look like:

/**
* Initialise the database of variable names.
* @param {!Blockly.Workspace} workspace Workspace to generate code from.
*/
Blockly.Json.init = function(workspace) {
 .....
};

There are other functions that the generator file contains, but taking a look at the existing code and adapting it for your needs should help you along the way.

Alex Dawson
  • 96
  • 2
  • 6
  • The BlockDefinitionExtractor linked to here, if I understand correctly, creates a blockly DOM for the preview. An even better fit for JSON generation is [BlockFactory.updateLanguage](https://github.com/google/blockly/blob/master/demos/blockfactory/factory.js#L125) and the call tree beyond that, particularly [Factoryutils.formatJson_](https://github.com/google/blockly/blob/master/demos/blockfactory/factory_utils.js#L180) – Silly Freak Mar 23 '20 at 11:02
  • 1
    My links to the block factory are probably a little misleading. I wanted to let OP know of an avenue that might help, but the tool doesn't actually use the Blockly library to create the output (although it does still create both block output, and JSON, as well as a a code generator stub for a language of choice). It was my understanding that OP wanted Blockly with a full custom generator for JSON syntax. For reference, [this](https://github.com/dawsonalex/arbi/blob/master/js/blockly/generators/arduino.js) is the C++ generator I was working on at the time. – Alex Dawson Mar 23 '20 at 11:54
0

Here's the minimal viable example I came up with:

I have defined a little custom block print:

Blockly.defineBlocksWithJsonArray([
  {
    type: 'print',
    message0: 'print %1',
    args0: [
      { type: 'field_input', name: 'EMOJI_CODE' }
    ]
  }
]);

Then I initialise the Blockly editor with this new block:

const ws = Blockly.inject('ide', {
  toolbox: {
    kind: 'flyoutToolbox',
    contents: [
      { kind: 'block', type: 'print' }
    ]
  }
});

Then I need to define what the block will generate.

In this example we convert strings to emojis e.g. :-) becomes . I define a new language and what the print block should do:

const emojiLang = new Blockly.Generator('EmojiLang');

emojiLang['print'] = function (block) {
  const code = block.getFieldValue('EMOJI_CODE');
  if (!code) return 'waiting…';
  if (code == ':-)') return '';
  if (code == ':-(') return '';
  if (code == ':-/') return '';
  return '(unknown)';
};

Finally I listen for changes in the editor to translate blocks into emoji:

ws.addChangeListener(function () {
  document.getElementById('out').innerHTML =
    emojiLang.workspaceToCode(ws);
});

Full Working Example

const emojiLang = new Blockly.Generator('EmojiLang');

emojiLang['print'] = function (block) {
  const code = block.getFieldValue('EMOJI_CODE');
  if (!code) return 'waiting…';
  if (code == ':-)') return '';
  if (code == ':-(') return '';
  if (code == ':-/') return '';
  return '(unknown)';
};

Blockly.defineBlocksWithJsonArray([
  {
    type: 'print',
    message0: 'print %1',
    args0: [
      { type: 'field_input', name: 'EMOJI_CODE' }
    ]
  }
]);

const ws = Blockly.inject('ide', {
  toolbox: {
    kind: 'flyoutToolbox',
    contents: [
      { kind: 'block', type: 'print' }
    ]
  }
});

ws.addChangeListener(function () {
  document.getElementById('out').innerHTML =
    emojiLang.workspaceToCode(ws);
});
<script src="https://unpkg.com/blockly/blockly.min.js"></script>

Emoji: <span id="out"></span>
<div id="ide" style="height:200px;width:400px;"></div>
customcommander
  • 17,580
  • 5
  • 58
  • 84