npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@mit-app-inventor/blockly-block-lexical-variables

v11.0.3

Published

A Blockly plugin providing lexical/local variable support and flydown variable getters and setters.

Downloads

140

Readme

blockly-block-lexical-variables Built on Blockly

Table of Contents

This plugin adds a set of Blockly blocks and fields that support lexical (aka local) variables, as well as a dynamic UI for obtaining variable and parameter getters and setters and for renaming variables. It also updates the UI for existing blocks that are implicitly lexically scoped, i.e.:

  • Function/Procedure definitions
  • For loops

For variable getter and setter blocks this plugin also provides dropdowns which allow the user to change the variable name to any variable allowed by scope. The plugin will also mark any variable blocks that are moved out of their allowable scope.

The plugin also adds a dropdown for procedure call blocks, allowing the user to change the call to be any other procedure of the same basic shape (i.e. statement shape or expression shape).

This plugin is based on code originally written for MIT App Inventor.

You can see a demo version of a Blockly app that has integrated this plugin here. The code for that demo is here.

If you want to define your own blocks that use the fields defined by this plugin, see the BYOB section

Blocks

Lexical/local variable declarations

Block type: 'local-declaration-statement' - The variable name will be scoped to be valid within the body of the block.

A picture of a lexical variable block

While hovering over the variable name:

A picture of a lexical variable block with getter and setter blocks

Global variable declaration

Block type: 'global-declaration-statement' - An block which declares a global variable. The variable name is scoped to the entire program.

A picture of a global variable block

and while hovering over the variable name:

A picture of a global variable block with getter and setter blocks

Variable/Parameter setters and getters

Setter

Block type: 'lexical_variable_set' - Note that despite the block type name, the same block is used for global variables, local variables, loop variables and function/procedure parameters. The names that appear in the dropdown will change according to the placement of the block. I.e., it will show the variables that are in scope for that getter according to which blocks it is within.

A picture of a setter block A picture of a setter block with a dropdown A picture of a setter block within another block

Getter

Block type: 'lexical_variable_get' - Exactly analogous to the setter block.

A picture of a getter block A picture of a getter block with a dropdown A picture of a getter block within another block

Disabling invalid getter/setter blocks

By default, getter and setter blocks remain enabled even if their selected variable is out of scope or doesn’t exist. You can change this behavior so that invalid blocks are automatically disabled by passing the disableInvalidBlocks option when initializing the plugin as demonstrated in the Usage section.

Loops

For

Block type: 'controls_for' - A block which enables a for loop

A picture of a for block A picture of a for block

Block type: 'controls_forEach' - A block which enables a loop over the items in a list

A picture of a for block A picture of a for block

Functions/procedures

Function/procedure definition with no return value.

Block type: 'procedures_defnoreturn'

A picture of a procedure definition block

A picture of a procedure definition block with flydown

Function/procedure definition with a return value.

Block type: 'procedures_defreturn'

A picture of a procedure definition block with return value

A picture of a procedure definition block with return and with flydown

Function/procedure call with no value

Block type: 'procedures_callnoreturn' - Note that, though I don't show it here, the procedure name field is a dropdown which allows the user to select any procedure and the block will change to match that procedures name and parameters.

A picture of a procedure call block or A picture of a procedure call block

Function/procedure call with value

Block type: 'procedures_callreturn' - This has the same dropdown behavior as the previous procedure call block.

A picture of a procedure call block with a value or A picture of a procedure call block with a value

Installation

Yarn

yarn add @mit-app-inventor/blockly-block-lexical-variables

npm

npm install @mit-app-inventor/blockly-block-lexical-variables --save

Usage

_Please make sure that your app which includes this plugin uses a relatively recent version of Blockly. As of this writing that would be version 11.2.2.

You'll want to include something like the following in your app:

import * as Blockly from 'blockly';
import {LexicalVariablesPlugin} from '@mit-app-inventor/blockly-block-lexical-variables';
...
const workspace = Blockly.inject(...);
...
// Load lexical variable plugin
LexicalVariablesPlugin.init(workspace);

You can also pass an options object to customize the plugin’s behavior:

LexicalVariablesPlugin.init(workspace, {
  disableInvalidBlocks: true,
});

Available options:

  • disableInvalidBlocks (boolean, default: false)
    Automatically disable variable getter/setter blocks when they reference a variable that is out of scope or doesn’t exist.

Note that unlike with standard Blockly, you should not use a custom toolbox category for your variables, as this would interfere with the way that variables are declared and used with this plugin. Just create an ordinary Variables category, if you want, and place the lexical-variable-get and lexical-variable-set blocks in there.

BYOB (Build Your Own Blocks), aka, how to build your own blocks using the lexical variable fields

The lexical variable fields are designed to be used in blocks that contain a set of methods that the lexical variable implementation will call. In the general case, you would need to define all of these methods (see FIELDS.md for details). However, if you are building a block that that doesn't have a mutation UI that needs to be kept in sync with the fields, then the situation is a bit simpler. In that case, you can use the lexicalVariableScopeMixin defined in mixins.js. If you use that mixin you only need to define these two methods for your block:

  • getDeclaredVarFieldNames(): a list of the names of the fields of the block's declared variables (e.g. ['VAR']).
  • getScopedInputName(): The name of the input that defines the block's scope (e.g., 'DO')

The mixin will then take care of the rest (i.e. define the rest of the methods that the block needs). You add the mixin to your block like this by calling this.mixin(lexicalVariableScopeMixin); in the block's init() method. You can see examples of how to use it in lexical-variables.js for the simple_local_declaration_statement block and in controls.js for thecontrols_forEach and controls_forRange blocks.

The core module exports the lexicalVariableScopeMixin as a field on the exported static LexicalVariablesPlugin class.

NOTE: If you are creating your own blocks and do not want to use the blocks defined in this plugin, you should import just the core module from this plugin, i.e.

import {LexicalVariablesPlugin} from '@mit-app-inventor/blockly-block-lexical-variables/core';

Here's snippet of what the code might look like to implement a simple_local_declaration_statement block, if you didn't want to use the blocks already defined in this plugin:

import * as Blockly from 'blockly/core';
import * as libraryBlocks from 'blockly/blocks';
import * as En from 'blockly/msg/en';
import {javascriptGenerator} from 'blockly/javascript';
import {LexicalVariablesPlugin} from '@mit-app-inventor/blockly-block-lexical-variables/core';

Blockly.setLocale(En);
const workspace = Blockly.inject(...);
LexicalVariablesPlugin.init(workspace);

const FieldParameterFlydown =  LexicalVariablesPlugin.FieldParameterFlydown;
const lexicalVariableScopeMixin =  LexicalVariablesPlugin.lexicalVariableScopeMixin;

Blockly.Blocks['simple_local_declaration_statement'] = {
    category: 'Variables',
    helpUrl: "help",
    init: function () {
        // Let the theme determine the color.
        this.setStyle('variable_blocks');
        const declInput = this.appendValueInput('DECL');
        declInput.appendField(
            'let')
            .appendField(new FieldParameterFlydown('name', true), 'VAR')
            .appendField('to')
            .setAlign(Blockly.inputs.Align.RIGHT);
        this.appendStatementInput('DO')
            .appendField('in');
        this.setPreviousStatement(true);
        this.setNextStatement(true);
        this.setTooltip('tooltip');
        this.mixin(lexicalVariableScopeMixin);
    },
    getDeclaredVarFieldNames: function () {
        return ['VAR'];
    },
    getScopedInputName: function () {
        return 'DO';
    },
}

javascriptGenerator.forBlock['simple_local_declaration_statement'] = function (block, generator) {
    let code = '{\n  let ';
    code += (Shared.usePrefixInCode ? 'local_' : '') +
        block.getFieldValue('VAR');
    code += ' = ' + (generator.valueToCode(block,
        'DECL', Order.NONE) || '0');
    code += ';\n';
    code += generator.statementToCode(block, 'DO');
    code += '}\n';
    return code;
}

Credits

As mentioned earlier, this plugin is based on code written for MIT App Inventor. The lexical variable implementation (and supporting blocks and UI) in App Inventor was developed primarily by Lyn Turbak but has had many contributors over the years including (in roughly chronological order):

  • Sharon Perl
  • Andrew McKinney
  • Hal Abelson
  • PMW
  • Ralph Morelli
  • Jeffry Schiller
  • Jose Flores
  • Joanie Weaver
  • Shirley Lu
  • mphox
  • Leo Burd
  • Dave Wolber
  • Harry Davis
  • WeiHua Li
  • jbensal
  • Shruti Rijhwani
  • Liz Looney
  • Evan Patton
  • Susan Lane
  • Colin Yang
  • Beka Westberg
  • Siddharth
  • Mark Friedman

If you contributed to this code at some point and I somehow neglected to mention you, I apologise. Let me know, file a bug or just submit a pull request on this file.

License

Apache 2.0