├── .gitignore ├── screenshot.png ├── src ├── consts.js ├── blockly.js ├── index.js ├── utils │ ├── bi_blockly │ │ ├── blocks │ │ │ ├── bi_blockly_overload.js │ │ │ └── bi_blockly.js │ │ └── generators │ │ │ └── javascript │ │ │ └── bi_blockly.js │ └── js2blocks.js ├── commands.js └── blocklyEditor.js ├── package.json ├── LICENSE ├── index.html ├── README.md └── dist └── grapesjs-blockly.min.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | private/ 3 | /locale 4 | node_modules/ 5 | *.log 6 | _index.html -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ju99ernaut/grapesjs-blockly/HEAD/screenshot.png -------------------------------------------------------------------------------- /src/consts.js: -------------------------------------------------------------------------------- 1 | export const 2 | cmdId = 'blockly-script', 3 | keyBlocklyXml = 'blockly-xml'; -------------------------------------------------------------------------------- /src/blockly.js: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Juan Carlos Orozco 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // https://github.com/JC-Orozco/BlocksIDE 4 | 5 | let Blockly; 6 | if (typeof window !== 'undefined') { 7 | Blockly = require('../node_modules/node-blockly/browser-raw.js'); 8 | } else { 9 | Blockly = require('../node_modules/node-blockly/_blockly.js'); 10 | } 11 | const biBlocks = require('./utils/bi_blockly/blocks/bi_blockly.js') 12 | biBlocks(Blockly); 13 | 14 | const blocklyJS = require('node-blockly/lib/javascript_compressed'); 15 | blocklyJS(Blockly); 16 | 17 | const biBlocksJS = require('./utils/bi_blockly/generators/javascript/bi_blockly.js') 18 | biBlocksJS(Blockly); 19 | 20 | console.log("Blockly"); 21 | 22 | module.exports = Blockly; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "grapesjs-blockly", 3 | "version": "1.0.2", 4 | "description": "Grapesjs Blockly", 5 | "main": "dist/grapesjs-blockly.min.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/Ju99ernaut/grapesjs-blockly.git" 9 | }, 10 | "scripts": { 11 | "start": "grapesjs-cli serve", 12 | "build": "grapesjs-cli build", 13 | "build:css": "node-sass src/styles.scss dist/grapesjs-indexeddb-ui.min.css --output-style compressed", 14 | "bump": "npm version patch -m 'Bump v%s'" 15 | }, 16 | "keywords": [ 17 | "grapesjs", 18 | "plugin" 19 | ], 20 | "devDependencies": { 21 | "grapesjs-cli": "^1.0.12", 22 | "node-sass": "^4.14.1" 23 | }, 24 | "license": "MIT", 25 | "dependencies": { 26 | "acorn": "^7.4.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License Copyright (c) 2020-current Grapesjs Blockly 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Grapesjs Blockly 7 | 8 | 9 | 10 | 11 | 12 | 13 | 20 | 21 | 22 | 23 | 24 |
25 |
26 | This is a demo content from _index.html. You can use this template file for 27 | development purpose. It won't be stored in your git repository 28 |
29 |
30 | 31 | 32 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import biBlocks from './utils/bi_blockly/blocks/bi_blockly'; 2 | import biBlocksJS from './utils/bi_blockly/generators/javascript/bi_blockly'; 3 | import commands from './commands'; 4 | 5 | export default (editor, opts = {}) => { 6 | const options = { 7 | ...{ 8 | // Blockly options 9 | blocklyOptions: { 10 | toolbox: '', 11 | toolboxPush: '', 12 | workspaceOptions: {} 13 | }, 14 | 15 | // Starter xml 16 | starter: 'letelthis', 17 | 18 | toolbarIcon: '', 19 | 20 | // Component types to allow script editing 21 | // Avoid components with predefined scripts 22 | blocklyTypesSupport: ['default', 'wrapper', 'text', 'textnode', 'image', 'video', 'svg'], 23 | 24 | // Object to extend the default component's toolbar button for the code, eg. `{ label: '', attributes: { title: 'Open blockly editor' } }` 25 | // Pass a falsy value to avoid adding the button 26 | toolbarBtnBlockly: {}, 27 | 28 | // On run success 29 | onRun: () => console.log('valid syntax'), 30 | 31 | // Logic when there is an error on run 32 | onError: err => console.log('error', err), 33 | 34 | // Title for the blockly modal 35 | modalTitle: 'Blockly', 36 | 37 | // Additional options for the code viewer, eg. `{ theme: 'hopscotch', readOnly: 0 }` 38 | codeViewOptions: {}, 39 | 40 | // Label for the default save button 41 | buttonLabel: 'Save', 42 | 43 | // Object to extend the default blockly command. 44 | // Check the source to see all available methods 45 | commandBlocklyScript: {}, 46 | }, 47 | ...opts 48 | }; 49 | 50 | 51 | 52 | if (!Blockly) { 53 | throw new Error('Blockly instance not found'); 54 | } 55 | 56 | // set blockly globally 57 | biBlocks(Blockly); 58 | 59 | biBlocksJS(Blockly); 60 | 61 | // load commands 62 | commands(editor, options); 63 | }; -------------------------------------------------------------------------------- /src/utils/bi_blockly/blocks/bi_blockly_overload.js: -------------------------------------------------------------------------------- 1 | // BlocksIDE is a project to create a complete js Blocks Development Platform 2 | // 3 | // Copyright 2016 Juan Carlos Orozco 4 | // 5 | // BlocksIDE was written by Juan Carlos Orozco and released under an Apache version 2 license. 6 | // 7 | // Git repositories for BlocksIDE are available at 8 | // 9 | // https://github.com/JC-Orozco/BlocksIDE 10 | // 11 | // Licensed under the Apache License, Version 2.0 (the "License"); 12 | // you may not use this file except in compliance with the License. 13 | // You may obtain a copy of the License at 14 | // 15 | // http://www.apache.org/licenses/LICENSE-2.0 16 | // 17 | // Unless required by applicable law or agreed to in writing, software 18 | // distributed under the License is distributed on an "AS IS" BASIS, 19 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | // See the License for the specific language governing permissions and 21 | // limitations under the License. 22 | 23 | function init_blockly_jc(){ 24 | // Blockly.Blockly.prototype.setXXX = Blockly.Blockly.prototype.setXXX_jc 25 | } 26 | 27 | Blockly.Blocks['math_arithmetic'] = { 28 | /** 29 | * Block for basic arithmetic operator. 30 | * @this Blockly.Block 31 | */ 32 | init: function() { 33 | var OPERATORS = 34 | [[Blockly.Msg.MATH_ADDITION_SYMBOL, 'ADD'], 35 | [Blockly.Msg.MATH_SUBTRACTION_SYMBOL, 'MINUS'], 36 | [Blockly.Msg.MATH_MULTIPLICATION_SYMBOL, 'MULTIPLY'], 37 | [Blockly.Msg.MATH_DIVISION_SYMBOL, 'DIVIDE'], 38 | [Blockly.Msg.MATH_POWER_SYMBOL, 'POWER']]; 39 | this.setHelpUrl(Blockly.Msg.MATH_ARITHMETIC_HELPURL); 40 | this.setColour(Blockly.Blocks.math.HUE); 41 | this.setOutput(true, null); // 'Number'); 42 | this.appendValueInput('A') 43 | .setCheck(null); // 'Number'); 44 | this.appendValueInput('B') 45 | .setCheck(null) // 'Number') 46 | .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP'); 47 | this.setInputsInline(true); 48 | // Assign 'this' to a variable for use in the tooltip closure below. 49 | var thisBlock = this; 50 | this.setTooltip(function() { 51 | var mode = thisBlock.getFieldValue('OP'); 52 | var TOOLTIPS = { 53 | 'ADD': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD, 54 | 'MINUS': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS, 55 | 'MULTIPLY': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY, 56 | 'DIVIDE': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE, 57 | 'POWER': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER 58 | }; 59 | return TOOLTIPS[mode]; 60 | }); 61 | } 62 | }; 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Grapesjs Blockly 2 | 3 | Attach code generated from `google blockly` to a component 4 | 5 | >Requires `Blockly` and `@blockly/block-plus-minus` plugin recommended. Try adding after all components 6 | 7 |

8 | screenshot.png 9 |

10 | 11 | [DEMO](https://codepen.io/ju99ernaut/pen/ExKOxKg) 12 | 13 | ### HTML 14 | ```html 15 | 16 | 17 | 18 | 19 | 20 |
21 | ``` 22 | 23 | ### JS 24 | ```js 25 | const editor = grapesjs.init({ 26 | container: '#gjs', 27 | height: '100%', 28 | fromElement: true, 29 | storageManager: false, 30 | plugins: ['grapesjs-blockly'], 31 | }); 32 | ``` 33 | 34 | ### CSS 35 | ```css 36 | body, html { 37 | margin: 0; 38 | height: 100%; 39 | } 40 | ``` 41 | 42 | 43 | ## Summary 44 | 45 | * Plugin name: `grapesjs-blockly` 46 | * Commands 47 | * `blockly-script` 48 | 49 | 50 | ## Options 51 | 52 | | Option | Description | Default | 53 | |-|-|- 54 | | `blocklyOptions` | Options to pass to blockly on init, `toolbox` defines blockly toolbox, `workspaceOptions` defines blockly injection options, `toolbox` will overwrite the default and `toolboxPush` will add to default | `{toolbox: '', toolboxPush: '', workspaceOptions: {}}` | 55 | | `starter` | Canvas starter blocks, defaulf setting generates `let el = this` | `...` | 56 | | `toolbarIcon` | Toolbar icon for opening blockly modal | `` | 57 | | `blocklyTypesSupport` | Component types to allow script editing from blockly, `avoid components with predefined scripts or scripts set elsewhere` | `['default', 'wrapper', 'text', 'textnode', 'image', 'video', 'svg']` | 58 | | `toolbarBtnBlockly` | Options to pass when extending toolbar | `{}` | 59 | | `onRun` | Logic to run if debug is successful | `() => console.log('valid syntax')` | 60 | | `onError` | Logic to run if debug finds errors | `err => console.log('error:',err)` | 61 | | `modalTitle` | Title for blockly modal | `Blockly` | 62 | | `codeViewOptions` | Additional options for the code viewer | `{}` | 63 | | `buttonLabel` | Label for the default save button | `save` | 64 | | `commandBlocklyScript` | Object to extend the default `blockly-script` command | `{}` | 65 | 66 | 67 | 68 | ## Download 69 | 70 | * CDN 71 | * `https://unpkg.com/grapesjs-blockly` 72 | * NPM 73 | * `npm i grapesjs-blockly` 74 | * GIT 75 | * `git clone https://github.com/Ju99ernaut/grapesjs-blockly.git` 76 | 77 | 78 | 79 | ## Usage 80 | 81 | Directly in the browser 82 | ```html 83 | 84 | 85 | 86 | 87 | 88 |
89 | 90 | 100 | ``` 101 | 102 | Modern javascript 103 | ```js 104 | import grapesjs from 'grapesjs'; 105 | import plugin from 'grapesjs-blockly'; 106 | import Blockly from 'blockly'; 107 | import 'grapesjs/dist/css/grapes.min.css'; 108 | 109 | const editor = grapesjs.init({ 110 | container : '#gjs', 111 | // ... 112 | plugins: [plugin], 113 | pluginsOpts: { 114 | [plugin]: { /* options */ } 115 | } 116 | // or 117 | plugins: [ 118 | editor => plugin(editor, { /* options */ }), 119 | ], 120 | }); 121 | ``` 122 | 123 | 124 | 125 | ## Development 126 | 127 | Clone the repository 128 | 129 | ```sh 130 | $ git clone https://github.com/Ju99ernaut/grapesjs-blockly.git 131 | $ cd grapesjs-blockly 132 | ``` 133 | 134 | Install dependencies 135 | 136 | ```sh 137 | $ npm i 138 | ``` 139 | 140 | Start the dev server 141 | 142 | ```sh 143 | $ npm start 144 | ``` 145 | 146 | Build the source 147 | 148 | ```sh 149 | $ npm run build 150 | ``` 151 | 152 | 153 | 154 | ## License 155 | 156 | MIT 157 | -------------------------------------------------------------------------------- /src/commands.js: -------------------------------------------------------------------------------- 1 | import { 2 | cmdId, 3 | keyBlocklyXml 4 | } from './consts'; 5 | //import { 6 | // parseCode 7 | //} from './utils/js2blocks'; 8 | import BlocklyEditor from './blocklyEditor'; 9 | 10 | export default (editor, opts = {}) => { 11 | const cm = editor.Commands; 12 | const md = editor.Modal; 13 | const domc = editor.Components; 14 | const { 15 | modalTitle, 16 | codeViewOptions, 17 | commandBlocklyScript, 18 | blocklyOptions, 19 | blocklyTypesSupport, 20 | toolbarIcon, 21 | onRun, 22 | onError, 23 | starter 24 | } = opts; 25 | 26 | let blocklyEditor = null; 27 | let content = null; 28 | 29 | const appendToContent = (target, content) => { 30 | if (content instanceof HTMLElement) { 31 | target.appendChild(content); 32 | } else if (content) { 33 | target.insertAdjacentHTML('beforeend', content); 34 | } 35 | }; 36 | 37 | // Add icons to specified component types 38 | blocklyTypesSupport && blocklyTypesSupport.forEach(type => { 39 | const typeOpt = domc.getType(type).model; 40 | domc.addType(type, { 41 | model: { 42 | initToolbar() { 43 | typeOpt.prototype.initToolbar.apply(this, arguments); 44 | const tb = this.get('toolbar'); 45 | const tbExists = tb.some(item => item.command === cmdId); 46 | 47 | if (!tbExists) { 48 | tb.unshift({ 49 | command: cmdId, 50 | label: toolbarIcon, 51 | ...opts.toolbarBtnBlockly 52 | }); 53 | this.set('toolbar', tb); 54 | } 55 | } 56 | } 57 | }); 58 | }) 59 | 60 | // Add the blockly command 61 | cm.add(cmdId, { 62 | keyBlocklyXml, 63 | 64 | run(editor, sender, opts = {}) { 65 | this.editor = editor; 66 | this.options = opts; 67 | this.target = opts.target || editor.getSelected(); 68 | const target = this.target; 69 | 70 | if (target) this.showCustomCode(target); 71 | }, 72 | 73 | stop(editor) { 74 | //blocklyEditor && blocklyEditor.hide(); 75 | blocklyEditor.workspace.clear(); 76 | md.close(); 77 | }, 78 | 79 | /** 80 | * Method which tells how to show the custom code 81 | * @param {Component} target 82 | */ 83 | showCustomCode(target) { 84 | const { 85 | editor, 86 | options 87 | } = this; 88 | const title = options.title || modalTitle; 89 | if (!content) content = this.getContent(); 90 | const code = target.getScriptString(); 91 | md.open({ 92 | title, 93 | content 94 | }).getModel().once('change:open', () => editor.stopCommand(this.id)); 95 | //? mount code editors 96 | if (!blocklyEditor) { 97 | blocklyEditor = new BlocklyEditor(content.querySelector('#blockly'), blocklyOptions); 98 | blocklyEditor.workspace.addChangeListener(() => this.updateWorkspace()); 99 | } 100 | const xml = target.get(keyBlocklyXml) || starter; //(code && parseCode(code)) || starter; 101 | Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(xml), blocklyEditor.workspace); 102 | }, 103 | 104 | /** 105 | * Custom pre-content. Can be a simple string or an HTMLElement 106 | */ 107 | getPreContent() {}, 108 | 109 | /** 110 | * Custom post-content. Can be a simple string or an HTMLElement 111 | */ 112 | getPostContent() { 113 | const postContent = document.createElement('div'); 114 | postContent.id = "code-viewer"; 115 | const codeViewer = this.getCodeViewer(); 116 | codeViewer.refresh(); 117 | setTimeout(() => codeViewer.focus(), 0); 118 | postContent.appendChild(codeViewer.getElement()); 119 | 120 | return postContent; //blockly el 121 | }, 122 | 123 | /** 124 | * Get all the content for the custom code 125 | * @return {HTMLElement} 126 | */ 127 | getContent() { 128 | const { 129 | editor 130 | } = this; 131 | const content = document.createElement('div'); 132 | const blocklyCont = document.createElement('div'); 133 | blocklyCont.id = "blockly-cont"; 134 | blocklyCont.innerHTML = `
`; 135 | const pfx = editor.getConfig('stylePrefix'); 136 | content.className = `${pfx}inject-logic`; 137 | appendToContent(content, this.getPreContent()); 138 | content.appendChild(blocklyCont); 139 | appendToContent(content, this.getPostContent()); 140 | appendToContent(content, this.getContentActions()); 141 | 142 | return content; 143 | }, 144 | 145 | /** 146 | * Get the actions content. Can be a simple string or an HTMLElement 147 | * @return {HTMLElement|String} 148 | */ 149 | getContentActions() { 150 | const { 151 | editor 152 | } = this; 153 | const actions = document.createElement('div'); 154 | actions.id = "actns"; 155 | actions.style = "position:absolute;bottom:260px;right:20px;z-index:2"; 156 | const btn = document.createElement('button'); 157 | const pfx = editor.getConfig('stylePrefix'); 158 | btn.innerHTML = opts.buttonLabel; 159 | btn.className = `${pfx}btn-prim ${pfx}btn-save__inject-logic`; 160 | btn.onclick = () => this.handleSave(); 161 | 162 | const runLogic = document.createElement('div'); 163 | runLogic.id = "logic-toolbar"; 164 | runLogic.className = "fa fa-bug"; 165 | runLogic.style = "margin:5px;padding:10px;background:rgba(0,0,0,0.2);border-radius:3px;border:1px solid rgba(0,0,0,0.2);cursor:pointer"; 166 | runLogic.onclick = () => this.runCode(); 167 | 168 | actions.appendChild(runLogic); 169 | actions.appendChild(btn); 170 | 171 | return actions; 172 | }, 173 | 174 | /** 175 | * Handle the main save task 176 | */ 177 | handleSave() { 178 | const { 179 | editor, 180 | target 181 | } = this; 182 | const code = this.getCodeViewer().getContent(); 183 | const xml = Blockly.Xml.workspaceToDom(blocklyEditor.workspace); 184 | target.set('script', code); 185 | target.set(keyBlocklyXml, Blockly.Xml.domToText(xml)); 186 | editor.Modal.close(); 187 | }, 188 | 189 | /** 190 | * Return the code viewer instance 191 | * @return {CodeViewer} 192 | */ 193 | getCodeViewer() { 194 | const { 195 | editor 196 | } = this; 197 | 198 | if (!this.codeViewer) { 199 | this.codeViewer = editor.CodeManager.createViewer({ 200 | codeName: 'javascript', 201 | theme: 'hopscotch', 202 | readOnly: 1, 203 | autoBeautify: 1, 204 | ...codeViewOptions, 205 | }); 206 | } 207 | 208 | return this.codeViewer; 209 | }, 210 | 211 | /** 212 | * Toggle between blockly and code viewer 213 | */ 214 | toggleCodeViewer() { 215 | const blocklyStyle = content.querySelector('#blockly').style; 216 | const codeViewerStyle = content.querySelector('#code-viewer').style; 217 | const hidden = (blocklyStyle.height == '0px') || (blocklyStyle.height == '0'); 218 | if (hidden) { 219 | blocklyStyle.height = "500px"; 220 | codeViewerStyle.display = "none"; 221 | } else { 222 | blocklyStyle.height = "0"; 223 | codeViewerStyle.display = "block"; 224 | } 225 | }, 226 | 227 | /** 228 | * Update code when blocks change 229 | */ 230 | updateWorkspace(e) { 231 | const blockly_code = Blockly.JavaScript.workspaceToCode(Blockly.mainWorkspace); 232 | try { 233 | // set readonly from generated 234 | this.getCodeViewer().setContent(blockly_code); 235 | } catch (e) { 236 | // readonly not found. 237 | } 238 | }, 239 | 240 | /** 241 | * Syncronize blockly when code changes 242 | */ 243 | sync() { 244 | const code = this.getCodeViewer().getContent(); 245 | //parseCode(code); 246 | }, 247 | 248 | /** 249 | * Evaluate code syntax 250 | */ 251 | runCode() { 252 | //console.log("run") 253 | try { 254 | const code = this.getCodeViewer().getContent(); 255 | Function('"use strict";' + code)(); // final code 256 | onRun && onRun(); 257 | } catch (err) { 258 | console.log("error", err); 259 | onError && onError(err); 260 | } 261 | }, 262 | 263 | ...commandBlocklyScript, 264 | }); 265 | } -------------------------------------------------------------------------------- /src/blocklyEditor.js: -------------------------------------------------------------------------------- 1 | export default class BlocklyEditor { 2 | constructor(div, opts = {}) { 3 | const toolbox = opts.toolbox || ``; 457 | this.workspace = Blockly.inject(div, { 458 | toolbox: toolbox, 459 | zoom: { 460 | controls: true, 461 | wheel: true, 462 | startScale: 1.0, 463 | maxScale: 3, 464 | minScale: 0.2, 465 | scaleSpeed: 1.2 466 | }, 467 | grid: { 468 | spacing: 20, 469 | length: 3, 470 | color: '#ccc', 471 | snap: true 472 | }, 473 | trashcan: true, 474 | ...opts.workspaceOptions 475 | }); 476 | } 477 | 478 | hide() {} 479 | } -------------------------------------------------------------------------------- /src/utils/bi_blockly/blocks/bi_blockly.js: -------------------------------------------------------------------------------- 1 | // BlocksIDE is a project to create a complete js Blocks Development Platform 2 | // 3 | // Copyright 2016 Juan Carlos Orozco 4 | // 5 | // BlocksIDE was written by Juan Carlos Orozco and released under an Apache version 2 license. 6 | // 7 | // Git repositories for BlocksIDE are available at 8 | // 9 | // https://github.com/JC-Orozco/BlocksIDE 10 | // 11 | // Licensed under the Apache License, Version 2.0 (the 'License'); 12 | // you may not use this file except in compliance with the License. 13 | // You may obtain a copy of the License at 14 | // 15 | // http://www.apache.org/licenses/LICENSE-2.0 16 | // 17 | // Unless required by applicable law or agreed to in writing, software 18 | // distributed under the License is distributed on an 'AS IS' BASIS, 19 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | // See the License for the specific language governing permissions and 21 | // limitations under the License. 22 | 23 | module.exports = function (Blockly) { 24 | //var goog = Blockly.goog; 25 | 'use strict'; 26 | 27 | //goog.provide('Blockly.Blocks.mm'); 28 | 29 | //goog.require('Blockly.Blocks'); 30 | 31 | // TODO: JCOA Add drop down list with operator options 32 | Blockly.Blocks['bi_comment'] = { 33 | init: function () { 34 | this.appendDummyInput() 35 | .appendField('comment'); 36 | this.setInputsInline(true); 37 | this.setPreviousStatement(true, null); 38 | this.setNextStatement(true, null); 39 | this.setColour(90); 40 | this.setTooltip(''); 41 | this.setHelpUrl('http://www.example.com/'); 42 | } 43 | }; 44 | 45 | // TODO: JCOA Add drop down list with operator options 46 | Blockly.Blocks['bi_assignment'] = { 47 | init: function () { 48 | this.appendValueInput('A') 49 | .setCheck(null) 50 | .appendField(''); 51 | this.appendValueInput('B') 52 | .setCheck(null) 53 | .appendField(new Blockly.FieldTextInput('='), 'OP'); 54 | this.setInputsInline(true); 55 | this.setPreviousStatement(true, null); 56 | this.setNextStatement(true, null); 57 | this.setColour(330); 58 | this.setTooltip(''); 59 | this.setHelpUrl('http://www.example.com/'); 60 | } 61 | }; 62 | 63 | // TODO: JCOA Add drop down list with operator options 64 | Blockly.Blocks['bi_assignment_return'] = { 65 | init: function () { 66 | this.appendValueInput('A') 67 | .setCheck(null) 68 | .appendField(''); 69 | this.appendValueInput('B') 70 | .setCheck(null) 71 | .appendField(new Blockly.FieldTextInput('='), 'OP'); 72 | this.setInputsInline(true); 73 | this.setOutput(true); 74 | this.setColour(330); 75 | this.setTooltip(''); 76 | this.setHelpUrl('http://www.example.com/'); 77 | } 78 | }; 79 | 80 | Blockly.Blocks['bi_math_arithmetic'] = { 81 | /** 82 | * Block for basic arithmetic operator. 83 | * @this Blockly.Block 84 | */ 85 | init: function () { 86 | var OPERATORS = [ 87 | [Blockly.Msg.MATH_ADDITION_SYMBOL, 'ADD'], 88 | [Blockly.Msg.MATH_SUBTRACTION_SYMBOL, 'MINUS'], 89 | [Blockly.Msg.MATH_MULTIPLICATION_SYMBOL, 'MULTIPLY'], 90 | [Blockly.Msg.MATH_DIVISION_SYMBOL, 'DIVIDE'], 91 | [Blockly.Msg.MATH_POWER_SYMBOL, 'POWER'] 92 | ]; 93 | this.setHelpUrl(Blockly.Msg.MATH_ARITHMETIC_HELPURL); 94 | this.setColour(270); 95 | this.setOutput(true, 'Number'); 96 | this.appendValueInput('A') 97 | .setCheck(null); // .setCheck('Number'); 98 | this.appendValueInput('B') 99 | .setCheck(null) // .setCheck('Number') 100 | .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP'); 101 | this.setInputsInline(true); 102 | // Assign 'this' to a variable for use in the tooltip closure below. 103 | var thisBlock = this; 104 | this.setTooltip(function () { 105 | var mode = thisBlock.getFieldValue('OP'); 106 | var TOOLTIPS = { 107 | 'ADD': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD, 108 | 'MINUS': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS, 109 | 'MULTIPLY': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY, 110 | 'DIVIDE': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE, 111 | 'POWER': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER 112 | }; 113 | return TOOLTIPS[mode]; 114 | }); 115 | } 116 | }; 117 | 118 | Blockly.Blocks['bi_logic_compare'] = { 119 | /** 120 | * Block for comparison operator. 121 | * @this Blockly.Block 122 | */ 123 | init: function () { 124 | var OPERATORS = this.RTL ? [ 125 | ['=', 'EQ'], 126 | ['\u2260', 'NEQ'], 127 | ['>', 'LT'], 128 | ['\u2265', 'LTE'], 129 | ['<', 'GT'], 130 | ['\u2264', 'GTE'] 131 | ] : [ 132 | ['=', 'EQ'], 133 | ['\u2260', 'NEQ'], 134 | ['<', 'LT'], 135 | ['\u2264', 'LTE'], 136 | ['>', 'GT'], 137 | ['\u2265', 'GTE'] 138 | ]; 139 | this.setHelpUrl(Blockly.Msg.LOGIC_COMPARE_HELPURL); 140 | this.setColour(190); 141 | this.setOutput(true, 'Boolean'); 142 | this.appendValueInput('A'); 143 | this.appendValueInput('B') 144 | .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP'); 145 | this.setInputsInline(true); 146 | // Assign 'this' to a variable for use in the tooltip closure below. 147 | var thisBlock = this; 148 | this.setTooltip(function () { 149 | var op = thisBlock.getFieldValue('OP'); 150 | var TOOLTIPS = { 151 | 'EQ': Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ, 152 | 'NEQ': Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ, 153 | 'LT': Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT, 154 | 'LTE': Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE, 155 | 'GT': Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT, 156 | 'GTE': Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE 157 | }; 158 | return TOOLTIPS[op]; 159 | }); 160 | this.prevBlocks_ = [null, null]; 161 | }, 162 | /** 163 | * Called whenever anything on the workspace changes. 164 | * Prevent mismatched types from being compared. 165 | * @param {!Blockly.Events.Abstract} e Change event. 166 | * @this Blockly.Block 167 | */ 168 | // onchange: function(e) { 169 | // var blockA = this.getInputTargetBlock('A'); 170 | // var blockB = this.getInputTargetBlock('B'); 171 | // // Disconnect blocks that existed prior to this change if they don't match. 172 | // if (blockA && blockB && 173 | // !blockA.outputConnection.checkType_(blockB.outputConnection)) { 174 | // // Mismatch between two inputs. Disconnect previous and bump it away. 175 | // // Ensure that any disconnections are grouped with the causing event. 176 | // Blockly.Events.setGroup(e.group); 177 | // for (var i = 0; i < this.prevBlocks_.length; i++) { 178 | // var block = this.prevBlocks_[i]; 179 | // if (block === blockA || block === blockB) { 180 | // block.unplug(); 181 | // block.bumpNeighbours_(); 182 | // } 183 | // } 184 | // Blockly.Events.setGroup(false); 185 | // } 186 | // this.prevBlocks_[0] = blockA; 187 | // this.prevBlocks_[1] = blockB; 188 | // } 189 | }; 190 | 191 | 192 | 193 | Blockly.Blocks['bi_logic_operation'] = { 194 | /** 195 | * Block for logical operations: 'and', 'or'. 196 | * @this Blockly.Block 197 | */ 198 | init: function () { 199 | var OPERATORS = [ 200 | [Blockly.Msg.LOGIC_OPERATION_AND, 'AND'], 201 | [Blockly.Msg.LOGIC_OPERATION_OR, 'OR'] 202 | ]; 203 | this.setHelpUrl(Blockly.Msg.LOGIC_OPERATION_HELPURL); 204 | this.setColour(190); 205 | this.setOutput(true, 'Boolean'); 206 | this.appendValueInput('A'); 207 | //.setCheck('Boolean'); 208 | this.appendValueInput('B') 209 | //.setCheck('Boolean') 210 | .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP'); 211 | this.setInputsInline(true); 212 | // Assign 'this' to a variable for use in the tooltip closure below. 213 | var thisBlock = this; 214 | this.setTooltip(function () { 215 | var op = thisBlock.getFieldValue('OP'); 216 | var TOOLTIPS = { 217 | 'AND': Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND, 218 | 'OR': Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR 219 | }; 220 | return TOOLTIPS[op]; 221 | }); 222 | } 223 | }; 224 | 225 | 226 | Blockly.Blocks['bi_try_catch'] = { 227 | init: function () { 228 | this.appendStatementInput('try') 229 | .setCheck(null) 230 | .appendField('try'); 231 | this.appendStatementInput('catch') 232 | .setCheck(null) 233 | .appendField('catch') 234 | .appendField(new Blockly.FieldTextInput(''), 'parameter'); 235 | this.appendStatementInput('finally') 236 | .setCheck(null) 237 | .appendField('finally'); 238 | this.setPreviousStatement(true, null); 239 | this.setNextStatement(true, null); 240 | this.setColour(90); 241 | this.setTooltip(''); 242 | this.setHelpUrl('http://www.example.com/'); 243 | } 244 | }; 245 | 246 | Blockly.Blocks['bi_catch'] = { 247 | init: function () { 248 | this.appendStatementInput('catch') 249 | .setCheck(null) 250 | .appendField('catch') 251 | .appendField(new Blockly.FieldTextInput(''), 'parameter'); 252 | this.setPreviousStatement(true, null); 253 | this.setNextStatement(true, null); 254 | this.setColour(90); 255 | this.setTooltip(''); 256 | this.setHelpUrl('http://www.example.com/'); 257 | } 258 | }; 259 | 260 | Blockly.Blocks['bi_throw'] = { 261 | init: function () { 262 | this.appendValueInput('throw') 263 | .setCheck(null) 264 | .appendField('throw'); 265 | // this.setOutput(true); 266 | this.setPreviousStatement(true, null); 267 | this.setNextStatement(true, null); 268 | this.setColour(120); 269 | this.setTooltip(''); 270 | this.setHelpUrl('http://www.example.com/'); 271 | } 272 | }; 273 | 274 | Blockly.Blocks['bi_yield'] = { 275 | init: function () { 276 | this.appendValueInput('yield') 277 | .setCheck(null) 278 | .appendField('yield') 279 | .appendField(new Blockly.FieldCheckbox('FALSE'), 'delegate'); 280 | //this.setOutput(true); 281 | this.setPreviousStatement(true, null); 282 | this.setNextStatement(true, null); 283 | this.setColour(120); 284 | this.setTooltip(''); 285 | this.setHelpUrl('http://www.example.com/'); 286 | } 287 | }; 288 | 289 | Blockly.Blocks['bi_yield_return'] = { 290 | init: function () { 291 | this.appendValueInput('yield') 292 | .setCheck(null) 293 | .appendField('yield') 294 | .appendField(new Blockly.FieldCheckbox('FALSE'), 'delegate'); 295 | this.setOutput(true); 296 | // this.setPreviousStatement(true, null); 297 | // this.setNextStatement(true, null); 298 | this.setColour(120); 299 | this.setTooltip(''); 300 | this.setHelpUrl('http://www.example.com/'); 301 | } 302 | }; 303 | 304 | Blockly.Blocks['bi_code_part'] = { 305 | init: function () { 306 | this.appendDummyInput() 307 | .appendField('Code part') 308 | .appendField(new Blockly.FieldTextInput(''), 'code'); 309 | this.setOutput(true, null); 310 | this.setColour(330); 311 | this.setTooltip(''); 312 | this.setHelpUrl('http://www.example.com/'); 313 | } 314 | }; 315 | 316 | Blockly.Blocks['bi_code_line'] = { 317 | init: function () { 318 | this.appendDummyInput() 319 | .appendField('Code line') 320 | .appendField(new Blockly.FieldTextInput(''), 'code'); 321 | this.setPreviousStatement(true, null); 322 | this.setNextStatement(true, null); 323 | this.setColour(330); 324 | this.setTooltip(''); 325 | this.setHelpUrl('http://www.example.com/'); 326 | } 327 | }; 328 | 329 | Blockly.Blocks['bi_access_field'] = { 330 | init: function () { 331 | this.appendDummyInput() 332 | .appendField('set') 333 | .appendField(new Blockly.FieldVariable('item'), 'variable'); 334 | this.appendDummyInput() 335 | .appendField('.') 336 | .appendField(new Blockly.FieldTextInput(''), 'field'); 337 | this.appendValueInput('input') 338 | .appendField('to'); 339 | this.setPreviousStatement(true, null); 340 | this.setNextStatement(true, null); 341 | this.setInputsInline(true); 342 | this.setColour(330); 343 | this.setTooltip(''); 344 | this.setHelpUrl('http://www.example.com/'); 345 | } 346 | }; 347 | 348 | Blockly.Blocks['bi_set_to'] = { 349 | init: function () { 350 | this.appendDummyInput() 351 | .appendField('set') 352 | .appendField(new Blockly.FieldTextInput(''), 'code'); 353 | this.appendValueInput('input') 354 | .appendField('to'); 355 | this.setPreviousStatement(true, null); 356 | this.setNextStatement(true, null); 357 | this.setInputsInline(true); 358 | this.setColour(330); 359 | this.setTooltip(''); 360 | this.setHelpUrl('http://www.example.com/'); 361 | } 362 | }; 363 | 364 | Blockly.Blocks['bi_for'] = { 365 | init: function () { 366 | // this.appendDummyInput() 367 | // .appendField('for'); 368 | this.appendStatementInput('init') 369 | .appendField('for init'); 370 | this.appendValueInput('test') 371 | .appendField('test'); 372 | this.appendStatementInput('update') 373 | .appendField('update'); 374 | this.appendStatementInput('chain') 375 | .appendField('loop') 376 | .setCheck(null); 377 | this.setPreviousStatement(true, null); 378 | this.setNextStatement(true, null); 379 | //this.setInputsInline(true); 380 | this.setColour(120); 381 | this.setTooltip(''); 382 | this.setHelpUrl('http://www.example.com/'); 383 | } 384 | }; 385 | 386 | // Generate a let (variable name) instruction on the js generator. 387 | Blockly.Blocks['bi_for_in'] = { 388 | init: function () { 389 | this.appendValueInput('array') 390 | .appendField('for') 391 | .appendField(new Blockly.FieldTextInput('i'), 'var') 392 | .appendField('in'); 393 | this.appendStatementInput('chain') 394 | .setCheck(null); 395 | this.setPreviousStatement(true, null); 396 | this.setNextStatement(true, null); 397 | //this.setInputsInline(true); 398 | this.setColour(120); 399 | this.setTooltip(''); 400 | this.setHelpUrl('http://www.example.com/'); 401 | } 402 | }; 403 | 404 | Blockly.Blocks['bi_continue'] = { 405 | init: function () { 406 | this.appendDummyInput() 407 | .appendField('continue'); 408 | this.setHelpUrl('http://www.example.com/'); 409 | this.setColour(120); 410 | this.setPreviousStatement(true, null); 411 | this.setNextStatement(true, null); 412 | this.setTooltip(''); 413 | } 414 | }; 415 | 416 | Blockly.Blocks['bi_break'] = { 417 | init: function () { 418 | this.appendDummyInput() 419 | .appendField('break'); 420 | this.setHelpUrl('http://www.example.com/'); 421 | this.setColour(120); 422 | this.setPreviousStatement(true, null); 423 | this.setNextStatement(true, null); 424 | this.setTooltip(''); 425 | } 426 | }; 427 | 428 | Blockly.Blocks['bi_s1'] = { 429 | /** 430 | * Block for creating a list with any number of elements of any type. 431 | * @this Blockly.Block 432 | */ 433 | init: function () { 434 | this.setHelpUrl('http://www.example.com/'); 435 | this.setColour(290); 436 | this.appendAddSubStatement('for init', 'items', 437 | null, 438 | ''); 439 | this.appendValueInput('test') 440 | .appendField('test') 441 | .setCheck(null); 442 | this.itemCount_ = 1; 443 | //this.updateShape_(); 444 | this.setInputsInline(false); 445 | this.setPreviousStatement(true, null); // 'Method'); 446 | this.setNextStatement(true, null); // 'Method'); 447 | //this.setOutput(true, 'Array'); 448 | this.setTooltip(''); 449 | } 450 | }; 451 | 452 | Blockly.Blocks['bi_return'] = { 453 | init: function () { 454 | this.appendValueInput('ret') 455 | .setCheck(null) 456 | .appendField('return') 457 | this.setPreviousStatement(true, null); 458 | this.setNextStatement(true, null); 459 | this.setColour(290); 460 | this.setTooltip(''); 461 | this.setHelpUrl('http://www.example.com/'); 462 | } 463 | }; 464 | 465 | Blockly.Blocks['bi_var'] = { 466 | init: function () { 467 | this.appendValueInput('val') 468 | .setCheck(null) 469 | .appendField(new Blockly.FieldDropdown([ 470 | ['var', 'var'], 471 | ['let', 'let'], 472 | ['const', 'const'] 473 | ]), 'var_type') 474 | .appendField(new Blockly.FieldTextInput('var1'), 'var'); 475 | this.setPreviousStatement(true, null); 476 | this.setNextStatement(true, null); 477 | this.setColour(330); 478 | this.setTooltip(''); 479 | this.setHelpUrl('http://www.example.com/'); 480 | } 481 | }; 482 | 483 | Blockly.Blocks['bi_var_name'] = { 484 | init: function () { 485 | this.appendDummyInput() 486 | .appendField('') 487 | .appendField(new Blockly.FieldTextInput('var1'), 'NAME'); 488 | this.setOutput(true, null); 489 | this.setColour(330); 490 | this.setTooltip(''); 491 | this.setHelpUrl('http://www.example.com/'); 492 | } 493 | }; 494 | 495 | Blockly.Blocks['bi_new'] = { 496 | init: function () { 497 | this.appendValueInput('chain') 498 | .appendField('new') 499 | .setCheck(null); 500 | //this.setPreviousStatement(true, null); 501 | this.setOutput(true, null); 502 | this.setColour(55); 503 | this.setTooltip(''); 504 | this.setHelpUrl('http://www.example.com/'); 505 | } 506 | }; 507 | 508 | Blockly.Blocks['bi_anonymous_class'] = { 509 | init: function () { 510 | this.appendDummyInput() 511 | .appendField('class') 512 | .appendField(new Blockly.FieldTextInput(''), 'NAME'); 513 | this.appendDummyInput() 514 | .appendField('extends') 515 | .appendField(new Blockly.FieldTextInput(''), 'extends'); 516 | this.appendStatementInput('chain') 517 | .setCheck(null); 518 | this.setHelpUrl('http://www.example.com/'); 519 | this.setColour(55); 520 | //this.setPreviousStatement(true, null); 521 | //this.setNextStatement(true, null); 522 | this.setOutput(true, null); 523 | this.setTooltip(''); 524 | } 525 | }; 526 | 527 | Blockly.Blocks['bi_class'] = { 528 | init: function () { 529 | this.appendDummyInput() 530 | .appendField('class') 531 | .appendField(new Blockly.FieldTextInput('Name'), 'NAME'); 532 | this.appendDummyInput() 533 | .appendField('extends') 534 | .appendField(new Blockly.FieldTextInput(''), 'extends'); 535 | this.appendStatementInput('chain') 536 | .setCheck(null); 537 | this.setHelpUrl('http://www.example.com/'); 538 | this.setColour(55); 539 | this.setPreviousStatement(true, null); 540 | this.setNextStatement(true, null); 541 | //this.setOutput(true, null); 542 | this.setTooltip(''); 543 | } 544 | }; 545 | 546 | Blockly.Blocks['bi_static'] = { 547 | init: function () { 548 | this.appendStatementInput('static') 549 | .setCheck(null) 550 | .appendField('static'); 551 | this.setPreviousStatement(true, null); 552 | this.setNextStatement(true, null); 553 | this.setColour(55); 554 | this.setTooltip(''); 555 | this.setHelpUrl('http://www.example.com/'); 556 | } 557 | }; 558 | 559 | Blockly.Blocks['bi_get'] = { 560 | init: function () { 561 | this.appendStatementInput('get') 562 | .setCheck(null) 563 | .appendField('get'); 564 | this.setPreviousStatement(true, null); 565 | this.setNextStatement(true, null); 566 | this.setColour(55); 567 | this.setTooltip(''); 568 | this.setHelpUrl('http://www.example.com/'); 569 | } 570 | }; 571 | 572 | Blockly.Blocks['bi_set'] = { 573 | init: function () { 574 | this.appendStatementInput('set') 575 | .setCheck(null) 576 | .appendField('set'); 577 | this.setPreviousStatement(true, null); 578 | this.setNextStatement(true, null); 579 | this.setColour(55); 580 | this.setTooltip(''); 581 | this.setHelpUrl('http://www.example.com/'); 582 | } 583 | }; 584 | 585 | Blockly.Blocks['bi_field'] = { 586 | init: function () { 587 | this.appendValueInput('chain') 588 | .appendField(new Blockly.FieldTextInput('field1'), 'NAME') 589 | .setCheck(null); // (['Field','Method']); 590 | this.setPreviousStatement(true, null); 591 | this.setNextStatement(true, null); 592 | this.setColour(330); 593 | this.setTooltip(''); 594 | this.setHelpUrl('http://www.example.com/'); 595 | } 596 | }; 597 | 598 | Blockly.Blocks['bi_field_return'] = { 599 | init: function () { 600 | this.appendValueInput('chain') 601 | .appendField('') 602 | .appendField(new Blockly.FieldTextInput('field1'), 'NAME') 603 | .setCheck(null); // (['Field','Method']); 604 | this.setOutput(true, null); // 'Field'); 605 | //this.setPreviousStatement(true, 'Field'); 606 | this.setColour(330); 607 | this.setTooltip(''); 608 | this.setHelpUrl('http://www.example.com/'); 609 | } 610 | }; 611 | 612 | Blockly.Blocks['bi_string_return'] = { 613 | init: function () { 614 | this.appendValueInput('chain') 615 | .appendField('"') 616 | .appendField(new Blockly.FieldTextInput(''), 'NAME') 617 | .appendField('"') 618 | .setCheck(null); // (['Field','Method']); 619 | this.setOutput(true, null); // 'Field'); 620 | //this.setPreviousStatement(true, 'Field'); 621 | this.setColour(160); 622 | this.setTooltip(''); 623 | this.setHelpUrl('http://www.example.com/'); 624 | } 625 | }; 626 | 627 | Blockly.Blocks['bi_index'] = { 628 | init: function () { 629 | this.appendValueInput('index') 630 | .appendField('[') 631 | .setCheck(null); // (['Field','Method']); 632 | this.appendValueInput('chain') 633 | .appendField(']') 634 | .setCheck(null); // (['Field','Method']); 635 | this.setInputsInline(true); 636 | this.setOutput(true, null); // 'Field'); 637 | //this.setPreviousStatement(true, 'Field'); 638 | this.setColour(260); 639 | this.setTooltip(''); 640 | this.setHelpUrl('http://www.example.com/'); 641 | } 642 | }; 643 | 644 | Blockly.Blocks['bi_adaptor'] = { 645 | init: function () { 646 | this.appendDummyInput() 647 | .appendField(''); 648 | this.appendStatementInput('chain') 649 | .setCheck(null); 650 | //this.setPreviousStatement(true, null); 651 | this.setOutput(true, null); 652 | this.setColour(55); 653 | this.setTooltip(''); 654 | this.setHelpUrl('http://www.example.com/'); 655 | } 656 | }; 657 | 658 | Blockly.Blocks['bi_statement'] = { 659 | init: function () { 660 | this.appendDummyInput() 661 | .appendField(''); 662 | this.appendStatementInput('chain') 663 | .setCheck(null); 664 | this.setPreviousStatement(true, null); 665 | this.setNextStatement(true, null); 666 | //this.setOutput(true, null); 667 | this.setColour(290); 668 | this.setTooltip(''); 669 | this.setHelpUrl('http://www.example.com/'); 670 | } 671 | }; 672 | 673 | // TODO: JCOA Make a drop down list of unary operators 674 | Blockly.Blocks['bi_unary'] = { 675 | init: function () { 676 | this.appendValueInput('expression') 677 | .setCheck(null) 678 | .appendField(new Blockly.FieldTextInput('++'), 'operator'); 679 | this.setPreviousStatement(true, null); 680 | this.setNextStatement(true, null); 681 | //this.setOutput(true, null); 682 | this.setColour(230); 683 | this.setTooltip(''); 684 | this.setHelpUrl('http://www.example.com/'); 685 | } 686 | }; 687 | 688 | Blockly.Blocks['bi_unary_return'] = { 689 | init: function () { 690 | this.appendValueInput('expression') 691 | .setCheck(null) 692 | .appendField(new Blockly.FieldTextInput('++'), 'operator'); 693 | // this.setPreviousStatement(true, null); 694 | // this.setNextStatement(true, null); 695 | this.setOutput(true, null); 696 | this.setColour(230); 697 | this.setTooltip(''); 698 | this.setHelpUrl('http://www.example.com/'); 699 | } 700 | }; 701 | 702 | // TODO: JCOA Make a drop down list of unary operators 703 | Blockly.Blocks['bi_unary_postfix'] = { 704 | init: function () { 705 | this.appendValueInput('expression') 706 | .appendField('postfix') 707 | .setCheck(null) 708 | .appendField(new Blockly.FieldTextInput('++'), 'operator'); 709 | this.setPreviousStatement(true, null); 710 | this.setNextStatement(true, null); 711 | //this.setOutput(true, null); 712 | this.setColour(230); 713 | this.setTooltip(''); 714 | this.setHelpUrl('http://www.example.com/'); 715 | } 716 | }; 717 | 718 | Blockly.Blocks['bi_unary_postfix_return'] = { 719 | init: function () { 720 | this.appendValueInput('expression') 721 | .appendField('postfix') 722 | .setCheck(null) 723 | .appendField(new Blockly.FieldTextInput('++'), 'operator'); 724 | // this.setPreviousStatement(true, null); 725 | // this.setNextStatement(true, null); 726 | this.setOutput(true, null); 727 | this.setColour(230); 728 | this.setTooltip(''); 729 | this.setHelpUrl('http://www.example.com/'); 730 | } 731 | }; 732 | 733 | Blockly.Blocks['bi_spread'] = { 734 | init: function () { 735 | this.appendValueInput('arg_array') 736 | .setCheck(null) 737 | .appendField('...'); 738 | this.setOutput(true, null); 739 | this.setColour(290); 740 | this.setTooltip(''); 741 | this.setHelpUrl('http://www.example.com/'); 742 | } 743 | }; 744 | 745 | Blockly.Blocks['bi_parenthesis'] = { 746 | init: function () { 747 | this.appendValueInput('expression') 748 | .setCheck(null) 749 | .appendField('(_)'); 750 | this.setOutput(true, null); 751 | this.setColour(230); 752 | this.setTooltip(''); 753 | this.setHelpUrl('http://www.example.com/'); 754 | } 755 | }; 756 | return Blockly.Blocks; 757 | } -------------------------------------------------------------------------------- /src/utils/bi_blockly/generators/javascript/bi_blockly.js: -------------------------------------------------------------------------------- 1 | // BlocksIDE is a project to create a complete js Blocks Development Platform 2 | // 3 | // Copyright 2016 Juan Carlos Orozco 4 | // 5 | // BlocksIDE was written by Juan Carlos Orozco and released under an Apache version 2 license. 6 | // 7 | // Git repositories for BlocksIDE are available at 8 | // 9 | // https://github.com/JC-Orozco/BlocksIDE 10 | // 11 | // Licensed under the Apache License, Version 2.0 (the "License"); 12 | // you may not use this file except in compliance with the License. 13 | // You may obtain a copy of the License at 14 | // 15 | // http://www.apache.org/licenses/LICENSE-2.0 16 | // 17 | // Unless required by applicable law or agreed to in writing, software 18 | // distributed under the License is distributed on an "AS IS" BASIS, 19 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | // See the License for the specific language governing permissions and 21 | // limitations under the License. 22 | 23 | module.exports = function(Blockly){ 24 | 25 | Blockly.JavaScript['bi_comment'] = function(block) { 26 | // TODO: Assemble JavaScript into code variable. 27 | var code = ''; // '...;\n'; 28 | return code; 29 | }; 30 | 31 | Blockly.JavaScript['bi_assignment'] = function(block) { 32 | var value_left = Blockly.JavaScript.valueToCode(block, 'A', Blockly.JavaScript.ORDER_ATOMIC); 33 | var value_right = Blockly.JavaScript.valueToCode(block, 'B', Blockly.JavaScript.ORDER_ATOMIC); 34 | var text_operator = block.getFieldValue('OP'); 35 | var code = value_left+' '+text_operator+' '+value_right +"\n"; 36 | return code; 37 | }; 38 | 39 | Blockly.JavaScript['bi_assignment_return'] = function(block) { 40 | var value_left = Blockly.JavaScript.valueToCode(block, 'A', Blockly.JavaScript.ORDER_ATOMIC); 41 | var value_right = Blockly.JavaScript.valueToCode(block, 'B', Blockly.JavaScript.ORDER_ATOMIC); 42 | var text_operator = block.getFieldValue('OP'); 43 | var code = value_left+' '+text_operator+' '+value_right; 44 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 45 | }; 46 | 47 | Blockly.JavaScript['bi_math_arithmetic'] = function(block) { 48 | // Basic arithmetic operators, and power. 49 | var OPERATORS = { 50 | 'ADD': [' + ', Blockly.JavaScript.ORDER_ADDITION], 51 | 'MINUS': [' - ', Blockly.JavaScript.ORDER_SUBTRACTION], 52 | 'MULTIPLY': [' * ', Blockly.JavaScript.ORDER_MULTIPLICATION], 53 | 'DIVIDE': [' / ', Blockly.JavaScript.ORDER_DIVISION], 54 | 'POWER': [null, Blockly.JavaScript.ORDER_COMMA] // Handle power separately. 55 | }; 56 | var tuple = OPERATORS[block.getFieldValue('OP')]; 57 | var operator = ' '; 58 | var order = Blockly.JavaScript.ORDER_ATOMIC; 59 | if(tuple){ 60 | operator = tuple[0]; 61 | order = tuple[1]; 62 | } 63 | var argument0 = Blockly.JavaScript.valueToCode(block, 'A', order) || '0'; 64 | var argument1 = Blockly.JavaScript.valueToCode(block, 'B', order) || '0'; 65 | var code; 66 | // Power in JavaScript requires a special case since it has no operator. 67 | if (!operator) { 68 | code = 'Math.pow(' + argument0 + ', ' + argument1 + ')'; 69 | return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; 70 | } 71 | code = argument0 + operator + argument1; 72 | return [code, order]; 73 | }; 74 | 75 | Blockly.JavaScript['bi_logic_compare'] = function(block) { 76 | // Comparison operator. 77 | var OPERATORS = { 78 | 'EQ': '==', 79 | 'NEQ': '!=', 80 | 'LT': '<', 81 | 'LTE': '<=', 82 | 'GT': '>', 83 | 'GTE': '>=' 84 | }; 85 | var operator = OPERATORS[block.getFieldValue('OP')]; 86 | var order = (operator === '==' || operator === '!=') ? 87 | Blockly.JavaScript.ORDER_EQUALITY : Blockly.JavaScript.ORDER_RELATIONAL; 88 | var argument0 = Blockly.JavaScript.valueToCode(block, 'A', order) || '0'; 89 | var argument1 = Blockly.JavaScript.valueToCode(block, 'B', order) || '0'; 90 | var code = argument0 + ' ' + operator + ' ' + argument1; 91 | return [code, order]; 92 | }; 93 | 94 | Blockly.JavaScript['bi_logic_operation'] = function(block) { 95 | // Operations 'and', 'or'. 96 | var operator = (block.getFieldValue('OP') === 'AND') ? '&&' : '||'; 97 | var order = (operator === '&&') ? Blockly.JavaScript.ORDER_LOGICAL_AND : 98 | Blockly.JavaScript.ORDER_LOGICAL_OR; 99 | var argument0 = Blockly.JavaScript.valueToCode(block, 'A', order); 100 | var argument1 = Blockly.JavaScript.valueToCode(block, 'B', order); 101 | if (!argument0 && !argument1) { 102 | // If there are no arguments, then the return value is false. 103 | argument0 = 'false'; 104 | argument1 = 'false'; 105 | } else { 106 | // Single missing arguments have no effect on the return value. 107 | var defaultArgument = (operator === '&&') ? 'true' : 'false'; 108 | if (!argument0) { 109 | argument0 = defaultArgument; 110 | } 111 | if (!argument1) { 112 | argument1 = defaultArgument; 113 | } 114 | } 115 | var code = argument0 + ' ' + operator + ' ' + argument1; 116 | return [code, order]; 117 | }; 118 | 119 | Blockly.JavaScript['bi_try_catch'] = function(block) { 120 | var statement_try = Blockly.JavaScript.statementToCode(block, 'try'); 121 | var statement_catch = Blockly.JavaScript.statementToCode(block, 'catch'); 122 | var statement_finally = Blockly.JavaScript.statementToCode(block, 'finally'); 123 | var text_parameter = block.getFieldValue('parameter'); 124 | var code = 'try{\n'+statement_try+'\n} catch('+text_parameter+'){\n'+statement_catch+'\n} finally{\n'+statement_finally+"}\n"; 125 | return code; 126 | }; 127 | 128 | Blockly.JavaScript['bi_catch'] = function(block) { 129 | var statement_catch = Blockly.JavaScript.statementToCode(block, 'catch'); 130 | var text_parameter = block.getFieldValue('parameter'); 131 | var code = 'catch('+text_parameter+'){\n'+statement_catch+'}\n'; 132 | return code; 133 | }; 134 | 135 | Blockly.JavaScript['bi_throw'] = function(block) { 136 | var value_throw = Blockly.JavaScript.valueToCode(block, 'throw', Blockly.JavaScript.ORDER_ATOMIC); 137 | var code = 'throw '+value_throw+'\n'; 138 | return code; 139 | }; 140 | 141 | Blockly.JavaScript['bi_yield'] = function(block) { 142 | var value_yield = Blockly.JavaScript.valueToCode(block, 'yield', Blockly.JavaScript.ORDER_ATOMIC); 143 | var checkbox_delegate = block.getFieldValue('delegate') === 'TRUE'; 144 | var code = ''; 145 | if(checkbox_delegate){ 146 | code = 'yield* ' 147 | } else{ 148 | code = 'yield ' 149 | } 150 | code += value_yield+'\n'; 151 | return code; 152 | }; 153 | 154 | Blockly.JavaScript['bi_yield_return'] = function(block) { 155 | var value_yield = Blockly.JavaScript.valueToCode(block, 'yield', Blockly.JavaScript.ORDER_ATOMIC); 156 | var checkbox_delegate = block.getFieldValue('delegate') === 'TRUE'; 157 | var code = ''; 158 | if(checkbox_delegate){ 159 | code = 'yield* ' 160 | } else{ 161 | code = 'yield ' 162 | } 163 | code += value_yield; 164 | //return code; 165 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 166 | }; 167 | 168 | Blockly.JavaScript['bi_export'] = function(block) { 169 | var statement_chain = Blockly.JavaScript.statementToCode(block, 'export'); 170 | return 'export '+statement_chain 171 | } 172 | 173 | Blockly.JavaScript['bi_import'] = function(block) { 174 | // var value_import = Blockly.JavaScript.valueToCode(block, 'import', Blockly.JavaScript.ORDER_ATOMIC); 175 | var codeArr = new Array(block.itemCount_-1); 176 | for (var n = 1; n < block.itemCount_; n++) { 177 | codeArr[n-1] = Blockly.JavaScript.valueToCode(block, 'items' + n, 178 | Blockly.JavaScript.ORDER_COMMA) || 'null'; 179 | } 180 | var value_from = Blockly.JavaScript.valueToCode(block, 'from', Blockly.JavaScript.ORDER_ATOMIC); 181 | var code = 'import ' 182 | if(block.itemCount_ === 2){ 183 | code += codeArr[0] 184 | } else{ 185 | code += '{'+codeArr.join(',')+'}' 186 | } 187 | code += ' from '+value_from+'\n' 188 | return code 189 | } 190 | 191 | Blockly.JavaScript['bi_import_as'] = function(block) { 192 | var text_import = block.getFieldValue('input'); 193 | var text_as = block.getFieldValue('as'); 194 | var code = text_import+' as '+text_as 195 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 196 | } 197 | 198 | Blockly.JavaScript['bi_code_part'] = function(block) { 199 | var text_code = block.getFieldValue('code'); 200 | var code = text_code; 201 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 202 | }; 203 | 204 | Blockly.JavaScript['bi_code_line'] = function(block) { 205 | var text_code = block.getFieldValue('code'); 206 | var code = text_code+"\n"; 207 | return code; 208 | }; 209 | 210 | Blockly.JavaScript['bi_access_field'] = function(block) { 211 | var value_variable = Blockly.JavaScript.variableDB_.getName(block.getFieldValue('variable'), Blockly.Variables.NAME_TYPE); 212 | var text_field = block.getFieldValue('field'); 213 | var value_input = Blockly.JavaScript.valueToCode(block, 'input', Blockly.JavaScript.ORDER_ATOMIC); 214 | var code = value_variable+"."+text_field+" = "+value_input+"\n"; 215 | return code; 216 | }; 217 | 218 | Blockly.JavaScript['bi_set_to'] = function(block) { 219 | var text_code = block.getFieldValue('code'); 220 | var value_input = Blockly.JavaScript.valueToCode(block, 'input', Blockly.JavaScript.ORDER_ATOMIC); 221 | var code = text_code+" = "+value_input+"\n"; 222 | return code; 223 | }; 224 | 225 | // Fix, init statements must be separated by a comma 226 | Blockly.JavaScript['bi_for'] = function(block) { 227 | Blockly.Generator.prototype.STATEMENT_PREFIX = ', ' 228 | var statement_init = Blockly.JavaScript.statementToCode(block, 'init'); 229 | Blockly.Generator.prototype.STATEMENT_PREFIX = null; 230 | var value_test = Blockly.JavaScript.valueToCode(block, 'test', Blockly.JavaScript.ORDER_ATOMIC); 231 | Blockly.Generator.prototype.STATEMENT_PREFIX = ', ' 232 | var statement_update = Blockly.JavaScript.statementToCode(block, 'update'); 233 | Blockly.Generator.prototype.STATEMENT_PREFIX = null; 234 | var statement_chain = Blockly.JavaScript.statementToCode(block, 'chain'); 235 | // g on this REGEX means match all ocurences 236 | statement_init = statement_init.replace(', ', '').replace(/\n {2}/g, '').trim(); 237 | statement_update = statement_update.replace(', ', '').replace(/\n {2}/g, '').trim(); 238 | var code = 'for( '+statement_init+'; '+value_test+'; '+statement_update+' ){\n'+statement_chain+'}\n'; 239 | return code; 240 | }; 241 | 242 | Blockly.JavaScript['bi_for_in'] = function(block) { 243 | var text_var = block.getFieldValue('var'); 244 | var value_array = Blockly.JavaScript.valueToCode(block, 'array', Blockly.JavaScript.ORDER_ATOMIC); 245 | var statement_chain = Blockly.JavaScript.statementToCode(block, 'chain'); 246 | var code = 'for(let '+text_var+' in '+value_array+'){\n'+statement_chain+'}\n'; 247 | return code; 248 | }; 249 | 250 | Blockly.JavaScript['bi_switch'] = function(block) { 251 | var value_switch = Blockly.JavaScript.valueToCode(block, 'switch', Blockly.JavaScript.ORDER_ATOMIC); 252 | var statement_default = Blockly.JavaScript.statementToCode(block, 'default'); 253 | var codeArr = new Array(block.itemCount_-1); 254 | for (var n = 1; n < block.itemCount_; n++) { 255 | codeArr[n-1] = Blockly.JavaScript.valueToCode(block, 'items' + n, 256 | Blockly.JavaScript.ORDER_COMMA) || 'null'; 257 | } 258 | var code = 'switch(' + value_switch + '){\n' + codeArr.join('\n') + '\ndefault: ' + statement_default +'}\n'; 259 | return code; 260 | } 261 | 262 | Blockly.JavaScript['bi_case'] = function(block) { 263 | var value_case = Blockly.JavaScript.valueToCode(block, 'case', Blockly.JavaScript.ORDER_ATOMIC); 264 | var statement_st = Blockly.JavaScript.statementToCode(block, 'statement'); 265 | var code = 'case '+value_case+':' + statement_st //+ '\n'; 266 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 267 | } 268 | 269 | Blockly.JavaScript['bi_continue'] = function(block) { 270 | return '\ncontinue\n' 271 | } 272 | 273 | Blockly.JavaScript['bi_break'] = function(block) { 274 | return '\nbreak\n' 275 | } 276 | 277 | Blockly.JavaScript['bi_s1'] = function(block) { 278 | // Create a list with any number of elements of any type. 279 | var value_chain = Blockly.JavaScript.valueToCode(block, 'chain', Blockly.JavaScript.ORDER_ATOMIC); 280 | var codeArr = new Array(block.itemCount_); // block.itemCount_); 281 | for (var n = 0; n < block.itemCount_; n++) { 282 | // code[n] = Blockly.JavaScript.valueToCode(block, 'ADD' + n, 283 | // Blockly.JavaScript.ORDER_COMMA) || 'null'; 284 | // TODO: Fix the naming on the AddSubGroup block and use code above 285 | codeArr[n] = //Blockly.JavaScript.valueToCode(block, 'items' + n, 286 | // Blockly.JavaScript.ORDER_COMMA) || 'null'; 287 | Blockly.JavaScript.statementToCode(block, 'items' + n) || ''; 288 | } 289 | var chain = ""; 290 | if(value_chain !== ""){ 291 | chain = "\n ."+value_chain.trim(); 292 | } 293 | //var code = text_name.substr(1, text_name.length-2) + '(' + codeArr.join(', ') + ')' + chain; 294 | var code = 'for(' + codeArr.join(', ') + '){' + chain+'}\n'; 295 | //return [code, Blockly.JavaScript.ORDER_ATOMIC]; 296 | return code; 297 | }; 298 | 299 | Blockly.JavaScript['bi_call_statement'] = function(block) { 300 | // Create a list with any number of elements of any type. 301 | var text_name = block.getFieldValue('NAME'); 302 | var value_chain = Blockly.JavaScript.valueToCode(block, 'chain', Blockly.JavaScript.ORDER_ATOMIC); 303 | var codeArr = new Array(block.itemCount_-1); 304 | for (var n = 1; n < block.itemCount_; n++) { 305 | // code[n] = Blockly.JavaScript.valueToCode(block, 'ADD' + n, 306 | // Blockly.JavaScript.ORDER_COMMA) || 'null'; 307 | // TODO: Fix the naming on the AddSubGroup block and use code above 308 | codeArr[n-1] = Blockly.JavaScript.valueToCode(block, 'items' + n, 309 | Blockly.JavaScript.ORDER_COMMA) || 'null'; 310 | } 311 | var chain = ""; 312 | if(value_chain !== ""){ 313 | chain = "."+value_chain.trim(); 314 | } 315 | //var code = text_name.substr(1, text_name.length-2) + '(' + codeArr.join(', ') + ')' + chain; 316 | var code = text_name + '(' + codeArr.join(', ') + ')' + chain+'\n'; 317 | //return [code, Blockly.JavaScript.ORDER_ATOMIC]; 318 | return code; 319 | }; 320 | 321 | Blockly.JavaScript['bi_call'] = function(block) { 322 | // Create a list with any number of elements of any type. 323 | var text_name = block.getFieldValue('NAME'); 324 | var value_chain = Blockly.JavaScript.valueToCode(block, 'chain', Blockly.JavaScript.ORDER_ATOMIC); 325 | var codeArr = new Array(block.itemCount_-1); 326 | for (var n = 1; n < block.itemCount_; n++) { 327 | // code[n] = Blockly.JavaScript.valueToCode(block, 'ADD' + n, 328 | // Blockly.JavaScript.ORDER_COMMA) || 'null'; 329 | // TODO: Fix the naming on the AddSubGroup block and use code above 330 | codeArr[n-1] = Blockly.JavaScript.valueToCode(block, 'items' + n, 331 | Blockly.JavaScript.ORDER_COMMA) || 'null'; 332 | } 333 | var chain = ""; 334 | if(value_chain !== ""){ 335 | chain = "."+value_chain.trim(); 336 | } 337 | //var code = text_name.substr(1, text_name.length-2) + '(' + codeArr.join(', ') + ')' + chain; 338 | var code = text_name + '(' + codeArr.join(', ') + ')' + chain; 339 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 340 | //return code; 341 | }; 342 | 343 | Blockly.JavaScript['bi_direct_call_editable'] = function(block) { 344 | var value_function = Blockly.JavaScript.valueToCode(block, 'function', Blockly.JavaScript.ORDER_ATOMIC); 345 | var value_chain = Blockly.JavaScript.valueToCode(block, 'chain', Blockly.JavaScript.ORDER_ATOMIC); 346 | var codeArr = new Array(block.itemCount_-1); // block.itemCount_); 347 | for (var n = 1; n < block.itemCount_; n++) { 348 | // code[n] = Blockly.JavaScript.valueToCode(block, 'ADD' + n, 349 | // Blockly.JavaScript.ORDER_COMMA) || 'null'; 350 | // TODO: Fix the naming on the AddSubGroup block and use code above 351 | codeArr[n-1] = Blockly.JavaScript.valueToCode(block, 'items' + n, 352 | Blockly.JavaScript.ORDER_COMMA) || 'null'; 353 | } 354 | var chain = ""; 355 | if(value_chain !== ""){ 356 | chain = "\n ."+value_chain.trim(); 357 | } 358 | //var code = text_name.substr(1, text_name.length-2) + '(' + codeArr.join(', ') + ')' + chain; 359 | var code = '(' + value_function + ')(' + codeArr.join(', ') + ')' + chain+'\n'; 360 | //return [code, Blockly.JavaScript.ORDER_ATOMIC]; 361 | return code; 362 | }; 363 | 364 | Blockly.JavaScript['bi_direct_call_editable_return'] = function(block) { 365 | var value_function = Blockly.JavaScript.valueToCode(block, 'function', Blockly.JavaScript.ORDER_ATOMIC); 366 | var value_chain = Blockly.JavaScript.valueToCode(block, 'chain', Blockly.JavaScript.ORDER_ATOMIC); 367 | var codeArr = new Array(block.itemCount_-1); // block.itemCount_); 368 | for (var n = 1; n < block.itemCount_; n++) { 369 | // code[n] = Blockly.JavaScript.valueToCode(block, 'ADD' + n, 370 | // Blockly.JavaScript.ORDER_COMMA) || 'null'; 371 | // TODO: Fix the naming on the AddSubGroup block and use code above 372 | codeArr[n-1] = Blockly.JavaScript.valueToCode(block, 'items' + n, 373 | Blockly.JavaScript.ORDER_COMMA) || 'null'; 374 | } 375 | var chain = ""; 376 | if(value_chain !== ""){ 377 | chain = "\n ."+value_chain.trim(); 378 | } 379 | //var code = text_name.substr(1, text_name.length-2) + '(' + codeArr.join(', ') + ')' + chain; 380 | var code = '(' + value_function + ')(' + codeArr.join(', ') + ')' + chain; 381 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 382 | //return code; 383 | }; 384 | 385 | Blockly.JavaScript['bi_call_editable'] = function(block) { 386 | var text_name = block.getFieldValue('NAME'); 387 | var value_chain = Blockly.JavaScript.valueToCode(block, 'chain', Blockly.JavaScript.ORDER_ATOMIC); 388 | var codeArr = new Array(block.itemCount_-1); // block.itemCount_); 389 | for (var n = 1; n < block.itemCount_; n++) { 390 | // code[n] = Blockly.JavaScript.valueToCode(block, 'ADD' + n, 391 | // Blockly.JavaScript.ORDER_COMMA) || 'null'; 392 | // TODO: Fix the naming on the AddSubGroup block and use code above 393 | codeArr[n-1] = Blockly.JavaScript.valueToCode(block, 'items' + n, 394 | Blockly.JavaScript.ORDER_COMMA) || 'null'; 395 | } 396 | var chain = ""; 397 | if(value_chain !== ""){ 398 | chain = "\n ."+value_chain.trim(); 399 | } 400 | //var code = text_name.substr(1, text_name.length-2) + '(' + codeArr.join(', ') + ')' + chain; 401 | var code = text_name + '(' + codeArr.join(', ') + ')' + chain+'\n'; 402 | //return [code, Blockly.JavaScript.ORDER_ATOMIC]; 403 | return code; 404 | }; 405 | 406 | Blockly.JavaScript['bi_call_editable_return'] = function(block) { 407 | var text_name = block.getFieldValue('NAME'); 408 | var value_chain = Blockly.JavaScript.valueToCode(block, 'chain', Blockly.JavaScript.ORDER_ATOMIC); 409 | var codeArr = new Array(block.itemCount_-1); // block.itemCount_); 410 | for (var n = 1; n < block.itemCount_; n++) { 411 | // code[n] = Blockly.JavaScript.valueToCode(block, 'ADD' + n, 412 | // Blockly.JavaScript.ORDER_COMMA) || 'null'; 413 | // TODO: Fix the naming on the AddSubGroup block and use code above 414 | codeArr[n-1] = Blockly.JavaScript.valueToCode(block, 'items' + n, 415 | Blockly.JavaScript.ORDER_COMMA) || 'null'; 416 | } 417 | var chain = ""; 418 | if(value_chain !== ""){ 419 | chain = "\n ."+value_chain.trim(); 420 | } 421 | //var code = text_name.substr(1, text_name.length-2) + '(' + codeArr.join(', ') + ')' + chain; 422 | var code = text_name + '(' + codeArr.join(', ') + ')' + chain; 423 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 424 | //return code; 425 | }; 426 | 427 | Blockly.JavaScript['bi_function_return'] = function(block) { 428 | //var text_name = block.getFieldValue('name'); 429 | var function_type = block.getFieldValue('function_type'); 430 | var text_name = block.getFieldValue('name'); 431 | var text_args = block.getFieldValue('args'); 432 | var statements_chain = Blockly.JavaScript.statementToCode(block, 'chain'); 433 | var chain = statements_chain; 434 | var code = function_type+text_name+'('; 435 | code += text_args + '){\n' + chain +'}\n'; 436 | 437 | //return [code, Blockly.JavaScript.ORDER_NONE]; 438 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 439 | //return code; 440 | }; 441 | 442 | Blockly.JavaScript['bi_function'] = function(block) { 443 | var text_name = block.getFieldValue('name'); 444 | var function_type = block.getFieldValue('function_type'); 445 | var text_args = block.getFieldValue('args'); 446 | var statements_chain = Blockly.JavaScript.statementToCode(block, 'chain'); 447 | var chain = statements_chain; 448 | var code = function_type+text_name+'('; 449 | code += text_args + '){\n' + chain +'}\n'; 450 | return code; 451 | }; 452 | 453 | Blockly.JavaScript['bi_return'] = function(block) { 454 | var value_ret = Blockly.JavaScript.valueToCode(block, 'ret', Blockly.JavaScript.ORDER_ATOMIC); 455 | var code = 'return '+value_ret+'\n'; 456 | //return [code, Blockly.JavaScript.ORDER_ATOMIC]; 457 | return code; 458 | }; 459 | 460 | Blockly.JavaScript['bi_maps_set'] = function(block) { 461 | var text_name = block.getFieldValue('name'); 462 | var text_val = block.getFieldValue('val'); 463 | var statements_chain = Blockly.JavaScript.statementToCode(block, 'chain'); 464 | var chain = statements_chain; 465 | var code = 'set '+text_name+'('; 466 | code += text_val + '){\n' + chain +'}\n'; 467 | 468 | //return [code, Blockly.JavaScript.ORDER_NONE]; 469 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 470 | //return code; 471 | }; 472 | 473 | Blockly.JavaScript['bi_maps_get'] = function(block) { 474 | var text_name = block.getFieldValue('name'); 475 | var statements_chain = Blockly.JavaScript.statementToCode(block, 'chain'); 476 | var chain = statements_chain; 477 | var code = 'get ' + text_name+'('; 478 | code += '){\n' + chain +'}\n'; 479 | 480 | //return [code, Blockly.JavaScript.ORDER_NONE]; 481 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 482 | //return code; 483 | }; 484 | 485 | Blockly.JavaScript['bi_var'] = function(block) { 486 | var var_type = block.getFieldValue('var_type'); 487 | var text_var = block.getFieldValue('var'); 488 | var value_val = Blockly.JavaScript.valueToCode(block, 'val', Blockly.JavaScript.ORDER_ATOMIC); 489 | var code = var_type+' '+text_var; 490 | if(value_val === ''){ 491 | code += '\n'; 492 | } else{ 493 | code +=' = '+value_val +'\n'; 494 | } 495 | //return [code, Blockly.JavaScript.ORDER_NONE]; 496 | return code; 497 | }; 498 | 499 | Blockly.JavaScript['bi_var_name'] = function(block) { 500 | var text_name = block.getFieldValue('NAME'); 501 | var code = text_name; 502 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 503 | //return code; 504 | }; 505 | 506 | Blockly.JavaScript['bi_new'] = function(block) { 507 | var value_chain = Blockly.JavaScript.valueToCode(block, 'chain', Blockly.JavaScript.ORDER_ATOMIC); 508 | var chain = value_chain.trim(); 509 | var code = "new "+chain; 510 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 511 | //return code; 512 | }; 513 | 514 | Blockly.JavaScript['bi_anonymous_class'] = function(block) { 515 | var text_name = block.getFieldValue('NAME'); 516 | var text_extends = block.getFieldValue('extends'); 517 | var statement_chain = Blockly.JavaScript.statementToCode(block, 'chain'); 518 | var code = 'class '+text_name 519 | if(text_extends !== '') 520 | code += ' extends '+text_extends 521 | code += '{\n'+statement_chain+'}'; 522 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 523 | //return code; 524 | }; 525 | 526 | Blockly.JavaScript['bi_class'] = function(block) { 527 | var text_name = block.getFieldValue('NAME'); 528 | var text_extends = block.getFieldValue('extends'); 529 | var statement_chain = Blockly.JavaScript.statementToCode(block, 'chain'); 530 | var code = 'class '+text_name 531 | if(text_extends !== '') 532 | code += ' extends '+text_extends 533 | code += '{\n'+statement_chain+'}\n'; 534 | //return [code, Blockly.JavaScript.ORDER_ATOMIC]; 535 | return code; 536 | }; 537 | 538 | Blockly.JavaScript['bi_static'] = function(block) { 539 | var statement_chain = Blockly.JavaScript.statementToCode(block, 'static'); 540 | return 'static '+statement_chain 541 | } 542 | 543 | Blockly.JavaScript['bi_get'] = function(block) { 544 | var statement_chain = Blockly.JavaScript.statementToCode(block, 'get'); 545 | return 'get '+statement_chain 546 | } 547 | 548 | Blockly.JavaScript['bi_set'] = function(block) { 549 | var statement_chain = Blockly.JavaScript.statementToCode(block, 'set'); 550 | return 'set '+statement_chain 551 | } 552 | 553 | Blockly.JavaScript['bi_field'] = function(block) { 554 | var value_chain = Blockly.JavaScript.valueToCode(block, 'chain', Blockly.JavaScript.ORDER_ATOMIC); 555 | var text_name = block.getFieldValue('NAME'); 556 | var chain = ''; 557 | if(value_chain !== ''){ 558 | if(value_chain[0] === '['){ 559 | chain = value_chain.trim(); 560 | } else{ 561 | chain = '.'+value_chain.trim(); 562 | } 563 | } 564 | var code = text_name+chain+'\n'; 565 | //return [code, Blockly.JavaScript.ORDER_ATOMIC]; 566 | return code; 567 | }; 568 | 569 | Blockly.JavaScript['bi_field_return'] = function(block) { 570 | var value_chain = Blockly.JavaScript.valueToCode(block, 'chain', Blockly.JavaScript.ORDER_ATOMIC); 571 | var text_name = block.getFieldValue('NAME'); 572 | var chain = ''; 573 | if(value_chain !== ''){ 574 | if(value_chain[0] === '['){ 575 | chain = value_chain.trim(); 576 | } else{ 577 | chain = '.'+value_chain.trim(); 578 | } 579 | } 580 | var code = text_name+chain; 581 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 582 | //return code; 583 | }; 584 | 585 | Blockly.JavaScript['bi_string_return'] = function(block) { 586 | var value_chain = Blockly.JavaScript.valueToCode(block, 'chain', Blockly.JavaScript.ORDER_ATOMIC); 587 | var text_name = block.getFieldValue('NAME'); 588 | var chain = ''; 589 | if(value_chain !== ''){ 590 | if(value_chain[0] === '['){ 591 | chain = value_chain.trim(); 592 | } else{ 593 | chain = '.'+value_chain.trim(); 594 | } 595 | } 596 | var code = '"'+text_name+'"'+chain; 597 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 598 | //return code; 599 | }; 600 | 601 | Blockly.JavaScript['bi_index'] = function(block) { 602 | var value_chain = Blockly.JavaScript.valueToCode(block, 'chain', Blockly.JavaScript.ORDER_ATOMIC); 603 | var value_index = Blockly.JavaScript.valueToCode(block, 'index', Blockly.JavaScript.ORDER_ATOMIC); 604 | var chain = ''; 605 | if(value_chain !== ''){ 606 | chain = '.'+value_chain.trim(); 607 | } 608 | var code = '['+value_index+']'+chain; 609 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 610 | //return code; 611 | }; 612 | 613 | Blockly.JavaScript['bi_adaptor'] = function(block) { 614 | var statements_chain = Blockly.JavaScript.statementToCode(block, 'chain'); 615 | var chain = statements_chain.trim(); 616 | var code = chain; 617 | //var code = statements_chain; 618 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 619 | //return code; 620 | }; 621 | 622 | Blockly.JavaScript['bi_statement'] = function(block) { 623 | var statements_chain = Blockly.JavaScript.statementToCode(block, 'chain'); 624 | var chain = statements_chain.trim(); 625 | var code = chain; 626 | //var code = statements_chain; 627 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 628 | //return code; 629 | }; 630 | 631 | Blockly.JavaScript['bi_unary'] = function(block) { 632 | function isLetter(c) { 633 | return c.toLowerCase() !== c.toUpperCase(); 634 | } 635 | var value_expression = Blockly.JavaScript.valueToCode(block, 'expression', Blockly.JavaScript.ORDER_ATOMIC); 636 | var text_operator = block.getFieldValue('operator'); 637 | if(isLetter(text_operator[0])){ 638 | text_operator += ' '; 639 | } 640 | var code = text_operator+value_expression +'\n'; 641 | //return [code, Blockly.JavaScript.ORDER_ATOMIC]; 642 | return code; 643 | }; 644 | 645 | Blockly.JavaScript['bi_unary_return'] = function(block) { 646 | function isLetter(c) { 647 | return c.toLowerCase() !== c.toUpperCase(); 648 | } 649 | var value_expression = Blockly.JavaScript.valueToCode(block, 'expression', Blockly.JavaScript.ORDER_ATOMIC); 650 | var text_operator = block.getFieldValue('operator'); 651 | if(isLetter(text_operator[0])){ 652 | text_operator += ' '; 653 | } 654 | var code = text_operator+value_expression; 655 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 656 | //return code; 657 | }; 658 | 659 | Blockly.JavaScript['bi_unary_postfix'] = function(block) { 660 | function isLetter(c) { 661 | return c.toLowerCase() !== c.toUpperCase(); 662 | } 663 | var value_expression = Blockly.JavaScript.valueToCode(block, 'expression', Blockly.JavaScript.ORDER_ATOMIC); 664 | var text_operator = block.getFieldValue('operator'); 665 | if(isLetter(text_operator[0])){ 666 | text_operator += ' '; 667 | } 668 | var code = value_expression+text_operator+'\n'; 669 | //return [code, Blockly.JavaScript.ORDER_ATOMIC]; 670 | return code; 671 | }; 672 | 673 | Blockly.JavaScript['bi_unary_postfix_return'] = function(block) { 674 | function isLetter(c) { 675 | return c.toLowerCase() !== c.toUpperCase(); 676 | } 677 | var value_expression = Blockly.JavaScript.valueToCode(block, 'expression', Blockly.JavaScript.ORDER_ATOMIC); 678 | var text_operator = block.getFieldValue('operator'); 679 | if(isLetter(text_operator[0])){ 680 | text_operator += ' '; 681 | } 682 | var code = value_expression+text_operator; 683 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 684 | //return code; 685 | }; 686 | 687 | Blockly.JavaScript['bi_spread'] = function(block) { 688 | var value_name = Blockly.JavaScript.valueToCode(block, 'arg_array', Blockly.JavaScript.ORDER_ATOMIC); 689 | var code = '...'+value_name; 690 | return [code, Blockly.JavaScript.ORDER_ATOMIC]; 691 | //return [code, Blockly.JavaScript.ORDER_NONE]; 692 | //return code; 693 | }; 694 | return Blockly.JavaScript;} 695 | -------------------------------------------------------------------------------- /dist/grapesjs-blockly.min.js: -------------------------------------------------------------------------------- 1 | /*! grapesjs-blockly - 1.0.2 */ 2 | !function(e,t){'object'==typeof exports&&'object'==typeof module?module.exports=t():'function'==typeof define&&define.amd?define([],t):'object'==typeof exports?exports["grapesjs-blockly"]=t():e["grapesjs-blockly"]=t()}(window,(function(){return function(e){var t={};function n(a){if(t[a])return t[a].exports;var i=t[a]={i:a,l:!1,exports:{}};return e[a].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,a){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:a})},n.r=function(e){'undefined'!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:'Module'}),Object.defineProperty(e,'__esModule',{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&'object'==typeof e&&e&&e.__esModule)return e;var a=Object.create(null);if(n.r(a),Object.defineProperty(a,'default',{enumerable:!0,value:e}),2&t&&'string'!=typeof e)for(var i in e)n.d(a,i,function(t){return e[t]}.bind(null,i));return a},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,'a',t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=5)}([function(e,t){e.exports=function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}},function(e,t){e.exports=function(e){'use strict';return e.Blocks.bi_comment={init:function(){this.appendDummyInput().appendField('comment'),this.setInputsInline(!0),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setColour(90),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_assignment={init:function(){this.appendValueInput('A').setCheck(null).appendField(''),this.appendValueInput('B').setCheck(null).appendField(new e.FieldTextInput('='),'OP'),this.setInputsInline(!0),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setColour(330),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_assignment_return={init:function(){this.appendValueInput('A').setCheck(null).appendField(''),this.appendValueInput('B').setCheck(null).appendField(new e.FieldTextInput('='),'OP'),this.setInputsInline(!0),this.setOutput(!0),this.setColour(330),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_math_arithmetic={init:function(){var t=[[e.Msg.MATH_ADDITION_SYMBOL,'ADD'],[e.Msg.MATH_SUBTRACTION_SYMBOL,'MINUS'],[e.Msg.MATH_MULTIPLICATION_SYMBOL,'MULTIPLY'],[e.Msg.MATH_DIVISION_SYMBOL,'DIVIDE'],[e.Msg.MATH_POWER_SYMBOL,'POWER']];this.setHelpUrl(e.Msg.MATH_ARITHMETIC_HELPURL),this.setColour(270),this.setOutput(!0,'Number'),this.appendValueInput('A').setCheck(null),this.appendValueInput('B').setCheck(null).appendField(new e.FieldDropdown(t),'OP'),this.setInputsInline(!0);var n=this;this.setTooltip((function(){var t=n.getFieldValue('OP');return{ADD:e.Msg.MATH_ARITHMETIC_TOOLTIP_ADD,MINUS:e.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS,MULTIPLY:e.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY,DIVIDE:e.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE,POWER:e.Msg.MATH_ARITHMETIC_TOOLTIP_POWER}[t]}))}},e.Blocks.bi_logic_compare={init:function(){var t=this.RTL?[['=','EQ'],["≠",'NEQ'],['>','LT'],["≥",'LTE'],['<','GT'],["≤",'GTE']]:[['=','EQ'],["≠",'NEQ'],['<','LT'],["≤",'LTE'],['>','GT'],["≥",'GTE']];this.setHelpUrl(e.Msg.LOGIC_COMPARE_HELPURL),this.setColour(190),this.setOutput(!0,'Boolean'),this.appendValueInput('A'),this.appendValueInput('B').appendField(new e.FieldDropdown(t),'OP'),this.setInputsInline(!0);var n=this;this.setTooltip((function(){var t=n.getFieldValue('OP');return{EQ:e.Msg.LOGIC_COMPARE_TOOLTIP_EQ,NEQ:e.Msg.LOGIC_COMPARE_TOOLTIP_NEQ,LT:e.Msg.LOGIC_COMPARE_TOOLTIP_LT,LTE:e.Msg.LOGIC_COMPARE_TOOLTIP_LTE,GT:e.Msg.LOGIC_COMPARE_TOOLTIP_GT,GTE:e.Msg.LOGIC_COMPARE_TOOLTIP_GTE}[t]})),this.prevBlocks_=[null,null]}},e.Blocks.bi_logic_operation={init:function(){var t=[[e.Msg.LOGIC_OPERATION_AND,'AND'],[e.Msg.LOGIC_OPERATION_OR,'OR']];this.setHelpUrl(e.Msg.LOGIC_OPERATION_HELPURL),this.setColour(190),this.setOutput(!0,'Boolean'),this.appendValueInput('A'),this.appendValueInput('B').appendField(new e.FieldDropdown(t),'OP'),this.setInputsInline(!0);var n=this;this.setTooltip((function(){var t=n.getFieldValue('OP');return{AND:e.Msg.LOGIC_OPERATION_TOOLTIP_AND,OR:e.Msg.LOGIC_OPERATION_TOOLTIP_OR}[t]}))}},e.Blocks.bi_try_catch={init:function(){this.appendStatementInput('try').setCheck(null).appendField('try'),this.appendStatementInput('catch').setCheck(null).appendField('catch').appendField(new e.FieldTextInput(''),'parameter'),this.appendStatementInput('finally').setCheck(null).appendField('finally'),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setColour(90),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_catch={init:function(){this.appendStatementInput('catch').setCheck(null).appendField('catch').appendField(new e.FieldTextInput(''),'parameter'),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setColour(90),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_throw={init:function(){this.appendValueInput('throw').setCheck(null).appendField('throw'),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setColour(120),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_yield={init:function(){this.appendValueInput('yield').setCheck(null).appendField('yield').appendField(new e.FieldCheckbox('FALSE'),'delegate'),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setColour(120),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_yield_return={init:function(){this.appendValueInput('yield').setCheck(null).appendField('yield').appendField(new e.FieldCheckbox('FALSE'),'delegate'),this.setOutput(!0),this.setColour(120),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_code_part={init:function(){this.appendDummyInput().appendField('Code part').appendField(new e.FieldTextInput(''),'code'),this.setOutput(!0,null),this.setColour(330),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_code_line={init:function(){this.appendDummyInput().appendField('Code line').appendField(new e.FieldTextInput(''),'code'),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setColour(330),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_access_field={init:function(){this.appendDummyInput().appendField('set').appendField(new e.FieldVariable('item'),'variable'),this.appendDummyInput().appendField('.').appendField(new e.FieldTextInput(''),'field'),this.appendValueInput('input').appendField('to'),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setInputsInline(!0),this.setColour(330),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_set_to={init:function(){this.appendDummyInput().appendField('set').appendField(new e.FieldTextInput(''),'code'),this.appendValueInput('input').appendField('to'),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setInputsInline(!0),this.setColour(330),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_for={init:function(){this.appendStatementInput('init').appendField('for init'),this.appendValueInput('test').appendField('test'),this.appendStatementInput('update').appendField('update'),this.appendStatementInput('chain').appendField('loop').setCheck(null),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setColour(120),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_for_in={init:function(){this.appendValueInput('array').appendField('for').appendField(new e.FieldTextInput('i'),'var').appendField('in'),this.appendStatementInput('chain').setCheck(null),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setColour(120),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_continue={init:function(){this.appendDummyInput().appendField('continue'),this.setHelpUrl('http://www.example.com/'),this.setColour(120),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setTooltip('')}},e.Blocks.bi_break={init:function(){this.appendDummyInput().appendField('break'),this.setHelpUrl('http://www.example.com/'),this.setColour(120),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setTooltip('')}},e.Blocks.bi_s1={init:function(){this.setHelpUrl('http://www.example.com/'),this.setColour(290),this.appendAddSubStatement('for init','items',null,''),this.appendValueInput('test').appendField('test').setCheck(null),this.itemCount_=1,this.setInputsInline(!1),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setTooltip('')}},e.Blocks.bi_return={init:function(){this.appendValueInput('ret').setCheck(null).appendField('return'),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setColour(290),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_var={init:function(){this.appendValueInput('val').setCheck(null).appendField(new e.FieldDropdown([['var','var'],['let','let'],['const','const']]),'var_type').appendField(new e.FieldTextInput('var1'),'var'),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setColour(330),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_var_name={init:function(){this.appendDummyInput().appendField('').appendField(new e.FieldTextInput('var1'),'NAME'),this.setOutput(!0,null),this.setColour(330),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_new={init:function(){this.appendValueInput('chain').appendField('new').setCheck(null),this.setOutput(!0,null),this.setColour(55),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_anonymous_class={init:function(){this.appendDummyInput().appendField('class').appendField(new e.FieldTextInput(''),'NAME'),this.appendDummyInput().appendField('extends').appendField(new e.FieldTextInput(''),'extends'),this.appendStatementInput('chain').setCheck(null),this.setHelpUrl('http://www.example.com/'),this.setColour(55),this.setOutput(!0,null),this.setTooltip('')}},e.Blocks.bi_class={init:function(){this.appendDummyInput().appendField('class').appendField(new e.FieldTextInput('Name'),'NAME'),this.appendDummyInput().appendField('extends').appendField(new e.FieldTextInput(''),'extends'),this.appendStatementInput('chain').setCheck(null),this.setHelpUrl('http://www.example.com/'),this.setColour(55),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setTooltip('')}},e.Blocks.bi_static={init:function(){this.appendStatementInput('static').setCheck(null).appendField('static'),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setColour(55),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_get={init:function(){this.appendStatementInput('get').setCheck(null).appendField('get'),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setColour(55),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_set={init:function(){this.appendStatementInput('set').setCheck(null).appendField('set'),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setColour(55),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_field={init:function(){this.appendValueInput('chain').appendField(new e.FieldTextInput('field1'),'NAME').setCheck(null),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setColour(330),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_field_return={init:function(){this.appendValueInput('chain').appendField('').appendField(new e.FieldTextInput('field1'),'NAME').setCheck(null),this.setOutput(!0,null),this.setColour(330),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_string_return={init:function(){this.appendValueInput('chain').appendField('"').appendField(new e.FieldTextInput(''),'NAME').appendField('"').setCheck(null),this.setOutput(!0,null),this.setColour(160),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_index={init:function(){this.appendValueInput('index').appendField('[').setCheck(null),this.appendValueInput('chain').appendField(']').setCheck(null),this.setInputsInline(!0),this.setOutput(!0,null),this.setColour(260),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_adaptor={init:function(){this.appendDummyInput().appendField(''),this.appendStatementInput('chain').setCheck(null),this.setOutput(!0,null),this.setColour(55),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_statement={init:function(){this.appendDummyInput().appendField(''),this.appendStatementInput('chain').setCheck(null),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setColour(290),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_unary={init:function(){this.appendValueInput('expression').setCheck(null).appendField(new e.FieldTextInput('++'),'operator'),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setColour(230),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_unary_return={init:function(){this.appendValueInput('expression').setCheck(null).appendField(new e.FieldTextInput('++'),'operator'),this.setOutput(!0,null),this.setColour(230),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_unary_postfix={init:function(){this.appendValueInput('expression').appendField('postfix').setCheck(null).appendField(new e.FieldTextInput('++'),'operator'),this.setPreviousStatement(!0,null),this.setNextStatement(!0,null),this.setColour(230),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_unary_postfix_return={init:function(){this.appendValueInput('expression').appendField('postfix').setCheck(null).appendField(new e.FieldTextInput('++'),'operator'),this.setOutput(!0,null),this.setColour(230),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_spread={init:function(){this.appendValueInput('arg_array').setCheck(null).appendField('...'),this.setOutput(!0,null),this.setColour(290),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks.bi_parenthesis={init:function(){this.appendValueInput('expression').setCheck(null).appendField('(_)'),this.setOutput(!0,null),this.setColour(230),this.setTooltip(''),this.setHelpUrl('http://www.example.com/')}},e.Blocks}},function(e,t){e.exports=function(e){return e.JavaScript.bi_comment=function(e){return''},e.JavaScript.bi_assignment=function(t){var n=e.JavaScript.valueToCode(t,'A',e.JavaScript.ORDER_ATOMIC),a=e.JavaScript.valueToCode(t,'B',e.JavaScript.ORDER_ATOMIC);return n+' '+t.getFieldValue('OP')+' '+a+"\n"},e.JavaScript.bi_assignment_return=function(t){var n=e.JavaScript.valueToCode(t,'A',e.JavaScript.ORDER_ATOMIC),a=e.JavaScript.valueToCode(t,'B',e.JavaScript.ORDER_ATOMIC);return[n+' '+t.getFieldValue('OP')+' '+a,e.JavaScript.ORDER_ATOMIC]},e.JavaScript.bi_math_arithmetic=function(t){var n={ADD:[' + ',e.JavaScript.ORDER_ADDITION],MINUS:[' - ',e.JavaScript.ORDER_SUBTRACTION],MULTIPLY:[' * ',e.JavaScript.ORDER_MULTIPLICATION],DIVIDE:[' / ',e.JavaScript.ORDER_DIVISION],POWER:[null,e.JavaScript.ORDER_COMMA]}[t.getFieldValue('OP')],a=' ',i=e.JavaScript.ORDER_ATOMIC;n&&(a=n[0],i=n[1]);var l=e.JavaScript.valueToCode(t,'A',i)||'0',o=e.JavaScript.valueToCode(t,'B',i)||'0';return a?[l+a+o,i]:['Math.pow('+l+', '+o+')',e.JavaScript.ORDER_FUNCTION_CALL]},e.JavaScript.bi_logic_compare=function(t){var n={EQ:'==',NEQ:'!=',LT:'<',LTE:'<=',GT:'>',GTE:'>='}[t.getFieldValue('OP')],a='=='===n||'!='===n?e.JavaScript.ORDER_EQUALITY:e.JavaScript.ORDER_RELATIONAL;return[(e.JavaScript.valueToCode(t,'A',a)||'0')+' '+n+' '+(e.JavaScript.valueToCode(t,'B',a)||'0'),a]},e.JavaScript.bi_logic_operation=function(t){var n='AND'===t.getFieldValue('OP')?'&&':'||',a='&&'===n?e.JavaScript.ORDER_LOGICAL_AND:e.JavaScript.ORDER_LOGICAL_OR,i=e.JavaScript.valueToCode(t,'A',a),l=e.JavaScript.valueToCode(t,'B',a);if(i||l){var o='&&'===n?'true':'false';i||(i=o),l||(l=o)}else i='false',l='false';return[i+' '+n+' '+l,a]},e.JavaScript.bi_try_catch=function(t){var n=e.JavaScript.statementToCode(t,'try'),a=e.JavaScript.statementToCode(t,'catch'),i=e.JavaScript.statementToCode(t,'finally');return'try{\n'+n+'\n} catch('+t.getFieldValue('parameter')+'){\n'+a+'\n} finally{\n'+i+"}\n"},e.JavaScript.bi_catch=function(t){var n=e.JavaScript.statementToCode(t,'catch');return'catch('+t.getFieldValue('parameter')+'){\n'+n+'}\n'},e.JavaScript.bi_throw=function(t){return'throw '+e.JavaScript.valueToCode(t,'throw',e.JavaScript.ORDER_ATOMIC)+'\n'},e.JavaScript.bi_yield=function(t){var n=e.JavaScript.valueToCode(t,'yield',e.JavaScript.ORDER_ATOMIC),a='';return a='TRUE'===t.getFieldValue('delegate')?'yield* ':'yield ',a+=n+'\n'},e.JavaScript.bi_yield_return=function(t){var n=e.JavaScript.valueToCode(t,'yield',e.JavaScript.ORDER_ATOMIC),a='';return a='TRUE'===t.getFieldValue('delegate')?'yield* ':'yield ',[a+=n,e.JavaScript.ORDER_ATOMIC]},e.JavaScript.bi_export=function(t){return'export '+e.JavaScript.statementToCode(t,'export')},e.JavaScript.bi_import=function(t){for(var n=new Array(t.itemCount_-1),a=1;a1&&void 0!==arguments[1]?arguments[1]:{};u()(this,e);var a=n.toolbox||"\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n 10\n \n \n \n \n \n \n i\n \n \n 1\n \n \n \n \n 10\n \n \n \n \n 1\n \n \n \n \n \n \n \n \n 123\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n 1\n \n \n \n \n 100\n \n \n \n \n \n \n 1\n \n \n \n \n 100\n \n \n \n \n \n \n \n \n \n \n \n \n 5\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n abc\n \n \n \n \n \n \n \n \n \n \n \n \n \n {textVariable}\n \n \n \n \n abc\n \n \n \n \n \n \n {textVariable}\n \n \n \n \n \n \n {textVariable}\n \n \n \n \n \n \n abc\n \n \n \n \n \n \n abc\n \n \n \n \n \n \n abc\n \n \n \n \n \n \n abc\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n 100\n \n \n \n \n 50\n \n \n \n \n 0\n \n \n \n \n \n \n #ff0000\n \n \n \n \n #3333ff\n \n \n \n \n 0.5\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n ".concat(n.toolboxPush,"\n \n \n \n \n \n \n randomize\n \n \n x\n \n \n 1\n \n \n \n \n \n \n list\n \n \n \n \n \n \n 1\n \n \n \n \n y\n \n \n \n \n 1\n \n \n \n \n \n \n list\n \n \n \n \n \n \n \n \n temp\n \n \n \n GET\n FROM_START\n \n \n y\n \n \n \n \n list\n \n \n \n \n \n \n \n \n y\n \n \n \n \n list\n \n \n \n \n \n GET\n FROM_START\n \n \n x\n \n \n \n \n list\n \n \n \n \n \n \n \n \n x\n \n \n \n \n list\n \n \n \n \n temp\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n 'Twas brillig, and the slithy toves\n \n \n \n \n \n \n Did gyre and gimble in the wabe:\n \n \n \n \n \n \n All mimsy were the borogroves,\n \n \n \n \n \n \n And the mome raths outgrabe.\n \n \n \n \n \n \n \n \n \n \n \n \n \"Beware the Jabberwock, my son!\n \n \n \n \n \n \n The jaws that bite, the claws that catch!\n \n \n \n \n \n \n Beware the Jubjub bird, and shun\n \n \n \n \n \n \n The frumious Bandersnatch!\"\n \n \n \n \n \n \n \n \n \n \n \n ");this.workspace=Blockly.inject(t,b({toolbox:a,zoom:{controls:!0,wheel:!0,startScale:1,maxScale:3,minScale:.2,scaleSpeed:1.2},grid:{spacing:20,length:3,color:'#ccc',snap:!0},trashcan:!0},n.workspaceOptions))}return m()(e,[{key:"hide",value:function(){}}]),e}();function _(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function f(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:{},n=e.Commands,a=e.Modal,i=e.Components,l=t.modalTitle,o=t.codeViewOptions,r=t.commandBlocklyScript,c=t.blocklyOptions,s=t.blocklyTypesSupport,u=t.toolbarIcon,d=t.onRun,m=t.onError,h=t.starter,b=null,_=null,T=function(e,t){t instanceof HTMLElement?e.appendChild(t):t&&e.insertAdjacentHTML('beforeend',t)};s&&s.forEach((function(e){var n=i.getType(e).model;i.addType(e,{model:{initToolbar:function(){n.prototype.initToolbar.apply(this,arguments);var e=this.get('toolbar'),a=e.some((function(e){return e.command===p}));a||(e.unshift(f({command:p,label:u},t.toolbarBtnBlockly)),this.set('toolbar',e))}}})})),n.add(p,f({keyBlocklyXml:"blockly-xml",run:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};this.editor=e,this.options=n,this.target=n.target||e.getSelected();var a=this.target;a&&this.showCustomCode(a)},stop:function(e){b.workspace.clear(),a.close()},showCustomCode:function(e){var t=this,n=this.editor,i=this.options.title||l;_||(_=this.getContent());e.getScriptString();a.open({title:i,content:_}).getModel().once('change:open',(function(){return n.stopCommand(t.id)})),b||(b=new v(_.querySelector('#blockly'),c)).workspace.addChangeListener((function(){return t.updateWorkspace()}));var o=e.get("blockly-xml")||h;Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(o),b.workspace)},getPreContent:function(){},getPostContent:function(){var e=document.createElement('div');e.id="code-viewer";var t=this.getCodeViewer();return t.refresh(),setTimeout((function(){return t.focus()}),0),e.appendChild(t.getElement()),e},getContent:function(){var e=this.editor,t=document.createElement('div'),n=document.createElement('div');n.id="blockly-cont",n.innerHTML="
";var a=e.getConfig('stylePrefix');return t.className="".concat(a,"inject-logic"),T(t,this.getPreContent()),t.appendChild(n),T(t,this.getPostContent()),T(t,this.getContentActions()),t},getContentActions:function(){var e=this,n=this.editor,a=document.createElement('div');a.id="actns",a.style="position:absolute;bottom:260px;right:20px;z-index:2";var i=document.createElement('button'),l=n.getConfig('stylePrefix');i.innerHTML=t.buttonLabel,i.className="".concat(l,"btn-prim ").concat(l,"btn-save__inject-logic"),i.onclick=function(){return e.handleSave()};var o=document.createElement('div');return o.id="logic-toolbar",o.className="fa fa-bug",o.style="margin:5px;padding:10px;background:rgba(0,0,0,0.2);border-radius:3px;border:1px solid rgba(0,0,0,0.2);cursor:pointer",o.onclick=function(){return e.runCode()},a.appendChild(o),a.appendChild(i),a},handleSave:function(){var e=this.editor,t=this.target,n=this.getCodeViewer().getContent(),a=Blockly.Xml.workspaceToDom(b.workspace);t.set('script',n),t.set("blockly-xml",Blockly.Xml.domToText(a)),e.Modal.close()},getCodeViewer:function(){var e=this.editor;return this.codeViewer||(this.codeViewer=e.CodeManager.createViewer(f({codeName:'javascript',theme:'hopscotch',readOnly:1,autoBeautify:1},o))),this.codeViewer},toggleCodeViewer:function(){var e=_.querySelector('#blockly').style,t=_.querySelector('#code-viewer').style;'0px'==e.height||'0'==e.height?(e.height="500px",t.display="none"):(e.height="0",t.display="block")},updateWorkspace:function(e){var t=Blockly.JavaScript.workspaceToCode(Blockly.mainWorkspace);try{this.getCodeViewer().setContent(t)}catch(e){}},sync:function(){this.getCodeViewer().getContent()},runCode:function(){try{var e=this.getCodeViewer().getContent();Function('"use strict";'+e)(),d&&d()}catch(e){console.log("error",e),m&&m(e)}}},r))};function k(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function y(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:{},n=y(y({},{blocklyOptions:{toolbox:'',toolboxPush:'',workspaceOptions:{}},starter:'letelthis',toolbarIcon:'',blocklyTypesSupport:['default','wrapper','text','textnode','image','video','svg'],toolbarBtnBlockly:{},onRun:function(){return console.log('valid syntax')},onError:function(e){return console.log('error',e)},modalTitle:'Blockly',codeViewOptions:{},buttonLabel:'Save',commandBlocklyScript:{}}),t);if(!Blockly)throw new Error('Blockly instance not found');o()(Blockly),c()(Blockly),T(e,n)}}])})); 3 | //# sourceMappingURL=grapesjs-blockly.min.js.map -------------------------------------------------------------------------------- /src/utils/js2blocks.js: -------------------------------------------------------------------------------- 1 | // BlocksIDE is a project to create a complete js Blocks Development Platform 2 | // 3 | // Copyright 2016 Juan Carlos Orozco 4 | // 5 | // BlocksIDE was written by Juan Carlos Orozco and released under an Apache version 2 license. 6 | // 7 | // Git repositories for BlocksIDE are available at 8 | // 9 | // https://github.com/JC-Orozco/BlocksIDE 10 | // 11 | // Licensed under the Apache License, Version 2.0 (the "License"); 12 | // you may not use this file except in compliance with the License. 13 | // You may obtain a copy of the License at 14 | // 15 | // http://www.apache.org/licenses/LICENSE-2.0 16 | // 17 | // Unless required by applicable law or agreed to in writing, software 18 | // distributed under the License is distributed on an "AS IS" BASIS, 19 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | // See the License for the specific language governing permissions and 21 | // limitations under the License. 22 | 23 | // Uses code from walk.js script of acorn.js javascript code parser under MIT license 24 | // https://github.com/ternjs/acorn 25 | 26 | //require('acorn') 27 | import { 28 | parse 29 | } from 'acorn'; 30 | //import acorn from 'acorn-dynamic-import'; 31 | //import walk, { base } from 'acorn-jsx-walk'; 32 | //import walk from 'acorn/dist/walk.js' 33 | 34 | //var script1 = '/test/code_math1.js'; 35 | //var script1 = '/test/code_arrays1.js'; 36 | //var script1 = '/test/code_maps1.js'; 37 | //var script1 = '/test/code_loops1.js'; 38 | //var script1 = '/test/code_switch1.js'; 39 | //var script1 = '/test/code_paths1.js'; 40 | //var script1 = '/test/code_functions1.js'; 41 | //var script1 = '/test/code_class1.js'; 42 | //var script1 = '/test/code_try1.js'; 43 | //var script1 = '/test/code_generator1.js'; 44 | //var script1 = '/test/code_export1.js'; 45 | //var script1 = '/test/code_import1.js'; 46 | 47 | //var script1 = '/test/code1_e.js'; 48 | 49 | //var tokens = []; 50 | //var out1 = document.getElementById("out1"); 51 | 52 | var debug = true; 53 | 54 | //var outln = function(msg){ 55 | // out1.innerHTML += msg+'
'; 56 | //} 57 | // 58 | //var out = function(msg){ 59 | // out1.innerHTML += msg; 60 | //} 61 | /////////////////////////// 62 | export function simple(node, visitors, base1, state, override) { 63 | if (!base1) base1 = base; 64 | (function c(node, st, override) { 65 | let type = override || node.type, 66 | found = visitors[type] 67 | base1[type](node, st, c) 68 | if (found) found(node, st) 69 | })(node, state, override) 70 | } 71 | 72 | // An ancestor walk keeps an array of ancestor nodes (including the 73 | // current node) and passes them to the callback as third parameter 74 | // (and also as state parameter when no other state is present). 75 | export function ancestor(node, visitors, base1, state) { 76 | if (!base1) base1 = base 77 | let ancestors = []; 78 | (function c(node, st, override) { 79 | let type = override || node.type, 80 | found = visitors[type] 81 | let isNew = node !== ancestors[ancestors.length - 1] 82 | if (isNew) ancestors.push(node) 83 | base1[type](node, st, c) 84 | if (found) found(node, st || ancestors, ancestors) 85 | if (isNew) ancestors.pop() 86 | })(node, state) 87 | } 88 | 89 | // A recursive walk is one where your functions override the default 90 | // walkers. They can modify and replace the state parameter that's 91 | // threaded through the walk, and can opt how and whether to walk 92 | // their child nodes (by calling their third argument on these 93 | // nodes). 94 | export function recursive(node, state, funcs, base1, override) { 95 | if (!base1) base1 = base 96 | let visitor = funcs ? make(funcs, base1) : base; 97 | (function c(node, st, override) { 98 | visitor[override || node.type](node, st, c) 99 | })(node, state, override) 100 | } 101 | 102 | function makeTest(test) { 103 | if (typeof test === "string") 104 | return type => type === test 105 | else if (!test) 106 | return () => true 107 | else 108 | return test 109 | } 110 | 111 | class Found { 112 | constructor(node, state) { 113 | this.node = node; 114 | this.state = state 115 | } 116 | } 117 | 118 | // Find a node with a given start, end, and type (all are optional, 119 | // null can be used as wildcard). Returns a {node, state} object, or 120 | // undefined when it doesn't find a matching node. 121 | export function findNodeAt(node, start, end, test, base1, state) { 122 | test = makeTest(test) 123 | if (!base1) base1 = base 124 | try { 125 | ; 126 | (function c(node, st, override) { 127 | let type = override || node.type 128 | if ((start == null || node.start <= start) && 129 | (end == null || node.end >= end)) 130 | base1[type](node, st, c) 131 | if ((start === null || node.start === start) && 132 | (end === null || node.end === end) && 133 | test(type, node)) 134 | throw new Found(node, st) 135 | })(node, state) 136 | } catch (e) { 137 | if (e instanceof Found) return e 138 | throw e 139 | } 140 | } 141 | 142 | // Find the innermost node of a given type that contains the given 143 | // position. Interface similar to findNodeAt. 144 | export function findNodeAround(node, pos, test, base1, state) { 145 | test = makeTest(test) 146 | if (!base1) base1 = base 147 | try { 148 | ; 149 | (function c(node, st, override) { 150 | let type = override || node.type 151 | if (node.start > pos || node.end < pos) return 152 | base1[type](node, st, c) 153 | if (test(type, node)) throw new Found(node, st) 154 | })(node, state) 155 | } catch (e) { 156 | if (e instanceof Found) return e 157 | throw e 158 | } 159 | } 160 | 161 | // Find the outermost matching node after a given position. 162 | export function findNodeAfter(node, pos, test, base1, state) { 163 | test = makeTest(test) 164 | if (!base1) base1 = base 165 | try { 166 | ; 167 | (function c(node, st, override) { 168 | if (node.end < pos) return 169 | let type = override || node.type 170 | if (node.start >= pos && test(type, node)) throw new Found(node, st) 171 | base1[type](node, st, c) 172 | })(node, state) 173 | } catch (e) { 174 | if (e instanceof Found) return e 175 | throw e 176 | } 177 | } 178 | 179 | // Find the outermost matching node before a given position. 180 | export function findNodeBefore(node, pos, test, base1, state) { 181 | test = makeTest(test) 182 | if (!base1) base1 = base 183 | let max; 184 | (function c(node, st, override) { 185 | if (node.start > pos) return 186 | let type = override || node.type 187 | if (node.end <= pos && (!max || max.node.end < node.end) && test(type, node)) 188 | max = new Found(node, st) 189 | base1[type](node, st, c) 190 | })(node, state) 191 | return max 192 | } 193 | 194 | // Fallback to an Object.create polyfill for older environments. 195 | const create = Object.create || function (proto) { 196 | function Ctor() {} 197 | Ctor.prototype = proto 198 | return new Ctor() 199 | } 200 | 201 | // Used to create a custom walker. Will fill in all missing node 202 | // type properties with the defaults. 203 | export function make(funcs, base1) { 204 | if (!base1) base1 = base 205 | let visitor = create(base1) 206 | for (var type in funcs) visitor[type] = funcs[type] 207 | return visitor 208 | } 209 | 210 | function skipThrough(node, st, c) { 211 | c(node, st) 212 | } 213 | 214 | function ignore(_node, _st, _c) {} 215 | 216 | // Node walkers. 217 | 218 | export const base = {} 219 | 220 | base.Program = base.BlockStatement = (node, st, c) => { 221 | for (let i = 0; i < node.body.length; ++i) 222 | c(node.body[i], st, "Statement") 223 | } 224 | base.Statement = skipThrough 225 | base.EmptyStatement = ignore 226 | base.ExpressionStatement = base.ParenthesizedExpression = 227 | (node, st, c) => c(node.expression, st, "Expression") 228 | base.IfStatement = (node, st, c) => { 229 | c(node.test, st, "Expression") 230 | c(node.consequent, st, "Statement") 231 | if (node.alternate) c(node.alternate, st, "Statement") 232 | } 233 | base.LabeledStatement = (node, st, c) => c(node.body, st, "Statement") 234 | base.BreakStatement = base.ContinueStatement = ignore 235 | base.WithStatement = (node, st, c) => { 236 | c(node.object, st, "Expression") 237 | c(node.body, st, "Statement") 238 | } 239 | base.SwitchStatement = (node, st, c) => { 240 | c(node.discriminant, st, "Expression") 241 | for (let i = 0; i < node.cases.length; ++i) { 242 | let cs = node.cases[i] 243 | if (cs.test) c(cs.test, st, "Expression") 244 | for (let j = 0; j < cs.consequent.length; ++j) 245 | c(cs.consequent[j], st, "Statement") 246 | } 247 | } 248 | base.ReturnStatement = base.YieldExpression = base.AwaitExpression = (node, st, c) => { 249 | if (node.argument) c(node.argument, st, "Expression") 250 | } 251 | base.ThrowStatement = base.SpreadElement = 252 | (node, st, c) => c(node.argument, st, "Expression") 253 | base.TryStatement = (node, st, c) => { 254 | c(node.block, st, "Statement") 255 | if (node.handler) c(node.handler, st) 256 | if (node.finalizer) c(node.finalizer, st, "Statement") 257 | } 258 | base.CatchClause = (node, st, c) => { 259 | c(node.param, st, "Pattern") 260 | c(node.body, st, "ScopeBody") 261 | } 262 | base.WhileStatement = base.DoWhileStatement = (node, st, c) => { 263 | c(node.test, st, "Expression") 264 | c(node.body, st, "Statement") 265 | } 266 | base.ForStatement = (node, st, c) => { 267 | if (node.init) c(node.init, st, "ForInit") 268 | if (node.test) c(node.test, st, "Expression") 269 | if (node.update) c(node.update, st, "Expression") 270 | c(node.body, st, "Statement") 271 | } 272 | base.ForInStatement = base.ForOfStatement = (node, st, c) => { 273 | c(node.left, st, "ForInit") 274 | c(node.right, st, "Expression") 275 | c(node.body, st, "Statement") 276 | } 277 | base.ForInit = (node, st, c) => { 278 | if (node.type === "VariableDeclaration") c(node, st) 279 | else c(node, st, "Expression") 280 | } 281 | base.DebuggerStatement = ignore 282 | 283 | base.FunctionDeclaration = (node, st, c) => c(node, st, "Function") 284 | base.VariableDeclaration = (node, st, c) => { 285 | for (let i = 0; i < node.declarations.length; ++i) 286 | c(node.declarations[i], st) 287 | } 288 | base.VariableDeclarator = (node, st, c) => { 289 | c(node.id, st, "Pattern") 290 | if (node.init) c(node.init, st, "Expression") 291 | } 292 | 293 | base.Function = (node, st, c) => { 294 | if (node.id) c(node.id, st, "Pattern") 295 | for (let i = 0; i < node.params.length; i++) 296 | c(node.params[i], st, "Pattern") 297 | c(node.body, st, node.expression ? "ScopeExpression" : "ScopeBody") 298 | } 299 | // FIXME drop these node types in next major version 300 | // (They are awkward, and in ES6 every block can be a scope.) 301 | base.ScopeBody = (node, st, c) => c(node, st, "Statement") 302 | base.ScopeExpression = (node, st, c) => c(node, st, "Expression") 303 | 304 | base.Pattern = (node, st, c) => { 305 | if (node.type === "Identifier") 306 | c(node, st, "VariablePattern") 307 | else if (node.type === "MemberExpression") 308 | c(node, st, "MemberPattern") 309 | else 310 | c(node, st) 311 | } 312 | base.VariablePattern = ignore 313 | base.MemberPattern = skipThrough 314 | base.RestElement = (node, st, c) => c(node.argument, st, "Pattern") 315 | base.ArrayPattern = (node, st, c) => { 316 | for (let i = 0; i < node.elements.length; ++i) { 317 | let elt = node.elements[i] 318 | if (elt) c(elt, st, "Pattern") 319 | } 320 | } 321 | base.ObjectPattern = (node, st, c) => { 322 | for (let i = 0; i < node.properties.length; ++i) 323 | c(node.properties[i].value, st, "Pattern") 324 | } 325 | 326 | base.Expression = skipThrough 327 | base.ThisExpression = base.Super = base.MetaProperty = ignore 328 | base.ArrayExpression = (node, st, c) => { 329 | for (let i = 0; i < node.elements.length; ++i) { 330 | let elt = node.elements[i] 331 | if (elt) c(elt, st, "Expression") 332 | } 333 | } 334 | base.ObjectExpression = (node, st, c) => { 335 | for (let i = 0; i < node.properties.length; ++i) 336 | c(node.properties[i], st) 337 | } 338 | base.FunctionExpression = base.ArrowFunctionExpression = base.FunctionDeclaration 339 | base.SequenceExpression = base.TemplateLiteral = (node, st, c) => { 340 | for (let i = 0; i < node.expressions.length; ++i) 341 | c(node.expressions[i], st, "Expression") 342 | } 343 | base.UnaryExpression = base.UpdateExpression = (node, st, c) => { 344 | c(node.argument, st, "Expression") 345 | } 346 | base.BinaryExpression = base.LogicalExpression = (node, st, c) => { 347 | c(node.left, st, "Expression") 348 | c(node.right, st, "Expression") 349 | } 350 | base.AssignmentExpression = base.AssignmentPattern = (node, st, c) => { 351 | c(node.left, st, "Pattern") 352 | c(node.right, st, "Expression") 353 | } 354 | base.ConditionalExpression = (node, st, c) => { 355 | c(node.test, st, "Expression") 356 | c(node.consequent, st, "Expression") 357 | c(node.alternate, st, "Expression") 358 | } 359 | base.NewExpression = base.CallExpression = (node, st, c) => { 360 | c(node.callee, st, "Expression") 361 | if (node.arguments) 362 | for (let i = 0; i < node.arguments.length; ++i) 363 | c(node.arguments[i], st, "Expression") 364 | } 365 | base.MemberExpression = (node, st, c) => { 366 | c(node.object, st, "Expression") 367 | if (node.computed) c(node.property, st, "Expression") 368 | } 369 | base.ExportNamedDeclaration = base.ExportDefaultDeclaration = (node, st, c) => { 370 | if (node.declaration) 371 | c(node.declaration, st, node.type === "ExportNamedDeclaration" || node.declaration.id ? "Statement" : "Expression") 372 | if (node.source) c(node.source, st, "Expression") 373 | } 374 | base.ExportAllDeclaration = (node, st, c) => { 375 | c(node.source, st, "Expression") 376 | } 377 | base.ImportDeclaration = (node, st, c) => { 378 | for (let i = 0; i < node.specifiers.length; i++) 379 | c(node.specifiers[i], st) 380 | c(node.source, st, "Expression") 381 | } 382 | base.ImportSpecifier = base.ImportDefaultSpecifier = base.ImportNamespaceSpecifier = base.Identifier = base.Literal = ignore 383 | 384 | base.TaggedTemplateExpression = (node, st, c) => { 385 | c(node.tag, st, "Expression") 386 | c(node.quasi, st) 387 | } 388 | base.ClassDeclaration = base.ClassExpression = (node, st, c) => c(node, st, "Class") 389 | base.Class = (node, st, c) => { 390 | if (node.id) c(node.id, st, "Pattern") 391 | if (node.superClass) c(node.superClass, st, "Expression") 392 | for (let i = 0; i < node.body.body.length; i++) 393 | c(node.body.body[i], st) 394 | } 395 | base.MethodDefinition = base.Property = (node, st, c) => { 396 | if (node.computed) c(node.key, st, "Expression") 397 | c(node.value, st, "Expression") 398 | } 399 | 400 | /////////////////////////// 401 | export function walk1(ast, comments, block_loc, options) { 402 | var st = {}; 403 | var funcs = {}; 404 | options = options || {} 405 | comments = comments || [] 406 | var last_comment = 0 407 | options.joinTopBlocks = options.joinTopBlocks || false 408 | 409 | var createElement = Blockly.utils.xml.createElement; 410 | 411 | //var xml = ['xml']; 412 | var xml1 = createElement('xml'); 413 | var root_node = xml1; 414 | var current_node = root_node; 415 | //var variable_next = null; 416 | var current_call = false; 417 | var current_path_chain = []; 418 | var expression_statement = false; 419 | var for_init = false; 420 | var first_variable_declarator = true; 421 | var id = 0; 422 | 423 | var newNode = function (name, attrs, text, ast_node) { 424 | var block1 425 | if (name === 'block') { 426 | block_loc[id] = ast_node.loc 427 | console.log(id + ' ' + ast_node.loc.start.line); 428 | attrs.id = id; 429 | id += 1; 430 | block1 = createElement('block'); 431 | 432 | let comm1 433 | let first = true 434 | let i = last_comment 435 | while (i < comments.length && comments[i].loc.start.line <= ast_node.loc.start.line) { 436 | if (first) { 437 | first = false 438 | comm1 = createElement('comment') 439 | comm1.setAttribute('pinned', 'false') 440 | comm1.append(comments[i].value) 441 | block1.append(comm1) 442 | } else { 443 | comm1.append('\n' + comments[i].value) 444 | } 445 | i += 1 446 | } 447 | last_comment = i 448 | } else { 449 | block1 = createElement(name); 450 | } 451 | for (var key in attrs) { 452 | block1.setAttribute(key, attrs[key]); 453 | } 454 | if (text) block1.append(text); 455 | return block1; 456 | }; 457 | 458 | // Based on acornjs walk.js recursive parser: 459 | //var skipThrough = function(node, st, c) { c(node, st) } 460 | var ignore = function (_node, _st, _c) {} 461 | 462 | funcs.Program = funcs.BlockStatement = (node, st, c) => { 463 | for (let i = 0; i < node.body.length; ++i) 464 | c(node.body[i], st, "Statement") 465 | } 466 | funcs.Statement = function (node, st, c) { 467 | if (debug) console.log("Statement"); 468 | c(node, st) 469 | if (!options.joinTopBlocks && current_node === root_node) { 470 | let lastChild = current_node.children.length 471 | //console.log('Statement '+lastChild); 472 | current_node.children[lastChild - 1].setAttribute('x', '0'); 473 | current_node.children[lastChild - 1].setAttribute('y', (lastChild * 10).toString()); 474 | } else { 475 | if (current_node.children.length > 0) { 476 | var next1 = newNode('next'); 477 | current_node.children[0].appendChild(next1); 478 | current_node = next1; 479 | } 480 | } 481 | } 482 | funcs.EmptyStatement = ignore 483 | funcs.ExpressionStatement = (node, st, c) => { 484 | if (debug) console.log("ExpressionStatement"); 485 | expression_statement = true; 486 | c(node.expression, st, "Expression") 487 | } 488 | funcs.ParenthesizedExpression = (node, st, c) => { 489 | if (debug) console.log("ParenthesizedExpression"); 490 | c(node.expression, st, "Expression") 491 | } 492 | funcs.IfStatement = (node, st, c) => { 493 | if (debug) console.log("IfStatement"); 494 | var block1 = newNode('block', { 495 | type: 'controls_if' 496 | }, '', node); 497 | current_node.appendChild(block1); 498 | if (node.alternate) { 499 | var mutation1 = newNode('mutation', { 500 | else: '1' 501 | }); 502 | block1.appendChild(mutation1); 503 | } 504 | var value1 = newNode('value', { 505 | name: 'IF0' 506 | }); 507 | block1.appendChild(value1); 508 | var node1 = current_node; 509 | current_node = value1; 510 | c(node.test, st, "Expression") 511 | var statement1 = newNode('statement', { 512 | name: 'DO0' 513 | }); 514 | block1.appendChild(statement1); 515 | current_node = statement1; 516 | c(node.consequent, st, "Statement") 517 | if (node.alternate) { 518 | var statement2 = newNode('statement', { 519 | name: 'ELSE' 520 | }); 521 | block1.appendChild(statement2); 522 | current_node = statement2; 523 | c(node.alternate, st, "Statement") 524 | } 525 | current_node = node1; 526 | } 527 | funcs.LabeledStatement = (node, st, c) => { 528 | if (debug) console.log("LabeledStatement"); 529 | c(node.body, st, "Statement") 530 | } 531 | funcs.BreakStatement = function (node, st, c) { 532 | if (debug) console.log("ContinueStatement"); 533 | var block1 = newNode('block', { 534 | type: 'bi_break' 535 | }, '', node) 536 | current_node.appendChild(block1) 537 | } // ignore 538 | funcs.ContinueStatement = function (node, st, c) { 539 | if (debug) console.log("BreakStatement"); 540 | var block1 = newNode('block', { 541 | type: 'bi_continue' 542 | }, '', node) 543 | current_node.appendChild(block1) 544 | } // ignore 545 | funcs.WithStatement = (node, st, c) => { 546 | if (debug) console.log("WithStatement"); 547 | c(node.object, st, "Expression") 548 | c(node.body, st, "Statement") 549 | } 550 | funcs.SwitchStatement = (node, st, c) => { 551 | if (debug) console.log("SwitchStatement"); 552 | var block1 = newNode('block', { 553 | type: 'bi_switch' 554 | }, '', node); 555 | current_node.appendChild(block1); 556 | var node1 = current_node; 557 | // Check if default case is present 558 | var cases_len = node.cases.length 559 | var hasDefault = 0; 560 | if (cases_len && (node.cases[cases_len - 1].test == null)) { 561 | hasDefault = 1; 562 | } 563 | var mutation1 = newNode('mutation', { 564 | items: node.cases.length + 1 - hasDefault 565 | }) // TODO: Take out +1 when items count corrected on AddSub block 566 | block1.appendChild(mutation1) 567 | var switch1 = newNode('value', { 568 | name: 'switch' 569 | }) 570 | block1.appendChild(switch1) 571 | current_node = switch1; 572 | c(node.discriminant, st, "Expression") 573 | for (let i = 0; i < node.cases.length - hasDefault; ++i) { 574 | let item = newNode('value', { 575 | name: 'items' + (i + 1) 576 | }) 577 | block1.appendChild(item) 578 | let case1 = newNode('block', { 579 | type: 'bi_case' 580 | }, '', node) 581 | item.appendChild(case1) 582 | let test1 = newNode('value', { 583 | name: 'case' 584 | }) 585 | case1.appendChild(test1) 586 | current_node = test1 587 | let cs = node.cases[i] 588 | if (cs.test) c(cs.test, st, "Expression") 589 | let statement1 = newNode('value', { 590 | name: 'statement' 591 | }) 592 | case1.appendChild(statement1) 593 | current_node = statement1 594 | for (let j = 0; j < cs.consequent.length; ++j) 595 | c(cs.consequent[j], st, "Statement") 596 | } 597 | if (hasDefault) { 598 | let default1 = newNode('statement', { 599 | name: 'default' 600 | }) 601 | block1.appendChild(default1) 602 | current_node = default1 603 | let cs = node.cases[node.cases.length - 1] 604 | for (let j = 0; j < cs.consequent.length; ++j) 605 | c(cs.consequent[j], st, "Statement") 606 | } 607 | current_node = node1 608 | } 609 | funcs.ReturnStatement = (node, st, c) => { 610 | if (debug) console.log("ReturnStatement"); 611 | var block1 = newNode('block', { 612 | type: 'bi_return' 613 | }, '', node); 614 | var value1 = newNode('value', { 615 | name: 'ret' 616 | }); 617 | block1.appendChild(value1); 618 | current_node.appendChild(block1); 619 | var node1 = current_node; 620 | current_node = value1; 621 | if (node.argument) c(node.argument, st, "Expression") 622 | current_node = node1; 623 | } 624 | funcs.YieldExpression = (node, st, c) => { 625 | if (debug) console.log("YieldExpression"); 626 | var block1; 627 | var delegate1; 628 | if (node.delegate) { 629 | delegate1 = newNode('field', { 630 | name: 'delegate' 631 | }, 'TRUE') 632 | } else { 633 | delegate1 = newNode('field', { 634 | name: 'delegate' 635 | }, 'FALSE') 636 | } 637 | if (expression_statement) { 638 | expression_statement = false; 639 | block1 = newNode('block', { 640 | type: 'bi_yield' 641 | }, '', node); 642 | } else { 643 | block1 = newNode('block', { 644 | type: 'bi_yield_return' 645 | }, '', node); 646 | } 647 | block1.appendChild(delegate1); 648 | var value1 = newNode('value', { 649 | name: 'yield' 650 | }); 651 | block1.appendChild(value1); 652 | current_node.appendChild(block1); 653 | var node1 = current_node; 654 | current_node = value1; 655 | if (node.argument) c(node.argument, st, "Expression") 656 | current_node = node1; 657 | } 658 | funcs.AwaitExpression = (node, st, c) => { 659 | if (debug) console.log("AwaitExpression"); 660 | if (node.argument) c(node.argument, st, "Expression") 661 | } 662 | funcs.ThrowStatement = 663 | (node, st, c) => { 664 | if (debug) console.log("ThrowStatement"); 665 | var block1 = newNode('block', { 666 | type: 'bi_throw' 667 | }, '', node) 668 | current_node.appendChild(block1) 669 | var throw1 = newNode('value', { 670 | name: 'throw' 671 | }) 672 | block1.appendChild(throw1) 673 | var node1 = current_node 674 | current_node = throw1 675 | c(node.argument, st, "Expression") 676 | current_node = node1 677 | } 678 | funcs.SpreadElement = 679 | (node, st, c) => { 680 | if (debug) console.log("SpreadElement"); 681 | var block1 = newNode('block', { 682 | type: 'bi_spread' 683 | }, '', node) 684 | current_node.appendChild(block1) 685 | var spread1 = newNode('value', { 686 | name: 'arg_array' 687 | }) 688 | block1.appendChild(spread1) 689 | var node1 = current_node 690 | current_node = spread1 691 | c(node.argument, st, "Expression") 692 | current_node = node1 693 | } 694 | funcs.TryStatement = (node, st, c) => { 695 | if (debug) console.log("TryStatement"); 696 | var block1 = newNode('block', { 697 | type: 'bi_try_catch' 698 | }, '', node) 699 | current_node.appendChild(block1) 700 | var node1 = current_node 701 | var try1 = newNode('statement', { 702 | name: 'try' 703 | }) 704 | block1.appendChild(try1) 705 | current_node = try1 706 | c(node.block, st, "Statement") 707 | if (node.handler) { 708 | let param1 = newNode('field', { 709 | name: 'parameter' 710 | }, node.handler.param.name) 711 | block1.appendChild(param1) 712 | let catch1 = newNode('statement', { 713 | name: 'catch' 714 | }) 715 | block1.appendChild(catch1) 716 | current_node = catch1 717 | c(node.handler, st) 718 | } 719 | if (node.finalizer) { 720 | let finally1 = newNode('statement', { 721 | name: 'finally' 722 | }) 723 | block1.appendChild(finally1) 724 | current_node = finally1 725 | c(node.finalizer, st, "Statement") 726 | } 727 | current_node = node1 728 | } 729 | funcs.CatchClause = (node, st, c) => { 730 | if (debug) console.log("CatchClause"); 731 | //c(node.param, st, "Pattern") // JCOA: Already taken care of in the TryStatement 732 | c(node.body, st, "ScopeBody") 733 | } 734 | funcs.WhileStatement = funcs.DoWhileStatement = (node, st, c) => { 735 | if (debug) console.log("WhileStatement"); 736 | var block1 = newNode('block', { 737 | type: 'controls_whileUntil' 738 | }, '', node) 739 | current_node.appendChild(block1); 740 | var mode1 = newNode('field', { 741 | name: 'MODE' 742 | }, 'WHILE') 743 | block1.appendChild(mode1) 744 | var test1 = newNode('value', { 745 | name: 'BOOL' 746 | }) 747 | block1.appendChild(test1) 748 | var node1 = current_node; 749 | current_node = test1; 750 | c(node.test, st, "Expression") 751 | var body1 = newNode('statement', { 752 | name: 'DO' 753 | }) 754 | block1.appendChild(body1) 755 | current_node = body1; 756 | c(node.body, st, "Statement") 757 | current_node = node1 758 | } 759 | funcs.ForStatement = (node, st, c) => { 760 | if (debug) console.log("ForStatement"); 761 | var block1 = newNode('block', { 762 | type: 'bi_for' 763 | }, '', node); 764 | current_node.appendChild(block1); 765 | var init1 = newNode('statement', { 766 | name: 'init' 767 | }); 768 | block1.appendChild(init1); 769 | var node1 = current_node; 770 | current_node = init1; 771 | if (node.init) c(node.init, st, "ForInit") 772 | var test1 = newNode('value', { 773 | name: 'test' 774 | }); 775 | block1.appendChild(test1); 776 | current_node = test1; 777 | if (node.test) c(node.test, st, "Expression") 778 | var update1 = newNode('statement', { 779 | name: 'update' 780 | }); 781 | block1.appendChild(update1); 782 | current_node = update1; 783 | expression_statement = true; 784 | if (node.update) c(node.update, st, "Expression") 785 | //if (node.update) c(node.update, st, "Statement") 786 | var statement1 = newNode('statement', { 787 | name: 'chain' 788 | }); 789 | block1.appendChild(statement1); 790 | current_node = statement1; 791 | c(node.body, st, "Statement") 792 | current_node = node1; 793 | } 794 | // TODO: Separate ForOfStatement? 795 | // Only works with one variable declaration. 796 | funcs.ForInStatement = funcs.ForOfStatement = (node, st, c) => { 797 | if (debug) console.log("ForInStatement"); 798 | var block1 = newNode('block', { 799 | type: 'bi_for_in' 800 | }, '', node); 801 | current_node.appendChild(block1); 802 | var init1 = newNode('field', { 803 | name: 'var' 804 | }, node.left.declarations[0].id.name); // Only one declaration allowed. 805 | block1.appendChild(init1); 806 | //c(node.left, st, "ForInit") // We are setting the variable here. 807 | var array1 = newNode('value', { 808 | name: 'array' 809 | }); 810 | block1.appendChild(array1); 811 | var node1 = current_node; 812 | current_node = array1; 813 | c(node.right, st, "Expression") 814 | var statement1 = newNode('statement', { 815 | name: 'chain' 816 | }); 817 | block1.appendChild(statement1); 818 | current_node = statement1; 819 | c(node.body, st, "Statement") 820 | current_node = node1; 821 | } 822 | funcs.ForInit = (node, st, c) => { 823 | for_init = true; 824 | if (debug) console.log("ForInit"); 825 | if (node.type === "VariableDeclaration") { 826 | c(node, st) 827 | } 828 | // else { 829 | // c(node, st, "Statement") 830 | // } 831 | else { 832 | expression_statement = true; 833 | c(node, st, "Expression") 834 | } 835 | for_init = false; 836 | } 837 | funcs.DebuggerStatement = ignore 838 | 839 | funcs.FunctionDeclaration = (node, st, c) => { 840 | if (debug) console.log("FunctionDeclaration"); 841 | c(node, st, "Function") 842 | } 843 | funcs.VariableDeclaration = (node, st, c) => { 844 | first_variable_declarator = true; 845 | //variable_next = null; 846 | if (debug) console.log("VariableDeclaration"); 847 | for (let i = 0; i < node.declarations.length; ++i) { 848 | node.declarations[i].kind = node.kind; 849 | c(node.declarations[i], st) 850 | } 851 | } 852 | funcs.VariableDeclarator = (node, st, c) => { 853 | if (debug) console.log("VariableDeclarator"); 854 | //c(node.id, st, "Pattern") // Commented to avoid duplicating var name block. 855 | // JCOA: Can I reuse the blockly block constructor? 856 | if (!first_variable_declarator) { 857 | let next1 = newNode('next'); 858 | current_node.children[0].appendChild(next1); 859 | current_node = next1; 860 | //let node1 = current_node; 861 | if (for_init) { 862 | let block1 = newNode('block', { 863 | type: 'bi_assignment' 864 | }, '', node); 865 | current_node.appendChild(block1); 866 | var field1 = newNode('field', { 867 | name: 'OP' 868 | }, '='); 869 | block1.appendChild(field1); 870 | var left = newNode('value', { 871 | name: 'A' 872 | }); 873 | block1.appendChild(left); 874 | var node1 = current_node; 875 | current_node = left; 876 | c(node.id, st, "Pattern") 877 | var right = newNode('value', { 878 | name: 'B' 879 | }); 880 | block1.appendChild(right); 881 | current_node = right; 882 | 883 | if (node.init) c(node.init, st, "Expression") 884 | current_node = node1; 885 | } else { 886 | let node1 = current_node; 887 | let block1 = newNode('block', { 888 | type: 'bi_var' 889 | }, '', node) 890 | block1.appendChild(newNode('field', { 891 | name: 'var_type' 892 | }, node.kind)); 893 | block1.appendChild(newNode('field', { 894 | name: 'var' 895 | }, node.id.name)); 896 | let value1 = newNode('value', { 897 | name: 'val' 898 | }); 899 | block1.appendChild(value1); 900 | current_node.appendChild(block1); 901 | current_node = value1; 902 | if (node.init) c(node.init, st, "Expression") 903 | current_node = node1; 904 | } 905 | } else { 906 | let node1 = current_node; 907 | let block1 = newNode('block', { 908 | type: 'bi_var' 909 | }, '', node) 910 | block1.appendChild(newNode('field', { 911 | name: 'var_type' 912 | }, node.kind)); 913 | block1.appendChild(newNode('field', { 914 | name: 'var' 915 | }, node.id.name)); 916 | let value1 = newNode('value', { 917 | name: 'val' 918 | }); 919 | block1.appendChild(value1); 920 | //if(variable_next){ 921 | // variable_next.appendChild(block1) 922 | //} else { 923 | current_node.appendChild(block1); 924 | //} 925 | current_node = value1; 926 | if (node.init) c(node.init, st, "Expression") 927 | current_node = node1; 928 | //variable_next = newNode('next') 929 | //current_node.appendChild(variable_next); 930 | ////current_node.appendChild(variable_next); 931 | //block1.appendChild(variable_next); 932 | } 933 | first_variable_declarator = false; 934 | } 935 | funcs.Function = function (node, st, c) { 936 | if (debug) console.log("Function"); 937 | var block1; 938 | var generator1; 939 | if (node.generator) { 940 | generator1 = newNode('field', { 941 | name: 'function_type' 942 | }, 'function* ') 943 | } else { 944 | generator1 = newNode('field', { 945 | name: 'function_type' 946 | }, 'function ') 947 | } 948 | //console.log(expression_statement) 949 | if (node.id) { 950 | //c(node.id, st, "Pattern") // JCOA: We are already using this name below (Function name) 951 | //console.log(node.id.name); 952 | if (expression_statement) { 953 | block1 = newNode('block', { 954 | type: 'bi_function_return' 955 | }, '', node); 956 | } else { 957 | block1 = newNode('block', { 958 | type: 'bi_function' 959 | }, '', node); 960 | } 961 | block1.appendChild(generator1) 962 | block1.appendChild(newNode('field', { 963 | name: 'name' 964 | }, node.id.name)); 965 | } else if (node.method) { 966 | block1 = newNode('block', { 967 | type: 'bi_function' 968 | }, '', node); 969 | block1.appendChild(newNode('field', { 970 | name: 'function_type' 971 | }, '')); 972 | block1.appendChild(newNode('field', { 973 | name: 'name' 974 | }, node.method)); 975 | } else { 976 | block1 = newNode('block', { 977 | type: 'bi_function_return' 978 | }, '', node); 979 | block1.appendChild(generator1) 980 | block1.appendChild(newNode('field', { 981 | name: 'name' 982 | }, '')); 983 | } 984 | var args = []; 985 | for (var i = 0; i < node.params.length; i++) { 986 | //c(node.params[i], st, "Pattern") // JCOA: We are already using this name below 987 | args.push(node.params[i].name); 988 | } 989 | block1.appendChild(newNode('field', { 990 | name: 'args' 991 | }, args.join(','))); 992 | var statement1 = newNode('statement', { 993 | name: 'chain' 994 | }); 995 | block1.appendChild(statement1); 996 | current_node.appendChild(block1); 997 | var node1 = current_node; 998 | current_node = statement1; 999 | c(node.body, st, node.expression ? "ScopeExpression" : "ScopeBody") 1000 | current_node = node1; 1001 | }; 1002 | 1003 | // FIXME drop these node types in next major version 1004 | // (They are awkward, and in ES6 every block can be a scope.) 1005 | //funcs.ScopeBody = (node, st, c) => c(node, st, "Statement") 1006 | //funcs.ScopeExpression = (node, st, c) => c(node, st, "Expression") 1007 | 1008 | funcs.Pattern = function (node, st, c) { 1009 | if (debug) console.log("Pattern " + node.type); 1010 | if (node.type === "Identifier") { 1011 | //make_text_block_from_text(node.name); 1012 | //outln(node.name); // TODO: Maybe do this on the custom VariablePattern funcs function 1013 | // var block1 = newNode('block', {type:'bi_field_return'}, '', node); 1014 | // block1.appendChild(newNode('field',{name:'NAME'},node.name)); 1015 | // var statement1 = newNode('statement',{name:'chain'}); 1016 | // block1.appendChild(statement1); 1017 | // current_path_chain.push(statement1); 1018 | // current_node.appendChild(block1); 1019 | c(node, st, "VariablePattern"); 1020 | } else if (node.type === "MemberExpression") 1021 | //outln(node.property.name); 1022 | c(node, st, "MemberPattern") 1023 | else 1024 | c(node, st) 1025 | }; 1026 | funcs.VariablePattern = function (node, st, c) { 1027 | if (debug) console.log("VariablePattern " + node.name); 1028 | var block1 = newNode('block', { 1029 | type: 'bi_var_name' 1030 | }, '', node); 1031 | block1.appendChild(newNode('field', { 1032 | name: 'NAME' 1033 | }, node.name)); 1034 | current_node.appendChild(block1); 1035 | }; // ignore 1036 | funcs.MemberPattern = function (node, st, c) { 1037 | if (debug) console.log("MemberPattern"); 1038 | c(node, st) 1039 | }; // skipTrough 1040 | funcs.RestElement = (node, st, c) => { 1041 | if (debug) console.log("RestElement"); 1042 | c(node.argument, st, "Pattern") 1043 | } 1044 | funcs.ArrayPattern = (node, st, c) => { 1045 | if (debug) console.log("ArrayPattern"); 1046 | for (let i = 0; i < node.elements.length; ++i) { 1047 | let elt = node.elements[i] 1048 | if (elt) c(elt, st, "Pattern") 1049 | } 1050 | } 1051 | funcs.ObjectPattern = (node, st, c) => { 1052 | if (debug) console.log("ObjectPattern"); 1053 | for (let i = 0; i < node.properties.length; ++i) 1054 | c(node.properties[i].value, st, "Pattern") 1055 | } 1056 | funcs.Expression = function (node, st, c) { 1057 | c(node, st) 1058 | }; // skipTrough() 1059 | funcs.ThisExpression = function (node, st, c) { 1060 | if (debug) console.log("ThisExpression"); 1061 | var block1; 1062 | if (current_call) { 1063 | current_call = false; 1064 | } else { 1065 | if (expression_statement) { 1066 | expression_statement = false; 1067 | block1 = newNode('block', { 1068 | type: 'bi_field' 1069 | }, '', node); 1070 | } else { 1071 | block1 = newNode('block', { 1072 | type: 'bi_field_return' 1073 | }, '', node); 1074 | } 1075 | block1.appendChild(newNode('field', { 1076 | name: 'NAME' 1077 | }, "this")); 1078 | var value1 = newNode('value', { 1079 | name: 'chain' 1080 | }); 1081 | block1.appendChild(value1); 1082 | current_path_chain.push(value1); 1083 | current_node.appendChild(block1); 1084 | } 1085 | }; // ignore 1086 | funcs.Super = function (node, st, c) { 1087 | if (debug) console.log("Super"); 1088 | var block1; 1089 | if (current_call) { 1090 | current_call = false; 1091 | } else { 1092 | if (expression_statement) { 1093 | expression_statement = false; 1094 | block1 = newNode('block', { 1095 | type: 'bi_field' 1096 | }, '', node); 1097 | } else { 1098 | block1 = newNode('block', { 1099 | type: 'bi_field_return' 1100 | }, '', node); 1101 | } 1102 | block1.appendChild(newNode('field', { 1103 | name: 'NAME' 1104 | }, "super")); 1105 | var value1 = newNode('value', { 1106 | name: 'chain' 1107 | }); 1108 | block1.appendChild(value1); 1109 | current_path_chain.push(value1); 1110 | current_node.appendChild(block1); 1111 | } 1112 | }; // ignore 1113 | funcs.MetaProperty = function (node, st, c) { 1114 | if (debug) console.log("MetaProperty"); 1115 | }; // ignore 1116 | funcs.ArrayExpression = (node, st, c) => { 1117 | if (debug) console.log("ArrayExpression"); 1118 | var block1 = newNode('block', { 1119 | type: 'lists_create_with' 1120 | }, '', node); 1121 | current_node.appendChild(block1); 1122 | var mutation1 = newNode('mutation', { 1123 | items: node.elements.length + 1 1124 | }); // TODO: Take out the +1 when list items number is corrected on core/blocks.js AddSub... 1125 | block1.appendChild(mutation1); 1126 | var node1 = current_node; 1127 | for (let i = 0; i < node.elements.length; ++i) { 1128 | let element1 = newNode('value', { 1129 | name: 'items' + (i + 1) 1130 | }); 1131 | block1.appendChild(element1); 1132 | current_node = element1; 1133 | let elt = node.elements[i] 1134 | if (elt) c(elt, st, "Expression") 1135 | } 1136 | current_node = node1; 1137 | } 1138 | funcs.ObjectExpression = (node, st, c) => { 1139 | if (debug) console.log("ObjectExpression"); 1140 | var block1 = newNode('block', { 1141 | type: 'maps_create_with' 1142 | }, '', node); 1143 | current_node.appendChild(block1); 1144 | var mutation1 = newNode('mutation', { 1145 | items: node.properties.length + 1 1146 | }); // TODO: Take out the +1 when list items number is corrected on core/blocks.js AddSub... 1147 | block1.appendChild(mutation1); 1148 | var node1 = current_node; 1149 | for (let i = 0; i < node.properties.length; ++i) { 1150 | let property1 = newNode('value', { 1151 | name: 'ADD' + (i + 1) 1152 | }); 1153 | block1.appendChild(property1); 1154 | current_node = property1; 1155 | c(node.properties[i], st) 1156 | } 1157 | current_node = node1; 1158 | } 1159 | // TODO. Separate and add debug print to each of this methods 1160 | funcs.FunctionExpression = funcs.ArrowFunctionExpression = funcs.FunctionDeclaration 1161 | funcs.SequenceExpression = funcs.TemplateLiteral = (node, st, c) => { 1162 | if (debug) console.log("SequenceExpression"); 1163 | var node1 = current_node; 1164 | for (let i = 0; i < node.expressions.length; ++i) { 1165 | if (i > 0) { 1166 | let next1 = newNode('next'); 1167 | current_node.children[0].appendChild(next1); 1168 | current_node = next1; 1169 | } 1170 | expression_statement = true; 1171 | c(node.expressions[i], st, "Expression"); 1172 | } 1173 | current_node = node1; 1174 | } 1175 | // TODO: Add ExpressionStatement case. Unary statement and Unary expression blocks. 1176 | // node.operator equal to for ex. '++' 1177 | funcs.UnaryExpression = funcs.UpdateExpression = (node, st, c) => { 1178 | if (debug) console.log("UnaryExpression"); 1179 | var block1 1180 | if (expression_statement) { 1181 | expression_statement = false; // Force to false. 1182 | if (node.prefix) { 1183 | block1 = newNode('block', { 1184 | type: 'bi_unary' 1185 | }, '', node); 1186 | } else { 1187 | block1 = newNode('block', { 1188 | type: 'bi_unary_postfix' 1189 | }, '', node); 1190 | } 1191 | } else { 1192 | if (node.prefix) { 1193 | block1 = newNode('block', { 1194 | type: 'bi_unary_return' 1195 | }, '', node); 1196 | } else { 1197 | block1 = newNode('block', { 1198 | type: 'bi_unary_postfix_return' 1199 | }, '', node); 1200 | } 1201 | } 1202 | current_node.appendChild(block1); 1203 | var field1 = newNode('field', { 1204 | name: 'operator' 1205 | }, node.operator); 1206 | block1.appendChild(field1); 1207 | var value1 = newNode('value', { 1208 | name: 'expression' 1209 | }); 1210 | block1.appendChild(value1); 1211 | var node1 = current_node; 1212 | current_node = value1; 1213 | c(node.argument, st, "Expression") 1214 | current_node = node1; 1215 | } 1216 | funcs.BinaryExpression = (node, st, c) => { 1217 | if (debug) console.log("BinaryExpression"); 1218 | var op; 1219 | var type = 'bi_math_arithmetic'; 1220 | switch (node.operator) { 1221 | case '+': 1222 | op = 'ADD'; 1223 | break; 1224 | case '-': 1225 | op = 'MINUS'; 1226 | break; 1227 | case '*': 1228 | op = 'MULTIPLY'; 1229 | break; 1230 | case '/': 1231 | op = 'DIVIDE'; 1232 | break; 1233 | case '**': 1234 | op = 'POWER'; 1235 | break; 1236 | case '==': 1237 | op = 'EQ'; 1238 | type = 'bi_logic_compare'; 1239 | break; 1240 | case '!=': 1241 | op = 'NEQ'; 1242 | type = 'bi_logic_compare'; 1243 | break; 1244 | case '<': 1245 | op = 'LT'; 1246 | type = 'bi_logic_compare'; 1247 | break; 1248 | case '<=': 1249 | op = 'LTE'; 1250 | type = 'bi_logic_compare'; 1251 | break; 1252 | case '>': 1253 | op = 'GT'; 1254 | type = 'bi_logic_compare'; 1255 | break; 1256 | case '>=': 1257 | op = 'GTE'; 1258 | type = 'bi_logic_compare'; 1259 | break; 1260 | case '&&': 1261 | op = 'AND'; 1262 | type = 'bi_logic_operation'; 1263 | break; 1264 | case '||': 1265 | op = 'OR'; 1266 | type = 'bi_logic_operation'; 1267 | break; 1268 | default: 1269 | op = node.operator; 1270 | type = 'bi_assignment_return'; 1271 | } 1272 | var block1 = newNode('block', { 1273 | type: type 1274 | }, '', node); 1275 | block1.appendChild(newNode('field', { 1276 | name: 'OP' 1277 | }, op)); 1278 | var value1 = newNode('value', { 1279 | name: 'A' 1280 | }); 1281 | block1.appendChild(value1); 1282 | current_node.appendChild(block1); 1283 | var node1 = current_node; 1284 | current_node = value1; 1285 | expression_statement = false; // JCOA: Avoid incompatible type link on the blocks 1286 | c(node.left, st, "Expression") 1287 | var value2 = newNode('value', { 1288 | name: 'B' 1289 | }); 1290 | block1.appendChild(value2); 1291 | current_node = value2; 1292 | expression_statement = false; // JCOA: Avoid incompatible type link on the blocks 1293 | c(node.right, st, "Expression") 1294 | current_node = node1; 1295 | } 1296 | funcs.LogicalExpression = (node, st, c) => { 1297 | if (debug) console.log("LogicalExpression"); 1298 | var op; 1299 | var type = 'bi_logic_operation'; 1300 | switch (node.operator) { 1301 | case '&&': 1302 | op = 'AND'; 1303 | break; 1304 | case '||': 1305 | op = 'OR'; 1306 | break; 1307 | default: 1308 | } 1309 | var block1 = newNode('block', { 1310 | type: type 1311 | }, '', node); 1312 | block1.appendChild(newNode('field', { 1313 | name: 'OP' 1314 | }, op)); 1315 | var value1 = newNode('value', { 1316 | name: 'A' 1317 | }); 1318 | block1.appendChild(value1); 1319 | current_node.appendChild(block1); 1320 | var node1 = current_node; 1321 | current_node = value1; 1322 | expression_statement = false; // JCOA: Avoid incompatible type link on the blocks 1323 | c(node.left, st, "Expression") 1324 | var value2 = newNode('value', { 1325 | name: 'B' 1326 | }); 1327 | block1.appendChild(value2); 1328 | current_node = value2; 1329 | expression_statement = false; // JCOA: Avoid incompatible type link on the blocks 1330 | c(node.right, st, "Expression") 1331 | current_node = node1; 1332 | } 1333 | funcs.AssignmentExpression = funcs.AssignmentPattern = (node, st, c) => { 1334 | if (debug) console.log("AssignmentExpression"); 1335 | var block1; 1336 | if (expression_statement) { 1337 | expression_statement = false; 1338 | block1 = newNode('block', { 1339 | type: 'bi_assignment' 1340 | }, '', node); 1341 | } else { 1342 | block1 = newNode('block', { 1343 | type: 'bi_assignment_return' 1344 | }, '', node); 1345 | } 1346 | current_node.appendChild(block1); 1347 | var field1 = newNode('field', { 1348 | name: 'OP' 1349 | }, node.operator); 1350 | block1.appendChild(field1); 1351 | var left = newNode('value', { 1352 | name: 'A' 1353 | }); 1354 | block1.appendChild(left); 1355 | var node1 = current_node; 1356 | current_node = left; 1357 | c(node.left, st, "Pattern") 1358 | var right = newNode('value', { 1359 | name: 'B' 1360 | }); 1361 | block1.appendChild(right); 1362 | current_node = right; 1363 | c(node.right, st, "Expression") 1364 | current_node = node1; 1365 | } 1366 | funcs.ConditionalExpression = (node, st, c) => { 1367 | if (debug) console.log("ConditionalExpression"); 1368 | c(node.test, st, "Expression") 1369 | c(node.consequent, st, "Expression") 1370 | c(node.alternate, st, "Expression") 1371 | } 1372 | funcs.NewExpression = (node, st, c) => { 1373 | if (debug) console.log("NewExpression"); 1374 | var block1 = newNode('block', { 1375 | type: 'bi_new' 1376 | }, '', node); 1377 | current_node.appendChild(block1); 1378 | var value1 = newNode('value', { 1379 | name: 'chain' 1380 | }); 1381 | block1.appendChild(value1); 1382 | current_call = true; 1383 | var call1 = newNode('block', { 1384 | type: 'bi_call_editable_return' 1385 | }, '', node); 1386 | value1.appendChild(call1) 1387 | var mutation1 = newNode('mutation', { 1388 | items: node.arguments.length + 1, 1389 | names: '' 1390 | }) // TODO: Take out +1 when AddSub... is fixed on the actual length required. 1391 | call1.appendChild(mutation1); 1392 | call1.appendChild(newNode('field', { 1393 | name: 'NAME' 1394 | }, node.callee.name)); 1395 | c(node.callee, st, "Expression") 1396 | //if (node.arguments) for (let i = 0; i < node.arguments.length; ++i) 1397 | // c(node.arguments[i], st, "Expression") 1398 | var node1 = current_node; 1399 | if (node.arguments) 1400 | for (let i = 0; i < node.arguments.length; ++i) { 1401 | let value2 = newNode('value', { 1402 | name: 'items' + (i + 1) 1403 | }); 1404 | call1.appendChild(value2); 1405 | current_node = value2; 1406 | c(node.arguments[i], st, "Expression") 1407 | } 1408 | current_node = node1; 1409 | block1.appendChild(value1); 1410 | } 1411 | funcs.CallExpression = (node, st, c) => { 1412 | if (debug) console.log("CallExpression"); 1413 | current_call = true; 1414 | var block1; 1415 | var node3; 1416 | var value1; 1417 | var name; 1418 | if (node.callee.type === "MemberExpression") { 1419 | block1 = newNode('block', { 1420 | type: 'bi_call_editable_return' 1421 | }, '', node); 1422 | name = node.callee.property.name; 1423 | } else if (node.callee.type === "Identifier") { 1424 | if (expression_statement) { 1425 | expression_statement = false; 1426 | block1 = newNode('block', { 1427 | type: 'bi_call_editable' 1428 | }, '', node); 1429 | } else { 1430 | block1 = newNode('block', { 1431 | type: 'bi_call_editable_return' 1432 | }, '', node); 1433 | } 1434 | current_node.appendChild(block1); 1435 | name = node.callee.name; 1436 | } else if (node.callee.type === "FunctionExpression") { 1437 | if (expression_statement) { 1438 | expression_statement = false; 1439 | block1 = newNode('block', { 1440 | type: 'bi_direct_call_editable' 1441 | }, '', node); 1442 | } else { 1443 | block1 = newNode('block', { 1444 | type: 'bi_direct_call_editable_return' 1445 | }, '', node); 1446 | } 1447 | current_node.appendChild(block1); 1448 | } 1449 | var mutation1 = newNode('mutation', { 1450 | items: node.arguments.length + 1, 1451 | names: '' 1452 | }) // TODO: Take out +1 when AddSub... is fixed on the actual length required. 1453 | block1.appendChild(mutation1); 1454 | node3 = current_node 1455 | if (node.callee.type === "FunctionExpression") { 1456 | let func1 = newNode('value', { 1457 | name: 'function' 1458 | }, '') 1459 | block1.appendChild(func1); 1460 | current_node = func1 1461 | current_call = false 1462 | expression_statement = true; 1463 | } else { 1464 | block1.appendChild(newNode('field', { 1465 | name: 'NAME' 1466 | }, name)); 1467 | } 1468 | value1 = newNode('value', { 1469 | name: 'chain' 1470 | }); 1471 | current_path_chain.push(value1); 1472 | c(node.callee, st, "Expression") 1473 | current_node = node3; 1474 | var path_chain1 = current_path_chain; // Save path chain 1475 | current_path_chain = []; 1476 | var node1 = current_node; 1477 | if (node.arguments) 1478 | for (let i = 0; i < node.arguments.length; ++i) { 1479 | let value2 = newNode('value', { 1480 | name: 'items' + (i + 1) 1481 | }); 1482 | block1.appendChild(value2); 1483 | current_node = value2; 1484 | c(node.arguments[i], st, "Expression") 1485 | } 1486 | current_node = node1; 1487 | block1.appendChild(value1); 1488 | current_path_chain = path_chain1; // Restore path chain 1489 | if (node.callee.type === "MemberExpression") { 1490 | if (current_path_chain.length > 0) { 1491 | let node2 = current_path_chain.pop(); 1492 | node2.appendChild(block1); 1493 | } 1494 | } 1495 | } 1496 | funcs.MemberExpression = (node, st, c) => { 1497 | if (debug) console.log("MemberExpression " + node.property.name); 1498 | var is_call = current_call; 1499 | var block1; 1500 | var block2; 1501 | if (is_call) { 1502 | current_call = false; 1503 | } else { 1504 | if (node.computed) { 1505 | block1 = newNode('block', { 1506 | type: 'bi_index' 1507 | }, '', node); 1508 | block2 = newNode('value', { 1509 | name: 'index' 1510 | }); 1511 | block1.appendChild(block2); 1512 | } else { 1513 | block1 = newNode('block', { 1514 | type: 'bi_field_return' 1515 | }, '', node); 1516 | block1.appendChild(newNode('field', { 1517 | name: 'NAME' 1518 | }, node.property.name)); 1519 | } 1520 | var value1 = newNode('value', { 1521 | name: 'chain' 1522 | }); 1523 | block1.appendChild(value1); 1524 | current_path_chain.push(value1); 1525 | } 1526 | c(node.object, st, "Expression") 1527 | if (node.computed) { 1528 | if (is_call) { 1529 | current_call = false; 1530 | } else { 1531 | //block2 = newNode('block', {type:'bi_index'}, '', node); 1532 | //current_node.appendChild(block2); 1533 | //let block3 = newNode('value', {name:'index'}); 1534 | //block2.appendChild(block3); 1535 | let node1 = current_node; 1536 | current_node = block2; 1537 | var path_chain1 = current_path_chain; // Save path chain 1538 | current_path_chain = []; 1539 | c(node.property, st, "Expression") 1540 | current_path_chain = path_chain1; 1541 | current_node = node1; 1542 | } 1543 | } else { 1544 | if (is_call) { 1545 | current_call = false; 1546 | } 1547 | } 1548 | if (!is_call) { 1549 | if (current_path_chain.length > 0) { 1550 | let node1 = current_path_chain.pop(); 1551 | node1.appendChild(block1); 1552 | } 1553 | } 1554 | //current_path_chain.appendChild(block1); 1555 | } 1556 | funcs.ExportNamedDeclaration = (node, st, c) => { 1557 | if (debug) console.log("ExportNamedDeclaration"); 1558 | var block1 = newNode('block', { 1559 | type: 'bi_export' 1560 | }, '', node); 1561 | current_node.appendChild(block1); 1562 | var statement1 = newNode('statement', { 1563 | name: 'export' 1564 | }); 1565 | block1.appendChild(statement1) 1566 | var node1 = current_node; 1567 | current_node = statement1; 1568 | if (node.declaration) 1569 | c(node.declaration, st, node.type === "ExportNamedDeclaration" || node.declaration.id ? "Statement" : "Expression") 1570 | if (node.source) c(node.source, st, "Expression") 1571 | current_node = node1; 1572 | } 1573 | funcs.ExportDefaultDeclaration = (node, st, c) => { 1574 | if (debug) console.log("ExportDefaultDeclaration"); 1575 | if (node.declaration) 1576 | c(node.declaration, st, node.type === "ExportNamedDeclaration" || node.declaration.id ? "Statement" : "Expression") 1577 | if (node.source) c(node.source, st, "Expression") 1578 | } 1579 | funcs.ExportAllDeclaration = (node, st, c) => { 1580 | if (debug) console.log("ExportAllDeclaration"); 1581 | c(node.source, st, "Expression") 1582 | } 1583 | funcs.ImportDeclaration = (node, st, c) => { 1584 | if (debug) console.log("ImportDeclaration"); 1585 | var block1 = newNode('block', { 1586 | type: 'bi_import' 1587 | }, '', node); 1588 | current_node.appendChild(block1); 1589 | var node1 = current_node; 1590 | var mutation1 = newNode('mutation', { 1591 | items: node.specifiers.length + 1 1592 | }) // TODO: Take out +1 when items count corrected on AddSub block 1593 | block1.appendChild(mutation1) 1594 | for (let i = 0; i < node.specifiers.length; i++) { 1595 | let item = newNode('value', { 1596 | name: 'items' + (i + 1) 1597 | }) 1598 | block1.appendChild(item) 1599 | current_node = item 1600 | c(node.specifiers[i], st) 1601 | } 1602 | var from1 = newNode('value', { 1603 | name: 'from' 1604 | }); 1605 | block1.appendChild(from1) 1606 | current_node = from1; 1607 | c(node.source, st, "Expression") 1608 | current_node = node1 1609 | } 1610 | funcs.ImportSpecifier = function (node, st, c) { 1611 | if (debug) console.log("ImportSpecifier"); 1612 | var block1 1613 | if (node.imported.name === node.local.name) { 1614 | block1 = newNode('block', { 1615 | type: 'bi_var_name' 1616 | }, '', node); 1617 | block1.appendChild(newNode('field', { 1618 | name: 'NAME' 1619 | }, node.local.name)); 1620 | } else { 1621 | block1 = newNode('block', { 1622 | type: 'bi_import_as' 1623 | }, '', node); 1624 | block1.appendChild(newNode('field', { 1625 | name: 'input' 1626 | }, node.imported.name)); 1627 | block1.appendChild(newNode('field', { 1628 | name: 'as' 1629 | }, node.local.name)); 1630 | } 1631 | current_node.appendChild(block1); 1632 | } //ignore 1633 | funcs.ImportDefaultSpecifier = function (node, st, c) { 1634 | if (debug) console.log("ImportDefaultSpecifier"); 1635 | var block1 1636 | if (node.local.name === '') { 1637 | block1 = newNode('block', { 1638 | type: 'bi_var_name' 1639 | }, '', node); 1640 | block1.appendChild(newNode('field', { 1641 | name: 'NAME' 1642 | }, '*')); 1643 | } else { 1644 | block1 = newNode('block', { 1645 | type: 'bi_import_as' 1646 | }, '', node); 1647 | block1.appendChild(newNode('field', { 1648 | name: 'input' 1649 | }, '*')); 1650 | block1.appendChild(newNode('field', { 1651 | name: 'as' 1652 | }, node.local.name)); 1653 | } 1654 | current_node.appendChild(block1); 1655 | } //ignore 1656 | funcs.ImportNamespaceSpecifier = function (node, st, c) { 1657 | if (debug) console.log("ImportNameSpecifier"); 1658 | var block1 = newNode('block', { 1659 | type: 'bi_var_name' 1660 | }, '', node); 1661 | block1.appendChild(newNode('field', { 1662 | name: 'NAME' 1663 | }, node.local.name)); 1664 | current_node.appendChild(block1); 1665 | } //ignore 1666 | 1667 | funcs.Identifier = function (node, st, c) { 1668 | if (debug) console.log("Identifier " + node.name); 1669 | if (current_call) { 1670 | current_call = false; 1671 | } else { 1672 | var block1; 1673 | if (expression_statement) { 1674 | expression_statement = false; 1675 | block1 = newNode('block', { 1676 | type: 'bi_field' 1677 | }, '', node); 1678 | } else { 1679 | block1 = newNode('block', { 1680 | type: 'bi_field_return' 1681 | }, '', node); 1682 | } 1683 | block1.appendChild(newNode('field', { 1684 | name: 'NAME' 1685 | }, node.name)); 1686 | var value1 = newNode('value', { 1687 | name: 'chain' 1688 | }); 1689 | block1.appendChild(value1); 1690 | current_path_chain.push(value1); 1691 | current_node.appendChild(block1); 1692 | } 1693 | } //ignore 1694 | funcs.Literal = (node, st, c) => { 1695 | if (debug) console.log("Literal " + node.value); 1696 | // TODO: Test literal string 1697 | // var block1 = goog.dom.createDom('block'); 1698 | // block1.setAttribute('type', 'math_number'); 1699 | // var field1 = goog.dom.createDom('field'); 1700 | // field1.setAttribute('name', 'NUM'); 1701 | // field1.append(node.value); 1702 | // block1.appendChild(field1); 1703 | var block1; 1704 | var field1; 1705 | if (node.value instanceof RegExp) { 1706 | // TODO JCOA: Add a specific block for RegExp 1707 | block1 = newNode('block', { 1708 | type: 'bi_var_name' 1709 | }, '', node); 1710 | block1.appendChild(newNode('field', { 1711 | name: "NAME" 1712 | }, node.value)); 1713 | } else { 1714 | switch (typeof node.value) { 1715 | case 'number': 1716 | block1 = newNode('block', { 1717 | type: 'math_number' 1718 | }, '', node); 1719 | block1.appendChild(newNode('field', { 1720 | name: 'NUM' 1721 | }, node.value.toString())); 1722 | break; 1723 | case 'boolean': 1724 | block1 = newNode('block', { 1725 | type: 'logic_boolean' 1726 | }, '', node) 1727 | if (node.value) { 1728 | field1 = newNode('field', { 1729 | name: 'BOOL' 1730 | }, 'TRUE') 1731 | } else { 1732 | field1 = newNode('field', { 1733 | name: 'BOOL' 1734 | }, 'FALSE') 1735 | } 1736 | block1.appendChild(field1) 1737 | break 1738 | default: 1739 | block1 = newNode('block', { 1740 | type: 'bi_string_return' 1741 | }, '', node); 1742 | block1.appendChild(newNode('field', { 1743 | name: 'NAME' 1744 | }, node.value)); 1745 | let value1 = newNode('value', { 1746 | name: 'chain' 1747 | }); 1748 | block1.appendChild(value1); 1749 | current_path_chain.push(value1); 1750 | } 1751 | } 1752 | current_node.appendChild(block1); 1753 | } // ignore() 1754 | funcs.TaggedTemplateExpression = (node, st, c) => { 1755 | if (debug) console.log("TaggedTemplateExpression " + node.tag); 1756 | c(node.tag, st, "Expression") 1757 | c(node.quasi, st) 1758 | } 1759 | funcs.Class = (node, st, c) => { 1760 | if (debug) console.log("Class"); 1761 | var block1; 1762 | if (node.id) { 1763 | block1 = newNode('block', { 1764 | type: 'bi_class' 1765 | }, '', node); 1766 | block1.appendChild(newNode('field', { 1767 | name: 'NAME' 1768 | }, node.id.name)); 1769 | // c(node.id, st, "Pattern") // JCOA: We are already using the class name. 1770 | } else { 1771 | block1 = newNode('block', { 1772 | type: 'bi_anonymous_class' 1773 | }, '', node); 1774 | } 1775 | if (node.superClass) { 1776 | let extends1 = newNode('field', { 1777 | name: 'extends' 1778 | }, node.superClass.name) 1779 | block1.appendChild(extends1) 1780 | // c(node.superClass, st, "Expression") // JCOA Already used the node.superClass.name 1781 | } 1782 | var statement1 = newNode('statement', { 1783 | name: 'chain' 1784 | }); 1785 | block1.appendChild(statement1); 1786 | current_node.appendChild(block1); 1787 | var node1 = current_node; 1788 | current_node = statement1; 1789 | for (let i = 0; i < node.body.body.length; i++) 1790 | c(node.body.body[i], st) 1791 | current_node = node1; 1792 | } 1793 | // body.body[i].kind -> constructor, get, set, method 1794 | // body.body[i].key.name 1795 | funcs.MethodDefinition = (node, st, c) => { 1796 | if (debug) console.log("MethodDefinition " + node.kind); 1797 | var block1 1798 | var node1 = current_node 1799 | var statement1 1800 | if (node.static) { 1801 | let static1 = newNode('block', { 1802 | type: 'bi_static' 1803 | }, '', node) 1804 | current_node.appendChild(static1) 1805 | let statement2 = newNode('statement', { 1806 | name: 'static' 1807 | }) 1808 | static1.appendChild(statement2) 1809 | current_node = statement2 1810 | } 1811 | switch (node.kind) { 1812 | case 'constructor': 1813 | //block1 = newNode('block', {type: 'bi_var'}, '', node); 1814 | //block1.appendChild(newNode('field', {name:'var'}, node.kind)); 1815 | node.value.method = node.kind 1816 | break; 1817 | case 'method': 1818 | node.value.method = node.key.name 1819 | break; 1820 | case 'get': 1821 | block1 = newNode('block', { 1822 | type: 'bi_get' 1823 | }, '', node) 1824 | current_node.appendChild(block1) 1825 | statement1 = newNode('statement', { 1826 | name: 'get' 1827 | }) 1828 | block1.appendChild(statement1) 1829 | current_node = statement1 1830 | node.value.method = node.key.name 1831 | break 1832 | case 'set': 1833 | block1 = newNode('block', { 1834 | type: 'bi_set' 1835 | }, '', node) 1836 | current_node.appendChild(block1) 1837 | statement1 = newNode('statement', { 1838 | name: 'set' 1839 | }) 1840 | block1.appendChild(statement1) 1841 | current_node = statement1 1842 | node.value.method = node.key.name 1843 | break 1844 | default: 1845 | //block1 = newNode('block', {type: 'bi_var'}, '', node); 1846 | //block1.appendChild(newNode('field', {name:'var'}, node.kind)); 1847 | break; 1848 | } 1849 | if (node.computed) c(node.key, st, "Expression") 1850 | c(node.value, st, "Expression") 1851 | let next1 = newNode('next') 1852 | node1.children[0].appendChild(next1); 1853 | current_node = next1 1854 | //current_node = node1; 1855 | } 1856 | // TODO: Take into account all node.computed cases. 1857 | funcs.Property = (node, st, c) => { 1858 | if (debug) console.log("Property " + node.kind); 1859 | var block1; 1860 | var node1; 1861 | var chain1; 1862 | switch (node.kind) { 1863 | case 'set': 1864 | block1 = newNode('block', { 1865 | type: 'bi_maps_set' 1866 | }, '', node); 1867 | current_node.appendChild(block1); 1868 | if (node.computed === false) { 1869 | block1.appendChild(newNode('field', { 1870 | name: 'name' 1871 | }, node.key.name)); 1872 | } else { 1873 | block1.appendChild(newNode('field', { 1874 | name: 'name' 1875 | }, '[' + node.key.name + ']')); 1876 | } 1877 | block1.appendChild(newNode('field', { 1878 | name: 'val' 1879 | }, node.value.params[0].name)); 1880 | chain1 = newNode('statement', { 1881 | name: 'chain' 1882 | }); 1883 | block1.appendChild(chain1); 1884 | node1 = current_node; 1885 | current_node = chain1; 1886 | c(node.value.body, st, "Statement") 1887 | current_node = node1; 1888 | break; 1889 | case 'get': 1890 | block1 = newNode('block', { 1891 | type: 'bi_maps_get' 1892 | }, '', node); 1893 | current_node.appendChild(block1); 1894 | if (node.computed === false) { 1895 | block1.appendChild(newNode('field', { 1896 | name: 'name' 1897 | }, node.key.name)); 1898 | } else { 1899 | block1.appendChild(newNode('field', { 1900 | name: 'name' 1901 | }, '[' + node.key.name + ']')); 1902 | } 1903 | chain1 = newNode('statement', { 1904 | name: 'chain' 1905 | }); 1906 | block1.appendChild(chain1); 1907 | node1 = current_node; 1908 | current_node = chain1; 1909 | c(node.value.body, st, "Statement") 1910 | current_node = node1; 1911 | break; 1912 | default: 1913 | block1 = newNode('block', { 1914 | type: 'maps_create' 1915 | }, '', node); 1916 | current_node.appendChild(block1); 1917 | //var key1 = newNode('value', {name:'KEY'}, node.key.name); 1918 | let key1 = newNode('value', { 1919 | name: 'KEY' 1920 | }); 1921 | block1.appendChild(key1); 1922 | node1 = current_node; 1923 | current_node = key1; 1924 | if (node.computed) { 1925 | c(node.key, st, "Expression") 1926 | } else { 1927 | let block2 = newNode('block', { 1928 | type: 'text' 1929 | }, '', node) 1930 | key1.appendChild(block2); 1931 | let field2; 1932 | if (node.key.name) { 1933 | // This applies to: myKey: 'value' 1934 | field2 = newNode('field', { 1935 | name: 'TEXT' 1936 | }, node.key.name); 1937 | } else { 1938 | // This applies to: 'myKey': 'value' 1939 | field2 = newNode('field', { 1940 | name: 'TEXT' 1941 | }, node.key.value); 1942 | } 1943 | block2.appendChild(field2); 1944 | } 1945 | let value1 = newNode('value', { 1946 | name: 'VAL' 1947 | }); 1948 | block1.appendChild(value1); 1949 | current_node = value1; 1950 | c(node.value, st, "Expression") 1951 | current_node = node1; 1952 | } 1953 | } 1954 | 1955 | // acorn. 1956 | //walk. 1957 | recursive(ast, st, funcs); 1958 | 1959 | let fake_last_line_node = {} 1960 | fake_last_line_node.loc = {} 1961 | fake_last_line_node.loc.start = {} 1962 | fake_last_line_node.loc.start.line = 999999 // JCOA TODO: Use total lines of text 1963 | 1964 | if (last_comment < comments.length) { 1965 | current_node.appendChild(newNode('block', { 1966 | type: 'bi_comment' 1967 | }, '', fake_last_line_node)) 1968 | } 1969 | 1970 | return xml1; 1971 | } 1972 | 1973 | export function parseCode(code) { 1974 | let workspace = Blockly.mainWorkspace; 1975 | let ast1, xml1; 1976 | let options; 1977 | let comments = []; 1978 | let block_loc = []; 1979 | try { 1980 | //console1.value = ''; 1981 | ///window._BIDE.b2c_error = false 1982 | options = { 1983 | sourceType: 'module', 1984 | locations: true, 1985 | onComment: comments 1986 | }; 1987 | ast1 = parse(code, options); 1988 | console.log(comments) 1989 | xml1 = walk1(ast1, comments, block_loc); 1990 | //console.log(xml1); 1991 | workspace.clear(); 1992 | Blockly.Xml.domToWorkspace(xml1, workspace); 1993 | workspace.cleanUp(); // workspace.cleanUp_(); // In old Blockly 1994 | //window._BIDE.updateWorkspace() 1995 | //workspace.addChangeListener(window._BIDE.updateWorkspace); 1996 | //var blockly_code = Blockly.JavaScript.workspaceToCode(Blockly.mainWorkspace); 1997 | //console.log(blockly_code); 1998 | } catch (err) { 1999 | console.log(err) 2000 | //window._BIDE.b2c_error = true 2001 | 2002 | let tb = workspace.topBlocks_ 2003 | let id = tb[tb.length - 1].id 2004 | //console.log(id) 2005 | console.log('Error line number: ' + block_loc[id].start.line) 2006 | //workspace.clear(); 2007 | //Blockly.Xml.domToWorkspace(workspace, xml1); 2008 | //workspace.cleanUp_(); //workspace.addChangeListener(window._BIDE.updateWorkspace); 2009 | 2010 | //console1.value += err+'\n'; 2011 | } 2012 | } 2013 | 2014 | //var parse1 = function(){ 2015 | // var client = new XMLHttpRequest(); 2016 | // client.open('GET', script1); 2017 | // client.onreadystatechange = function() { 2018 | // if(client.readyState == 4){ 2019 | // //out1.innerHTML += client.responseText; 2020 | // var code1 = client.responseText; 2021 | // //var ast1 = acorn.parse(code1); 2022 | // parseCode(code1); 2023 | // } 2024 | // } 2025 | // client.send(); 2026 | //} --------------------------------------------------------------------------------