Other extensions#
The JupyterLab-Blockly extension is ready to be used as a base for other projects: you can register new Blocks, Toolboxes and Generators. It is a great tool for fast prototyping.
Creating a new JupyterLab extension#
You can easily create a new JupyterLab extension by using a cookiecutter
. You can read more documentation about cookiecutters
here, but the process is fairly straight-forward.
After running the following command:
cookiecutter https://github.com/jupyterlab/extension-cookiecutter-ts
the cookiecutter
will ask for some basic information about your project. Once completed, it will create a directory containing several files, all forming the base of your project. You will mostly work in the index.ts
file, located in the src
folder.
An example of creating a simple JupyterLab extension, which also contains the instructions of how to fill the information asked by the cookiecutter
, can be found here.
Importing JupyterLab-Blockly#
Firstly you need to install and add jupyterlab-blockly
as a dependency for your extension:
jlpm add jupyterlab-blockly
Once it is part of your project, all you need to do is import IBlocklyRegistry
, as it follows:
// src/index.ts
import { IBlocklyRegistry } from 'jupyterlab-blockly';
The BlocklyRegistry
is the class that the JupyterLab-Blockly extension exposes to other plugins. This registry allows other plugins to register new Toolboxes, Blocks and Generators that users can use in the Blockly editor.
Registering new Blocks#
The IBlocklyRegistry
offers a function registerBlocks
, which allows you to include new Blocks in your project. Blockly offers a tool which helps you easily create new Blocks and get their JSON definition and generator code in all supported programming languages.
NOTE : Once you create a new block, it won’t appear into your Blockly editor, unless you add it to a Toolbox.
/**
* Register new blocks.
*
* @argument blocks Blocks to register.
*/
registerBlocks(blocks: BlockDefinition[]): void {
Blockly.defineBlocksWithJsonArray(blocks);
}
Registering a new Toolbox#
Using the registerToolbox
function, provided by IBlocklyRegistry
, you can register a new toolbox. Once registered, the toolbox will appear automatically in your Blockly editor. You can find more information about switching to another toolbox here.
/**
* Register a toolbox for the editor.
*
* @argument name Name of the toolbox.
*
* @argument value Toolbox to register.
*/
registerToolbox(name: string, value: ToolboxDefinition): void {
this._toolboxes.set(name, value);
}
Registering a new Generator#
Lastly, IBlocklyRegistry
offers the function registerGenerator
which lets you register a new Generator. You can read more about switching kernels here.
/**
* Register new generators.
*
* @argument name Name of the generator.
*
* @argument generator Generator to register.
*
* #### Notes
* When registering a generator, the name should correspond to the language
* used by a kernel.
*
* If you register a generator for an existing language this will be overwritten.
*/
registerGenerator(name: string, generator: Blockly.Generator): void {
this._generators.set(name, generator);
}
Example - JupyterLab-Niryo-One#
The JupyterLab-Niryo-One extension was built on top of JupyterLab-Blockly and poses as the perfect example. The Github repository gives access to its entire codebase.
The following code snippet showcases how to register a new toolbox, BlocklyNiryo.Toolbox
, as niryo
.
// src/index.ts : 10-23
/**
* Initialization data for the jupyterlab-niryo-one extension.
*/
const plugin: JupyterFrontEndPlugin<void> = {
id: 'jupyterlab-niryo-one:plugin',
autoStart: true,
requires: [IBlocklyRegistry],
activate: (app: JupyterFrontEnd, blockly: IBlocklyRegistry) => {
console.log('JupyterLab extension jupyterlab-niryo-one is activated!');
//Registering the new toolbox containing all Niryo One blocks.
blockly.registerToolbox('niryo', BlocklyNiryo.Toolbox);
}
};
NOTE : BlocklyNiryo
is defined in niryo-one-python-generators.ts
.
Include patches#
Currently, for the extension to work, you will need to include the following patch from the JupyterLab-Blockly extension (make sure it is placed in a file named @jupyterlab+codeeditor+3.4.3.patch
, inside the patches
folder):
// patches/@jupyterlab+codeeditor+3.4.3.patch
diff --git a/node_modules/@jupyterlab/codeeditor/lib/editor.d.ts b/node_modules/@jupyterlab/codeeditor/lib/editor.d.ts
index ffe8d1f..d63b2f8 100644
--- a/node_modules/@jupyterlab/codeeditor/lib/editor.d.ts
+++ b/node_modules/@jupyterlab/codeeditor/lib/editor.d.ts
@@ -44,7 +44,7 @@ export declare namespace CodeEditor {
/**
* An interface describing editor state coordinates.
*/
- interface ICoordinate extends JSONObject, ClientRect {
+ interface ICoordinate extends JSONObject {
}
/**
* A range.
You will also need to modify the MANIFEST.in
file:
recursive-include patches *.patch
the package.json
file:
"scripts": {
...
"postinstall": "patch-package"
}
and, finally, add patch-package
as a dependency:
jlpm add patch-package
Additional configurations#
You will need to request the jupyterlab-blockly
package as a dependency of your extension, in order to ensure it is installed and available to provide the token IBlocklyRegistry
. To do this, you need to add the following line to your setup.py
file.
// setup.py : 57
setup_args = dict(
...
install_requires=['jupyterlab-blockly>=0.1.1,<0.2']
...
)
Moreover, as we are working with deduplication of dependencies and the extension you are creating requires a service identified by a token from jupyterlab-blockly
, you need to add the following configuration to your package.json
file.
// package.json : 88-101
"jupyterlab": {
"sharedPackages": {
"jupyterlab-blockly": {
"bundled": false,
"singleton": true
},
"blockly": {
"bundled": false,
"singleton": true
}
}
}
This ensures your extension will get the exact same token the provider is using to identify the service and exclude it from its bundle as the provider will give a copy of the token. You can read more about deduplication of dependencies here, in the official Extension Developer Guide for JupyterLab.