|
1 | 1 | # Other extensions |
2 | 2 |
|
3 | | -... instructions on how to built on top of the JupyterLab-Blockly extension |
| 3 | +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. |
| 4 | + |
| 5 | +## Creating a new JupyterLab extension |
| 6 | +You can easily create a new JupyterLab extension by using a `cookiecutter`. You can read more documentation about `cookiecutters` [here](https://cookiecutter.readthedocs.io/en/latest/), but the process is fairly straight-forward. |
| 7 | + |
| 8 | +After running the following command: |
| 9 | +``` |
| 10 | +cookiecutter https://github.com/jupyterlab/extension-cookiecutter-ts |
| 11 | +``` |
| 12 | + 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. |
| 13 | + |
| 14 | +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](https://github.com/jupyterlab/extension-examples/tree/master/hello-world). |
| 15 | + |
| 16 | + |
| 17 | +## Importing JupyterLab-Blockly |
| 18 | +Firstly you need to install and add `jupyterlab-blockly` as a dependency for your extension: |
| 19 | +``` |
| 20 | +jlpm add jupyterlab-blockly |
| 21 | +``` |
| 22 | + |
| 23 | +Once it is part of your project, all you need to do is import `IBlocklyRegisty`, as it follows: |
| 24 | +```typescript |
| 25 | +// src/index.ts |
| 26 | + |
| 27 | +import { IBlocklyRegisty } from 'jupyterlab-blockly'; |
| 28 | +``` |
| 29 | + |
| 30 | +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. |
| 31 | + |
| 32 | +### Registering new Blocks |
| 33 | +The `IBlocklyRegisty` offers a function `registerBlocks`, which allows you to include new Blocks in your project. Blockly offers a [tool](https://blockly-demo.appspot.com/static/demos/blockfactory/index.html) which helps you easily create new Blocks and get their JSON definition and generator code in all supported programming languages. |
| 34 | + |
| 35 | +**NOTE** : Once you create a new block, it won't appear into your Blockly editor, unless you add it to a Toolbox. |
| 36 | + |
| 37 | +```typescript |
| 38 | + /** |
| 39 | + * Register new blocks. |
| 40 | + * |
| 41 | + * @argument blocks Blocks to register. |
| 42 | + */ |
| 43 | + registerBlocks(blocks: JSONObject[]): void { |
| 44 | + Blockly.defineBlocksWithJsonArray(blocks); |
| 45 | + } |
| 46 | +``` |
| 47 | + |
| 48 | +### Registering a new Toolbox |
| 49 | +Using the `registerToolbox` function, provided by `IBlocklyRegisty`, 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](https://jupyterlab-blockly.readthedocs.io/en/latest/toolbox.html). |
| 50 | + |
| 51 | +```typescript |
| 52 | +/** |
| 53 | + * Register a toolbox for the editor. |
| 54 | + * |
| 55 | + * @argument name Name of the toolbox. |
| 56 | + * |
| 57 | + * @argument value Toolbox to register. |
| 58 | + */ |
| 59 | + registerToolbox(name: string, value: JSONObject): void { |
| 60 | + this._toolboxes.set(name, value); |
| 61 | + } |
| 62 | +``` |
| 63 | + |
| 64 | +### Registering a new Generator |
| 65 | +Lastly, `IBlocklyRegisty` offers the function `registerGenerator` which lets you register a new Generator. You can read more about switching kernels [here](https://jupyterlab-blockly.readthedocs.io/en/latest/kernels.html). |
| 66 | + |
| 67 | +```typescript |
| 68 | + |
| 69 | + /** |
| 70 | + * Register new generators. |
| 71 | + * |
| 72 | + * @argument name Name of the generator. |
| 73 | + * |
| 74 | + * @argument generator Generator to register. |
| 75 | + * |
| 76 | + * #### Notes |
| 77 | + * When registering a generator, the name should correspond to the language |
| 78 | + * used by a kernel. |
| 79 | + * |
| 80 | + * If you register a generator for an existing language this will be overwritten. |
| 81 | + */ |
| 82 | + registerGenerator(name: string, generator: Blockly.Generator): void { |
| 83 | + this._generators.set(name, generator); |
| 84 | + } |
| 85 | +``` |
| 86 | + |
| 87 | + |
| 88 | +## Example - JupyterLab-Niryo-One |
| 89 | +The [JupyterLab-Niryo-One](https://github.com/QuantStack/jupyterlab-niryo-one/) extension was built on top of JupyterLab-Blockly and poses as the perfect example. The [Github repository](https://github.com/QuantStack/jupyterlab-niryo-one/) gives access to its entire codebase. |
| 90 | + |
| 91 | +The following code snippet showcases how to register a new toolbox, `BlocklyNiryo.Toolbox`, as `niryo`. |
| 92 | +```typescript |
| 93 | +// src/index.ts : 10-23 |
| 94 | + |
| 95 | +/** |
| 96 | + * Initialization data for the jupyterlab-niryo-one extension. |
| 97 | + */ |
| 98 | +const plugin: JupyterFrontEndPlugin<void> = { |
| 99 | + id: 'jupyterlab-niryo-one:plugin', |
| 100 | + autoStart: true, |
| 101 | + requires: [IBlocklyRegisty], |
| 102 | + activate: (app: JupyterFrontEnd, blockly: IBlocklyRegisty) => { |
| 103 | + console.log('JupyterLab extension jupyterlab-niryo-one is activated!'); |
| 104 | + |
| 105 | + //Registering the new toolbox containing all Niryo One blocks. |
| 106 | + blockly.registerToolbox('niryo', BlocklyNiryo.Toolbox); |
| 107 | + } |
| 108 | +}; |
| 109 | +``` |
| 110 | + |
| 111 | +**NOTE** : `BlocklyNiryo` is defined in `niryo-one-python-generators.ts`. |
| 112 | + |
| 113 | + |
| 114 | +## Include patches |
| 115 | +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): |
| 116 | + |
| 117 | +``` |
| 118 | +// patches/@jupyterlab+codeeditor+3.4.3.patch |
| 119 | +
|
| 120 | +diff --git a/node_modules/@jupyterlab/codeeditor/lib/editor.d.ts b/node_modules/@jupyterlab/codeeditor/lib/editor.d.ts |
| 121 | +index ffe8d1f..d63b2f8 100644 |
| 122 | +--- a/node_modules/@jupyterlab/codeeditor/lib/editor.d.ts |
| 123 | ++++ b/node_modules/@jupyterlab/codeeditor/lib/editor.d.ts |
| 124 | +@@ -44,7 +44,7 @@ export declare namespace CodeEditor { |
| 125 | + /** |
| 126 | + * An interface describing editor state coordinates. |
| 127 | + */ |
| 128 | +- interface ICoordinate extends JSONObject, ClientRect { |
| 129 | ++ interface ICoordinate extends JSONObject { |
| 130 | + } |
| 131 | + /** |
| 132 | + * A range. |
| 133 | +``` |
| 134 | + |
| 135 | +You will also need to modify the `MANIFEST.in` file: |
| 136 | +``` |
| 137 | +recursive-include patches *.patch |
| 138 | +``` |
| 139 | +the `package.json` file: |
| 140 | +``` |
| 141 | +"scripts": { |
| 142 | + ... |
| 143 | + "postinstall": "patch-package" |
| 144 | +} |
| 145 | +```` |
| 146 | +and, finally, add `patch-package` as a dependency: |
| 147 | +``` |
| 148 | +jlpm add patch-package |
| 149 | +``` |
0 commit comments