diff --git a/.github/workflows/assign_reviewers.yml b/.github/workflows/assign_reviewers.yml index 042f1553e7..850c7c805f 100644 --- a/.github/workflows/assign_reviewers.yml +++ b/.github/workflows/assign_reviewers.yml @@ -15,9 +15,11 @@ on: jobs: requested-reviewer: runs-on: ubuntu-latest + permissions: + pull-requests: write steps: - name: Assign requested reviewer - uses: actions/github-script@v5 + uses: actions/github-script@v7 with: script: | try { diff --git a/codelabs/custom_generator/custom_generator.md b/codelabs/custom_generator/custom_generator.md index 34ab94ac6a..5f8db1134d 100644 --- a/codelabs/custom_generator/custom_generator.md +++ b/codelabs/custom_generator/custom_generator.md @@ -203,7 +203,7 @@ A custom language generator is simply an instance of `Blockly.Generator`. Create ```js import * as Blockly from 'blockly'; -export const jsonGenerator = new Blockly.Generator('JSON'); +export const jsonGenerator = new Blockly.CodeGenerator('JSON'); ``` ### Generate code diff --git a/codelabs/keyboard_navigation/AST.png b/codelabs/keyboard_navigation/AST.png deleted file mode 100644 index 556e883ed6..0000000000 Binary files a/codelabs/keyboard_navigation/AST.png and /dev/null differ diff --git a/codelabs/keyboard_navigation/block_terms.png b/codelabs/keyboard_navigation/block_terms.png deleted file mode 100644 index 789a3dce15..0000000000 Binary files a/codelabs/keyboard_navigation/block_terms.png and /dev/null differ diff --git a/codelabs/keyboard_navigation/flashing_cursor.gif b/codelabs/keyboard_navigation/flashing_cursor.gif deleted file mode 100644 index a6db40a29e..0000000000 Binary files a/codelabs/keyboard_navigation/flashing_cursor.gif and /dev/null differ diff --git a/codelabs/keyboard_navigation/keyboard_navigation.md b/codelabs/keyboard_navigation/keyboard_navigation.md deleted file mode 100644 index 6249e8160d..0000000000 --- a/codelabs/keyboard_navigation/keyboard_navigation.md +++ /dev/null @@ -1,567 +0,0 @@ -author: Abby Schmiedt -summary: Codelab to configure keyboard navigation -id: keyboard-navigation -categories: blockly,codelab,accessibility,keyboard navigation -status: Published -Feedback Link: https://github.com/google/blockly-samples/issues/new/choose - -# Keyboard navigation - -## Codelab overview - -Keyboard navigation is the first step in making Blockly more accessible. This guide focuses on how to modify keyboard navigation. - -### What you'll learn - -- How to change the behavior of a cursor. -- How to change the look of cursors and markers. -- How to add a shortcut. -- How to change the current key mappings. - -### What you'll build - -- A cursor that displays a red blinking image over the block. -- A cursor that skips over previous and next connections. -- A keyboard shortcut for moving the cursor to the top of a stack. - -### What you'll need - -- Basic understanding of blocks and toolboxes in Blockly. -- NPM installed ([instructions](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)). -- Comfort using the command line/terminal. -- Familiarity with the blockly keyboard navigation [documentation](https://developers.google.com/blockly/guides/configure/web/keyboard-nav). - -## Setup - -This codelab will demonstrate how to install the [keyboard navigation plugin](https://www.npmjs.com/package/@blockly/keyboard-navigation) on top of the Blockly sample app and then add code to create and use a custom `Cursor` and `Marker`. - -### The application - -Use the [`npx @blockly/create-package app`](https://www.npmjs.com/package/@blockly/create-package) command to create a standalone application that contains a sample setup of Blockly, including custom blocks and a display of the generated code and output. - 1. Run `npx @blockly/create-package app keyboard-navigation-codelab`. This will create a blockly application in the folder `keyboard-navigation-codelab`. - 1. `cd` into the new directory: `cd keyboard-navigation-codelab`. - 1. Install the [keyboard navigation plugin](https://www.npmjs.com/package/@blockly/keyboard-navigation): `npm install @blockly/keyboard-navigation --save` - 1. Run `npm start` to start the server and run the sample application. - 1. The sample app will automatically run in the browser window that opens. - -## Terminology - -A [**Marker**](https://developers.google.com/blockly/reference/js/blockly.marker_class) holds a location and is not movable. A marker is used to mark a location on the workspace, such as marking the spot where the user can drop a block from the toolbox. - -A [**Cursor**](https://developers.google.com/blockly/reference/js/blockly.cursor_class) is a marker that can move. It extends a `Blockly.Marker` but adds logic to allow the marker to move through the blocks, inputs, fields, connections and workspace coordinates. - -The below image displays different parts of a block that a user can navigate to using keyboard navigation. - -![Displays the different parts of a block. The previous connection on the top of a block. The next connection on the bottom of a block. Input value as a cut out of a puzzle piece. The statement input as a connection inside of a block. The output connection as a puzzle piece.](./block_terms.png) - -## Initialize NavigationController plugin - -First, import and set up a `NavigationController` in `index.js`. `NavigationController` is the class in charge of registering all keyboard shortcuts. - -Import `NavigationController` at the top of `index.js`: - -```js -import {NavigationController} from '@blockly/keyboard-navigation'; -``` - -Then, somewhere after the existing code that injects the workspace, create an instance of `NavigationController`, initialize it, and add it to the workspace: - -```js -// Initialize NavigationController plugin and add to our workspace. -const navigationController = new NavigationController(); -navigationController.init(); -navigationController.addWorkspace(ws); -``` - -At this point, the app will have default keyboard navigation enabled. Pressing **ctrl + shift + k** will enter the user into keyboard navigation mode. From here, `WASD` style commands can be used to navigate around. Further details can be found in [the blockly keyboard navigation documentation](https://developers.google.com/blockly/guides/configure/web/keyboard-nav). - -## Understand AST Nodes - -Blockly organizes all the different components in a workspace in a structured way by representing them as an abstract syntax tree ([AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree)). - -The following image displays the AST for a workspace. - -![](./AST.png) - -There are four different levels to the AST: -1. Workspace Level (green): Holds all workspace nodes. -1. Stack Level (blue): Holds all stack nodes. -1. Block and Connection Level (red): Holds all block and connection nodes. -1. Field and Input Level (yellow): Holds all field and input nodes. - -For a more detailed explanation of the different levels please see the [keyboard navigation documentation](https://developers.google.com/blockly/guides/configure/web/keyboard-nav#using_the_default_cursor). - -### Create AST nodes - -The `Blockly.ASTNode` class is used to represent the AST. The `Blockly.ASTNode` class holds a workspace component. This component can be a block, connection, field, input or workspace coordinate. - -The following code shows how to create a `Blockly.ASTNode` for the different workspace components: - -```js -const workspaceNode = Blockly.ASTNode.createWorkspaceNode( - workspace, wsCoordinate); -const stackNode = Blockly.ASTNode.createStackNode(topBlock); -const connectionNode = Blockly.ASTNode.createConnectionNode(connection); -const blockNode = Blockly.ASTNode.createBlockNode(block); -const fieldNode = Blockly.ASTNode.createFieldNode(field); -const inputNode = Blockly.ASTNode.createInputNode(input); -``` - -### Use AST nodes - -These nodes are used in the cursor to decide where to go and what to draw. - -Every node can: -1. Return the node below it (`in()`) -1. Return the node above it (`out()`) -1. Return the previous node (`prev()`) -1. Return the next node (`next()`) - -For example, the following code can be used to get the stack node from a workspace node: - -```js -const stackNode = workspaceNode.in(); -``` - -## Define and set a custom marker - -The `Blockly.blockRendering.MarkerSvg` class contains the logic to draw cursors and markers. It decides what to draw depending on the current node the cursor or marker holds. - -To start, create a new directory at `src/markers` and add a file inside named `custom_marker_svg.js`. - -At the top of the file, import `blockly/core`: - -```js -import * as Blockly from 'blockly/core'; -``` - -Then define a new custom marker and have it extend `Blockly.blockRendering.MarkerSvg`: - -```js -class CustomMarkerSvg extends Blockly.blockRendering.MarkerSvg { - constructor(workspace, constants, marker) { - super(workspace, constants, marker); - } -} -``` - -Now, inside `CustomMarkerSvg`, override `createDomInternal_()`. This method is in charge of creating all DOM elements for the marker. Add a new path element for when the cursor is on a block: - -```js - /** - * @override - */ - createDomInternal_() { - super.createDomInternal_(); - - // Create the svg element for the marker when it is on a block and set the - // parent to markerSvg_. - this.blockPath_ = Blockly.utils.dom.createSvgElement( - 'path', {}, this.markerSvg_); - - // If this is a cursor make the cursor blink. - if (this.isCursor()) { - const blinkProperties = this.getBlinkProperties_(); - Blockly.utils.dom.createSvgElement('animate', blinkProperties, - this.blockPath_); - } - } -``` - -Next, create a method named `showWithBlock_(curNode)` that will: - -- Update the block path. -- Set the current marker. -- Set the parent. -- Show the current marker. - -This method will be called within `showAtLocation_(curNode)` when the user moves to a new block: - -```js - showWithBlock_(curNode) { - // Get the block from the AST Node - const block = curNode.getLocation(); - - // Get the path of the block. - const blockPath = block.pathObject.svgPath.getAttribute('d'); - - // Set the path for the cursor. - this.blockPath_.setAttribute('d', blockPath); - - // Set the current marker. - this.currentMarkerSvg = this.blockPath_; - - // Set the parent of the cursor as the block. - this.setParent_(block); - - // Show the current marker. - this.showCurrent_(); - } -``` - -Then, override `showAtLocation_(curNode)`. This method is used to decide what to display at a given node: - -```js - /** - * @override - */ - showAtLocation_(curNode) { - let handled = false; - // If the cursor is on a block call the new method we created to draw the - // cursor. - if (curNode.getType() == Blockly.ASTNode.types.BLOCK) { - this.showWithBlock_(curNode); - handled = true; - } - - // If we have not drawn the cursor let the parent draw it. - if (!handled) { - super.showAtLocation_.call(this, curNode); - } - } -``` - -Finally, override the `hide()` method: - -```js - /** - * @override - */ - hide() { - super.hide(); - // Hide the marker we created. - this.blockPath_.style.display = 'none'; - } -``` - -### Renderer setup - -Override the renderer to have it use the cursor `CustomMarkerSvg`. For more information on customizing a renderer see the custom renderer [codelab](https://blocklycodelabs.dev/codelabs/custom-renderer/index.html). - -Add the following code to the bottom of `custom_marker_svg.js`, outside of the `CustomMarkerSvg` class definition: - -```js -class CustomRenderer extends Blockly.geras.Renderer { - constructor(name) { - super(name); - } -} -Blockly.blockRendering.register('custom_renderer', CustomRenderer); -``` - -Now override the method responsible for returning the drawer for markers and cursors. - -Add the following method inside the `CustomRenderer` class: - -```js -makeMarkerDrawer(workspace, marker) { - return new CustomMarkerSvg(workspace, this.getConstants(), marker); -} -``` - -In order to use the custom renderer, it has to be imported at the top of `index.js`. - -```js -import './markers/custom_marker_svg'; -``` - -Then, change the call to `Blockly.inject` to pass the newly registered renderer named `custom_renderer`: - -```js -const ws = Blockly.inject(blocklyDiv, { - toolbox: toolbox, - renderer: 'custom_renderer', -}); -``` - -### Test it out - -Open the sample app and drag a function block on to the workspace. Press **ctrl + shift + k** to enter into keyboard navigation mode. Notice how the entire block starts flashing red. - -![The cursor flashing red](./flashing_cursor.gif) - -## Define and set a custom cursor - -Create a new directory at `src/cursors` and add a file inside named `custom.js`. - -At the top of the new file, add an import of `blockly/core`: - -```js -import * as Blockly from 'blockly/core'; -``` - -Then define a new custom cursor and have it extend the base cursor, `Blockly.Cursor`: - -```js -export class CustomCursor extends Blockly.Cursor { - constructor() { - super(); - } -} -``` - -Import the cursor at the top of `src/index.js`. - -```js -import {CustomCursor} from './cursors/custom'; -``` - -Somewhere after the existing code that injects the workspace, use its `MarkerManager` to set the new custom cursor: - -```js -// Add CustomCursor to workspace -ws.getMarkerManager().setCursor(new CustomCursor()); -``` - -## Change the cursor behavior - -### Override the move methods - -Override the methods that move the cursor in order to skip over previous and next connections. - -Add the following code to `cursors/custom.js`, inside the `CustomCursor` class definition (these implementations are just a starting point that will be improved upon in the next step): - -```js - next() { - // The current Blockly.ASTNode the cursor is on. - const curNode = this.getCurNode(); - if (!curNode) { - return null; - } - // The next Blockly.ASTNode. - let newNode = curNode.next(); - if (newNode) { - this.setCurNode(newNode); - } - return newNode; - } - - in() { - const curNode = this.getCurNode(); - if (!curNode) { - return null; - } - let newNode = curNode.in(); - if (newNode) { - this.setCurNode(newNode); - } - return newNode; - } - - prev() { - const curNode = this.getCurNode(); - if (!curNode) { - return null; - } - let newNode = curNode.prev(); - if (newNode) { - this.setCurNode(newNode); - } - return newNode; - } - - out() { - const curNode = this.getCurNode(); - if (!curNode) { - return null; - } - let newNode = curNode.out(); - if (newNode) { - this.setCurNode(newNode); - } - return newNode; - } -``` - -### Modify the move methods - -Now add logic to the move methods to skip over the previous and next connections. The following image represents the logic being added. The red boxes represent the nodes to skip. - -![Displays the abstract syntax tree with the previous and next connection nodes highlighted in red.](./skip_connections.png) - -Change the `next` method so it will skip over any previous or next connections and go straight to the next block: - -```js - next() { - const curNode = this.getCurNode(); - if (!curNode) { - return null; - } - let newNode = curNode.next(); - // While the newNode exists and is either a previous or next type go to the - // next value. - while (newNode && (newNode.getType() === Blockly.ASTNode.types.PREVIOUS || - newNode.getType() === Blockly.ASTNode.types.NEXT)) { - newNode = newNode.next(); - } - if (newNode) { - this.setCurNode(newNode); - } - return newNode; - } -``` - -Change the `prev` method so it will skip over any previous or next connections and go straight to the previous block: - -```js - prev() { - const curNode = this.getCurNode(); - if (!curNode) { - return null; - } - let newNode = curNode.prev(); - // While the newNode exists and is either a previous or next connection go - // to the previous value. - while (newNode && (newNode.getType() === Blockly.ASTNode.types.PREVIOUS || - newNode.getType() === Blockly.ASTNode.types.NEXT)) { - newNode = newNode.prev(); - } - if (newNode) { - this.setCurNode(newNode); - } - return newNode; - } -``` - -Change the `in` method so that it will skip over any previous connections and go straight to the contained block: - -```js - in() { - const curNode = this.getCurNode(); - if (!curNode) { - return null; - } - let newNode = curNode.in(); - // If the newNode is a previous connection go to the next value in the - // level. This will be the block. - if (newNode && newNode.getType() === Blockly.ASTNode.types.PREVIOUS) { - newNode = newNode.next(); - } - if (newNode) { - this.setCurNode(newNode); - } - return newNode; - } -``` - -#### Test it out - -Open the sample app and enter into keyboard navigation mode (**ctrl + shift + k**). Drag some blocks on to the workspace and navigate to the first block. From here hit the **S** key to go to the next block. Notice how the cursor skips over the previous and next connection and goes straight to the next block. - -![](./new_cursor.gif) - -## Adding a shortcut - -This section will add a shortcut that will allow users to move their cursor to the top of their current stack by pressing **ctrl + W**. - -### Create a key mapping - -A key mapping connects a key code or combination of key codes to a shortcut. When the key code or combination of key codes are pressed the shortcut will run. - -Primary keys can be combined with modifier keys by using the `createSerializedKey()` method. A list of the available modifier keys are: - -- `Blockly.ShortcutRegistry.modifierKeys.SHIFT` -- `Blockly.ShortcutRegistry.modifierKeys.CONTROL` -- `Blockly.ShortcutRegistry.modifierKeys.ALT` -- `Blockly.ShortcutRegistry.modifierKeys.META` - -Create a key code for **ctrl + W** by adding the following code to the bottom of `index.js`: - -```js -// Create a serialized key from the primary key and any modifiers. -const ctrlW = Blockly.ShortcutRegistry.registry.createSerializedKey( - Blockly.utils.KeyCodes.W, [Blockly.ShortcutRegistry.modifierKeys.Control]); -``` - -### Create a shortcut - -A shortcut has several properties: -- `name`: The name of the shortcut. This must be unique. -- `keyCodes`: A list of key codes that when pressed will trigger this shortcut. This shortcut will use the `ctrlW` defined above. -- `preconditionFn`: A function that returns true if and only if the shortcut should be run. This shortcut will only run when `workspace.keyboardAccessibilityMode` is true. -- `callback`: A function that is called when the shortcut has been executed. This should return true if the shortcut has been handled. If a shortcut returns true, no other shortcuts with the same key mapping will be handled. - -Add the following code to the bottom of `index.js`: - -```js -const moveToStack = { - name: 'moveToStack', - keyCodes: [ctrlW], // The custom key mapping. - preconditionFn: function(workspace) { - return workspace.keyboardAccessibilityMode; - }, - callback: function(workspace) { - const cursor = workspace.getCursor(); - // Gets the current node. - const currentNode = cursor.getCurNode(); - // Gets the source block from the current node. - const currentBlock = currentNode.getSourceBlock(); - // If we are on a workspace node there will be no source block. - if (currentBlock) { - // Gets the top block in the stack. - const rootBlock = currentBlock.getRootBlock(); - // Gets the top node on a block. This is either the previous connection, - // output connection, or the block itself. - const topNode = Blockly.ASTNode.createTopNode(rootBlock); - // Update the location of the cursor. - cursor.setCurNode(topNode); - return true; - } - }, -}; - -``` -Once the shortcut is created, it can be registered by adding the following code to the bottom of `index.js`: - -```js -Blockly.ShortcutRegistry.registry.register(moveToStack); -``` - -### Test it out - -Open the sample app and create a stack of blocks. Enter into keyboard navigation mode (**ctrl + shift + k**). Move the cursor down a few blocks and then press **ctrl + W**. Notice how the cursor jumps to the top of the stack of blocks. - -![](./skip_to_top.gif) - -## Change current key mappings - -This section will update key mappings so users can use the arrow keys for their cursor instead of the default **WASD** keys. - -Before adding the key mappings below, import the shortcut names by adding the -following line to the top of `index.js`: - -```js -import {Constants} from '@blockly/keyboard-navigation'; -``` - -Now set the keys for the next, previous, in, and out actions at the bottom of `index.js`: - -```js -Blockly.ShortcutRegistry.registry.removeAllKeyMappings(Constants.SHORTCUT_NAMES.OUT); -Blockly.ShortcutRegistry.registry.addKeyMapping(Blockly.utils.KeyCodes.LEFT, Constants.SHORTCUT_NAMES.OUT); - -Blockly.ShortcutRegistry.registry.removeAllKeyMappings(Constants.SHORTCUT_NAMES.IN); -Blockly.ShortcutRegistry.registry.addKeyMapping(Blockly.utils.KeyCodes.RIGHT, Constants.SHORTCUT_NAMES.IN); - -Blockly.ShortcutRegistry.registry.removeAllKeyMappings(Constants.SHORTCUT_NAMES.PREVIOUS); -Blockly.ShortcutRegistry.registry.addKeyMapping(Blockly.utils.KeyCodes.UP, Constants.SHORTCUT_NAMES.PREVIOUS); - -Blockly.ShortcutRegistry.registry.removeAllKeyMappings(Constants.SHORTCUT_NAMES.NEXT); -Blockly.ShortcutRegistry.registry.addKeyMapping(Blockly.utils.KeyCodes.DOWN, Constants.SHORTCUT_NAMES.NEXT); -``` - -Note: For a full list of the shortcuts registered in the keyboard navigation plugin see the [constants file](https://github.com/google/blockly-samples/blob/master/plugins/keyboard-navigation/src/constants.js). - -### Test it out - -Open the sample app and enter into keyboard navigation mode (**ctrl + shift + k**). The arrow keys can now be used to move around instead of the default **WASD** keys. - -## Summary - -There is still a lot of work to be done in figuring out the best way to provide -keyboard navigation support for users. - -In this codelab you learned: -- How to create a new cursor. -- How to change the look of markers and cursors. -- How to add shortcuts. diff --git a/codelabs/keyboard_navigation/new_cursor.gif b/codelabs/keyboard_navigation/new_cursor.gif deleted file mode 100644 index 635cb876dc..0000000000 Binary files a/codelabs/keyboard_navigation/new_cursor.gif and /dev/null differ diff --git a/codelabs/keyboard_navigation/skip_connections.png b/codelabs/keyboard_navigation/skip_connections.png deleted file mode 100644 index c4d6c77a72..0000000000 Binary files a/codelabs/keyboard_navigation/skip_connections.png and /dev/null differ diff --git a/codelabs/keyboard_navigation/skip_to_top.gif b/codelabs/keyboard_navigation/skip_to_top.gif deleted file mode 100644 index 2da398380a..0000000000 Binary files a/codelabs/keyboard_navigation/skip_to_top.gif and /dev/null differ diff --git a/eslint.config.js b/eslint.config.js index 3bd67633df..4ce99166d9 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -40,6 +40,7 @@ module.exports = [ '**/dist/', '**/build/', 'examples/blockly-svelte/public/bundle.js', + 'plugins/migration/test/manual-test-data/', // specific examples that are sometimes copied into plugins 'plugins/dev-create/templates/sample-app', 'plugins/dev-create/templates/sample-app-ts', diff --git a/gh-pages/_index.html b/gh-pages/_index.html index eb8d2e97fd..ac2486fc20 100644 --- a/gh-pages/_index.html +++ b/gh-pages/_index.html @@ -286,7 +286,7 @@

- + @@ -297,6 +297,12 @@

A plugin that allows users to manipulate and connect blocks using a keyboard-driven cursor.

+

+ This plugin (and its demo) is temporarily unavailable while we + develop an new and improved version; you can follow along with + our work in the blockly-keyboard-experimentation + GitHub repository. +

diff --git a/plugins/block-dynamic-connection/CHANGELOG.md b/plugins/block-dynamic-connection/CHANGELOG.md index 03bd02926a..7db1f6b7ac 100644 --- a/plugins/block-dynamic-connection/CHANGELOG.md +++ b/plugins/block-dynamic-connection/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.7.14](https://github.com/google/blockly-samples/compare/@blockly/block-dynamic-connection@0.7.13...@blockly/block-dynamic-connection@0.7.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/block-dynamic-connection + + + + + +## [0.7.13](https://github.com/google/blockly-samples/compare/@blockly/block-dynamic-connection@0.7.12...@blockly/block-dynamic-connection@0.7.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/block-dynamic-connection + + + + + +## [0.7.12](https://github.com/google/blockly-samples/compare/@blockly/block-dynamic-connection@0.7.11...@blockly/block-dynamic-connection@0.7.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/block-dynamic-connection + + + + + ## [0.7.11](https://github.com/google/blockly-samples/compare/@blockly/block-dynamic-connection@0.7.10...@blockly/block-dynamic-connection@0.7.11) (2024-11-07) **Note:** Version bump only for package @blockly/block-dynamic-connection diff --git a/plugins/block-dynamic-connection/package-lock.json b/plugins/block-dynamic-connection/package-lock.json index 261a044ae4..9e0f3955b8 100644 --- a/plugins/block-dynamic-connection/package-lock.json +++ b/plugins/block-dynamic-connection/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/block-dynamic-connection", - "version": "0.7.11", + "version": "0.7.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/block-dynamic-connection", - "version": "0.7.11", + "version": "0.7.14", "license": "Apache-2.0", "devDependencies": { "chai": "^4.2.0", diff --git a/plugins/block-dynamic-connection/package.json b/plugins/block-dynamic-connection/package.json index de9fae96b1..88aa8483a3 100644 --- a/plugins/block-dynamic-connection/package.json +++ b/plugins/block-dynamic-connection/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/block-dynamic-connection", - "version": "0.7.11", + "version": "0.7.14", "description": "A group of blocks that add connections dynamically.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -40,8 +40,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "chai": "^4.2.0", "mocha": "^10.2.0", "typescript": "^5.4.5" diff --git a/plugins/block-plus-minus/CHANGELOG.md b/plugins/block-plus-minus/CHANGELOG.md index b4be0ea9be..4aed2badfb 100644 --- a/plugins/block-plus-minus/CHANGELOG.md +++ b/plugins/block-plus-minus/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [8.0.14](https://github.com/google/blockly-samples/compare/@blockly/block-plus-minus@8.0.13...@blockly/block-plus-minus@8.0.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/block-plus-minus + + + + + +## [8.0.13](https://github.com/google/blockly-samples/compare/@blockly/block-plus-minus@8.0.12...@blockly/block-plus-minus@8.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/block-plus-minus + + + + + +## [8.0.12](https://github.com/google/blockly-samples/compare/@blockly/block-plus-minus@8.0.11...@blockly/block-plus-minus@8.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/block-plus-minus + + + + + ## [8.0.11](https://github.com/google/blockly-samples/compare/@blockly/block-plus-minus@8.0.10...@blockly/block-plus-minus@8.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/block-plus-minus diff --git a/plugins/block-plus-minus/package-lock.json b/plugins/block-plus-minus/package-lock.json index f2279d352f..a29283d3ed 100644 --- a/plugins/block-plus-minus/package-lock.json +++ b/plugins/block-plus-minus/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/block-plus-minus", - "version": "8.0.11", + "version": "8.0.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/block-plus-minus", - "version": "8.0.11", + "version": "8.0.14", "license": "Apache-2.0", "devDependencies": { "chai": "^4.2.0", diff --git a/plugins/block-plus-minus/package.json b/plugins/block-plus-minus/package.json index ed8c2ffe4b..cc6841c9ae 100644 --- a/plugins/block-plus-minus/package.json +++ b/plugins/block-plus-minus/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/block-plus-minus", - "version": "8.0.11", + "version": "8.0.14", "description": "A group of blocks that replace the built-in mutator UI with a +/- based UI.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -39,8 +39,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "chai": "^4.2.0", "mocha": "^10.2.0", "sinon": "^9.0.1" diff --git a/plugins/block-shareable-procedures/CHANGELOG.md b/plugins/block-shareable-procedures/CHANGELOG.md index 7101903887..462742ebac 100644 --- a/plugins/block-shareable-procedures/CHANGELOG.md +++ b/plugins/block-shareable-procedures/CHANGELOG.md @@ -3,6 +3,41 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [5.0.15](https://github.com/google/blockly-samples/compare/@blockly/block-shareable-procedures@5.0.14...@blockly/block-shareable-procedures@5.0.15) (2025-02-27) + + +### Bug Fixes + +* Mitigate shareable procedure flyout bug. ([a37225a](https://github.com/google/blockly-samples/commit/a37225a6dc4369fcec14e2a704eaa6bef9842b8c)) + + + + + +## [5.0.14](https://github.com/google/blockly-samples/compare/@blockly/block-shareable-procedures@5.0.13...@blockly/block-shareable-procedures@5.0.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/block-shareable-procedures + + + + + +## [5.0.13](https://github.com/google/blockly-samples/compare/@blockly/block-shareable-procedures@5.0.12...@blockly/block-shareable-procedures@5.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/block-shareable-procedures + + + + + +## [5.0.12](https://github.com/google/blockly-samples/compare/@blockly/block-shareable-procedures@5.0.11...@blockly/block-shareable-procedures@5.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/block-shareable-procedures + + + + + ## [5.0.11](https://github.com/google/blockly-samples/compare/@blockly/block-shareable-procedures@5.0.10...@blockly/block-shareable-procedures@5.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/block-shareable-procedures diff --git a/plugins/block-shareable-procedures/package-lock.json b/plugins/block-shareable-procedures/package-lock.json index 6627a2a8dc..e6487b02ff 100644 --- a/plugins/block-shareable-procedures/package-lock.json +++ b/plugins/block-shareable-procedures/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/block-shareable-procedures", - "version": "5.0.11", + "version": "5.0.15", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@blockly/block-shareable-procedures", - "version": "5.0.11", + "version": "5.0.15", "license": "Apache-2.0", "devDependencies": { "chai": "^4.3.7", diff --git a/plugins/block-shareable-procedures/package.json b/plugins/block-shareable-procedures/package.json index 48ce23de2f..3a90e4928b 100644 --- a/plugins/block-shareable-procedures/package.json +++ b/plugins/block-shareable-procedures/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/block-shareable-procedures", - "version": "5.0.11", + "version": "5.0.15", "description": "A plugin that adds procedure blocks which are backed by explicit data models.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -41,8 +41,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "chai": "^4.3.7", "jsdom": "^16.4.0", "jsdom-global": "^3.0.2", diff --git a/plugins/block-shareable-procedures/src/blocks.ts b/plugins/block-shareable-procedures/src/blocks.ts index 83346409a6..07f2cc50ca 100644 --- a/plugins/block-shareable-procedures/src/blocks.ts +++ b/plugins/block-shareable-procedures/src/blocks.ts @@ -1068,7 +1068,10 @@ const procedureCallerUpdateShapeMixin = { doProcedureUpdate: function () { if (!this.getProcedureModel()) return; const id = this.getProcedureModel().getId(); - if (!this.getTargetWorkspace_().getProcedureMap().has(id)) { + if ( + !this.getTargetWorkspace_().getProcedureMap().has(id) && + !this.isInFlyout + ) { this.dispose(true); return; } diff --git a/plugins/block-test/CHANGELOG.md b/plugins/block-test/CHANGELOG.md index 9dfe1872d6..ee1eec88e6 100644 --- a/plugins/block-test/CHANGELOG.md +++ b/plugins/block-test/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [6.0.11](https://github.com/google/blockly-samples/compare/@blockly/block-test@6.0.10...@blockly/block-test@6.0.11) (2024-12-03) + +**Note:** Version bump only for package @blockly/block-test + + + + + ## [6.0.10](https://github.com/google/blockly-samples/compare/@blockly/block-test@6.0.9...@blockly/block-test@6.0.10) (2024-11-07) **Note:** Version bump only for package @blockly/block-test diff --git a/plugins/block-test/package-lock.json b/plugins/block-test/package-lock.json index b57a6f2925..14cc1222f9 100644 --- a/plugins/block-test/package-lock.json +++ b/plugins/block-test/package-lock.json @@ -1,15 +1,15 @@ { "name": "@blockly/block-test", - "version": "6.0.10", + "version": "6.0.11", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/block-test", - "version": "6.0.10", + "version": "6.0.11", "license": "Apache 2.0", "devDependencies": { - "@blockly/dev-scripts": "^4.0.6" + "@blockly/dev-scripts": "^4.0.7" }, "engines": { "node": ">=8.17.0" diff --git a/plugins/block-test/package.json b/plugins/block-test/package.json index e0492d1968..b24df6bcd1 100644 --- a/plugins/block-test/package.json +++ b/plugins/block-test/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/block-test", - "version": "6.0.10", + "version": "6.0.11", "description": "A group of Blockly test blocks.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -39,7 +39,7 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6" + "@blockly/dev-scripts": "^4.0.7" }, "peerDependencies": { "blockly": "^11.0.0" diff --git a/plugins/content-highlight/CHANGELOG.md b/plugins/content-highlight/CHANGELOG.md index 5f6adec1ca..6c66ad8e5e 100644 --- a/plugins/content-highlight/CHANGELOG.md +++ b/plugins/content-highlight/CHANGELOG.md @@ -3,6 +3,41 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [5.0.15](https://github.com/google/blockly-samples/compare/@blockly/workspace-content-highlight@5.0.14...@blockly/workspace-content-highlight@5.0.15) (2025-02-20) + + +### Bug Fixes + +* update content highlight when undoing the deletion of blocks. ([#2487](https://github.com/google/blockly-samples/issues/2487)) ([b216e9e](https://github.com/google/blockly-samples/commit/b216e9eeaf84e5f51af2bc72b8b15a40c7137697)) + + + + + +## [5.0.14](https://github.com/google/blockly-samples/compare/@blockly/workspace-content-highlight@5.0.13...@blockly/workspace-content-highlight@5.0.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/workspace-content-highlight + + + + + +## [5.0.13](https://github.com/google/blockly-samples/compare/@blockly/workspace-content-highlight@5.0.12...@blockly/workspace-content-highlight@5.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/workspace-content-highlight + + + + + +## [5.0.12](https://github.com/google/blockly-samples/compare/@blockly/workspace-content-highlight@5.0.11...@blockly/workspace-content-highlight@5.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/workspace-content-highlight + + + + + ## [5.0.11](https://github.com/google/blockly-samples/compare/@blockly/workspace-content-highlight@5.0.10...@blockly/workspace-content-highlight@5.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/workspace-content-highlight diff --git a/plugins/content-highlight/package-lock.json b/plugins/content-highlight/package-lock.json index e0ce8cd264..fb2c9d961a 100644 --- a/plugins/content-highlight/package-lock.json +++ b/plugins/content-highlight/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/workspace-content-highlight", - "version": "5.0.11", + "version": "5.0.15", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/workspace-content-highlight", - "version": "5.0.11", + "version": "5.0.15", "license": "Apache-2.0", "devDependencies": { "typescript": "^5.4.5" diff --git a/plugins/content-highlight/package.json b/plugins/content-highlight/package.json index 72286d1216..8049142616 100644 --- a/plugins/content-highlight/package.json +++ b/plugins/content-highlight/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/workspace-content-highlight", - "version": "5.0.11", + "version": "5.0.15", "description": "A Blockly workspace plugin that adds a highlight around the content area.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -43,8 +43,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "typescript": "^5.4.5" }, "peerDependencies": { diff --git a/plugins/content-highlight/src/index.ts b/plugins/content-highlight/src/index.ts index 4ec5a2d23f..e87c687b9d 100644 --- a/plugins/content-highlight/src/index.ts +++ b/plugins/content-highlight/src/index.ts @@ -15,6 +15,7 @@ import * as Blockly from 'blockly/core'; */ const contentChangeEvents = [ Blockly.Events.VIEWPORT_CHANGE, + Blockly.Events.BLOCK_CREATE, Blockly.Events.BLOCK_MOVE, Blockly.Events.BLOCK_DELETE, Blockly.Events.COMMENT_MOVE, diff --git a/plugins/continuous-toolbox/CHANGELOG.md b/plugins/continuous-toolbox/CHANGELOG.md index 3a73e9ff07..d124b0bec8 100644 --- a/plugins/continuous-toolbox/CHANGELOG.md +++ b/plugins/continuous-toolbox/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [6.0.14](https://github.com/google/blockly-samples/compare/@blockly/continuous-toolbox@6.0.13...@blockly/continuous-toolbox@6.0.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/continuous-toolbox + + + + + +## [6.0.13](https://github.com/google/blockly-samples/compare/@blockly/continuous-toolbox@6.0.12...@blockly/continuous-toolbox@6.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/continuous-toolbox + + + + + +## [6.0.12](https://github.com/google/blockly-samples/compare/@blockly/continuous-toolbox@6.0.11...@blockly/continuous-toolbox@6.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/continuous-toolbox + + + + + ## [6.0.11](https://github.com/google/blockly-samples/compare/@blockly/continuous-toolbox@6.0.10...@blockly/continuous-toolbox@6.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/continuous-toolbox diff --git a/plugins/continuous-toolbox/package-lock.json b/plugins/continuous-toolbox/package-lock.json index dff8845f3d..b084d403e5 100644 --- a/plugins/continuous-toolbox/package-lock.json +++ b/plugins/continuous-toolbox/package-lock.json @@ -1,16 +1,16 @@ { "name": "@blockly/continuous-toolbox", - "version": "6.0.11", + "version": "6.0.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/continuous-toolbox", - "version": "6.0.11", + "version": "6.0.14", "license": "Apache-2.0", "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11" + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0" }, "engines": { "node": ">=8.17.0" diff --git a/plugins/continuous-toolbox/package.json b/plugins/continuous-toolbox/package.json index 3b3d256e11..2cee9ff6f2 100644 --- a/plugins/continuous-toolbox/package.json +++ b/plugins/continuous-toolbox/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/continuous-toolbox", - "version": "6.0.11", + "version": "6.0.14", "description": "A Blockly plugin that adds a continous-scrolling style toolbox and flyout", "scripts": { "build": "blockly-scripts build", @@ -39,8 +39,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11" + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0" }, "peerDependencies": { "blockly": "^11.0.0" diff --git a/plugins/cross-tab-copy-paste/CHANGELOG.md b/plugins/cross-tab-copy-paste/CHANGELOG.md index d75ea6ae9b..05ed0d9550 100644 --- a/plugins/cross-tab-copy-paste/CHANGELOG.md +++ b/plugins/cross-tab-copy-paste/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [6.0.14](https://github.com/google/blockly-samples/compare/@blockly/plugin-cross-tab-copy-paste@6.0.13...@blockly/plugin-cross-tab-copy-paste@6.0.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/plugin-cross-tab-copy-paste + + + + + +## [6.0.13](https://github.com/google/blockly-samples/compare/@blockly/plugin-cross-tab-copy-paste@6.0.12...@blockly/plugin-cross-tab-copy-paste@6.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/plugin-cross-tab-copy-paste + + + + + +## [6.0.12](https://github.com/google/blockly-samples/compare/@blockly/plugin-cross-tab-copy-paste@6.0.11...@blockly/plugin-cross-tab-copy-paste@6.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/plugin-cross-tab-copy-paste + + + + + ## [6.0.11](https://github.com/google/blockly-samples/compare/@blockly/plugin-cross-tab-copy-paste@6.0.10...@blockly/plugin-cross-tab-copy-paste@6.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/plugin-cross-tab-copy-paste diff --git a/plugins/cross-tab-copy-paste/package-lock.json b/plugins/cross-tab-copy-paste/package-lock.json index d2473f4947..1805e9ac15 100644 --- a/plugins/cross-tab-copy-paste/package-lock.json +++ b/plugins/cross-tab-copy-paste/package-lock.json @@ -1,16 +1,16 @@ { "name": "@blockly/plugin-cross-tab-copy-paste", - "version": "6.0.11", + "version": "6.0.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/plugin-cross-tab-copy-paste", - "version": "6.0.11", + "version": "6.0.14", "license": "Apache-2.0", "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11" + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0" }, "engines": { "node": ">=8.17.0" diff --git a/plugins/cross-tab-copy-paste/package.json b/plugins/cross-tab-copy-paste/package.json index 53abf093ac..a9d27074ac 100644 --- a/plugins/cross-tab-copy-paste/package.json +++ b/plugins/cross-tab-copy-paste/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/plugin-cross-tab-copy-paste", - "version": "6.0.11", + "version": "6.0.14", "description": "Allows you to copy blocks with cross-tab.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -40,8 +40,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11" + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0" }, "peerDependencies": { "blockly": "^11.0.0" diff --git a/plugins/dev-scripts/CHANGELOG.md b/plugins/dev-scripts/CHANGELOG.md index 50ee3701f7..5a7e8d6205 100644 --- a/plugins/dev-scripts/CHANGELOG.md +++ b/plugins/dev-scripts/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [4.0.7](https://github.com/google/blockly-samples/compare/@blockly/dev-scripts@4.0.6...@blockly/dev-scripts@4.0.7) (2024-12-03) + +**Note:** Version bump only for package @blockly/dev-scripts + + + + + ## [4.0.6](https://github.com/google/blockly-samples/compare/@blockly/dev-scripts@4.0.5...@blockly/dev-scripts@4.0.6) (2024-11-07) diff --git a/plugins/dev-scripts/package-lock.json b/plugins/dev-scripts/package-lock.json index 1c2c141274..03b53c7b1c 100644 --- a/plugins/dev-scripts/package-lock.json +++ b/plugins/dev-scripts/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/dev-scripts", - "version": "4.0.6", + "version": "4.0.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@blockly/dev-scripts", - "version": "4.0.6", + "version": "4.0.7", "license": "Apache-2.0", "dependencies": { "@babel/code-frame": "^7.8.3", diff --git a/plugins/dev-scripts/package.json b/plugins/dev-scripts/package.json index feab7bb06a..8add4d19ed 100644 --- a/plugins/dev-scripts/package.json +++ b/plugins/dev-scripts/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/dev-scripts", - "version": "4.0.6", + "version": "4.0.7", "description": "Configuration and scripts for Blockly plugins.", "scripts": { "lint": "eslint ." diff --git a/plugins/dev-tools/CHANGELOG.md b/plugins/dev-tools/CHANGELOG.md index 32210b1030..a4e3447801 100644 --- a/plugins/dev-tools/CHANGELOG.md +++ b/plugins/dev-tools/CHANGELOG.md @@ -3,6 +3,36 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [8.1.0](https://github.com/google/blockly-samples/compare/@blockly/dev-tools@8.0.13...@blockly/dev-tools@8.1.0) (2025-02-13) + + +### Features + +* Added button to Advanced Playground to import state. ([#2483](https://github.com/google/blockly-samples/issues/2483)) ([fed7ee0](https://github.com/google/blockly-samples/commit/fed7ee0e82cd0a2f3d2f00cec69abd5932feb42f)) + + + + + +## [8.0.13](https://github.com/google/blockly-samples/compare/@blockly/dev-tools@8.0.12...@blockly/dev-tools@8.0.13) (2024-12-19) + + +### Bug Fixes + +* Update screenshot plugin for compatibility with CSS vars. ([#2472](https://github.com/google/blockly-samples/issues/2472)) ([eecfccd](https://github.com/google/blockly-samples/commit/eecfccda56027a613d76f9ace70e62d9143f1c2e)) + + + + + +## [8.0.12](https://github.com/google/blockly-samples/compare/@blockly/dev-tools@8.0.11...@blockly/dev-tools@8.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/dev-tools + + + + + ## [8.0.11](https://github.com/google/blockly-samples/compare/@blockly/dev-tools@8.0.10...@blockly/dev-tools@8.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/dev-tools diff --git a/plugins/dev-tools/package-lock.json b/plugins/dev-tools/package-lock.json index c8e73b7bee..677520674e 100644 --- a/plugins/dev-tools/package-lock.json +++ b/plugins/dev-tools/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/dev-tools", - "version": "8.0.11", + "version": "8.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@blockly/dev-tools", - "version": "8.0.11", + "version": "8.1.0", "license": "Apache-2.0", "dependencies": { "chai": "^4.2.0", diff --git a/plugins/dev-tools/package.json b/plugins/dev-tools/package.json index dc0903be25..3d046efee4 100644 --- a/plugins/dev-tools/package.json +++ b/plugins/dev-tools/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/dev-tools", - "version": "8.0.11", + "version": "8.1.0", "description": "A library of common utilities for Blockly extension development.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -38,11 +38,11 @@ "src" ], "dependencies": { - "@blockly/block-test": "^6.0.10", - "@blockly/theme-dark": "^7.0.9", - "@blockly/theme-deuteranopia": "^6.0.9", - "@blockly/theme-highcontrast": "^6.0.9", - "@blockly/theme-tritanopia": "^6.0.9", + "@blockly/block-test": "^6.0.11", + "@blockly/theme-dark": "^7.0.10", + "@blockly/theme-deuteranopia": "^6.0.10", + "@blockly/theme-highcontrast": "^6.0.10", + "@blockly/theme-tritanopia": "^6.0.10", "chai": "^4.2.0", "dat.gui": "^0.7.7", "lodash.assign": "^4.2.0", @@ -51,7 +51,7 @@ "sinon": "^9.0.2" }, "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", + "@blockly/dev-scripts": "^4.0.7", "@types/dat.gui": "^0.7.5" }, "peerDependencies": { diff --git a/plugins/dev-tools/src/playground/index.js b/plugins/dev-tools/src/playground/index.js index c0f8001ee4..70a9c9c8ef 100644 --- a/plugins/dev-tools/src/playground/index.js +++ b/plugins/dev-tools/src/playground/index.js @@ -24,7 +24,12 @@ import {id} from './id'; import {addCodeEditor} from './monaco'; import {addGUIControls} from './options'; import {LocalStorageState} from './state'; -import {renderCheckbox, renderCodeTab, renderPlayground} from './ui'; +import { + renderButton, + renderCheckbox, + renderCodeTab, + renderPlayground, +} from './ui'; // Declare external types to make eslint happy. /* global dat, monaco */ @@ -222,6 +227,7 @@ export function createPlayground( // Update editor state. editorXmlContextKey.set(isXml); editorJsonContextKey.set(isJson); + updateImportButtonDisplay(); playgroundState.set('activeTab', tab.state.name); playgroundState.save(); }; @@ -341,6 +347,26 @@ export function createPlayground( playgroundState.save(); }); + // Create a button to import state from the editor tab to the workspace. + const importButton = renderButton('Import'); + tabButtons.appendChild(importButton); + importButton.addEventListener('click', (e) => { + if (editorXmlContextKey.get()) { + editor.getAction('import-xml').run(); + } + if (editorJsonContextKey.get()) { + editor.getAction('import-json').run(); + } + }); + const updateImportButtonDisplay = function () { + // The import button is only relevant for the XML and JSON tabs. + if (editorXmlContextKey.get() || editorJsonContextKey.get()) { + importButton.style.display = ''; + } else { + importButton.style.display = 'none'; + } + }; + // Set the initial tab as active. const activeTab = playgroundState.get('activeTab'); let currentTab = tabs[activeTab]; @@ -552,7 +578,10 @@ function registerEditorCommands(editor, playground) { const xml = editor.getModel().getValue(); const workspace = playground.getWorkspace(); try { - Blockly.Xml.domToWorkspace(Blockly.utils.xml.textToDom(xml), workspace); + Blockly.Xml.clearWorkspaceAndLoadFromXml( + Blockly.utils.xml.textToDom(xml), + workspace, + ); } catch (e) { // If this fails that's fine. return false; diff --git a/plugins/dev-tools/src/playground/ui.js b/plugins/dev-tools/src/playground/ui.js index 9e24f665f1..855b0becd9 100644 --- a/plugins/dev-tools/src/playground/ui.js +++ b/plugins/dev-tools/src/playground/ui.js @@ -109,7 +109,6 @@ export function renderPlayground(container) { const tabButtons = document.createElement('div'); tabButtons.style.position = 'absolute'; tabButtons.style.height = '30px'; - tabButtons.style.width = '50px'; tabButtons.style.top = '0'; tabButtons.style.right = '0'; tabButtons.style.display = 'flex'; @@ -166,3 +165,15 @@ export function renderCheckbox(id, label) { checkboxLabel.setAttribute('for', id); return [checkbox, checkboxLabel]; } + +/** + * Render a button. + * @param {string} label The text content of the button. + * @returns {HTMLButtonElement} The button element. + */ +export function renderButton(label) { + const button = document.createElement('button'); + button.setAttribute('type', 'button'); + button.textContent = label; + return button; +} diff --git a/plugins/dev-tools/src/screenshot.js b/plugins/dev-tools/src/screenshot.js index b10bf89741..6b233dd051 100644 --- a/plugins/dev-tools/src/screenshot.js +++ b/plugins/dev-tools/src/screenshot.js @@ -84,7 +84,11 @@ function workspaceToSvg_(workspace, callback, customCss) { ); svg.setAttribute('width', width); svg.setAttribute('height', height); - svg.setAttribute('style', 'background-color: transparent'); + svg.setAttribute( + 'style', + 'background-color: transparent; ' + + workspace.getInjectionDiv().style.cssText, // has CSS vars for SVG filters + ); const css = [].slice .call(document.head.querySelectorAll('style')) diff --git a/plugins/disable-top-blocks/CHANGELOG.md b/plugins/disable-top-blocks/CHANGELOG.md index 668dfba2ac..9aecad62ec 100644 --- a/plugins/disable-top-blocks/CHANGELOG.md +++ b/plugins/disable-top-blocks/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.5.14](https://github.com/google/blockly-samples/compare/@blockly/disable-top-blocks@0.5.13...@blockly/disable-top-blocks@0.5.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/disable-top-blocks + + + + + +## [0.5.13](https://github.com/google/blockly-samples/compare/@blockly/disable-top-blocks@0.5.12...@blockly/disable-top-blocks@0.5.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/disable-top-blocks + + + + + +## [0.5.12](https://github.com/google/blockly-samples/compare/@blockly/disable-top-blocks@0.5.11...@blockly/disable-top-blocks@0.5.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/disable-top-blocks + + + + + ## [0.5.11](https://github.com/google/blockly-samples/compare/@blockly/disable-top-blocks@0.5.10...@blockly/disable-top-blocks@0.5.11) (2024-11-07) **Note:** Version bump only for package @blockly/disable-top-blocks diff --git a/plugins/disable-top-blocks/package-lock.json b/plugins/disable-top-blocks/package-lock.json index 7de7a9e986..9dc1330df6 100644 --- a/plugins/disable-top-blocks/package-lock.json +++ b/plugins/disable-top-blocks/package-lock.json @@ -1,16 +1,16 @@ { "name": "@blockly/disable-top-blocks", - "version": "0.5.11", + "version": "0.5.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/disable-top-blocks", - "version": "0.5.11", + "version": "0.5.14", "license": "Apache-2.0", "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11" + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0" }, "engines": { "node": ">=8.17.0" diff --git a/plugins/disable-top-blocks/package.json b/plugins/disable-top-blocks/package.json index 191929eca8..54d0dfefe1 100644 --- a/plugins/disable-top-blocks/package.json +++ b/plugins/disable-top-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/disable-top-blocks", - "version": "0.5.11", + "version": "0.5.14", "description": "A Blockly plugin that shows the 'disable' context menu option only on non-orphan blocks.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -38,8 +38,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11" + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0" }, "peerDependencies": { "blockly": "^11.0.0" diff --git a/plugins/eslint-config/package.json b/plugins/eslint-config/package.json index ce64e8a7ce..36f3f42863 100644 --- a/plugins/eslint-config/package.json +++ b/plugins/eslint-config/package.json @@ -1,6 +1,7 @@ { "name": "@blockly/eslint-config", "version": "4.0.1", + "private": true, "description": "ESlint configuration used by Blockly plugins.", "files": [ "index.js" diff --git a/plugins/field-angle/CHANGELOG.md b/plugins/field-angle/CHANGELOG.md index 5218afaca0..7ea91c5316 100644 --- a/plugins/field-angle/CHANGELOG.md +++ b/plugins/field-angle/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [5.0.14](https://github.com/google/blockly-samples/compare/@blockly/field-angle@5.0.13...@blockly/field-angle@5.0.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/field-angle + + + + + +## [5.0.13](https://github.com/google/blockly-samples/compare/@blockly/field-angle@5.0.12...@blockly/field-angle@5.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/field-angle + + + + + +## [5.0.12](https://github.com/google/blockly-samples/compare/@blockly/field-angle@5.0.11...@blockly/field-angle@5.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/field-angle + + + + + ## [5.0.11](https://github.com/google/blockly-samples/compare/@blockly/field-angle@5.0.10...@blockly/field-angle@5.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/field-angle diff --git a/plugins/field-angle/package-lock.json b/plugins/field-angle/package-lock.json index 436070e579..08c89ba518 100644 --- a/plugins/field-angle/package-lock.json +++ b/plugins/field-angle/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/field-angle", - "version": "5.0.11", + "version": "5.0.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/field-angle", - "version": "5.0.11", + "version": "5.0.14", "license": "Apache-2.0", "devDependencies": { "chai": "^4.2.0", diff --git a/plugins/field-angle/package.json b/plugins/field-angle/package.json index bda233683b..4e7f3e24ff 100644 --- a/plugins/field-angle/package.json +++ b/plugins/field-angle/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/field-angle", - "version": "5.0.11", + "version": "5.0.14", "description": "A Blockly angle field.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -40,8 +40,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "chai": "^4.2.0", "sinon": "^9.0.1", "typescript": "^5.4.5" diff --git a/plugins/field-bitmap/CHANGELOG.md b/plugins/field-bitmap/CHANGELOG.md index a9cd64b736..0709df2617 100644 --- a/plugins/field-bitmap/CHANGELOG.md +++ b/plugins/field-bitmap/CHANGELOG.md @@ -3,6 +3,41 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [5.0.15](https://github.com/google/blockly-samples/compare/@blockly/field-bitmap@5.0.14...@blockly/field-bitmap@5.0.15) (2025-02-27) + + +### Bug Fixes + +* [#2463](https://github.com/google/blockly-samples/issues/2463) update event handling for field-bitmap to support touch ([c105002](https://github.com/google/blockly-samples/commit/c1050025e41dd456c822301555b1b3a20577d03e)) + + + + + +## [5.0.14](https://github.com/google/blockly-samples/compare/@blockly/field-bitmap@5.0.13...@blockly/field-bitmap@5.0.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/field-bitmap + + + + + +## [5.0.13](https://github.com/google/blockly-samples/compare/@blockly/field-bitmap@5.0.12...@blockly/field-bitmap@5.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/field-bitmap + + + + + +## [5.0.12](https://github.com/google/blockly-samples/compare/@blockly/field-bitmap@5.0.11...@blockly/field-bitmap@5.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/field-bitmap + + + + + ## [5.0.11](https://github.com/google/blockly-samples/compare/@blockly/field-bitmap@5.0.10...@blockly/field-bitmap@5.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/field-bitmap diff --git a/plugins/field-bitmap/package-lock.json b/plugins/field-bitmap/package-lock.json index 9a456cb1b5..8ee96365fa 100644 --- a/plugins/field-bitmap/package-lock.json +++ b/plugins/field-bitmap/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/field-bitmap", - "version": "5.0.11", + "version": "5.0.15", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/field-bitmap", - "version": "5.0.11", + "version": "5.0.15", "license": "Apache-2.0", "devDependencies": { "chai": "^4.3.6", diff --git a/plugins/field-bitmap/package.json b/plugins/field-bitmap/package.json index 86b6e62828..c7a5f80d56 100644 --- a/plugins/field-bitmap/package.json +++ b/plugins/field-bitmap/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/field-bitmap", - "version": "5.0.11", + "version": "5.0.15", "description": "A field that lets users input a pixel grid with their mouse.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -40,8 +40,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "chai": "^4.3.6", "mocha": "^10.7.0", "typescript": "^5.4.5" diff --git a/plugins/field-bitmap/src/field-bitmap.ts b/plugins/field-bitmap/src/field-bitmap.ts index 70b4fea421..e19156c66c 100644 --- a/plugins/field-bitmap/src/field-bitmap.ts +++ b/plugins/field-bitmap/src/field-bitmap.ts @@ -37,7 +37,7 @@ export class FieldBitmap extends Blockly.Field { private editorPixels: HTMLElement[][] | null = null; private blockDisplayPixels: SVGElement[][] | null = null; /** Stateful variables */ - private mouseIsDown = false; + private pointerIsDown = false; private valToPaintWith?: number; buttonOptions: Buttons; pixelSize: number; @@ -292,9 +292,13 @@ export class FieldBitmap extends Blockly.Field { // This prevents the normal max-height from adding a scroll bar for large images. Blockly.DropDownDiv.getContentDiv().classList.add('contains-bitmap-editor'); - this.bindEvent(dropdownEditor, 'mouseup', this.onMouseUp); - this.bindEvent(dropdownEditor, 'mouseleave', this.onMouseUp); - this.bindEvent(dropdownEditor, 'dragstart', (e: Event) => { + this.bindEvent(dropdownEditor, 'pointermove', this.onPointerMove); + this.bindEvent(dropdownEditor, 'pointerup', this.onPointerEnd); + this.bindEvent(dropdownEditor, 'pointerleave', this.onPointerEnd); + this.bindEvent(dropdownEditor, 'pointerdown', this.onPointerStart); + this.bindEvent(dropdownEditor, 'pointercancel', this.onPointerEnd); + // Stop the browser from handling touch events and cancelling the event. + this.bindEvent(dropdownEditor, 'touchmove', (e: Event) => { e.preventDefault(); }); @@ -314,16 +318,9 @@ export class FieldBitmap extends Blockly.Field { ? this.pixelColours.filled : this.pixelColours.empty; - // Handle clicking a pixel - this.bindEvent(button, 'mousedown', () => { - this.onMouseDownInPixel(r, c); - return true; - }); - - // Handle dragging into a pixel when mouse is down - this.bindEvent(button, 'mouseenter', () => { - this.onMouseEnterPixel(r, c); - }); + // Set the custom data attributes for row and column indices + button.setAttribute('data-row', r.toString()); + button.setAttribute('data-col', c.toString()); } pixelContainer.appendChild(rowDiv); } @@ -473,29 +470,63 @@ export class FieldBitmap extends Blockly.Field { } /** - * Called when a mousedown event occurs within the bounds of a pixel. + * Checks if a down event is on a pixel in this editor and if it is starts an + * edit gesture. + * + * @param e The down event. + */ + private onPointerStart(e: PointerEvent) { + const currentElement = document.elementFromPoint(e.clientX, e.clientY); + const rowIndex = currentElement?.getAttribute('data-row'); + const colIndex = currentElement?.getAttribute('data-col'); + if (rowIndex && colIndex) { + this.onPointerDownInPixel(parseInt(rowIndex), parseInt(colIndex)); + this.pointerIsDown = true; + e.preventDefault(); + } + } + + /** + * Updates the editor if we're in an edit gesture and the pointer is over a + * pixel. + * + * @param e The move event. + */ + private onPointerMove(e: PointerEvent) { + if (!this.pointerIsDown) { + return; + } + const currentElement = document.elementFromPoint(e.clientX, e.clientY); + const rowIndex = currentElement?.getAttribute('data-row'); + const colIndex = currentElement?.getAttribute('data-col'); + if (rowIndex && colIndex) { + this.updatePixelValue(parseInt(rowIndex), parseInt(colIndex)); + } + e.preventDefault(); + } + + /** + * Starts an interaction with the bitmap dropdown when there's a pointerdown + * within one of the pixels in the editor. * * @param r Row number of grid. * @param c Column number of grid. */ - private onMouseDownInPixel(r: number, c: number) { + private onPointerDownInPixel(r: number, c: number) { // Toggle that pixel to the opposite of its value const newPixelValue = 1 - this.getPixel(r, c); this.setPixel(r, c, newPixelValue); - this.mouseIsDown = true; + this.pointerIsDown = true; this.valToPaintWith = newPixelValue; } /** - * Called when the mouse drags over a pixel in the editor. + * Sets the specified pixel in the editor to the current value being painted. * * @param r Row number of grid. * @param c Column number of grid. */ - private onMouseEnterPixel(r: number, c: number) { - if (!this.mouseIsDown) { - return; - } + private updatePixelValue(r: number, c: number) { if ( this.valToPaintWith !== undefined && this.getPixel(r, c) !== this.valToPaintWith @@ -505,11 +536,11 @@ export class FieldBitmap extends Blockly.Field { } /** - * Resets mouse state (e.g. After either a mouseup event or if the mouse - * leaves the editor area). + * Resets pointer state (e.g. After either a pointerup event or if the + * gesture is canceled). */ - private onMouseUp() { - this.mouseIsDown = false; + private onPointerEnd() { + this.pointerIsDown = false; this.valToPaintWith = undefined; } @@ -594,10 +625,10 @@ export class FieldBitmap extends Blockly.Field { private bindEvent( element: HTMLElement, eventName: string, - callback: (e: Event) => void, + callback: (e: PointerEvent) => void, ) { this.boundEvents.push( - Blockly.browserEvents.conditionalBind(element, eventName, this, callback), + Blockly.browserEvents.bind(element, eventName, this, callback), ); } diff --git a/plugins/field-colour-hsv-sliders/CHANGELOG.md b/plugins/field-colour-hsv-sliders/CHANGELOG.md index e6c0261287..ae1ce742a6 100644 --- a/plugins/field-colour-hsv-sliders/CHANGELOG.md +++ b/plugins/field-colour-hsv-sliders/CHANGELOG.md @@ -3,6 +3,54 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [5.0.17](https://github.com/google/blockly-samples/compare/@blockly/field-colour-hsv-sliders@5.0.16...@blockly/field-colour-hsv-sliders@5.0.17) (2025-05-08) + +**Note:** Version bump only for package @blockly/field-colour-hsv-sliders + + + + + +## [5.0.16](https://github.com/google/blockly-samples/compare/@blockly/field-colour-hsv-sliders@5.0.15...@blockly/field-colour-hsv-sliders@5.0.16) (2025-03-27) + +**Note:** Version bump only for package @blockly/field-colour-hsv-sliders + + + + + +## [5.0.15](https://github.com/google/blockly-samples/compare/@blockly/field-colour-hsv-sliders@5.0.14...@blockly/field-colour-hsv-sliders@5.0.15) (2025-02-13) + +**Note:** Version bump only for package @blockly/field-colour-hsv-sliders + + + + + +## [5.0.14](https://github.com/google/blockly-samples/compare/@blockly/field-colour-hsv-sliders@5.0.13...@blockly/field-colour-hsv-sliders@5.0.14) (2025-01-23) + +**Note:** Version bump only for package @blockly/field-colour-hsv-sliders + + + + + +## [5.0.13](https://github.com/google/blockly-samples/compare/@blockly/field-colour-hsv-sliders@5.0.12...@blockly/field-colour-hsv-sliders@5.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/field-colour-hsv-sliders + + + + + +## [5.0.12](https://github.com/google/blockly-samples/compare/@blockly/field-colour-hsv-sliders@5.0.11...@blockly/field-colour-hsv-sliders@5.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/field-colour-hsv-sliders + + + + + ## [5.0.11](https://github.com/google/blockly-samples/compare/@blockly/field-colour-hsv-sliders@5.0.10...@blockly/field-colour-hsv-sliders@5.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/field-colour-hsv-sliders diff --git a/plugins/field-colour-hsv-sliders/package-lock.json b/plugins/field-colour-hsv-sliders/package-lock.json index e187cca896..ec5a03693f 100644 --- a/plugins/field-colour-hsv-sliders/package-lock.json +++ b/plugins/field-colour-hsv-sliders/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/field-colour-hsv-sliders", - "version": "5.0.11", + "version": "5.0.17", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/field-colour-hsv-sliders", - "version": "5.0.11", + "version": "5.0.17", "license": "Apache-2.0", "devDependencies": { "typescript": "^5.4.5" diff --git a/plugins/field-colour-hsv-sliders/package.json b/plugins/field-colour-hsv-sliders/package.json index 1c174d8371..ddb2614813 100644 --- a/plugins/field-colour-hsv-sliders/package.json +++ b/plugins/field-colour-hsv-sliders/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/field-colour-hsv-sliders", - "version": "5.0.11", + "version": "5.0.17", "description": "A Blockly colour field using HSV sliders.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -41,11 +41,11 @@ "src" ], "dependencies": { - "@blockly/field-colour": "^5.0.11" + "@blockly/field-colour": "^5.0.17" }, "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "typescript": "^5.4.5" }, "peerDependencies": { diff --git a/plugins/field-colour/CHANGELOG.md b/plugins/field-colour/CHANGELOG.md index b26a184ea6..e932b64a73 100644 --- a/plugins/field-colour/CHANGELOG.md +++ b/plugins/field-colour/CHANGELOG.md @@ -3,6 +3,63 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [5.0.17](https://github.com/google/blockly-samples/compare/@blockly/field-colour@5.0.16...@blockly/field-colour@5.0.17) (2025-05-08) + + +### Bug Fixes + +* Add `getClass()` to `FieldColour`. ([#2506](https://github.com/google/blockly-samples/issues/2506)) ([f5a577b](https://github.com/google/blockly-samples/commit/f5a577b8fe25b6fbf1502ca85902c22777fd8270)) + + + + + +## [5.0.16](https://github.com/google/blockly-samples/compare/@blockly/field-colour@5.0.15...@blockly/field-colour@5.0.16) (2025-03-27) + + +### Bug Fixes + +* Don't call blur() when mouse leaves the colour picker. ([#2499](https://github.com/google/blockly-samples/issues/2499)) ([e8d4a87](https://github.com/google/blockly-samples/commit/e8d4a874c44cdb0e1ad05b08122251b9e758655c)) + + + + + +## [5.0.15](https://github.com/google/blockly-samples/compare/@blockly/field-colour@5.0.14...@blockly/field-colour@5.0.15) (2025-02-13) + +**Note:** Version bump only for package @blockly/field-colour + + + + + +## [5.0.14](https://github.com/google/blockly-samples/compare/@blockly/field-colour@5.0.13...@blockly/field-colour@5.0.14) (2025-01-23) + + +### Bug Fixes + +* Fix bug that prevented keyboard navigation of color swatches. ([#2479](https://github.com/google/blockly-samples/issues/2479)) ([5945e7c](https://github.com/google/blockly-samples/commit/5945e7c0412faedc08c422f9f538ef22193cc659)) + + + + + +## [5.0.13](https://github.com/google/blockly-samples/compare/@blockly/field-colour@5.0.12...@blockly/field-colour@5.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/field-colour + + + + + +## [5.0.12](https://github.com/google/blockly-samples/compare/@blockly/field-colour@5.0.11...@blockly/field-colour@5.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/field-colour + + + + + ## [5.0.11](https://github.com/google/blockly-samples/compare/@blockly/field-colour@5.0.10...@blockly/field-colour@5.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/field-colour diff --git a/plugins/field-colour/package-lock.json b/plugins/field-colour/package-lock.json index 001ae23069..29292421d8 100644 --- a/plugins/field-colour/package-lock.json +++ b/plugins/field-colour/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/field-colour", - "version": "5.0.11", + "version": "5.0.17", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/field-colour", - "version": "5.0.11", + "version": "5.0.17", "license": "Apache-2.0", "devDependencies": { "@typescript-eslint/parser": "^5.59.5", diff --git a/plugins/field-colour/package.json b/plugins/field-colour/package.json index ce5d006ddf..e6c02aed06 100644 --- a/plugins/field-colour/package.json +++ b/plugins/field-colour/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/field-colour", - "version": "5.0.11", + "version": "5.0.17", "description": "A Blockly colour field.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -40,8 +40,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "@typescript-eslint/parser": "^5.59.5", "chai": "^4.2.0", "sinon": "^9.0.1", diff --git a/plugins/field-colour/src/field_colour.ts b/plugins/field-colour/src/field_colour.ts index dc5c88dfe4..1fb72115c4 100644 --- a/plugins/field-colour/src/field_colour.ts +++ b/plugins/field-colour/src/field_colour.ts @@ -475,7 +475,7 @@ export class FieldColour extends Blockly.Field { * @param dy Change of y. */ private moveHighlightBy(dx: number, dy: number) { - if (!this.highlightedIndex) { + if (this.highlightedIndex === null) { return; } @@ -547,11 +547,10 @@ export class FieldColour extends Blockly.Field { } /** - * Handle a mouse leave event. Blur the picker and unhighlight - * the currently highlighted colour. + * Handle a mouse leave event by unnhighlighting the currently highlighted + * colour. */ private onMouseLeave() { - this.picker?.blur(); const highlighted = this.getHighlighted(); if (highlighted) { Blockly.utils.dom.removeClass(highlighted, 'blocklyColourHighlighted'); @@ -564,7 +563,7 @@ export class FieldColour extends Blockly.Field { * @returns Highlighted item (null if none). */ private getHighlighted(): HTMLElement | null { - if (!this.highlightedIndex) { + if (this.highlightedIndex === null) { return null; } @@ -732,6 +731,15 @@ export class FieldColour extends Blockly.Field { // the static fromJson method. return new this(options.colour, undefined, options); } + + /** + * Returns the class of this field. + * + * @returns FieldColour. + */ + getClass() { + return FieldColour; + } } /** The default value for this field. */ diff --git a/plugins/field-date/CHANGELOG.md b/plugins/field-date/CHANGELOG.md index 8b3e99003a..6da12492ee 100644 --- a/plugins/field-date/CHANGELOG.md +++ b/plugins/field-date/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [9.0.14](https://github.com/google/blockly-samples/compare/@blockly/field-date@9.0.13...@blockly/field-date@9.0.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/field-date + + + + + +## [9.0.13](https://github.com/google/blockly-samples/compare/@blockly/field-date@9.0.12...@blockly/field-date@9.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/field-date + + + + + +## [9.0.12](https://github.com/google/blockly-samples/compare/@blockly/field-date@9.0.11...@blockly/field-date@9.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/field-date + + + + + ## [9.0.11](https://github.com/google/blockly-samples/compare/@blockly/field-date@9.0.10...@blockly/field-date@9.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/field-date diff --git a/plugins/field-date/package-lock.json b/plugins/field-date/package-lock.json index 3188571ff2..931659822b 100644 --- a/plugins/field-date/package-lock.json +++ b/plugins/field-date/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/field-date", - "version": "9.0.11", + "version": "9.0.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/field-date", - "version": "9.0.11", + "version": "9.0.14", "license": "Apache-2.0", "devDependencies": { "chai": "^4.2.0", diff --git a/plugins/field-date/package.json b/plugins/field-date/package.json index ea07be08e3..989c908154 100644 --- a/plugins/field-date/package.json +++ b/plugins/field-date/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/field-date", - "version": "9.0.11", + "version": "9.0.14", "description": "A Blockly date picker field that uses the browser's date picker.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -42,8 +42,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "chai": "^4.2.0", "sinon": "^9.0.1", "typescript": "^5.4.5" diff --git a/plugins/field-dependent-dropdown/CHANGELOG.md b/plugins/field-dependent-dropdown/CHANGELOG.md index b54a73474f..257bcca149 100644 --- a/plugins/field-dependent-dropdown/CHANGELOG.md +++ b/plugins/field-dependent-dropdown/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [4.0.14](https://github.com/google/blockly-samples/compare/@blockly/field-dependent-dropdown@4.0.13...@blockly/field-dependent-dropdown@4.0.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/field-dependent-dropdown + + + + + +## [4.0.13](https://github.com/google/blockly-samples/compare/@blockly/field-dependent-dropdown@4.0.12...@blockly/field-dependent-dropdown@4.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/field-dependent-dropdown + + + + + +## [4.0.12](https://github.com/google/blockly-samples/compare/@blockly/field-dependent-dropdown@4.0.11...@blockly/field-dependent-dropdown@4.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/field-dependent-dropdown + + + + + ## [4.0.11](https://github.com/google/blockly-samples/compare/@blockly/field-dependent-dropdown@4.0.10...@blockly/field-dependent-dropdown@4.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/field-dependent-dropdown diff --git a/plugins/field-dependent-dropdown/package-lock.json b/plugins/field-dependent-dropdown/package-lock.json index 7645a13aa5..ae6698aca0 100644 --- a/plugins/field-dependent-dropdown/package-lock.json +++ b/plugins/field-dependent-dropdown/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/field-dependent-dropdown", - "version": "4.0.11", + "version": "4.0.14", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@blockly/field-dependent-dropdown", - "version": "4.0.11", + "version": "4.0.14", "license": "Apache-2.0", "devDependencies": { "chai": "^4.2.0", diff --git a/plugins/field-dependent-dropdown/package.json b/plugins/field-dependent-dropdown/package.json index 35f331a1a0..3318646560 100644 --- a/plugins/field-dependent-dropdown/package.json +++ b/plugins/field-dependent-dropdown/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/field-dependent-dropdown", - "version": "4.0.11", + "version": "4.0.14", "description": "A Blockly dropdown field that automatically updates its available options depending on the value of another field.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -41,8 +41,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "chai": "^4.2.0", "sinon": "^9.0.1", "typescript": "^5.4.5" diff --git a/plugins/field-grid-dropdown/CHANGELOG.md b/plugins/field-grid-dropdown/CHANGELOG.md index 9494ee524f..0aefe3121b 100644 --- a/plugins/field-grid-dropdown/CHANGELOG.md +++ b/plugins/field-grid-dropdown/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [5.0.14](https://github.com/google/blockly-samples/compare/@blockly/field-grid-dropdown@5.0.13...@blockly/field-grid-dropdown@5.0.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/field-grid-dropdown + + + + + +## [5.0.13](https://github.com/google/blockly-samples/compare/@blockly/field-grid-dropdown@5.0.12...@blockly/field-grid-dropdown@5.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/field-grid-dropdown + + + + + +## [5.0.12](https://github.com/google/blockly-samples/compare/@blockly/field-grid-dropdown@5.0.11...@blockly/field-grid-dropdown@5.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/field-grid-dropdown + + + + + ## [5.0.11](https://github.com/google/blockly-samples/compare/@blockly/field-grid-dropdown@5.0.10...@blockly/field-grid-dropdown@5.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/field-grid-dropdown diff --git a/plugins/field-grid-dropdown/package-lock.json b/plugins/field-grid-dropdown/package-lock.json index c60ad35804..dc219e1e1a 100644 --- a/plugins/field-grid-dropdown/package-lock.json +++ b/plugins/field-grid-dropdown/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/field-grid-dropdown", - "version": "5.0.11", + "version": "5.0.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/field-grid-dropdown", - "version": "5.0.11", + "version": "5.0.14", "license": "Apache 2.0", "devDependencies": { "typescript": "^5.4.5" diff --git a/plugins/field-grid-dropdown/package.json b/plugins/field-grid-dropdown/package.json index 08495cfb3c..79777e9749 100644 --- a/plugins/field-grid-dropdown/package.json +++ b/plugins/field-grid-dropdown/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/field-grid-dropdown", - "version": "5.0.11", + "version": "5.0.14", "description": "A Blockly dropdown field with grid layout.", "scripts": { "build": "blockly-scripts build", @@ -39,8 +39,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "typescript": "^5.4.5" }, "peerDependencies": { diff --git a/plugins/field-multilineinput/CHANGELOG.md b/plugins/field-multilineinput/CHANGELOG.md index 54699b357a..d539783345 100644 --- a/plugins/field-multilineinput/CHANGELOG.md +++ b/plugins/field-multilineinput/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [5.0.15](https://github.com/google/blockly-samples/compare/@blockly/field-multilineinput@5.0.14...@blockly/field-multilineinput@5.0.15) (2025-02-13) + +**Note:** Version bump only for package @blockly/field-multilineinput + + + + + +## [5.0.14](https://github.com/google/blockly-samples/compare/@blockly/field-multilineinput@5.0.13...@blockly/field-multilineinput@5.0.14) (2024-12-19) + +**Note:** Version bump only for package @blockly/field-multilineinput + + + + + +## [5.0.13](https://github.com/google/blockly-samples/compare/@blockly/field-multilineinput@5.0.12...@blockly/field-multilineinput@5.0.13) (2024-12-03) + +**Note:** Version bump only for package @blockly/field-multilineinput + + + + + ## [5.0.12](https://github.com/google/blockly-samples/compare/@blockly/field-multilineinput@5.0.11...@blockly/field-multilineinput@5.0.12) (2024-11-07) **Note:** Version bump only for package @blockly/field-multilineinput diff --git a/plugins/field-multilineinput/package-lock.json b/plugins/field-multilineinput/package-lock.json index 0bde5c2d7e..117725375f 100644 --- a/plugins/field-multilineinput/package-lock.json +++ b/plugins/field-multilineinput/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/field-multilineinput", - "version": "5.0.12", + "version": "5.0.15", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/field-multilineinput", - "version": "5.0.12", + "version": "5.0.15", "license": "Apache-2.0", "devDependencies": { "chai": "^4.2.0", diff --git a/plugins/field-multilineinput/package.json b/plugins/field-multilineinput/package.json index c6d94237a1..8b1b79aa47 100644 --- a/plugins/field-multilineinput/package.json +++ b/plugins/field-multilineinput/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/field-multilineinput", - "version": "5.0.12", + "version": "5.0.15", "description": "A Blockly multilineinput field.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -40,8 +40,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "chai": "^4.2.0", "sinon": "^9.0.1", "typescript": "^5.4.5" diff --git a/plugins/field-slider/CHANGELOG.md b/plugins/field-slider/CHANGELOG.md index 530bc9e495..3cfa1343a0 100644 --- a/plugins/field-slider/CHANGELOG.md +++ b/plugins/field-slider/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [7.0.14](https://github.com/google/blockly-samples/compare/@blockly/field-slider@7.0.13...@blockly/field-slider@7.0.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/field-slider + + + + + +## [7.0.13](https://github.com/google/blockly-samples/compare/@blockly/field-slider@7.0.12...@blockly/field-slider@7.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/field-slider + + + + + +## [7.0.12](https://github.com/google/blockly-samples/compare/@blockly/field-slider@7.0.11...@blockly/field-slider@7.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/field-slider + + + + + ## [7.0.11](https://github.com/google/blockly-samples/compare/@blockly/field-slider@7.0.10...@blockly/field-slider@7.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/field-slider diff --git a/plugins/field-slider/package-lock.json b/plugins/field-slider/package-lock.json index 9b772fed0d..d5212882d5 100644 --- a/plugins/field-slider/package-lock.json +++ b/plugins/field-slider/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/field-slider", - "version": "7.0.11", + "version": "7.0.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/field-slider", - "version": "7.0.11", + "version": "7.0.14", "license": "Apache-2.0", "devDependencies": { "chai": "^4.2.0", diff --git a/plugins/field-slider/package.json b/plugins/field-slider/package.json index 043a38ea92..c297fffb13 100644 --- a/plugins/field-slider/package.json +++ b/plugins/field-slider/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/field-slider", - "version": "7.0.11", + "version": "7.0.14", "description": "A Blockly slider field.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -39,8 +39,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "chai": "^4.2.0", "sinon": "^9.0.1", "typescript": "^5.4.5" diff --git a/plugins/fixed-edges/CHANGELOG.md b/plugins/fixed-edges/CHANGELOG.md index 70dfe75db4..6fdcc1a3d1 100644 --- a/plugins/fixed-edges/CHANGELOG.md +++ b/plugins/fixed-edges/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [5.0.14](https://github.com/google/blockly-samples/compare/@blockly/fixed-edges@5.0.13...@blockly/fixed-edges@5.0.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/fixed-edges + + + + + +## [5.0.13](https://github.com/google/blockly-samples/compare/@blockly/fixed-edges@5.0.12...@blockly/fixed-edges@5.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/fixed-edges + + + + + +## [5.0.12](https://github.com/google/blockly-samples/compare/@blockly/fixed-edges@5.0.11...@blockly/fixed-edges@5.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/fixed-edges + + + + + ## [5.0.11](https://github.com/google/blockly-samples/compare/@blockly/fixed-edges@5.0.10...@blockly/fixed-edges@5.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/fixed-edges diff --git a/plugins/fixed-edges/package-lock.json b/plugins/fixed-edges/package-lock.json index 955596bf51..5c222d4471 100644 --- a/plugins/fixed-edges/package-lock.json +++ b/plugins/fixed-edges/package-lock.json @@ -1,16 +1,16 @@ { "name": "@blockly/fixed-edges", - "version": "5.0.11", + "version": "5.0.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/fixed-edges", - "version": "5.0.11", + "version": "5.0.14", "license": "Apache-2.0", "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11" + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0" }, "engines": { "node": ">=8.17.0" diff --git a/plugins/fixed-edges/package.json b/plugins/fixed-edges/package.json index 915ef9df5d..26ca5d34d1 100644 --- a/plugins/fixed-edges/package.json +++ b/plugins/fixed-edges/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/fixed-edges", - "version": "5.0.11", + "version": "5.0.14", "description": "A plugin that provides a MetricsManager that can be used to prevent the workspace from expanding to the top/left/right/bottom when blocks are dragged to that edge.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -38,8 +38,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11" + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0" }, "peerDependencies": { "blockly": "^11.0.0" diff --git a/plugins/keyboard-navigation/CHANGELOG.md b/plugins/keyboard-navigation/CHANGELOG.md deleted file mode 100644 index 91f7f28b8c..0000000000 --- a/plugins/keyboard-navigation/CHANGELOG.md +++ /dev/null @@ -1,558 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## [0.6.11](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.6.10...@blockly/keyboard-navigation@0.6.11) (2024-11-07) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.6.10](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.6.9...@blockly/keyboard-navigation@0.6.10) (2024-09-26) - - -### Bug Fixes - -* **field-*:** Remove unneeded `fieldRegistry.unregister` calls ([#2454](https://github.com/google/blockly-samples/issues/2454)) ([b3ba30e](https://github.com/google/blockly-samples/commit/b3ba30e23dddf0bd98c266659aa229ba6ba685b0)), closes [#2453](https://github.com/google/blockly-samples/issues/2453) - - - - - -## [0.6.9](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.6.8...@blockly/keyboard-navigation@0.6.9) (2024-08-29) - - -### Bug Fixes - -* predeploy plugins ([#2449](https://github.com/google/blockly-samples/issues/2449)) ([6b36d8b](https://github.com/google/blockly-samples/commit/6b36d8b344a969f79d89bbc7dcee29ae554759f9)) - - - - - -## [0.6.8](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.6.7...@blockly/keyboard-navigation@0.6.8) (2024-08-22) - - -### Bug Fixes - -* lerna v8 breaking our whole shebangle ([#2446](https://github.com/google/blockly-samples/issues/2446)) ([b8b4c21](https://github.com/google/blockly-samples/commit/b8b4c21d4eaf81f527336ae46f6679ff99ac23c3)) - - - - - -## [0.6.7](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.6.6...@blockly/keyboard-navigation@0.6.7) (2024-08-08) - - -### Bug Fixes - -* **keyboard-navigation:** remove references to blockly.fieldcolour ([#2441](https://github.com/google/blockly-samples/issues/2441)) ([81787b7](https://github.com/google/blockly-samples/commit/81787b7008b2e255da74487ee32eafeff2477177)) - - - -## [0.6.6](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.6.5...@blockly/keyboard-navigation@0.6.6) (2024-08-01) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.6.5](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.6.4...@blockly/keyboard-navigation@0.6.5) (2024-07-25) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.6.4](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.6.3...@blockly/keyboard-navigation@0.6.4) (2024-07-11) - - -### Reverts - -* Revert "chore(deps): Bump the npm_and_yarn group across 54 directories with 19 updates (#2403)" (#2410) ([bad8ffb](https://github.com/google/blockly-samples/commit/bad8ffbf85caa4e5b68d2f010cd0deaa9e3dd98f)), closes [#2403](https://github.com/google/blockly-samples/issues/2403) [#2410](https://github.com/google/blockly-samples/issues/2410) -* Revert "chore(deps): Bump the npm_and_yarn group across 6 directories with 11…" (#2408) ([95b13c7](https://github.com/google/blockly-samples/commit/95b13c7de3b6b3892b5c04bdc02a798ff04061b4)), closes [#2408](https://github.com/google/blockly-samples/issues/2408) - - - -## [0.6.3](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.6.2...@blockly/keyboard-navigation@0.6.3) (2024-07-04) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.6.2](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.6.1...@blockly/keyboard-navigation@0.6.2) (2024-06-06) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.6.1](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.6.0...@blockly/keyboard-navigation@0.6.1) (2024-05-30) - - -### Bug Fixes - -* multiple blockly instances ([#2375](https://github.com/google/blockly-samples/issues/2375)) ([b231e59](https://github.com/google/blockly-samples/commit/b231e598f2f5f5b0abbfd01d981e35572ad50a26)) - - - -## [0.6.0](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.5.13...@blockly/keyboard-navigation@0.6.0) (2024-05-21) - - -### ⚠ BREAKING CHANGES - -* update all plugins to v11 of blockly -* **dev-scripts:** This PR removes the support that was added - -### Features - -* support keyboard navigation of flyout buttons ([#2200](https://github.com/google/blockly-samples/issues/2200)) ([c2abe4d](https://github.com/google/blockly-samples/commit/c2abe4da9808f64161d5dc89a5e4d1b546ec279b)) -* update all plugins to v11 of blockly ([5fcd3e7](https://github.com/google/blockly-samples/commit/5fcd3e7d53eaadffe9bda9a378b404d34b2f8be2)) - - -### Bug Fixes - -* build for the v11 branch ([#2268](https://github.com/google/blockly-samples/issues/2268)) ([c7a4fc5](https://github.com/google/blockly-samples/commit/c7a4fc5e72c5e8d9e9bc926bbbbadd1eb31792fc)) -* Call blocks handle both manual disabling and disabled defs ([#2334](https://github.com/google/blockly-samples/issues/2334)) ([5eade55](https://github.com/google/blockly-samples/commit/5eade55779c4022d14ad4472ff32c93c78199887)) -* **dev-scripts:** Fixes, refactoring and simplification of `webpack.config.js` and `'blockly'` imports ([#2229](https://github.com/google/blockly-samples/issues/2229)) ([f5ffdb9](https://github.com/google/blockly-samples/commit/f5ffdb961e3b60ddb164087f4bddc4e6215906b7)), closes [#335](https://github.com/google/blockly-samples/issues/335) [#335](https://github.com/google/blockly-samples/issues/335) [#1630](https://github.com/google/blockly-samples/issues/1630) [#335](https://github.com/google/blockly-samples/issues/335) [#226](https://github.com/google/blockly-samples/issues/226) [google/blockly#7822](https://github.com/google/blockly/issues/7822) [google/blockly#7822](https://github.com/google/blockly/issues/7822) [/github.com/google/blockly-samples/pull/2229#issuecomment-1979123919](https://github.com/google//github.com/google/blockly-samples/pull/2229/issues/issuecomment-1979123919) -* update keyboard nav to use proper getContents ([#2342](https://github.com/google/blockly-samples/issues/2342)) ([4d429c0](https://github.com/google/blockly-samples/commit/4d429c092c59045b6a284f0d62a4afcda994e90d)) - - - -## [0.5.13](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.5.12...@blockly/keyboard-navigation@0.5.13) (2024-05-16) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.5.12](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.5.11...@blockly/keyboard-navigation@0.5.12) (2024-05-09) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.5.11](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.5.10...@blockly/keyboard-navigation@0.5.11) (2024-04-25) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.5.10](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.5.9...@blockly/keyboard-navigation@0.5.10) (2024-04-04) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.5.9](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.5.8...@blockly/keyboard-navigation@0.5.9) (2024-03-28) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.5.8](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.5.7...@blockly/keyboard-navigation@0.5.8) (2024-02-08) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.5.7](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.5.6...@blockly/keyboard-navigation@0.5.7) (2023-12-14) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.5.6](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.5.5...@blockly/keyboard-navigation@0.5.6) (2023-12-07) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.5.5](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.5.4...@blockly/keyboard-navigation@0.5.5) (2023-12-07) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.5.4](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.5.3...@blockly/keyboard-navigation@0.5.4) (2023-11-16) - - -### Bug Fixes - -* resolved 15 ESLint warnings ([#2065](https://github.com/google/blockly-samples/issues/2065)) ([2436337](https://github.com/google/blockly-samples/commit/243633746542bb1518fe2893c0421a5a6f79fd32)) - - - -## [0.5.3](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.5.2...@blockly/keyboard-navigation@0.5.3) (2023-11-09) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.5.2](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.5.1...@blockly/keyboard-navigation@0.5.2) (2023-11-02) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.5.1](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.5.0...@blockly/keyboard-navigation@0.5.1) (2023-10-30) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.5.0](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.4.7...@blockly/keyboard-navigation@0.5.0) (2023-09-28) - - -### ⚠ BREAKING CHANGES - -* changes for v10.2.0 (#1989) - -### release - -* changes for v10.2.0 ([#1989](https://github.com/google/blockly-samples/issues/1989)) ([4d81ea7](https://github.com/google/blockly-samples/commit/4d81ea7254412ef199a270fc740c2f45755a2725)), closes [#1844](https://github.com/google/blockly-samples/issues/1844) [#1845](https://github.com/google/blockly-samples/issues/1845) [#1863](https://github.com/google/blockly-samples/issues/1863) [#1880](https://github.com/google/blockly-samples/issues/1880) [#1885](https://github.com/google/blockly-samples/issues/1885) [#1886](https://github.com/google/blockly-samples/issues/1886) [#1887](https://github.com/google/blockly-samples/issues/1887) [#1888](https://github.com/google/blockly-samples/issues/1888) [#1919](https://github.com/google/blockly-samples/issues/1919) [#1920](https://github.com/google/blockly-samples/issues/1920) [#1983](https://github.com/google/blockly-samples/issues/1983) [#1984](https://github.com/google/blockly-samples/issues/1984) [#1985](https://github.com/google/blockly-samples/issues/1985) [#1991](https://github.com/google/blockly-samples/issues/1991) - - - -## [0.4.7](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.4.6...@blockly/keyboard-navigation@0.4.7) (2023-09-28) - - -### Bug Fixes - -* make keyboard nav compatible with v10.2.0 ([#1990](https://github.com/google/blockly-samples/issues/1990)) ([e0915b3](https://github.com/google/blockly-samples/commit/e0915b36afb7d049665673e89c4340bc01cdf08c)) - - - -## [0.4.6](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.4.5...@blockly/keyboard-navigation@0.4.6) (2023-09-14) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.4.5](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.4.4...@blockly/keyboard-navigation@0.4.5) (2023-08-17) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.4.4](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.4.3...@blockly/keyboard-navigation@0.4.4) (2023-07-24) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.4.3](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.4.2...@blockly/keyboard-navigation@0.4.3) (2023-07-20) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.4.2](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.4.1...@blockly/keyboard-navigation@0.4.2) (2023-07-13) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.4.1](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.4.0...@blockly/keyboard-navigation@0.4.1) (2023-07-06) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.4.0](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.3.18...@blockly/keyboard-navigation@0.4.0) (2023-06-28) - - -### ⚠ BREAKING CHANGES - -* update all plugins to use blockly-v10.0.0 (#1744) - -### Features - -* update all plugins to use blockly-v10.0.0 ([#1744](https://github.com/google/blockly-samples/issues/1744)) ([6cc88cb](https://github.com/google/blockly-samples/commit/6cc88cbef39d4ad664a668d3d46eb29ba7292f9c)) - - - -## [0.3.18](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.3.17...@blockly/keyboard-navigation@0.3.18) (2023-06-22) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.3.17](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.3.16...@blockly/keyboard-navigation@0.3.17) (2023-05-18) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.3.16](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.3.15...@blockly/keyboard-navigation@0.3.16) (2023-05-11) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.3.15](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.3.14...@blockly/keyboard-navigation@0.3.15) (2023-05-04) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.3.14](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.3.13...@blockly/keyboard-navigation@0.3.14) (2023-04-27) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.3.13](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.3.12...@blockly/keyboard-navigation@0.3.13) (2023-04-13) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.3.12](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.3.11...@blockly/keyboard-navigation@0.3.12) (2023-03-23) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.3.11](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.3.10...@blockly/keyboard-navigation@0.3.11) (2023-03-09) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.3.10](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.3.9...@blockly/keyboard-navigation@0.3.10) (2023-03-02) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.3.9](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.3.8...@blockly/keyboard-navigation@0.3.9) (2023-02-23) - - -### Bug Fixes - -* remove prepublishOnly scripts ([#1579](https://github.com/google/blockly-samples/issues/1579)) ([27da6cd](https://github.com/google/blockly-samples/commit/27da6cd04c38f6ba417f4e7446bb6218c475448d)) - - - -## [0.3.8](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.3.7...@blockly/keyboard-navigation@0.3.8) (2023-02-23) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.3.7](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.3.6...@blockly/keyboard-navigation@0.3.7) (2023-02-16) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.3.6](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.3.5...@blockly/keyboard-navigation@0.3.6) (2023-02-09) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.3.5](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.3.4...@blockly/keyboard-navigation@0.3.5) (2023-01-26) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.3.4](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.3.3...@blockly/keyboard-navigation@0.3.4) (2023-01-05) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.3.3](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.3.2...@blockly/keyboard-navigation@0.3.3) (2022-12-15) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.3.2](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.3.1...@blockly/keyboard-navigation@0.3.2) (2022-10-27) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.3.1](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.3.0...@blockly/keyboard-navigation@0.3.1) (2022-10-13) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## [0.3.0](https://github.com/google/blockly-samples/compare/@blockly/keyboard-navigation@0.2.22...@blockly/keyboard-navigation@0.3.0) (2022-10-05) - - -### ⚠ BREAKING CHANGES - -* update peer and devDependencies of all plugins to require Blockly v9 (#1314) - -### Bug Fixes - -* keyboard navigation tests ([#1311](https://github.com/google/blockly-samples/issues/1311)) ([8299646](https://github.com/google/blockly-samples/commit/8299646ecf26bf0a95df11bfb24ae2e219c88176)) -* references to deprecated functions in v9 ([#1313](https://github.com/google/blockly-samples/issues/1313)) ([cb2e679](https://github.com/google/blockly-samples/commit/cb2e67987e0b62a77c26adc660cc6ade1ba67954)) - - -### Miscellaneous Chores - -* update peer and devDependencies of all plugins to require Blockly v9 ([#1314](https://github.com/google/blockly-samples/issues/1314)) ([03d4912](https://github.com/google/blockly-samples/commit/03d4912c42c8de0f30493037ccc28dddaea0f266)) - - - -## 0.2.22 (2022-08-11) - - -### Bug Fixes - -* Remove the deprecated block-extension-tooltip ([#1215](https://github.com/google/blockly-samples/issues/1215)) ([a044478](https://github.com/google/blockly-samples/commit/a044478c86a73e3065bc866e427f175cbec6fc13)) - - - - - -## 0.2.21 (2022-08-04) - - -### Bug Fixes - -* fix the name of the package of suggested-blocks ([#1214](https://github.com/google/blockly-samples/issues/1214)) ([35aa8ec](https://github.com/google/blockly-samples/commit/35aa8ec73a60a4eb5b1e80cb2fc71dcd83d05e27)) - - - - - -## 0.2.19 (2022-07-21) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## 0.2.18 (2022-07-06) - - -### Bug Fixes - -* Update blockly-react to use functional components instead of class components. ([#1178](https://github.com/google/blockly-samples/issues/1178)) ([fa21187](https://github.com/google/blockly-samples/commit/fa21187cdbe4ec3a5c69f185540dd68a98eb69d7)) - - - - - -## 0.2.17 (2022-06-27) - - -### Bug Fixes - -* Update package import for keyboard navigation demo ([#1170](https://github.com/google/blockly-samples/issues/1170)) ([69c1725](https://github.com/google/blockly-samples/commit/69c1725b775279fcc397dc178935208d5f42b08c)) - - - - - -## 0.2.16 (2022-06-21) - -**Note:** Version bump only for package @blockly/keyboard-navigation - - - - - -## 0.2.15 (2022-06-08) - - -### Bug Fixes - -* package versions to support patch releases ([#1150](https://github.com/google/blockly-samples/issues/1150)) ([e1ae378](https://github.com/google/blockly-samples/commit/e1ae378d779531621c3d948566257d069002963f)) - - - - - -## 0.2.14 (2022-06-02) - - -### Bug Fixes - -* add git identity ([#1156](https://github.com/google/blockly-samples/issues/1156)) ([8d80924](https://github.com/google/blockly-samples/commit/8d809243b277375beb2ce75d4e157b5e17f78193)) diff --git a/plugins/keyboard-navigation/GETSTARTED.md b/plugins/keyboard-navigation/GETSTARTED.md deleted file mode 100644 index 99e93c7e9a..0000000000 --- a/plugins/keyboard-navigation/GETSTARTED.md +++ /dev/null @@ -1,24 +0,0 @@ -This package was bootstrapped with [@blockly/create-package](https://www.npmjs.com/package/@blockly/create-package). - -## Available Scripts - -In this directory, you can run: - -### `npm start` - -Runs the package in development mode. - -Open [http://localhost:3000/test](http://localhost:3000/test) to view the test -playground in the browser. The page will reload if you make edits. - -### `npm run build` - -Builds the package into the `dist` directory. - -### `npm run lint` - -Runs eslint on the `src` and `test` directories. - -### `npm run clean` - -Deletes the `dist` and `build` directories if they exist. diff --git a/plugins/keyboard-navigation/README.md b/plugins/keyboard-navigation/README.md deleted file mode 100644 index abf069175b..0000000000 --- a/plugins/keyboard-navigation/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# @blockly/keyboard-navigation [![Built on Blockly](https://tinyurl.com/built-on-blockly)](https://github.com/google/blockly) - -A [Blockly](https://www.npmjs.com/package/blockly) plugin that adds keyboard -navigation to Blockly. This allows users to use the keyboard to navigate the -toolbox and the blocks. More information on keyboard navigation can be found -on our [keyboard navigation documentation page](https://developers.google.com/blockly/guides/configure/web/keyboard-nav). - -## Installation - -### Yarn - -``` -yarn add @blockly/keyboard-navigation -``` - -### npm - -``` -npm install @blockly/keyboard-navigation --save -``` - -## Usage - -```js -import * as Blockly from 'blockly'; -import {NavigationController} from '@blockly/keyboard-navigation'; -// Inject Blockly. -const workspace = Blockly.inject('blocklyDiv', { - toolbox: toolboxCategories, -}); -// Initialize plugin. -const navigationController = new NavigationController(); -navigationController.init(); -navigationController.addWorkspace(workspace); -// Turns on keyboard navigation. -navigationController.enable(workspace); -``` - -## API - -This plugin exports the following classes: - -- `NavigationController`: Class in charge of registering all keyboard shortcuts. -- `Navigation`: This holds all the functions necessary to navigate around Blockly using the keyboard. -- `FlyoutCursor`: Cursor in charge of navigating the flyout. -- `LineCursor`: Alternative cursor that tries to navigate blocks like lines of code. - -You should only need to use these if you plan on changing the default functionality. - -## License - -Apache 2.0 diff --git a/plugins/keyboard-navigation/package-lock.json b/plugins/keyboard-navigation/package-lock.json deleted file mode 100644 index a8cd4831c6..0000000000 --- a/plugins/keyboard-navigation/package-lock.json +++ /dev/null @@ -1,3070 +0,0 @@ -{ - "name": "@blockly/keyboard-navigation", - "version": "0.6.11", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "@blockly/keyboard-navigation", - "version": "0.6.11", - "license": "Apache-2.0", - "devDependencies": { - "chai": "^4.2.0", - "jsdom": "^16.4.0", - "jsdom-global": "^3.0.2", - "mocha": "^10.7.0", - "sinon": "^9.0.1" - }, - "engines": { - "node": ">=8.17.0" - }, - "peerDependencies": { - "blockly": "^11.0.0" - } - }, - "node_modules/@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/@sinonjs/samsam": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", - "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", - "dev": true - }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true - }, - "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dev": true, - "dependencies": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - } - }, - "node_modules/acorn-globals/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", - "dev": true, - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cssom": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", - "dev": true - }, - "node_modules/cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "dependencies": { - "cssom": "~0.3.6" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - }, - "node_modules/data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", - "dev": true, - "dependencies": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decimal.js": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", - "dev": true - }, - "node_modules/deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", - "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", - "dev": true, - "dependencies": { - "webidl-conversions": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/domexception/node_modules/webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", - "dev": true, - "dependencies": { - "whatwg-encoding": "^1.0.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/jsdom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", - "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", - "dev": true, - "dependencies": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/jsdom-global": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsdom-global/-/jsdom-global-3.0.2.tgz", - "integrity": "sha1-a9KZwTsMRiay2iwDk81DhdYGrLk=", - "dev": true, - "peerDependencies": { - "jsdom": ">=10.0.0" - } - }, - "node_modules/just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "dev": true - }, - "node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/loupe": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.1.tgz", - "integrity": "sha512-EN1D3jyVmaX4tnajVlfbREU4axL647hLec1h/PXAb8CPDMJiYitcWF2UeLVNttRqaIqQs4x+mRvXf+d+TlDrCA==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.0" - } - }, - "node_modules/mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "dev": true, - "dependencies": { - "mime-db": "1.51.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mocha": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.0.tgz", - "integrity": "sha512-v8/rBWr2VO5YkspYINnvu81inSz2y3ODJrhO175/Exzor1RcEZZkizgE2A+w/CAXXoESS8Kys5E62dOHGHzULA==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.3", - "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", - "debug": "^4.3.5", - "diff": "^5.2.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^8.1.0", - "he": "^1.2.0", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^5.1.6", - "ms": "^2.1.3", - "serialize-javascript": "^6.0.2", - "strip-json-comments": "^3.1.1", - "supports-color": "^8.1.1", - "workerpool": "^6.5.1", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9", - "yargs-unparser": "^2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/mocha/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/mocha/node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/nise": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", - "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.7.0", - "@sinonjs/fake-timers": "^6.0.0", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nwsapi": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", - "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", - "dev": true - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "dependencies": { - "isarray": "0.0.1" - } - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dev": true, - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/sinon": { - "version": "9.2.4", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", - "integrity": "sha512-zljcULZQsJxVra28qIAL6ow1Z9tpattkCTEJR4RBP3TGc00FcttsP5pK284Nas5WjMZU5Yzy3kAIp3B3KRf5Yg==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.8.1", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/samsam": "^5.3.1", - "diff": "^4.0.2", - "nise": "^4.0.4", - "supports-color": "^7.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "node_modules/sinon/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", - "dev": true, - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie/node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dev": true, - "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "node_modules/w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "dev": true, - "dependencies": { - "browser-process-hrtime": "^1.0.0" - } - }, - "node_modules/w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dev": true, - "dependencies": { - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true, - "engines": { - "node": ">=10.4" - } - }, - "node_modules/whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, - "dependencies": { - "iconv-lite": "0.4.24" - } - }, - "node_modules/whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true - }, - "node_modules/whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", - "dev": true, - "dependencies": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/workerpool": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", - "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, - "@sinonjs/samsam": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", - "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", - "dev": true - }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, - "abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true - }, - "acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true - }, - "acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dev": true, - "requires": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - } - } - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true - }, - "braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "requires": { - "fill-range": "^7.1.1" - } - }, - "browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true - }, - "chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "cssom": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", - "dev": true - }, - "cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "requires": { - "cssom": "~0.3.6" - }, - "dependencies": { - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - } - } - }, - "data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", - "dev": true, - "requires": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" - } - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - }, - "decimal.js": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", - "dev": true - }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "requires": { - "type-detect": "^4.0.0" - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", - "dev": true - }, - "domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", - "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", - "dev": true, - "requires": { - "webidl-conversions": "^5.0.0" - }, - "dependencies": { - "webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true - } - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, - "form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "optional": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true - }, - "glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", - "dev": true, - "requires": { - "whatwg-encoding": "^1.0.5" - } - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "jsdom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", - "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", - "dev": true, - "requires": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - } - }, - "jsdom-global": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsdom-global/-/jsdom-global-3.0.2.tgz", - "integrity": "sha1-a9KZwTsMRiay2iwDk81DhdYGrLk=", - "dev": true - }, - "just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "dev": true - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, - "loupe": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.1.tgz", - "integrity": "sha512-EN1D3jyVmaX4tnajVlfbREU4axL647hLec1h/PXAb8CPDMJiYitcWF2UeLVNttRqaIqQs4x+mRvXf+d+TlDrCA==", - "dev": true, - "requires": { - "get-func-name": "^2.0.0" - } - }, - "mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", - "dev": true - }, - "mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "dev": true, - "requires": { - "mime-db": "1.51.0" - } - }, - "mocha": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.0.tgz", - "integrity": "sha512-v8/rBWr2VO5YkspYINnvu81inSz2y3ODJrhO175/Exzor1RcEZZkizgE2A+w/CAXXoESS8Kys5E62dOHGHzULA==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.3", - "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", - "debug": "^4.3.5", - "diff": "^5.2.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^8.1.0", - "he": "^1.2.0", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^5.1.6", - "ms": "^2.1.3", - "serialize-javascript": "^6.0.2", - "strip-json-comments": "^3.1.1", - "supports-color": "^8.1.1", - "workerpool": "^6.5.1", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9", - "yargs-unparser": "^2.0.0" - }, - "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, - "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "nise": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", - "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0", - "@sinonjs/fake-timers": "^6.0.0", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "nwsapi": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", - "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "requires": { - "isarray": "0.0.1" - } - }, - "pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true - }, - "querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dev": true, - "requires": { - "xmlchars": "^2.2.0" - } - }, - "serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "sinon": { - "version": "9.2.4", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", - "integrity": "sha512-zljcULZQsJxVra28qIAL6ow1Z9tpattkCTEJR4RBP3TGc00FcttsP5pK284Nas5WjMZU5Yzy3kAIp3B3KRf5Yg==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.8.1", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/samsam": "^5.3.1", - "diff": "^4.0.2", - "nise": "^4.0.4", - "supports-color": "^7.1.0" - }, - "dependencies": { - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - } - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", - "dev": true, - "requires": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "dependencies": { - "universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true - } - } - }, - "tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dev": true, - "requires": { - "punycode": "^2.1.1" - } - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "dev": true, - "requires": { - "browser-process-hrtime": "^1.0.0" - } - }, - "w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dev": true, - "requires": { - "xml-name-validator": "^3.0.0" - } - }, - "webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true - }, - "whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, - "requires": { - "iconv-lite": "0.4.24" - } - }, - "whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true - }, - "whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", - "dev": true, - "requires": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - } - }, - "word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true - }, - "workerpool": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", - "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "dev": true - }, - "xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - }, - "xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true - }, - "yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "dependencies": { - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - } - } - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } - } -} \ No newline at end of file diff --git a/plugins/keyboard-navigation/package.json b/plugins/keyboard-navigation/package.json deleted file mode 100644 index 0193fb9aff..0000000000 --- a/plugins/keyboard-navigation/package.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "name": "@blockly/keyboard-navigation", - "version": "0.6.11", - "description": "A Blockly plugin that adds keyboard navigation support.", - "scripts": { - "audit:fix": "blockly-scripts auditFix", - "build": "blockly-scripts build", - "clean": "blockly-scripts clean", - "lint": "eslint .", - "predeploy": "blockly-scripts predeploy", - "start": "blockly-scripts start", - "test": "blockly-scripts test" - }, - "main": "./dist/index.js", - "module": "./src/index.js", - "unpkg": "./dist/index.js", - "author": "Blockly Team", - "keywords": [ - "blockly", - "blockly-plugin", - "keyboard-navigation" - ], - "homepage": "https://github.com/google/blockly-samples/tree/master/plugins/keyboard-navigation#readme", - "bugs": { - "url": "https://github.com/google/blockly-samples/issues" - }, - "repository": { - "type": "git", - "url": "https://github.com/google/blockly-samples.git", - "directory": "plugins/keyboard-navigation" - }, - "license": "Apache-2.0", - "directories": { - "dist": "dist", - "src": "src" - }, - "files": [ - "dist", - "src" - ], - "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", - "chai": "^4.2.0", - "jsdom": "^16.4.0", - "jsdom-global": "^3.0.2", - "mocha": "^10.7.0", - "sinon": "^9.0.1" - }, - "peerDependencies": { - "blockly": "^11.0.0" - }, - "publishConfig": { - "access": "public", - "registry": "https://wombat-dressing-room.appspot.com" - }, - "engines": { - "node": ">=8.17.0" - } -} diff --git a/plugins/keyboard-navigation/src/constants.js b/plugins/keyboard-navigation/src/constants.js deleted file mode 100644 index 187ad47dcf..0000000000 --- a/plugins/keyboard-navigation/src/constants.js +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Constants for keyboard navigation. - * @author aschmiedt@google.com (Abby Schmiedt) - */ - -/** - * Keyboard navigation states. - * The different parts of Blockly that the user navigates between. - * @enum {string} - * @const - * @public - */ -export const STATE = { - WORKSPACE: 'workspace', - FLYOUT: 'flyout', - TOOLBOX: 'toolbox', -}; - -/** - * Default keyboard navigation shortcut names. - * @enum {string} - * @const - * @public - */ -export const SHORTCUT_NAMES = { - PREVIOUS: 'previous', - NEXT: 'next', - IN: 'in', - OUT: 'out', - INSERT: 'insert', - MARK: 'mark', - DISCONNECT: 'disconnect', - TOOLBOX: 'toolbox', - EXIT: 'exit', - TOGGLE_KEYBOARD_NAV: 'toggle_keyboard_nav', - COPY: 'keyboard_nav_copy', - CUT: 'keyboard_nav_cut', - PASTE: 'keyboard_nav_paste', - DELETE: 'keyboard_nav_delete', - MOVE_WS_CURSOR_UP: 'workspace_up', - MOVE_WS_CURSOR_DOWN: 'workspace_down', - MOVE_WS_CURSOR_LEFT: 'workspace_left', - MOVE_WS_CURSOR_RIGHT: 'workspace_right', -}; - -/** - * Types of possible messages passed into the loggingCallback in the Navigation - * class. - * @enum {string} - * @const - * @public - */ -export const LOGGING_MSG_TYPE = { - ERROR: 'error', - WARN: 'warn', - LOG: 'log', -}; diff --git a/plugins/keyboard-navigation/src/flyout_cursor.js b/plugins/keyboard-navigation/src/flyout_cursor.js deleted file mode 100644 index 20cd17b957..0000000000 --- a/plugins/keyboard-navigation/src/flyout_cursor.js +++ /dev/null @@ -1,93 +0,0 @@ -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview The class representing a cursor used to navigate the flyout. - * @author aschmiedt@google.com (Abby Schmiedt) - */ - -import * as Blockly from 'blockly/core'; - -/** - * Class for a flyout cursor. - * This controls how a user navigates blocks in the flyout. - * This cursor only allows a user to go to the previous or next stack. - * @constructor - * @extends {Blockly.Cursor} - */ -export class FlyoutCursor extends Blockly.Cursor { - /** - * The constructor for the FlyoutCursor. - */ - constructor() { - super(); - } - - /** - * Moves the cursor to the next stack of blocks in the flyout. - * @returns {Blockly.ASTNode} The next element, or null if the current node is - * not set or there is no next value. - * @override - */ - next() { - const curNode = this.getCurNode(); - if (!curNode) { - return null; - } - const newNode = curNode.next(); - - if (newNode) { - this.setCurNode(newNode); - } - return newNode; - } - - /** - * This is a no-op since a flyout cursor can not go in. - * @returns {null} Always null. - * @override - */ - in() { - return null; - } - - /** - * Moves the cursor to the previous stack of blocks in the flyout. - * @returns {Blockly.ASTNode} The previous element, or null if the current - * node is not set or there is no previous value. - * @override - */ - prev() { - const curNode = this.getCurNode(); - if (!curNode) { - return null; - } - const newNode = curNode.prev(); - - if (newNode) { - this.setCurNode(newNode); - } - return newNode; - } - - /** - * This is a no-op since a flyout cursor can not go out. - * @returns {null} Always null. - * @override - */ - out() { - return null; - } -} - -export const registrationType = Blockly.registry.Type.CURSOR; -export const registrationName = 'FlyoutCursor'; - -Blockly.registry.register(registrationType, registrationName, FlyoutCursor); - -export const pluginInfo = { - [registrationType]: registrationName, -}; diff --git a/plugins/keyboard-navigation/src/gesture_monkey_patch.js b/plugins/keyboard-navigation/src/gesture_monkey_patch.js deleted file mode 100644 index ba5d6eb790..0000000000 --- a/plugins/keyboard-navigation/src/gesture_monkey_patch.js +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Overrides methods on Blockly.Gesture in order to allow users - * to move the cursor to blocks or the workspace using shift click. - * TODO(google/blockly#4584): We do not have a way to do this currently without - * monkey patching Blockly. - * @author aschmiedt@google.com (Abby Schmiedt) - */ - -import * as Blockly from 'blockly/core'; - -const oldDoWorkspaceClick = Blockly.Gesture.prototype.doWorkspaceClick_; - -/** - * Execute a workspace click. When in accessibility mode shift clicking will - * move the cursor. - * @param {!Event} e A mouse up or touch end event. - * @this {Blockly.Gesture} - * @override - */ -Blockly.Gesture.prototype.doWorkspaceClick_ = function (e) { - oldDoWorkspaceClick.call(this, e); - const ws = this.creatorWorkspace_; - if (e.shiftKey && ws.keyboardAccessibilityMode) { - const screenCoord = new Blockly.utils.Coordinate(e.clientX, e.clientY); - const wsCoord = Blockly.utils.svgMath.screenToWsCoordinates( - ws, - screenCoord, - ); - const wsNode = Blockly.ASTNode.createWorkspaceNode(ws, wsCoord); - ws.getCursor().setCurNode(wsNode); - } -}; - -const oldDoBlockClick = Blockly.Gesture.prototype.doBlockClick_; - -/** - * Execute a block click. When in accessibility mode shift clicking will move - * the cursor to the block. - * @this {Blockly.Gesture} - * @override - */ -Blockly.Gesture.prototype.doBlockClick_ = function (e) { - oldDoBlockClick.call(this, e); - if ( - !this.targetBlock_.isInFlyout && - this.mostRecentEvent_.shiftKey && - this.targetBlock_.workspace.keyboardAccessibilityMode - ) { - this.creatorWorkspace_ - .getCursor() - .setCurNode(Blockly.ASTNode.createTopNode(this.targetBlock_)); - } -}; diff --git a/plugins/keyboard-navigation/src/index.js b/plugins/keyboard-navigation/src/index.js deleted file mode 100644 index 75ef7e0157..0000000000 --- a/plugins/keyboard-navigation/src/index.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as Constants from '../src/constants'; - -import { - FlyoutCursor, - pluginInfo as FlyoutCursorPluginInfo, -} from './flyout_cursor'; -import {LineCursor, pluginInfo as LineCursorPluginInfo} from './line_cursor'; -import {Navigation} from './navigation'; -import {NavigationController} from './navigation_controller'; - -export { - Constants, - FlyoutCursor, - FlyoutCursorPluginInfo, - LineCursor, - LineCursorPluginInfo, - Navigation, - NavigationController, -}; diff --git a/plugins/keyboard-navigation/src/line_cursor.js b/plugins/keyboard-navigation/src/line_cursor.js deleted file mode 100644 index 8f1595b925..0000000000 --- a/plugins/keyboard-navigation/src/line_cursor.js +++ /dev/null @@ -1,190 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview The class representing a line cursor. - * A line cursor tries to traverse the blocks and connections on a block as if - * they were lines of code in a text editor. Previous and next traverse previous - * connections, next connections and blocks, while in and out traverse input - * connections and fields. - * @author aschmiedt@google.com (Abby Schmiedt) - */ - -import * as Blockly from 'blockly/core'; - -/** - * Class for a line cursor. - * @constructor - * @extends {Blockly.BasicCursor} - */ -export class LineCursor extends Blockly.BasicCursor { - /** - * Constructor for a line cursor. - */ - constructor() { - super(); - } - - /** - * Moves the cursor to the next previous connection, next connection or block - * in the pre order traversal. Finds the next node in the pre order traversal. - * @returns {Blockly.ASTNode} The next node, or null if the current node is - * not set or there is no next value. - * @override - */ - next() { - const curNode = this.getCurNode(); - if (!curNode) { - return null; - } - let newNode = this.getNextNode_(curNode, this.validLineNode); - - // Skip the input or next value if there is a connected block. - if ( - newNode && - (newNode.getType() == Blockly.ASTNode.types.INPUT || - newNode.getType() == Blockly.ASTNode.types.NEXT) && - newNode.getLocation().targetBlock() - ) { - newNode = this.getNextNode_(newNode, this.validLineNode); - } - if (newNode) { - this.setCurNode(newNode); - } - return newNode; - } - - /** - * Moves the cursor to the next input connection or field - * in the pre order traversal. - * @returns {Blockly.ASTNode} The next node, or null if the current node is - * not set or there is no next value. - * @override - */ - in() { - const curNode = this.getCurNode(); - if (!curNode) { - return null; - } - const newNode = this.getNextNode_(curNode, this.validInLineNode); - - if (newNode) { - this.setCurNode(newNode); - } - return newNode; - } - /** - * Moves the cursor to the previous next connection or previous connection in - * the pre order traversal. - * @returns {Blockly.ASTNode} The previous node, or null if the current node - * is not set or there is no previous value. - * @override - */ - prev() { - const curNode = this.getCurNode(); - if (!curNode) { - return null; - } - let newNode = this.getPreviousNode_(curNode, this.validLineNode); - - if ( - newNode && - (newNode.getType() == Blockly.ASTNode.types.INPUT || - newNode.getType() == Blockly.ASTNode.types.NEXT) && - newNode.getLocation().targetBlock() - ) { - newNode = this.getPreviousNode_(newNode, this.validLineNode); - } - - if (newNode) { - this.setCurNode(newNode); - } - return newNode; - } - /** - * Moves the cursor to the previous input connection or field in the pre order - * traversal. - * @returns {Blockly.ASTNode} The previous node, or null if the current node - * is not set or there is no previous value. - * @override - */ - out() { - const curNode = this.getCurNode(); - if (!curNode) { - return null; - } - const newNode = this.getPreviousNode_(curNode, this.validInLineNode); - - if (newNode) { - this.setCurNode(newNode); - } - return newNode; - } - - /** - * Decides if the previous and next methods should traverse the given node. - * The previous and next method only traverse previous connections, next - * connections and blocks. - * @param {Blockly.ASTNode} node The AST node to check. - * @returns {boolean} True if the node should be visited, false otherwise. - * @protected - */ - validLineNode(node) { - if (!node) { - return false; - } - let isValid = false; - const location = node.getLocation(); - const type = node && node.getType(); - if (type == Blockly.ASTNode.types.BLOCK) { - if (location.outputConnection === null) { - isValid = true; - } - } else if ( - type == Blockly.ASTNode.types.INPUT && - location.type == Blockly.NEXT_STATEMENT - ) { - isValid = true; - } else if (type == Blockly.ASTNode.types.NEXT) { - isValid = true; - } - return isValid; - } - - /** - * Decides if the in and out methods should traverse the given node. - * The in and out method only traverse fields and input connections. - * @param {Blockly.ASTNode} node The AST node to check whether it is valid. - * @returns {boolean} True if the node should be visited, false otherwise. - * @protected - */ - validInLineNode(node) { - if (!node) { - return false; - } - let isValid = false; - const location = node.getLocation(); - const type = node && node.getType(); - if (type == Blockly.ASTNode.types.FIELD) { - isValid = true; - } else if ( - type == Blockly.ASTNode.types.INPUT && - location.type == Blockly.INPUT_VALUE - ) { - isValid = true; - } - return isValid; - } -} - -export const registrationName = 'LineCursor'; -export const registrationType = Blockly.registry.Type.CURSOR; - -Blockly.registry.register(registrationType, registrationName, LineCursor); - -export const pluginInfo = { - [registrationType]: registrationName, -}; diff --git a/plugins/keyboard-navigation/src/navigation.js b/plugins/keyboard-navigation/src/navigation.js deleted file mode 100644 index 9fc285ba8d..0000000000 --- a/plugins/keyboard-navigation/src/navigation.js +++ /dev/null @@ -1,1287 +0,0 @@ -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Holds all methods necessary to use Blockly through the - * keyboard. - * @author aschmiedt@google.com (Abby Schmiedt) - */ - -import * as Blockly from 'blockly/core'; -import * as Constants from './constants'; -import { - registrationName as cursorRegistrationName, - registrationType as cursorRegistrationType, -} from './flyout_cursor'; - -/** - * Class that holds all methods necessary for keyboard navigation to work. - */ -export class Navigation { - /** - * Constructor for keyboard navigation. - */ - constructor() { - /** - * Object holding the location of the cursor for each workspace. - * Possible locations of the cursor are: workspace, flyout or toolbox. - * @type {Object} - * @protected - */ - this.workspaceStates = {}; - - /** - * An optional method that allows a developer to customize how to handle - * logs, warnings, and errors. The first argument is one of 'log', 'warn', - * or 'error'. The second argument is the message. - * @type {?function(Constants.LOGGING_MSG_TYPE, string)} - * @public - */ - this.loggingCallback = null; - - /** - * The distance to move the cursor when the cursor is on the workspace. - * @type {number} - * @public - */ - this.WS_MOVE_DISTANCE = 40; - - /** - * The name of the marker to use for keyboard navigation. - * @type {string} - * @public - */ - this.MARKER_NAME = 'local_marker_1'; - - /** - * The default coordinate to use when focusing on the workspace and no - * blocks are present. In pixel coordinates, but will be converted to - * workspace coordinates when used to position the cursor. - * @type {!Blockly.utils.Coordinate} - * @public - */ - this.DEFAULT_WS_COORDINATE = new Blockly.utils.Coordinate(100, 100); - - /** - * The default coordinate to use when moving the cursor to the workspace - * after a block has been deleted. In pixel coordinates, but will be - * converted to workspace coordinates when used to position the cursor. - * @type {!Blockly.utils.Coordinate} - * @public - */ - this.WS_COORDINATE_ON_DELETE = new Blockly.utils.Coordinate(100, 100); - - /** - * Wrapper for method that deals with workspace changes. - * Used for removing change listener. - * @type {Function} - * @protected - */ - this.wsChangeWrapper = this.workspaceChangeListener.bind(this); - - /** - * Wrapper for method that deals with flyout changes. - * Used for removing change listener. - * @type {Function} - * @protected - */ - this.flyoutChangeWrapper = this.flyoutChangeListener.bind(this); - - /** - * The list of registered workspaces. - * Used when removing change listeners in dispose. - * @type {!Array} - * @protected - */ - this.workspaces = []; - } - - /** - * Adds all necessary change listeners and markers to a workspace for keyboard - * navigation to work. This must be called for keyboard navigation to work - * on a workspace. - * @param {!Blockly.WorkspaceSvg} workspace The workspace to add keyboard - * navigation to. - * @public - */ - addWorkspace(workspace) { - this.workspaces.push(workspace); - const flyout = workspace.getFlyout(); - workspace - .getMarkerManager() - .registerMarker(this.MARKER_NAME, new Blockly.Marker()); - workspace.addChangeListener(this.wsChangeWrapper); - - if (flyout) { - this.addFlyout(flyout); - } - } - - /** - * Removes all keyboard navigation change listeners and markers. - * @param {!Blockly.WorkspaceSvg} workspace The workspace to remove keyboard - * navigation from. - * @public - */ - removeWorkspace(workspace) { - const workspaceIdx = this.workspaces.indexOf(workspace); - const flyout = workspace.getFlyout(); - - if (workspace.getCursor()) { - this.disableKeyboardAccessibility(workspace); - } - - if (workspaceIdx > -1) { - this.workspaces.splice(workspaceIdx, 1); - } - if (workspace.getMarkerManager()) { - workspace.getMarkerManager().unregisterMarker(this.MARKER_NAME); - } - workspace.removeChangeListener(this.wsChangeWrapper); - - if (flyout) { - this.removeFlyout(flyout); - } - } - - /** - * Sets the state for the given workspace. - * @param {!Blockly.WorkspaceSvg} workspace The workspace to set the state on. - * @param {!Constants.STATE} state The navigation state. - * @protected - */ - setState(workspace, state) { - this.workspaceStates[workspace.id] = state; - } - - /** - * Gets the navigation state of the current workspace. - * @param {!Blockly.WorkspaceSvg} workspace The workspace to get the state of. - * @returns {!Constants.STATE} The state of the given workspace. - * @package - */ - getState(workspace) { - return this.workspaceStates[workspace.id]; - } - - /** - * Gets the marker created for keyboard navigation. - * @param {!Blockly.WorkspaceSvg} workspace The workspace to get the marker - * from. - * @returns {?Blockly.Marker} The marker created for keyboard navigation. - * @protected - */ - getMarker(workspace) { - return workspace.getMarker(this.MARKER_NAME); - } - - /** - * Adds all event listeners and cursors to the flyout that are needed for - * keyboard navigation to work. - * @param {!Blockly.IFlyout} flyout The flyout to add a cursor and change - * listeners to. - * @protected - */ - addFlyout(flyout) { - const flyoutWorkspace = flyout.getWorkspace(); - flyoutWorkspace.addChangeListener(this.flyoutChangeWrapper); - const FlyoutCursorClass = Blockly.registry.getClass( - cursorRegistrationType, - cursorRegistrationName, - ); - flyoutWorkspace.getMarkerManager().setCursor(new FlyoutCursorClass()); - } - - /** - * Removes all change listeners from the flyout that are needed for - * keyboard navigation to work. - * @param {!Blockly.IFlyout} flyout The flyout to add a cursor and event - * listeners to. - * @protected - */ - removeFlyout(flyout) { - const flyoutWorkspace = flyout.getWorkspace(); - flyoutWorkspace.removeChangeListener(this.flyoutChangeWrapper); - } - - /** - * Updates the state of keyboard navigation and the position of the cursor - * based on workspace events. - * @param {!Blockly.Events.Abstract} e The Blockly event to process. - * @protected - */ - workspaceChangeListener(e) { - const workspace = Blockly.Workspace.getById(e.workspaceId); - if (!workspace || !workspace.keyboardAccessibilityMode) { - return; - } - switch (e.type) { - case Blockly.Events.DELETE: - this.handleBlockDeleteByDrag(workspace, e); - break; - case Blockly.Events.BLOCK_CHANGE: - if (e.element === 'mutation') { - this.handleBlockMutation( - workspace, - /** @type {Blockly.Events.BlockChange} */ (e), - ); - } - break; - case Blockly.Events.CLICK: - this.handleWorkspaceClick( - workspace, - /** @type {Blockly.Events.Click} */ (e), - ); - break; - case Blockly.Events.TOOLBOX_ITEM_SELECT: - this.handleToolboxCategoryClick( - workspace, - /** @type {Blockly.Events.ToolboxItemSelect} */ (e), - ); - break; - case Blockly.Events.BLOCK_CREATE: - this.handleBlockCreate(workspace, e); - } - } - - /** - * Updates the state of keyboard navigation and the position of the cursor - * based on events emitted from the flyout's workspace. - * @param {!Blockly.Events.Abstract} e The Blockly event to process. - * @protected - */ - flyoutChangeListener(e) { - const flyoutWorkspace = Blockly.Workspace.getById(e.workspaceId); - const mainWorkspace = flyoutWorkspace.targetWorkspace; - const flyout = mainWorkspace.getFlyout(); - - // This is called for simple toolboxes and for toolboxes that have a flyout - // that does not close. Autoclosing flyouts close before we need to focus - // the cursor on the block that was clicked. - if ( - mainWorkspace && - mainWorkspace.keyboardAccessibilityMode && - !flyout.autoClose - ) { - if (e.type === Blockly.Events.CLICK && e.targetType === 'block') { - const block = flyoutWorkspace.getBlockById(e.blockId); - this.handleBlockClickInFlyout(mainWorkspace, block); - } else if (e.type === Blockly.Events.SELECTED) { - const block = flyoutWorkspace.getBlockById(e.newElementId); - this.handleBlockClickInFlyout(mainWorkspace, block); - } - } - } - - /** - * Moves the cursor to the workspace if a block has been dragged from a simple - * toolbox. For a category toolbox this is handled in - * handleToolboxCategoryClick_. - * @param {!Blockly.WorkspaceSvg} workspace The workspace the cursor belongs - * to. - * @param {!Blockly.Events.Abstract} e The Blockly event to process. - * @protected - */ - handleBlockCreate(workspace, e) { - if (this.getState(workspace) === Constants.STATE.FLYOUT) { - this.resetFlyout(workspace, !!workspace.getToolbox()); - this.setState(workspace, Constants.STATE.WORKSPACE); - } - } - - /** - * Moves the cursor to the block level when the block the cursor is on - * mutates. - * @param {!Blockly.WorkspaceSvg} workspace The workspace the cursor belongs - * to. - * @param {!Blockly.Events.BlockChange} e The Blockly event to process. - * @protected - */ - handleBlockMutation(workspace, e) { - const mutatedBlockId = e.blockId; - const cursor = workspace.getCursor(); - if (cursor) { - const curNode = cursor.getCurNode(); - const block = curNode ? curNode.getSourceBlock() : null; - if (block && block.id === mutatedBlockId) { - cursor.setCurNode(Blockly.ASTNode.createBlockNode(block)); - } - } - } - - /** - * Moves the cursor to the workspace when a user clicks on the workspace. - * @param {!Blockly.WorkspaceSvg} workspace The workspace the cursor belongs - * to. - * @param {!Blockly.Events.Click} e The Blockly event to process. - * @protected - */ - handleWorkspaceClick(workspace, e) { - const workspaceState = this.getState(workspace); - if (workspaceState !== Constants.STATE.WORKSPACE) { - this.resetFlyout(workspace, !!workspace.getToolbox()); - this.setState(workspace, Constants.STATE.WORKSPACE); - } - } - - /** - * Moves the cursor to the toolbox when a user clicks on a toolbox category. - * Moves the cursor to the workspace if theh user closes the toolbox category. - * @param {!Blockly.WorkspaceSvg} workspace The workspace the toolbox is on. - * @param {!Blockly.Events.ToolboxItemSelect} e The event emitted from the - * workspace. - * @protected - */ - handleToolboxCategoryClick(workspace, e) { - const workspaceState = this.getState(workspace); - if (e.newItem && workspaceState !== Constants.STATE.TOOLBOX) { - // If the toolbox category was just clicked, focus on the toolbox. - this.focusToolbox(workspace); - } else if (!e.newItem) { - // If the toolbox was closed, focus on the workspace. - this.resetFlyout(workspace, !!workspace.getToolbox()); - this.setState(workspace, Constants.STATE.WORKSPACE); - } - } - - /** - * Moves the cursor to the workspace when its parent block is deleted by - * being dragged to the flyout or to the trashcan. - * @param {!Blockly.WorkspaceSvg} workspace The workspace the block was on. - * @param {!Blockly.Events.Delete} e The event emitted when a block is - * deleted. - * @protected - */ - handleBlockDeleteByDrag(workspace, e) { - const deletedBlockId = e.blockId; - const ids = e.ids; - const cursor = workspace.getCursor(); - - // Make sure the cursor is on a block. - if ( - !cursor || - !cursor.getCurNode() || - !cursor.getCurNode().getSourceBlock() - ) { - return; - } - - const curNode = cursor.getCurNode(); - const sourceBlock = curNode.getSourceBlock(); - if (sourceBlock.id === deletedBlockId || ids.indexOf(sourceBlock.id) > -1) { - cursor.setCurNode( - Blockly.ASTNode.createWorkspaceNode( - workspace, - this.WS_COORDINATE_ON_DELETE, - ), - ); - } - } - - /** - * Handles when a user clicks on a block in the flyout by moving the cursor - * to that stack of blocks and setting the state of navigation to the flyout. - * @param {!Blockly.WorkspaceSvg} mainWorkspace The workspace the user clicked - * on. - * @param {!Blockly.BlockSvg} block The block the user clicked on. - * @protected - */ - handleBlockClickInFlyout(mainWorkspace, block) { - if (!block) { - return; - } - if (block.isShadow()) { - block = /** @type {Blockly.BlockSvg}*/ (block.getParent()); - } - this.getFlyoutCursor(mainWorkspace).setCurNode( - Blockly.ASTNode.createStackNode(block), - ); - this.setState(mainWorkspace, Constants.STATE.FLYOUT); - } - - /** - * Moves the cursor to the appropriate location before a block is deleted. - * This is used when the user deletes a block using the delete or backspace - * key. - * @param {!Blockly.WorkspaceSvg} workspace The workspace the block is being - * deleted on. - * @param {!Blockly.BlockSvg} deletedBlock The block that is being deleted. - * @package - */ - moveCursorOnBlockDelete(workspace, deletedBlock) { - if (!workspace || !workspace.getCursor()) { - return; - } - const cursor = workspace.getCursor(); - const curNode = cursor.getCurNode(); - const block = curNode ? curNode.getSourceBlock() : null; - - if (block === deletedBlock) { - // If the block has a parent move the cursor to their connection point. - if (block.getParent()) { - const topConnection = - block.previousConnection || block.outputConnection; - if (topConnection) { - cursor.setCurNode( - Blockly.ASTNode.createConnectionNode( - topConnection.targetConnection, - ), - ); - } - } else { - // If the block is by itself move the cursor to the workspace. - cursor.setCurNode( - Blockly.ASTNode.createWorkspaceNode( - block.workspace, - block.getRelativeToSurfaceXY(), - ), - ); - } - // If the cursor is on a block whose parent is being deleted, move the - // cursor to the workspace. - } else if (block && deletedBlock.getChildren(false).indexOf(block) > -1) { - cursor.setCurNode( - Blockly.ASTNode.createWorkspaceNode( - block.workspace, - block.getRelativeToSurfaceXY(), - ), - ); - } - } - - /** - * Sets the navigation state to toolbox and selects the first category in the - * toolbox. No-op if a toolbox does not exist on the given workspace. - * @param {!Blockly.WorkspaceSvg} workspace The workspace to get the toolbox - * on. - * @package - */ - focusToolbox(workspace) { - const toolbox = workspace.getToolbox(); - if (!toolbox) { - return; - } - - this.setState(workspace, Constants.STATE.TOOLBOX); - this.resetFlyout(workspace, false /* shouldHide */); - - if (!this.getMarker(workspace).getCurNode()) { - this.markAtCursor(workspace); - } - - if (!toolbox.getSelectedItem()) { - // Find the first item that is selectable. - const toolboxItems = toolbox.getToolboxItems(); - for (let i = 0, toolboxItem; (toolboxItem = toolboxItems[i]); i++) { - if (toolboxItem.isSelectable()) { - toolbox.selectItemByPosition(i); - break; - } - } - } - } - - /** - * Sets the navigation state to flyout and moves the cursor to the first - * block or button in the flyout. - * @param {!Blockly.WorkspaceSvg} workspace The workspace the flyout is on. - * @package - */ - focusFlyout(workspace) { - const flyout = workspace.getFlyout(); - - this.setState(workspace, Constants.STATE.FLYOUT); - - if (!this.getMarker(workspace).getCurNode()) { - this.markAtCursor(workspace); - } - - if (flyout && flyout.getWorkspace()) { - const flyoutContents = flyout.getContents(); - const firstFlyoutItem = flyoutContents[0]; - if (!firstFlyoutItem) return; - if (firstFlyoutItem.button) { - const astNode = Blockly.ASTNode.createButtonNode( - firstFlyoutItem.button, - ); - this.getFlyoutCursor(workspace).setCurNode(astNode); - } else if (firstFlyoutItem.block) { - const astNode = Blockly.ASTNode.createStackNode(firstFlyoutItem.block); - this.getFlyoutCursor(workspace).setCurNode(astNode); - } - } - } - - /** - * Sets the navigation state to workspace and moves the cursor to either the - * top block on a workspace or to the workspace. - * @param {!Blockly.WorkspaceSvg} workspace The workspace to focus on. - * @package - */ - focusWorkspace(workspace) { - workspace.hideChaff(); - const reset = !!workspace.getToolbox(); - - this.resetFlyout(workspace, reset); - this.setState(workspace, Constants.STATE.WORKSPACE); - this.setCursorOnWorkspaceFocus(workspace); - } - - /** - * Moves the cursor to the top connection point on on the first top block. - * If the workspace is empty, moves the cursor to the default location on - * the workspace. - * @param {!Blockly.WorkspaceSvg} workspace The main Blockly workspace. - * @protected - */ - setCursorOnWorkspaceFocus(workspace) { - const topBlocks = workspace.getTopBlocks(true); - const cursor = workspace.getCursor(); - const wsCoordinates = new Blockly.utils.Coordinate( - this.DEFAULT_WS_COORDINATE.x / workspace.scale, - this.DEFAULT_WS_COORDINATE.y / workspace.scale, - ); - if (topBlocks.length > 0) { - cursor.setCurNode(Blockly.ASTNode.createTopNode(topBlocks[0])); - } else { - const wsNode = Blockly.ASTNode.createWorkspaceNode( - workspace, - wsCoordinates, - ); - cursor.setCurNode(wsNode); - } - } - - /** - * Gets the cursor on the flyout's workspace. - * @param {!Blockly.WorkspaceSvg} workspace The main workspace the flyout is - * on. - * @returns {?Blockly.FlyoutCursor} The flyout's cursor or null if no flyout - * exists. - * @protected - */ - getFlyoutCursor(workspace) { - const flyout = workspace.getFlyout(); - const cursor = flyout ? flyout.getWorkspace().getCursor() : null; - - return /** @type {?Blockly.FlyoutCursor} */ (cursor); - } - - /** - * Inserts a block from the flyout. - * Tries to find a connection on the block to connect to the marked - * location. If no connection has been marked, or there is not a compatible - * connection then the block is placed on the workspace. - * @param {!Blockly.WorkspaceSvg} workspace The main workspace. The workspace - * the block will be placed on. - * @package - */ - insertFromFlyout(workspace) { - const newBlock = this.createNewBlock(workspace); - if (!newBlock) { - return; - } - const markerNode = this.getMarker(workspace).getCurNode(); - if ( - !this.tryToConnectMarkerAndCursor( - workspace, - markerNode, - Blockly.ASTNode.createBlockNode(newBlock), - ) - ) { - this.warn( - 'Something went wrong while inserting a block from the flyout.', - ); - } - - this.focusWorkspace(workspace); - workspace.getCursor().setCurNode(Blockly.ASTNode.createTopNode(newBlock)); - this.removeMark(workspace); - } - - /** - * Creates a new block based on the current block the flyout cursor is on. - * @param {!Blockly.WorkspaceSvg} workspace The main workspace. The workspace - * the block will be placed on. - * @returns {?Blockly.BlockSvg} The newly created block. - * @protected - */ - createNewBlock(workspace) { - const flyout = workspace.getFlyout(); - if (!flyout || !flyout.isVisible()) { - this.warn( - 'Trying to insert from the flyout when the flyout does not ' + - ' exist or is not visible', - ); - return null; - } - - const curBlock = /** @type {!Blockly.BlockSvg} */ ( - this.getFlyoutCursor(workspace).getCurNode().getLocation() - ); - if (!curBlock.isEnabled()) { - this.warn("Can't insert a disabled block."); - return null; - } - - const newBlock = flyout.createBlock(curBlock); - // Render to get the sizing right. - newBlock.render(); - // Connections are not tracked when the block is first created. Normally - // there's enough time for them to become tracked in the user's mouse - // movements, but not here. - newBlock.setConnectionTracking(true); - return newBlock; - } - - /** - * Hides the flyout cursor and optionally hides the flyout. - * @param {!Blockly.WorkspaceSvg} workspace The workspace. - * @param {boolean} shouldHide True if the flyout should be hidden. - * @protected - */ - resetFlyout(workspace, shouldHide) { - if (this.getFlyoutCursor(workspace)) { - this.getFlyoutCursor(workspace).hide(); - if (shouldHide) { - workspace.getFlyout().hide(); - } - } - } - - /** - * Connects the location of the marker and the location of the cursor. - * No-op if the marker or cursor node are null. - * @param {!Blockly.WorkspaceSvg} workspace The main workspace. - * @returns {boolean} True if the cursor and marker locations were connected, - * false otherwise. - * @package - */ - connectMarkerAndCursor(workspace) { - const markerNode = this.getMarker(workspace).getCurNode(); - const cursorNode = workspace.getCursor().getCurNode(); - - if (markerNode && cursorNode) { - return this.tryToConnectMarkerAndCursor( - workspace, - markerNode, - cursorNode, - ); - } - return false; - } - - /** - * Tries to connect the given marker and cursor node. - * @param {!Blockly.WorkspaceSvg} workspace The main workspace. - * @param {!Blockly.ASTNode} markerNode The node to try to connect to. - * @param {!Blockly.ASTNode} cursorNode The node to connect to the markerNode. - * @returns {boolean} True if the key was handled; false if something went - * wrong. - * @protected - */ - tryToConnectMarkerAndCursor(workspace, markerNode, cursorNode) { - if (!this.logConnectionWarning(markerNode, cursorNode)) { - return false; - } - - const markerType = markerNode.getType(); - const cursorType = cursorNode.getType(); - - const cursorLoc = cursorNode.getLocation(); - const markerLoc = markerNode.getLocation(); - if (markerNode.isConnection() && cursorNode.isConnection()) { - const cursorConnection = /** @type {!Blockly.RenderedConnection} */ ( - cursorLoc - ); - const markerConnection = /** @type {!Blockly.RenderedConnection} */ ( - markerLoc - ); - return this.connect(cursorConnection, markerConnection); - } else if ( - markerNode.isConnection() && - (cursorType == Blockly.ASTNode.types.BLOCK || - cursorType == Blockly.ASTNode.types.STACK) - ) { - const cursorBlock = /** @type {!Blockly.BlockSvg} */ (cursorLoc); - const markerConnection = /** @type {!Blockly.RenderedConnection} */ ( - markerLoc - ); - return this.insertBlock(cursorBlock, markerConnection); - } else if (markerType == Blockly.ASTNode.types.WORKSPACE) { - const block = cursorNode ? cursorNode.getSourceBlock() : null; - return this.moveBlockToWorkspace( - /** @type {Blockly.BlockSvg} */ (block), - markerNode, - ); - } - this.warn('Unexpected state in tryToConnectMarkerAndCursor.'); - return false; - } - - /** - * Warns the user if the given cursor or marker node can not be connected. - * @param {!Blockly.ASTNode} markerNode The node to try to connect to. - * @param {!Blockly.ASTNode} cursorNode The node to connect to the markerNode. - * @returns {boolean} True if the marker and cursor are valid types, false - * otherwise. - * @protected - */ - logConnectionWarning(markerNode, cursorNode) { - if (!markerNode) { - this.warn('Cannot insert with no marked node.'); - return false; - } - - if (!cursorNode) { - this.warn('Cannot insert with no cursor node.'); - return false; - } - const markerType = markerNode.getType(); - const cursorType = cursorNode.getType(); - - // Check the marker for invalid types. - if (markerType == Blockly.ASTNode.types.FIELD) { - this.warn('Should not have been able to mark a field.'); - return false; - } else if (markerType == Blockly.ASTNode.types.BLOCK) { - this.warn('Should not have been able to mark a block.'); - return false; - } else if (markerType == Blockly.ASTNode.types.STACK) { - this.warn('Should not have been able to mark a stack.'); - return false; - } - - // Check the cursor for invalid types. - if (cursorType == Blockly.ASTNode.types.FIELD) { - this.warn('Cannot attach a field to anything else.'); - return false; - } else if (cursorType == Blockly.ASTNode.types.WORKSPACE) { - this.warn('Cannot attach a workspace to anything else.'); - return false; - } - return true; - } - - /** - * Disconnects the block from its parent and moves it to the position of the - * workspace node. - * @param {?Blockly.BlockSvg} block The block to be moved to the workspace. - * @param {!Blockly.ASTNode} wsNode The workspace node holding the position - * the block will be moved to. - * @returns {boolean} True if the block can be moved to the workspace, - * false otherwise. - * @protected - */ - moveBlockToWorkspace(block, wsNode) { - if (!block) { - return false; - } - if (block.isShadow()) { - this.warn('Cannot move a shadow block to the workspace.'); - return false; - } - if (block.getParent()) { - block.unplug(false); - } - block.moveTo(wsNode.getWsCoordinate()); - return true; - } - - /** - * Disconnects the child block from its parent block. No-op if the two given - * connections are unrelated. - * @param {!Blockly.RenderedConnection} movingConnection The connection that - * is being moved. - * @param {!Blockly.RenderedConnection} destConnection The connection to be - * moved to. - * @protected - */ - disconnectChild(movingConnection, destConnection) { - const movingBlock = movingConnection.getSourceBlock(); - const destBlock = destConnection.getSourceBlock(); - let inferiorConnection; - - if (movingBlock.getRootBlock() === destBlock.getRootBlock()) { - if (movingBlock.getDescendants(false).indexOf(destBlock) > -1) { - inferiorConnection = this.getInferiorConnection(destConnection); - if (inferiorConnection) { - inferiorConnection.disconnect(); - } - } else { - inferiorConnection = this.getInferiorConnection(movingConnection); - if (inferiorConnection) { - inferiorConnection.disconnect(); - } - } - } - } - - /** - * Tries to connect the given connections. - * - * If the given connections are not compatible try finding compatible - * connections on the source blocks of the given connections. - * @param {?Blockly.RenderedConnection} movingConnection The connection that - * is being moved. - * @param {?Blockly.RenderedConnection} destConnection The connection to be - * moved to. - * @returns {boolean} True if the two connections or their target connections - * were connected, false otherwise. - * @protected - */ - connect(movingConnection, destConnection) { - if (!movingConnection || !destConnection) { - return false; - } - - const movingInferior = this.getInferiorConnection(movingConnection); - const destSuperior = this.getSuperiorConnection(destConnection); - - const movingSuperior = this.getSuperiorConnection(movingConnection); - const destInferior = this.getInferiorConnection(destConnection); - - if ( - movingInferior && - destSuperior && - this.moveAndConnect(movingInferior, destSuperior) - ) { - return true; - // Try swapping the inferior and superior connections on the blocks. - } else if ( - movingSuperior && - destInferior && - this.moveAndConnect(movingSuperior, destInferior) - ) { - return true; - } else if (this.moveAndConnect(movingConnection, destConnection)) { - return true; - } else { - const checker = movingConnection.getConnectionChecker(); - const reason = checker.canConnectWithReason( - movingConnection, - destConnection, - false, - ); - this.warn( - 'Connection failed with error: ' + - checker.getErrorMessage(reason, movingConnection, destConnection), - ); - return false; - } - } - - /** - * Finds the inferior connection on the source block if the given connection - * is superior. - * @param {?Blockly.RenderedConnection} connection The connection trying to be - * connected. - * @returns {?Blockly.RenderedConnection} The inferior connection or null if - * none exists. - * @protected - */ - getInferiorConnection(connection) { - const block = /** @type{!Blockly.BlockSvg} */ (connection.getSourceBlock()); - if (!connection.isSuperior()) { - return connection; - } else if (block.previousConnection) { - return block.previousConnection; - } else if (block.outputConnection) { - return block.outputConnection; - } else { - return null; - } - } - - /** - * Finds a superior connection on the source block if the given connection is - * inferior. - * @param {?Blockly.RenderedConnection} connection The connection trying to be - * connected. - * @returns {?Blockly.RenderedConnection} The superior connection or null if - * none exists. - * @protected - */ - getSuperiorConnection(connection) { - if (connection.isSuperior()) { - return connection; - } else if (connection.targetConnection) { - return connection.targetConnection; - } - return null; - } - - /** - * Moves the moving connection to the target connection and connects them. - * @param {?Blockly.RenderedConnection} movingConnection The connection that - * is being moved. - * @param {?Blockly.RenderedConnection} destConnection The connection to be - * moved to. - * @returns {boolean} True if the connections were connected, false otherwise. - * @protected - */ - moveAndConnect(movingConnection, destConnection) { - if (!movingConnection || !destConnection) { - return false; - } - const movingBlock = movingConnection.getSourceBlock(); - const checker = movingConnection.getConnectionChecker(); - - if ( - checker.canConnect(movingConnection, destConnection, false) && - !destConnection.getSourceBlock().isShadow() - ) { - this.disconnectChild(movingConnection, destConnection); - - // Position the root block near the connection so it does not move the - // other block when they are connected. - if (!destConnection.isSuperior()) { - const rootBlock = movingBlock.getRootBlock(); - - const originalOffsetToTarget = { - x: destConnection.x - movingConnection.x, - y: destConnection.y - movingConnection.y, - }; - const originalOffsetInBlock = movingConnection - .getOffsetInBlock() - .clone(); - rootBlock.positionNearConnection( - movingConnection, - originalOffsetToTarget, - originalOffsetInBlock, - ); - } - destConnection.connect(movingConnection); - return true; - } - return false; - } - - /** - * Tries to connect the given block to the destination connection, making an - * intelligent guess about which connection to use on the moving block. - * @param {!Blockly.BlockSvg} block The block to move. - * @param {!Blockly.RenderedConnection} destConnection The connection to - * connect to. - * @returns {boolean} Whether the connection was successful. - * @protected - */ - insertBlock(block, destConnection) { - switch (destConnection.type) { - case Blockly.PREVIOUS_STATEMENT: - if (this.connect(block.nextConnection, destConnection)) { - return true; - } - break; - case Blockly.NEXT_STATEMENT: - if (this.connect(block.previousConnection, destConnection)) { - return true; - } - break; - case Blockly.INPUT_VALUE: - if (this.connect(block.outputConnection, destConnection)) { - return true; - } - break; - case Blockly.OUTPUT_VALUE: - for (let i = 0; i < block.inputList.length; i++) { - const inputConnection = /** @type {Blockly.RenderedConnection} */ ( - block.inputList[i].connection - ); - if ( - inputConnection && - inputConnection.type === Blockly.INPUT_VALUE && - this.connect(inputConnection, destConnection) - ) { - return true; - } - } - // If there are no input values pass the output and destination - // connections to connect_ to find a way to connect the two. - if ( - block.outputConnection && - this.connect(block.outputConnection, destConnection) - ) { - return true; - } - break; - } - this.warn('This block can not be inserted at the marked location.'); - return false; - } - - /** - * Disconnects the connection that the cursor is pointing to, and bump blocks. - * This is a no-op if the connection cannot be broken or if the cursor is not - * pointing to a connection. - * @param {!Blockly.WorkspaceSvg} workspace The workspace. - * @package - */ - disconnectBlocks(workspace) { - const curNode = workspace.getCursor().getCurNode(); - if (!curNode.isConnection()) { - this.log( - 'Cannot disconnect blocks when the cursor is not on a connection', - ); - return; - } - const curConnection = /** @type {!Blockly.RenderedConnection} */ ( - curNode.getLocation() - ); - if (!curConnection.isConnected()) { - this.log('Cannot disconnect unconnected connection'); - return; - } - const superiorConnection = curConnection.isSuperior() - ? curConnection - : curConnection.targetConnection; - - const inferiorConnection = curConnection.isSuperior() - ? curConnection.targetConnection - : curConnection; - - if (inferiorConnection.getSourceBlock().isShadow()) { - this.log('Cannot disconnect a shadow block'); - return; - } - superiorConnection.disconnect(); - inferiorConnection.bumpAwayFrom(superiorConnection); - - const rootBlock = superiorConnection.getSourceBlock().getRootBlock(); - rootBlock.bringToFront(); - - const connectionNode = - Blockly.ASTNode.createConnectionNode(superiorConnection); - workspace.getCursor().setCurNode(connectionNode); - } - - /** - * Moves the marker to the cursor's current location. - * @param {!Blockly.WorkspaceSvg} workspace The workspace. - * @protected - */ - markAtCursor(workspace) { - this.getMarker(workspace).setCurNode(workspace.getCursor().getCurNode()); - } - - /** - * Removes the marker from its current location and hide it. - * @param {!Blockly.WorkspaceSvg} workspace The workspace. - * @protected - */ - removeMark(workspace) { - const marker = this.getMarker(workspace); - marker.setCurNode(null); - marker.hide(); - } - - /** - * Enables accessibility mode. - * @param {!Blockly.WorkspaceSvg} workspace The workspace to enable keyboard - * accessibility mode on. - * @package - */ - enableKeyboardAccessibility(workspace) { - if ( - this.workspaces.indexOf(workspace) > -1 && - !workspace.keyboardAccessibilityMode - ) { - workspace.keyboardAccessibilityMode = true; - this.focusWorkspace(workspace); - } - } - - /** - * Disables accessibility mode. - * @param {!Blockly.WorkspaceSvg} workspace The workspace to disable keyboard - * accessibility mode on. - * @package - */ - disableKeyboardAccessibility(workspace) { - if ( - this.workspaces.indexOf(workspace) > -1 && - workspace.keyboardAccessibilityMode - ) { - workspace.keyboardAccessibilityMode = false; - workspace.getCursor().hide(); - this.getMarker(workspace).hide(); - if (this.getFlyoutCursor(workspace)) { - this.getFlyoutCursor(workspace).hide(); - } - } - } - - /** - * Navigation log handler. If loggingCallback is defined, use it. - * Otherwise just log to the console.log. - * @param {string} msg The message to log. - * @protected - */ - log(msg) { - if (this.loggingCallback) { - this.loggingCallback(Constants.LOGGING_MSG_TYPE.LOG, msg); - } else { - console.log(msg); - } - } - - /** - * Navigation warning handler. If loggingCallback is defined, use it. - * Otherwise call console.warn. - * @param {string} msg The warning message. - * @protected - */ - warn(msg) { - if (this.loggingCallback) { - this.loggingCallback(Constants.LOGGING_MSG_TYPE.WARN, msg); - } else { - console.warn(msg); - } - } - - /** - * Navigation error handler. If loggingCallback is defined, use it. - * Otherwise call console.error. - * @param {string} msg The error message. - * @protected - */ - error(msg) { - if (this.loggingCallback) { - this.loggingCallback(Constants.LOGGING_MSG_TYPE.ERROR, msg); - } else { - console.error(msg); - } - } - - /** - * Moves the workspace cursor in the given direction. - * @param {!Blockly.WorkspaceSvg} workspace The workspace the cursor is on. - * @param {number} xDirection -1 to move cursor left. 1 to move cursor right. - * @param {number} yDirection -1 to move cursor up. 1 to move cursor down. - * @returns {boolean} True if the current node is a workspace, false - * otherwise. - * @package - */ - moveWSCursor(workspace, xDirection, yDirection) { - const cursor = workspace.getCursor(); - const curNode = workspace.getCursor().getCurNode(); - - if (curNode.getType() !== Blockly.ASTNode.types.WORKSPACE) { - return false; - } - - const wsCoord = curNode.getWsCoordinate(); - const newX = xDirection * this.WS_MOVE_DISTANCE + wsCoord.x; - const newY = yDirection * this.WS_MOVE_DISTANCE + wsCoord.y; - - cursor.setCurNode( - Blockly.ASTNode.createWorkspaceNode( - workspace, - new Blockly.utils.Coordinate(newX, newY), - ), - ); - return true; - } - - /** - * Handles hitting the enter key on the workspace. - * @param {!Blockly.WorkspaceSvg} workspace The workspace. - * @package - */ - handleEnterForWS(workspace) { - const cursor = workspace.getCursor(); - const curNode = cursor.getCurNode(); - const nodeType = curNode.getType(); - if (nodeType == Blockly.ASTNode.types.FIELD) { - /** @type {!Blockly.Field} */ (curNode.getLocation()).showEditor(); - } else if ( - curNode.isConnection() || - nodeType == Blockly.ASTNode.types.WORKSPACE - ) { - this.markAtCursor(workspace); - } else if (nodeType == Blockly.ASTNode.types.BLOCK) { - this.warn('Cannot mark a block.'); - } else if (nodeType == Blockly.ASTNode.types.STACK) { - this.warn('Cannot mark a stack.'); - } - } - - /** - * Pastes the copied block to the marked location. - * @param {Blockly.BlockCopyData} copyData The data - * to paste into the workspace. - * @param {Blockly.WorkspaceSvg} workspace The workspace to paste the data - * into. - * @returns {boolean} True if the paste was sucessful, false otherwise. - * @package - */ - paste(copyData, workspace) { - let isHandled = false; - Blockly.Events.setGroup(true); - const block = /** @type {Blockly.BlockSvg} */ ( - Blockly.clipboard.paste(copyData, workspace) - ); - if (block) { - isHandled = this.insertPastedBlock(workspace, block); - } - Blockly.Events.setGroup(false); - return isHandled; - } - - /** - * Inserts the pasted block at the marked location if a compatible connection - * exists. If no connection has been marked, or there is not a compatible - * connection then the block is placed on the workspace. - * @param {!Blockly.WorkspaceSvg} workspace The workspace to paste the block - * on. - * @param {!Blockly.BlockSvg} block The block to paste. - * @returns {boolean} True if the block was pasted to the workspace, false - * otherwise. - * @protected - */ - insertPastedBlock(workspace, block) { - let isHandled = false; - const markedNode = workspace.getMarker(this.MARKER_NAME).getCurNode(); - if (markedNode) { - isHandled = this.tryToConnectMarkerAndCursor( - workspace, - markedNode, - Blockly.ASTNode.createBlockNode(block), - ); - } - return isHandled; - } - - /** - * Triggers a flyout button's callback. - * @param {!Blockly.WorkspaceSvg} workspace The main workspace. The workspace - * containing a flyout with a button. - * @package - */ - triggerButtonCallback(workspace) { - const button = /** @type {!Blockly.FlyoutButton} */ ( - this.getFlyoutCursor(workspace).getCurNode().getLocation() - ); - const buttonCallback = workspace.flyoutButtonCallbacks.get( - button.callbackKey, - ); - if (typeof buttonCallback === 'function') { - buttonCallback(button); - } else { - throw new Error('No callback function found for flyout button.'); - } - } - - /** - * Removes the change listeners on all registered workspaces. - * @package - */ - dispose() { - for (const workspace of this.workspaces) { - this.removeWorkspace(workspace); - } - } -} diff --git a/plugins/keyboard-navigation/src/navigation_controller.js b/plugins/keyboard-navigation/src/navigation_controller.js deleted file mode 100644 index 8f3820a906..0000000000 --- a/plugins/keyboard-navigation/src/navigation_controller.js +++ /dev/null @@ -1,1020 +0,0 @@ -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Registers all of the keyboard shortcuts that are necessary for - * navigating blockly using the keyboard. - * @author aschmiedt@google.com (Abby Schmiedt) - */ - -import './gesture_monkey_patch'; - -import * as Blockly from 'blockly/core'; - -import * as Constants from './constants'; -import {Navigation} from './navigation'; - -/** - * Class for registering shortcuts for keyboard navigation. - */ -export class NavigationController { - /** Data copied by the copy or cut keyboard shortcuts. */ - copyData = null; - - /** The workspace a copy or cut keyboard shortcut happened in. */ - copyWorkspace = null; - - /** - * Constructor used for registering shortcuts. - * This will register any default shortcuts for keyboard navigation. - * This is intended to be a singleton. - * @param {!Navigation=} optNavigation The class that handles keyboard - * navigation shortcuts. (Ex: inserting a block, focusing the flyout). - */ - constructor(optNavigation) { - /** - * Handles any keyboard navigation shortcuts. - * @type {!Navigation} - * @public - */ - this.navigation = optNavigation || new Navigation(); - } - - /** - * Registers the default keyboard shortcuts for keyboard navigation. - * @public - */ - init() { - this.addShortcutHandlers(); - this.registerDefaults(); - } - - /** - * Adds methods to core Blockly components that allows them to handle keyboard - * shortcuts when in keyboard navigation mode. - * @protected - */ - addShortcutHandlers() { - if (Blockly.FieldDropdown) { - Blockly.FieldDropdown.prototype.onShortcut = this.fieldDropdownHandler; - } - - if (Blockly.Toolbox) { - Blockly.Toolbox.prototype.onShortcut = this.toolboxHandler; - } - } - - /** - * Removes methods on core Blockly components that allows them to handle - * keyboard shortcuts. - * @protected - */ - removeShortcutHandlers() { - if (Blockly.FieldDropdown) { - Blockly.FieldDropdown.prototype.onShortcut = null; - } - - if (Blockly.Toolbox) { - Blockly.Toolbox.prototype.onShortcut = null; - } - } - - /** - * Handles the given keyboard shortcut. - * This is only triggered when keyboard accessibility mode is enabled. - * @param {!Blockly.ShortcutRegistry.KeyboardShortcut} shortcut The shortcut - * to be handled. - * @returns {boolean} True if the field handled the shortcut, - * false otherwise. - * @this {Blockly.FieldDropdown} - * @protected - */ - fieldDropdownHandler(shortcut) { - if (this.menu_) { - switch (shortcut.name) { - case Constants.SHORTCUT_NAMES.PREVIOUS: - this.menu_.highlightPrevious(); - return true; - case Constants.SHORTCUT_NAMES.NEXT: - this.menu_.highlightNext(); - return true; - default: - return false; - } - } - // If we haven't already handled the shortcut, let the default Field - // handler try. - return Blockly.Field.prototype.onShortcut.call(this, shortcut); - } - - /** - * Handles the given keyboard shortcut. - * This is only triggered when keyboard accessibility mode is enabled. - * @param {!Blockly.ShortcutRegistry.KeyboardShortcut} shortcut The shortcut - * to be handled. - * @returns {boolean} True if the toolbox handled the shortcut, - * false otherwise. - * @this {Blockly.Toolbox} - * @protected - */ - toolboxHandler(shortcut) { - if (!this.selectedItem_) { - return false; - } - switch (shortcut.name) { - case Constants.SHORTCUT_NAMES.PREVIOUS: - return this.selectPrevious_(); - case Constants.SHORTCUT_NAMES.OUT: - return this.selectParent_(); - case Constants.SHORTCUT_NAMES.NEXT: - return this.selectNext_(); - case Constants.SHORTCUT_NAMES.IN: - return this.selectChild_(); - default: - return false; - } - } - - /** - * Adds all necessary event listeners and markers to a workspace for keyboard - * navigation to work. This must be called for keyboard navigation to work - * on a workspace. - * @param {!Blockly.WorkspaceSvg} workspace The workspace to add keyboard - * navigation to. - * @public - */ - addWorkspace(workspace) { - this.navigation.addWorkspace(workspace); - } - - /** - * Removes all necessary event listeners and markers to a workspace for - * keyboard navigation to work. - * @param {!Blockly.WorkspaceSvg} workspace The workspace to remove keyboard - * navigation from. - * @public - */ - removeWorkspace(workspace) { - this.navigation.removeWorkspace(workspace); - } - - /** - * Turns on keyboard navigation. - * @param {!Blockly.WorkspaceSvg} workspace The workspace to turn on keyboard - * navigation for. - * @public - */ - enable(workspace) { - this.navigation.enableKeyboardAccessibility(workspace); - } - - /** - * Turns off keyboard navigation. - * @param {!Blockly.WorkspaceSvg} workspace The workspace to turn off keyboard - * navigation on. - * @public - */ - disable(workspace) { - this.navigation.disableKeyboardAccessibility(workspace); - } - - /** - * Gives the cursor to the field to handle if the cursor is on a field. - * @param {!Blockly.WorkspaceSvg} workspace The workspace to check. - * @param {!Blockly.ShortcutRegistry.KeyboardShortcut} shortcut The shortcut - * to give to the field. - * @returns {boolean} True if the shortcut was handled by the field, false - * otherwise. - * @protected - */ - fieldShortcutHandler(workspace, shortcut) { - const cursor = workspace.getCursor(); - if (!cursor || !cursor.getCurNode()) { - return false; - } - const curNode = cursor.getCurNode(); - if (curNode.getType() === Blockly.ASTNode.types.FIELD) { - return /** @type {!Blockly.Field} */ (curNode.getLocation()).onShortcut( - shortcut, - ); - } - return false; - } - - /** - * Keyboard shortcut to go to the previous location when in keyboard - * navigation mode. - * @protected - */ - registerPrevious() { - /** @type {!Blockly.ShortcutRegistry.KeyboardShortcut} */ - const previousShortcut = { - name: Constants.SHORTCUT_NAMES.PREVIOUS, - preconditionFn: (workspace) => { - return workspace.keyboardAccessibilityMode; - }, - callback: (workspace, e, shortcut) => { - const flyout = workspace.getFlyout(); - const toolbox = workspace.getToolbox(); - let isHandled = false; - switch (this.navigation.getState(workspace)) { - case Constants.STATE.WORKSPACE: - isHandled = this.fieldShortcutHandler(workspace, shortcut); - if (!isHandled) { - workspace.getCursor().prev(); - isHandled = true; - } - return isHandled; - case Constants.STATE.FLYOUT: - isHandled = this.fieldShortcutHandler(workspace, shortcut); - if (!isHandled) { - flyout.getWorkspace().getCursor().prev(); - isHandled = true; - } - return isHandled; - case Constants.STATE.TOOLBOX: - return toolbox && typeof toolbox.onShortcut == 'function' - ? toolbox.onShortcut(shortcut) - : false; - default: - return false; - } - }, - }; - - Blockly.ShortcutRegistry.registry.register(previousShortcut); - Blockly.ShortcutRegistry.registry.addKeyMapping( - Blockly.utils.KeyCodes.W, - previousShortcut.name, - ); - } - - /** - * Keyboard shortcut to turn keyboard navigation on or off. - * @protected - */ - registerToggleKeyboardNav() { - /** @type {!Blockly.ShortcutRegistry.KeyboardShortcut} */ - const toggleKeyboardNavShortcut = { - name: Constants.SHORTCUT_NAMES.TOGGLE_KEYBOARD_NAV, - callback: (workspace) => { - if (workspace.keyboardAccessibilityMode) { - this.navigation.disableKeyboardAccessibility(workspace); - } else { - this.navigation.enableKeyboardAccessibility(workspace); - } - return true; - }, - }; - - Blockly.ShortcutRegistry.registry.register(toggleKeyboardNavShortcut); - const ctrlShiftK = Blockly.ShortcutRegistry.registry.createSerializedKey( - Blockly.utils.KeyCodes.K, - [Blockly.utils.KeyCodes.CTRL, Blockly.utils.KeyCodes.SHIFT], - ); - Blockly.ShortcutRegistry.registry.addKeyMapping( - ctrlShiftK, - toggleKeyboardNavShortcut.name, - ); - } - - /** - * Keyboard shortcut to go to the out location when in keyboard navigation - * mode. - * @protected - */ - registerOut() { - /** @type {!Blockly.ShortcutRegistry.KeyboardShortcut} */ - const outShortcut = { - name: Constants.SHORTCUT_NAMES.OUT, - preconditionFn: (workspace) => { - return workspace.keyboardAccessibilityMode; - }, - callback: (workspace, e, shortcut) => { - const toolbox = workspace.getToolbox(); - let isHandled = false; - switch (this.navigation.getState(workspace)) { - case Constants.STATE.WORKSPACE: - isHandled = this.fieldShortcutHandler(workspace, shortcut); - if (!isHandled) { - workspace.getCursor().out(); - isHandled = true; - } - return isHandled; - case Constants.STATE.FLYOUT: - this.navigation.focusToolbox(workspace); - return true; - case Constants.STATE.TOOLBOX: - return toolbox && typeof toolbox.onShortcut == 'function' - ? toolbox.onShortcut(shortcut) - : false; - default: - return false; - } - }, - }; - - Blockly.ShortcutRegistry.registry.register(outShortcut); - Blockly.ShortcutRegistry.registry.addKeyMapping( - Blockly.utils.KeyCodes.A, - outShortcut.name, - ); - } - - /** - * Keyboard shortcut to go to the next location when in keyboard navigation - * mode. - * @protected - */ - registerNext() { - /** @type {!Blockly.ShortcutRegistry.KeyboardShortcut} */ - const nextShortcut = { - name: Constants.SHORTCUT_NAMES.NEXT, - preconditionFn: (workspace) => { - return workspace.keyboardAccessibilityMode; - }, - callback: (workspace, e, shortcut) => { - const toolbox = workspace.getToolbox(); - const flyout = workspace.getFlyout(); - let isHandled = false; - switch (this.navigation.getState(workspace)) { - case Constants.STATE.WORKSPACE: - isHandled = this.fieldShortcutHandler(workspace, shortcut); - if (!isHandled) { - workspace.getCursor().next(); - isHandled = true; - } - return isHandled; - case Constants.STATE.FLYOUT: - isHandled = this.fieldShortcutHandler(workspace, shortcut); - if (!isHandled) { - flyout.getWorkspace().getCursor().next(); - isHandled = true; - } - return isHandled; - case Constants.STATE.TOOLBOX: - return toolbox && typeof toolbox.onShortcut == 'function' - ? toolbox.onShortcut(shortcut) - : false; - default: - return false; - } - }, - }; - - Blockly.ShortcutRegistry.registry.register(nextShortcut); - Blockly.ShortcutRegistry.registry.addKeyMapping( - Blockly.utils.KeyCodes.S, - nextShortcut.name, - ); - } - - /** - * Keyboard shortcut to go to the in location when in keyboard navigation - * mode. - * @protected - */ - registerIn() { - /** @type {!Blockly.ShortcutRegistry.KeyboardShortcut} */ - const inShortcut = { - name: Constants.SHORTCUT_NAMES.IN, - preconditionFn: (workspace) => { - return workspace.keyboardAccessibilityMode; - }, - callback: (workspace, e, shortcut) => { - const toolbox = workspace.getToolbox(); - let isHandled = false; - switch (this.navigation.getState(workspace)) { - case Constants.STATE.WORKSPACE: - isHandled = this.fieldShortcutHandler(workspace, shortcut); - if (!isHandled) { - workspace.getCursor().in(); - isHandled = true; - } - return isHandled; - case Constants.STATE.TOOLBOX: - isHandled = - toolbox && typeof toolbox.onShortcut == 'function' - ? toolbox.onShortcut(shortcut) - : false; - if (!isHandled) { - this.navigation.focusFlyout(workspace); - } - return true; - default: - return false; - } - }, - }; - - Blockly.ShortcutRegistry.registry.register(inShortcut); - Blockly.ShortcutRegistry.registry.addKeyMapping( - Blockly.utils.KeyCodes.D, - inShortcut.name, - ); - } - - /** - * Keyboard shortcut to connect a block to a marked location when in keyboard - * navigation mode. - * @protected - */ - registerInsert() { - /** @type {!Blockly.ShortcutRegistry.KeyboardShortcut} */ - const insertShortcut = { - name: Constants.SHORTCUT_NAMES.INSERT, - preconditionFn: (workspace) => { - return ( - workspace.keyboardAccessibilityMode && !workspace.options.readOnly - ); - }, - callback: (workspace) => { - switch (this.navigation.getState(workspace)) { - case Constants.STATE.WORKSPACE: - return this.navigation.connectMarkerAndCursor(workspace); - default: - return false; - } - }, - }; - - Blockly.ShortcutRegistry.registry.register(insertShortcut); - Blockly.ShortcutRegistry.registry.addKeyMapping( - Blockly.utils.KeyCodes.I, - insertShortcut.name, - ); - } - - /** - * Keyboard shortcut to mark a location when in keyboard navigation mode. - * @protected - */ - registerMark() { - /** @type {!Blockly.ShortcutRegistry.KeyboardShortcut} */ - const markShortcut = { - name: Constants.SHORTCUT_NAMES.MARK, - preconditionFn: (workspace) => { - return ( - workspace.keyboardAccessibilityMode && !workspace.options.readOnly - ); - }, - callback: (workspace) => { - let flyoutCursor; - let curNode; - let nodeType; - - switch (this.navigation.getState(workspace)) { - case Constants.STATE.WORKSPACE: - this.navigation.handleEnterForWS(workspace); - return true; - case Constants.STATE.FLYOUT: - flyoutCursor = this.navigation.getFlyoutCursor(workspace); - if (!flyoutCursor) { - return false; - } - curNode = flyoutCursor.getCurNode(); - nodeType = curNode.getType(); - - switch (nodeType) { - case Blockly.ASTNode.types.STACK: - this.navigation.insertFromFlyout(workspace); - break; - case Blockly.ASTNode.types.BUTTON: - this.navigation.triggerButtonCallback(workspace); - break; - } - - return true; - default: - return false; - } - }, - }; - - Blockly.ShortcutRegistry.registry.register(markShortcut); - Blockly.ShortcutRegistry.registry.addKeyMapping( - Blockly.utils.KeyCodes.ENTER, - markShortcut.name, - ); - } - - /** - * Keyboard shortcut to disconnect two blocks when in keyboard navigation - * mode. - * @protected - */ - registerDisconnect() { - /** @type {!Blockly.ShortcutRegistry.KeyboardShortcut} */ - const disconnectShortcut = { - name: Constants.SHORTCUT_NAMES.DISCONNECT, - preconditionFn: (workspace) => { - return ( - workspace.keyboardAccessibilityMode && !workspace.options.readOnly - ); - }, - callback: (workspace) => { - switch (this.navigation.getState(workspace)) { - case Constants.STATE.WORKSPACE: - this.navigation.disconnectBlocks(workspace); - return true; - default: - return false; - } - }, - }; - - Blockly.ShortcutRegistry.registry.register(disconnectShortcut); - Blockly.ShortcutRegistry.registry.addKeyMapping( - Blockly.utils.KeyCodes.X, - disconnectShortcut.name, - ); - } - - /** - * Keyboard shortcut to focus on the toolbox when in keyboard navigation - * mode. - * @protected - */ - registerToolboxFocus() { - /** @type {!Blockly.ShortcutRegistry.KeyboardShortcut} */ - const focusToolboxShortcut = { - name: Constants.SHORTCUT_NAMES.TOOLBOX, - preconditionFn: (workspace) => { - return ( - workspace.keyboardAccessibilityMode && !workspace.options.readOnly - ); - }, - callback: (workspace) => { - switch (this.navigation.getState(workspace)) { - case Constants.STATE.WORKSPACE: - if (!workspace.getToolbox()) { - this.navigation.focusFlyout(workspace); - } else { - this.navigation.focusToolbox(workspace); - } - return true; - default: - return false; - } - }, - }; - - Blockly.ShortcutRegistry.registry.register(focusToolboxShortcut); - Blockly.ShortcutRegistry.registry.addKeyMapping( - Blockly.utils.KeyCodes.T, - focusToolboxShortcut.name, - ); - } - - /** - * Keyboard shortcut to exit the current location and focus on the workspace - * when in keyboard navigation mode. - * @protected - */ - registerExit() { - /** @type {!Blockly.ShortcutRegistry.KeyboardShortcut} */ - const exitShortcut = { - name: Constants.SHORTCUT_NAMES.EXIT, - preconditionFn: (workspace) => { - return workspace.keyboardAccessibilityMode; - }, - callback: (workspace) => { - switch (this.navigation.getState(workspace)) { - case Constants.STATE.FLYOUT: - this.navigation.focusWorkspace(workspace); - return true; - case Constants.STATE.TOOLBOX: - this.navigation.focusWorkspace(workspace); - return true; - default: - return false; - } - }, - }; - - Blockly.ShortcutRegistry.registry.register(exitShortcut, true); - Blockly.ShortcutRegistry.registry.addKeyMapping( - Blockly.utils.KeyCodes.ESC, - exitShortcut.name, - true, - ); - Blockly.ShortcutRegistry.registry.addKeyMapping( - Blockly.utils.KeyCodes.E, - exitShortcut.name, - true, - ); - } - - /** - * Keyboard shortcut to move the cursor on the workspace to the left when in - * keyboard navigation mode. - * @protected - */ - registerWorkspaceMoveLeft() { - /** @type {!Blockly.ShortcutRegistry.KeyboardShortcut} */ - const wsMoveLeftShortcut = { - name: Constants.SHORTCUT_NAMES.MOVE_WS_CURSOR_LEFT, - preconditionFn: (workspace) => { - return ( - workspace.keyboardAccessibilityMode && !workspace.options.readOnly - ); - }, - callback: (workspace) => { - return this.navigation.moveWSCursor(workspace, -1, 0); - }, - }; - - Blockly.ShortcutRegistry.registry.register(wsMoveLeftShortcut); - const shiftA = Blockly.ShortcutRegistry.registry.createSerializedKey( - Blockly.utils.KeyCodes.A, - [Blockly.utils.KeyCodes.SHIFT], - ); - Blockly.ShortcutRegistry.registry.addKeyMapping( - shiftA, - wsMoveLeftShortcut.name, - ); - } - - /** - * Keyboard shortcut to move the cursor on the workspace to the right when in - * keyboard navigation mode. - * @protected - */ - registerWorkspaceMoveRight() { - /** @type {!Blockly.ShortcutRegistry.KeyboardShortcut} */ - const wsMoveRightShortcut = { - name: Constants.SHORTCUT_NAMES.MOVE_WS_CURSOR_RIGHT, - preconditionFn: (workspace) => { - return ( - workspace.keyboardAccessibilityMode && !workspace.options.readOnly - ); - }, - callback: (workspace) => { - return this.navigation.moveWSCursor(workspace, 1, 0); - }, - }; - - Blockly.ShortcutRegistry.registry.register(wsMoveRightShortcut); - const shiftD = Blockly.ShortcutRegistry.registry.createSerializedKey( - Blockly.utils.KeyCodes.D, - [Blockly.utils.KeyCodes.SHIFT], - ); - Blockly.ShortcutRegistry.registry.addKeyMapping( - shiftD, - wsMoveRightShortcut.name, - ); - } - - /** - * Keyboard shortcut to move the cursor on the workspace up when in keyboard - * navigation mode. - * @protected - */ - registerWorkspaceMoveUp() { - /** @type {!Blockly.ShortcutRegistry.KeyboardShortcut} */ - const wsMoveUpShortcut = { - name: Constants.SHORTCUT_NAMES.MOVE_WS_CURSOR_UP, - preconditionFn: (workspace) => { - return ( - workspace.keyboardAccessibilityMode && !workspace.options.readOnly - ); - }, - callback: (workspace) => { - return this.navigation.moveWSCursor(workspace, 0, -1); - }, - }; - - Blockly.ShortcutRegistry.registry.register(wsMoveUpShortcut); - const shiftW = Blockly.ShortcutRegistry.registry.createSerializedKey( - Blockly.utils.KeyCodes.W, - [Blockly.utils.KeyCodes.SHIFT], - ); - Blockly.ShortcutRegistry.registry.addKeyMapping( - shiftW, - wsMoveUpShortcut.name, - ); - } - - /** - * Keyboard shortcut to move the cursor on the workspace down when in - * keyboard navigation mode. - * @protected - */ - registerWorkspaceMoveDown() { - /** @type {!Blockly.ShortcutRegistry.KeyboardShortcut} */ - const wsMoveDownShortcut = { - name: Constants.SHORTCUT_NAMES.MOVE_WS_CURSOR_DOWN, - preconditionFn: (workspace) => { - return ( - workspace.keyboardAccessibilityMode && !workspace.options.readOnly - ); - }, - callback: (workspace) => { - return this.navigation.moveWSCursor(workspace, 0, 1); - }, - }; - - Blockly.ShortcutRegistry.registry.register(wsMoveDownShortcut); - const shiftW = Blockly.ShortcutRegistry.registry.createSerializedKey( - Blockly.utils.KeyCodes.S, - [Blockly.utils.KeyCodes.SHIFT], - ); - Blockly.ShortcutRegistry.registry.addKeyMapping( - shiftW, - wsMoveDownShortcut.name, - ); - } - - /** - * Keyboard shortcut to copy the block the cursor is currently on. - * @protected - */ - registerCopy() { - /** @type {!Blockly.ShortcutRegistry.KeyboardShortcut} */ - const copyShortcut = { - name: Constants.SHORTCUT_NAMES.COPY, - preconditionFn: (workspace) => { - if ( - workspace.keyboardAccessibilityMode && - !workspace.options.readOnly - ) { - const curNode = workspace.getCursor().getCurNode(); - if (curNode && curNode.getSourceBlock()) { - const sourceBlock = curNode.getSourceBlock(); - return ( - !Blockly.Gesture.inProgress() && - sourceBlock && - sourceBlock.isDeletable() && - sourceBlock.isMovable() - ); - } - } - return false; - }, - callback: (workspace) => { - const sourceBlock = /** @type {Blockly.BlockSvg} */ ( - workspace.getCursor().getCurNode().getSourceBlock() - ); - workspace.hideChaff(); - this.copyData = sourceBlock.toCopyData(); - this.copyWorkspace = sourceBlock.workspace; - return !!this.copyData; - }, - }; - - Blockly.ShortcutRegistry.registry.register(copyShortcut); - - const ctrlC = Blockly.ShortcutRegistry.registry.createSerializedKey( - Blockly.utils.KeyCodes.C, - [Blockly.utils.KeyCodes.CTRL], - ); - Blockly.ShortcutRegistry.registry.addKeyMapping( - ctrlC, - copyShortcut.name, - true, - ); - - const altC = Blockly.ShortcutRegistry.registry.createSerializedKey( - Blockly.utils.KeyCodes.C, - [Blockly.utils.KeyCodes.ALT], - ); - Blockly.ShortcutRegistry.registry.addKeyMapping( - altC, - copyShortcut.name, - true, - ); - - const metaC = Blockly.ShortcutRegistry.registry.createSerializedKey( - Blockly.utils.KeyCodes.C, - [Blockly.utils.KeyCodes.META], - ); - Blockly.ShortcutRegistry.registry.addKeyMapping( - metaC, - copyShortcut.name, - true, - ); - } - - /** - * Register shortcut to paste the copied block to the marked location. - * @protected - */ - registerPaste() { - /** @type {!Blockly.ShortcutRegistry.KeyboardShortcut} */ - const pasteShortcut = { - name: Constants.SHORTCUT_NAMES.PASTE, - preconditionFn: (workspace) => { - return ( - workspace.keyboardAccessibilityMode && - !workspace.options.readOnly && - !Blockly.Gesture.inProgress() - ); - }, - callback: () => { - if (!this.copyData || !this.copyWorkspace) return false; - return this.navigation.paste(this.copyData, this.copyWorkspace); - }, - }; - - Blockly.ShortcutRegistry.registry.register(pasteShortcut); - - const ctrlV = Blockly.ShortcutRegistry.registry.createSerializedKey( - Blockly.utils.KeyCodes.V, - [Blockly.utils.KeyCodes.CTRL], - ); - Blockly.ShortcutRegistry.registry.addKeyMapping( - ctrlV, - pasteShortcut.name, - true, - ); - - const altV = Blockly.ShortcutRegistry.registry.createSerializedKey( - Blockly.utils.KeyCodes.V, - [Blockly.utils.KeyCodes.ALT], - ); - Blockly.ShortcutRegistry.registry.addKeyMapping( - altV, - pasteShortcut.name, - true, - ); - - const metaV = Blockly.ShortcutRegistry.registry.createSerializedKey( - Blockly.utils.KeyCodes.V, - [Blockly.utils.KeyCodes.META], - ); - Blockly.ShortcutRegistry.registry.addKeyMapping( - metaV, - pasteShortcut.name, - true, - ); - } - - /** - * Keyboard shortcut to copy and delete the block the cursor is on using - * ctrl+x, cmd+x, or alt+x. - * @protected - */ - registerCut() { - /** @type {!Blockly.ShortcutRegistry.KeyboardShortcut} */ - const cutShortcut = { - name: Constants.SHORTCUT_NAMES.CUT, - preconditionFn: (workspace) => { - if ( - workspace.keyboardAccessibilityMode && - !workspace.options.readOnly - ) { - const curNode = workspace.getCursor().getCurNode(); - if (curNode && curNode.getSourceBlock()) { - const sourceBlock = curNode.getSourceBlock(); - return ( - !Blockly.Gesture.inProgress() && - sourceBlock && - sourceBlock.isDeletable() && - sourceBlock.isMovable() && - !sourceBlock.workspace.isFlyout - ); - } - } - return false; - }, - callback: (workspace) => { - const sourceBlock = /** @type {Blockly.BlockSvg} */ ( - workspace.getCursor().getCurNode().getSourceBlock() - ); - this.copyData = sourceBlock.toCopyData(); - this.copyWorkspace = sourceBlock.workspace; - this.navigation.moveCursorOnBlockDelete(workspace, sourceBlock); - sourceBlock.checkAndDelete(); - return true; - }, - }; - - Blockly.ShortcutRegistry.registry.register(cutShortcut); - - const ctrlX = Blockly.ShortcutRegistry.registry.createSerializedKey( - Blockly.utils.KeyCodes.X, - [Blockly.utils.KeyCodes.CTRL], - ); - Blockly.ShortcutRegistry.registry.addKeyMapping( - ctrlX, - cutShortcut.name, - true, - ); - - const altX = Blockly.ShortcutRegistry.registry.createSerializedKey( - Blockly.utils.KeyCodes.X, - [Blockly.utils.KeyCodes.ALT], - ); - Blockly.ShortcutRegistry.registry.addKeyMapping( - altX, - cutShortcut.name, - true, - ); - - const metaX = Blockly.ShortcutRegistry.registry.createSerializedKey( - Blockly.utils.KeyCodes.X, - [Blockly.utils.KeyCodes.META], - ); - Blockly.ShortcutRegistry.registry.addKeyMapping( - metaX, - cutShortcut.name, - true, - ); - } - - /** - * Registers shortcut to delete the block the cursor is on using delete or - * backspace. - * @protected - */ - registerDelete() { - /** @type {!Blockly.ShortcutRegistry.KeyboardShortcut} */ - const deleteShortcut = { - name: Constants.SHORTCUT_NAMES.DELETE, - preconditionFn: function (workspace) { - if ( - workspace.keyboardAccessibilityMode && - !workspace.options.readOnly - ) { - const curNode = workspace.getCursor().getCurNode(); - if (curNode && curNode.getSourceBlock()) { - const sourceBlock = curNode.getSourceBlock(); - return sourceBlock && sourceBlock.isDeletable(); - } - } - return false; - }, - callback: (workspace, e) => { - const sourceBlock = workspace.getCursor().getCurNode().getSourceBlock(); - // Delete or backspace. - // Stop the browser from going back to the previous page. - // Do this first to prevent an error in the delete code from resulting - // in data loss. - e.preventDefault(); - // Don't delete while dragging. Jeez. - if (Blockly.Gesture.inProgress()) { - return false; - } - this.navigation.moveCursorOnBlockDelete(workspace, sourceBlock); - sourceBlock.checkAndDelete(); - return true; - }, - }; - Blockly.ShortcutRegistry.registry.register(deleteShortcut); - Blockly.ShortcutRegistry.registry.addKeyMapping( - Blockly.utils.KeyCodes.DELETE, - deleteShortcut.name, - true, - ); - Blockly.ShortcutRegistry.registry.addKeyMapping( - Blockly.utils.KeyCodes.BACKSPACE, - deleteShortcut.name, - true, - ); - } - - /** - * Registers all default keyboard shortcut items for keyboard navigation. This - * should be called once per instance of KeyboardShortcutRegistry. - * @protected - */ - registerDefaults() { - this.registerPrevious(); - this.registerNext(); - this.registerIn(); - this.registerOut(); - - this.registerDisconnect(); - this.registerExit(); - this.registerInsert(); - this.registerMark(); - this.registerToolboxFocus(); - this.registerToggleKeyboardNav(); - - this.registerWorkspaceMoveDown(); - this.registerWorkspaceMoveLeft(); - this.registerWorkspaceMoveUp(); - this.registerWorkspaceMoveRight(); - - this.registerCopy(); - this.registerPaste(); - this.registerCut(); - this.registerDelete(); - } - - /** - * Removes all the keyboard navigation shortcuts. - * @public - */ - dispose() { - const shortcutNames = Object.values(Constants.SHORTCUT_NAMES); - for (const name of shortcutNames) { - Blockly.ShortcutRegistry.registry.unregister(name); - } - this.removeShortcutHandlers(); - this.navigation.dispose(); - } -} diff --git a/plugins/keyboard-navigation/test/index.html b/plugins/keyboard-navigation/test/index.html deleted file mode 100644 index e0db0d3253..0000000000 --- a/plugins/keyboard-navigation/test/index.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - - Blockly Plugin Test - - - - -

- Keyboard Navigation is our first step towards an accessible Blockly.
- For more information on how the default keyboard navigation works please - see the -
documentation. -
-
- - Cursors
- The cursor controls how the user navigates the blocks, inputs, fields and - connections on a workspace. This demo shows three different cursors:
- Default Cursor: This cursor uses previous, next, in, and out to - navigate through the different parts of a block. See the - developer documentation - for more information.
- Basic Cursor: Uses pre order traversal to allow users to navigate - through everything using only the previous and next command.
- Line Cursor: We tried to make this cursor mimic a text editor. - Navigating up and down will take the cursor to the next and previous - "line" of code. Navigating in and out will move the cursor through all the - fields and inputs in that "line" of code. -

- - - -
- - - diff --git a/plugins/keyboard-navigation/test/index.js b/plugins/keyboard-navigation/test/index.js deleted file mode 100644 index 919ab31037..0000000000 --- a/plugins/keyboard-navigation/test/index.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Plugin test. - */ - -import {createPlayground} from '@blockly/dev-tools'; -import * as Blockly from 'blockly'; -import {toolbox} from './toolbox'; - -import {LineCursor, NavigationController} from '../src'; - -let controller; - -/** - * Create a workspace. - * @param {HTMLElement} blocklyDiv The blockly container div. - * @param {!Blockly.BlocklyOptions} options The Blockly options. - * @returns {!Blockly.WorkspaceSvg} The created workspace. - */ -function createWorkspace(blocklyDiv, options) { - const workspace = Blockly.inject(blocklyDiv, options); - controller.addWorkspace(workspace); - return workspace; -} - -document.addEventListener('DOMContentLoaded', function () { - controller = new NavigationController(); - controller.init(); - const defaultOptions = { - toolbox: toolbox, - }; - createPlayground( - document.getElementById('root'), - createWorkspace, - defaultOptions, - ); -}); - -document - .getElementById('accessibilityModeCheck') - .addEventListener('click', (e) => { - if (e.target.checked) { - controller.enable(Blockly.getMainWorkspace()); - } else { - controller.disable(Blockly.getMainWorkspace()); - } - }); - -document.getElementById('cursorChanger').addEventListener('change', (e) => { - const cursorType = e.target.value; - const accessibilityCheckbox = document.getElementById( - 'accessibilityModeCheck', - ); - const markerManager = Blockly.getMainWorkspace().getMarkerManager(); - const oldCurNode = markerManager.getCursor().getCurNode(); - - document.getElementById('cursorChanger').value = cursorType; - if (cursorType === 'basic') { - Blockly.ASTNode.NAVIGATE_ALL_FIELDS = false; - markerManager.setCursor(new Blockly.BasicCursor()); - } else if (cursorType === 'line') { - Blockly.ASTNode.NAVIGATE_ALL_FIELDS = true; - markerManager.setCursor(new LineCursor()); - } else { - Blockly.ASTNode.NAVIGATE_ALL_FIELDS = false; - markerManager.setCursor(new Blockly.Cursor()); - } - if (oldCurNode) { - markerManager.getCursor().setCurNode(oldCurNode); - } - - if (!accessibilityCheckbox.checked) { - accessibilityCheckbox.checked = true; - controller.enable(Blockly.getMainWorkspace()); - } - - document.activeElement.blur(); -}); diff --git a/plugins/keyboard-navigation/test/navigation_modify_test.mocha.js b/plugins/keyboard-navigation/test/navigation_modify_test.mocha.js deleted file mode 100644 index 492b98f9c5..0000000000 --- a/plugins/keyboard-navigation/test/navigation_modify_test.mocha.js +++ /dev/null @@ -1,691 +0,0 @@ -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -const chai = require('chai'); -const Blockly = require('blockly'); -const {Navigation} = require('../src/navigation'); -const assert = chai.assert; -const {testHelpers} = require('@blockly/dev-tools'); -const {captureWarnings} = testHelpers; - -suite('Insert/Modify', function () { - /** - * Check that modify failed. - * @param {Navigation} navigation The class under test. - * @param {Blockly.WorkspaceSvg} workspace The main workspace. - * @param {!Blockly.ASTNode} markerNode The node to try to connect to. - * @param {!Blockly.ASTNode} cursorNode The node to connect to the markerNode. - */ - function assertModifyFails(navigation, workspace, markerNode, cursorNode) { - let modifyResult; - const warnings = captureWarnings(function () { - modifyResult = navigation.tryToConnectMarkerAndCursor( - workspace, - markerNode, - cursorNode, - ); - }); - assert.isFalse(modifyResult); - assert.equal( - warnings.length, - 1, - 'Expecting 1 warnings for why modify failed.', - ); - } - - /** - * Define default blocks. - */ - function defineTestBlocks() { - Blockly.defineBlocksWithJsonArray([ - { - type: 'stack_block', - message0: '', - previousStatement: null, - nextStatement: null, - }, - { - type: 'row_block', - message0: '%1', - args0: [ - { - type: 'input_value', - name: 'INPUT', - }, - ], - output: null, - }, - { - type: 'statement_block', - message0: '%1', - args0: [ - { - type: 'input_statement', - name: 'NAME', - }, - ], - previousStatement: null, - nextStatement: null, - colour: 230, - tooltip: '', - helpUrl: '', - }, - ]); - } - - setup(function () { - this.jsdomCleanup = require('jsdom-global')( - '
', - ); - // We are running these tests in node even thought they require a rendered - // workspace, which doesn't exactly work. The rendering system expects - // cancelAnimationFrame to be defined so we need to define it. - window.cancelAnimationFrame = function () {}; - - // NOTE: block positions chosen such that they aren't unintentionally - // bumped out of bounds during tests. - const xmlText = ` - - - - - - - - - `; - - defineTestBlocks(); - - this.workspace = Blockly.inject('blocklyDiv', { - toolbox: ` - `, - }); - Blockly.Xml.domToWorkspace( - Blockly.utils.xml.textToDom(xmlText), - this.workspace, - ); - this.navigation = new Navigation(); - this.navigation.addWorkspace(this.workspace); - - this.stack_block_1 = this.workspace.getBlockById('stack_block_1'); - this.stack_block_2 = this.workspace.getBlockById('stack_block_2'); - this.row_block_1 = this.workspace.getBlockById('row_block_1'); - this.row_block_2 = this.workspace.getBlockById('row_block_2'); - this.statement_block_1 = this.workspace.getBlockById('statement_block_1'); - this.statement_block_2 = this.workspace.getBlockById('statement_block_2'); - this.navigation.enableKeyboardAccessibility(this.workspace); - }); - - teardown(function () { - delete Blockly.Blocks['stack_block']; - delete Blockly.Blocks['row_block']; - delete Blockly.Blocks['statement_block']; - window.cancelAnimationFrame = undefined; - this.jsdomCleanup(); - }); - - suite('Marked Connection', function () { - suite('Marker on next', function () { - setup(function () { - this.markerNode = Blockly.ASTNode.createConnectionNode( - this.stack_block_1.nextConnection, - ); - }); - test('Cursor on workspace', function () { - const cursorNode = Blockly.ASTNode.createWorkspaceNode( - this.workspace, - new Blockly.utils.Coordinate(0, 0), - ); - assertModifyFails( - this.navigation, - this.workspace, - this.markerNode, - cursorNode, - ); - }); - test('Cursor on compatible connection', function () { - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.stack_block_2.previousConnection, - ); - assert.isTrue( - this.navigation.tryToConnectMarkerAndCursor( - this.workspace, - this.markerNode, - cursorNode, - ), - ); - assert.equal(this.stack_block_1.getNextBlock().id, 'stack_block_2'); - }); - test('Cursor on incompatible connection', function () { - // Connect method will try to find a way to connect blocks with - // incompatible types. - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.stack_block_2.nextConnection, - ); - assert.isTrue( - this.navigation.tryToConnectMarkerAndCursor( - this.workspace, - this.markerNode, - cursorNode, - ), - ); - assert.equal(this.stack_block_1.getNextBlock(), this.stack_block_2); - }); - test('Cursor on really incompatible connection', function () { - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.row_block_1.outputConnection, - ); - assertModifyFails( - this.navigation, - this.workspace, - this.markerNode, - cursorNode, - ); - assert.isNull(this.stack_block_1.getNextBlock()); - }); - test('Cursor on block', function () { - const cursorNode = Blockly.ASTNode.createBlockNode(this.stack_block_2); - assert.isTrue( - this.navigation.tryToConnectMarkerAndCursor( - this.workspace, - this.markerNode, - cursorNode, - ), - ); - assert.equal(this.stack_block_1.getNextBlock().id, 'stack_block_2'); - }); - }); - - suite('Marker on previous', function () { - setup(function () { - this.markerNode = Blockly.ASTNode.createConnectionNode( - this.stack_block_1.previousConnection, - ); - }); - test('Cursor on compatible connection', function () { - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.stack_block_2.nextConnection, - ); - assert.isTrue( - this.navigation.tryToConnectMarkerAndCursor( - this.workspace, - this.markerNode, - cursorNode, - ), - ); - assert.equal(this.stack_block_1.getPreviousBlock().id, 'stack_block_2'); - }); - test('Cursor on incompatible connection', function () { - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.stack_block_2.previousConnection, - ); - assertModifyFails( - this.navigation, - this.workspace, - this.markerNode, - cursorNode, - ); - assert.isNull(this.stack_block_1.getPreviousBlock()); - }); - test('Cursor on really incompatible connection', function () { - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.row_block_1.outputConnection, - ); - assertModifyFails( - this.navigation, - this.workspace, - this.markerNode, - cursorNode, - ); - assert.isNull(this.stack_block_1.getNextBlock()); - }); - test('Cursor on block', function () { - const cursorNode = Blockly.ASTNode.createBlockNode(this.stack_block_2); - assert.isTrue( - this.navigation.tryToConnectMarkerAndCursor( - this.workspace, - this.markerNode, - cursorNode, - ), - ); - assert.equal(this.stack_block_1.getPreviousBlock().id, 'stack_block_2'); - }); - test('Cursor on incompatible block', function () { - const cursorNode = Blockly.ASTNode.createBlockNode(this.row_block_1); - assertModifyFails( - this.navigation, - this.workspace, - this.markerNode, - cursorNode, - ); - assert.isNull(this.stack_block_1.getPreviousBlock()); - }); - }); - - suite('Marker on value input', function () { - setup(function () { - this.markerNode = Blockly.ASTNode.createConnectionNode( - this.row_block_1.inputList[0].connection, - ); - }); - test('Cursor on compatible connection', function () { - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.row_block_2.outputConnection, - ); - assert.isTrue( - this.navigation.tryToConnectMarkerAndCursor( - this.workspace, - this.markerNode, - cursorNode, - ), - ); - assert.equal(this.row_block_2.getParent().id, 'row_block_1'); - }); - test('Cursor on incompatible connection', function () { - // Connect method will try to find a way to connect blocks with - // incompatible types. - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.row_block_2.inputList[0].connection, - ); - assert.isTrue( - this.navigation.tryToConnectMarkerAndCursor( - this.workspace, - this.markerNode, - cursorNode, - ), - ); - assert.equal( - this.row_block_1.inputList[0].connection.targetBlock(), - this.row_block_2, - ); - }); - test('Cursor on really incompatible connection', function () { - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.stack_block_1.previousConnection, - ); - assertModifyFails( - this.navigation, - this.workspace, - this.markerNode, - cursorNode, - ); - }); - test('Cursor on block', function () { - const cursorNode = Blockly.ASTNode.createBlockNode(this.row_block_2); - assert.isTrue( - this.navigation.tryToConnectMarkerAndCursor( - this.workspace, - this.markerNode, - cursorNode, - ), - ); - assert.equal(this.row_block_2.getParent().id, 'row_block_1'); - }); - }); - - suite('Marked Statement input', function () { - setup(function () { - this.statement_block_1.inputList[0].connection.connect( - this.stack_block_1.previousConnection, - ); - this.stack_block_1.nextConnection.connect( - this.stack_block_2.previousConnection, - ); - this.markerNode = Blockly.ASTNode.createInputNode( - this.statement_block_1.inputList[0], - ); - }); - test('Cursor on block inside statement', function () { - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.stack_block_2.previousConnection, - ); - assert.isTrue( - this.navigation.tryToConnectMarkerAndCursor( - this.workspace, - this.markerNode, - cursorNode, - ), - ); - assert.equal( - this.stack_block_2.previousConnection.targetBlock(), - this.statement_block_1, - ); - }); - test('Cursor on stack', function () { - const cursorNode = Blockly.ASTNode.createStackNode( - this.statement_block_2, - ); - assert.isTrue( - this.navigation.tryToConnectMarkerAndCursor( - this.workspace, - this.markerNode, - cursorNode, - ), - ); - assert.equal( - this.statement_block_2.getParent().id, - 'statement_block_1', - ); - }); - test('Cursor on incompatible type', function () { - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.row_block_1.outputConnection, - ); - assertModifyFails( - this.navigation, - this.workspace, - this.markerNode, - cursorNode, - ); - assert.isNull(this.row_block_1.getParent()); - }); - }); - - suite('Marker on output', function () { - setup(function () { - this.markerNode = Blockly.ASTNode.createConnectionNode( - this.row_block_1.outputConnection, - ); - }); - test('Cursor on compatible connection', function () { - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.row_block_2.inputList[0].connection, - ); - assert.isTrue( - this.navigation.tryToConnectMarkerAndCursor( - this.workspace, - this.markerNode, - cursorNode, - ), - ); - assert.equal(this.row_block_1.getParent().id, 'row_block_2'); - }); - test('Cursor on incompatible connection', function () { - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.row_block_2.outputConnection, - ); - assertModifyFails( - this.navigation, - this.workspace, - this.markerNode, - cursorNode, - ); - }); - test('Cursor on really incompatible connection', function () { - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.stack_block_1.previousConnection, - ); - assertModifyFails( - this.navigation, - this.workspace, - this.markerNode, - cursorNode, - ); - }); - test('Cursor on block', function () { - const cursorNode = Blockly.ASTNode.createBlockNode(this.row_block_2); - assert.isTrue( - this.navigation.tryToConnectMarkerAndCursor( - this.workspace, - this.markerNode, - cursorNode, - ), - ); - assert.equal(this.row_block_1.getParent().id, 'row_block_2'); - }); - }); - }); - - suite('Marked Workspace', function () { - setup(function () { - this.markerNode = Blockly.ASTNode.createWorkspaceNode( - this.workspace, - new Blockly.utils.Coordinate(100, 200), - ); - }); - test('Cursor on row block', function () { - const cursorNode = Blockly.ASTNode.createBlockNode(this.row_block_1); - assert.isTrue( - this.navigation.tryToConnectMarkerAndCursor( - this.workspace, - this.markerNode, - cursorNode, - ), - ); - const pos = this.row_block_1.getRelativeToSurfaceXY(); - assert.equal(pos.x, 100); - assert.equal(pos.y, 200); - }); - - test('Cursor on output connection', function () { - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.row_block_1.outputConnection, - ); - assert.isTrue( - this.navigation.tryToConnectMarkerAndCursor( - this.workspace, - this.markerNode, - cursorNode, - ), - ); - const pos = this.row_block_1.getRelativeToSurfaceXY(); - assert.equal(pos.x, 100); - assert.equal(pos.y, 200); - }); - - test('Cursor on previous connection', function () { - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.stack_block_1.previousConnection, - ); - assert.isTrue( - this.navigation.tryToConnectMarkerAndCursor( - this.workspace, - this.markerNode, - cursorNode, - ), - ); - const pos = this.stack_block_1.getRelativeToSurfaceXY(); - assert.equal(pos.x, 100); - assert.equal(pos.y, 200); - }); - - test('Cursor on input connection', function () { - // Move the source block to the marked location on the workspace. - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.row_block_1.inputList[0].connection, - ); - assert.isTrue( - this.navigation.tryToConnectMarkerAndCursor( - this.workspace, - this.markerNode, - cursorNode, - ), - ); - }); - - test('Cursor on next connection', function () { - // Move the source block to the marked location on the workspace. - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.stack_block_1.nextConnection, - ); - assert.isTrue( - this.navigation.tryToConnectMarkerAndCursor( - this.workspace, - this.markerNode, - cursorNode, - ), - ); - }); - - test('Cursor on child block (row)', function () { - this.row_block_1.inputList[0].connection.connect( - this.row_block_2.outputConnection, - ); - - const cursorNode = Blockly.ASTNode.createBlockNode(this.row_block_2); - assert.isTrue( - this.navigation.tryToConnectMarkerAndCursor( - this.workspace, - this.markerNode, - cursorNode, - ), - ); - assert.isNull(this.row_block_2.getParent()); - const pos = this.row_block_2.getRelativeToSurfaceXY(); - assert.equal(pos.x, 100); - assert.equal(pos.y, 200); - }); - - test('Cursor on child block (stack)', function () { - this.stack_block_1.nextConnection.connect( - this.stack_block_2.previousConnection, - ); - - const cursorNode = Blockly.ASTNode.createBlockNode(this.stack_block_2); - assert.isTrue( - this.navigation.tryToConnectMarkerAndCursor( - this.workspace, - this.markerNode, - cursorNode, - ), - ); - assert.isNull(this.stack_block_2.getParent()); - const pos = this.stack_block_2.getRelativeToSurfaceXY(); - assert.equal(pos.x, 100); - assert.equal(pos.y, 200); - }); - - test('Cursor on workspace', function () { - const cursorNode = Blockly.ASTNode.createWorkspaceNode( - this.workspace, - new Blockly.utils.Coordinate(100, 100), - ); - assertModifyFails( - this.navigation, - this.workspace, - this.markerNode, - cursorNode, - ); - }); - }); - - suite('Marked Block', function () { - suite('Marked any block', function () { - // These tests are using a stack block, but do not depend on the type of - // the block. - setup(function () { - this.markerNode = Blockly.ASTNode.createBlockNode(this.stack_block_1); - }); - test('Cursor on workspace', function () { - const cursorNode = Blockly.ASTNode.createWorkspaceNode( - this.workspace, - new Blockly.utils.Coordinate(100, 100), - ); - assertModifyFails( - this.navigation, - this.workspace, - this.markerNode, - cursorNode, - ); - }); - }); - suite('Marked stack block', function () { - setup(function () { - this.markerNode = Blockly.ASTNode.createBlockNode(this.stack_block_1); - }); - test('Cursor on row block', function () { - const cursorNode = Blockly.ASTNode.createBlockNode(this.row_block_1); - assertModifyFails( - this.navigation, - this.workspace, - this.markerNode, - cursorNode, - ); - }); - test('Cursor on stack block', function () { - const cursorNode = Blockly.ASTNode.createBlockNode(this.stack_block_1); - assertModifyFails( - this.navigation, - this.workspace, - this.markerNode, - cursorNode, - ); - }); - test('Cursor on next connection', function () { - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.stack_block_2.nextConnection, - ); - assertModifyFails( - this.navigation, - this.workspace, - this.markerNode, - cursorNode, - ); - }); - test('Cursor on previous connection', function () { - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.stack_block_2.previousConnection, - ); - assertModifyFails( - this.navigation, - this.workspace, - this.markerNode, - cursorNode, - ); - }); - }); - suite('Marked row block', function () { - setup(function () { - this.markerNode = Blockly.ASTNode.createBlockNode(this.row_block_1); - }); - test('Cursor on stack block', function () { - const cursorNode = Blockly.ASTNode.createBlockNode(this.stack_block_1); - assertModifyFails( - this.navigation, - this.workspace, - this.markerNode, - cursorNode, - ); - }); - test('Cursor on row block', function () { - const cursorNode = Blockly.ASTNode.createBlockNode(this.row_block_1); - assertModifyFails( - this.navigation, - this.workspace, - this.markerNode, - cursorNode, - ); - }); - test('Cursor on value input connection', function () { - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.row_block_2.inputList[0].connection, - ); - assertModifyFails( - this.navigation, - this.workspace, - this.markerNode, - cursorNode, - ); - }); - test('Cursor on output connection', function () { - const cursorNode = Blockly.ASTNode.createConnectionNode( - this.row_block_2.outputConnection, - ); - assertModifyFails( - this.navigation, - this.workspace, - this.markerNode, - cursorNode, - ); - }); - }); - }); -}); diff --git a/plugins/keyboard-navigation/test/navigation_test.mocha.js b/plugins/keyboard-navigation/test/navigation_test.mocha.js deleted file mode 100644 index ed5c67e989..0000000000 --- a/plugins/keyboard-navigation/test/navigation_test.mocha.js +++ /dev/null @@ -1,1365 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview - * @author aschmiedt@google.com (Abby Schmiedt) - */ -'use strict'; - -const chai = require('chai'); -const sinon = require('sinon'); - -const Blockly = require('blockly'); -const {NavigationController, Constants} = require('../src/index'); -const { - createNavigationWorkspace, - createKeyDownEvent, -} = require('./test_helper'); - -suite('Navigation', function () { - setup(function () { - this.jsdomCleanup = require('jsdom-global')( - '
', - ); - // We are running these tests in node even thought they require a rendered - // workspace, which doesn't exactly work. The rendering system expects - // cancelAnimationFrame to be defined so we need to define it. - window.cancelAnimationFrame = function () {}; - this.controller = new NavigationController(); - this.controller.init(); - this.navigation = this.controller.navigation; - - this.getContextStub = sinon - .stub(window.HTMLCanvasElement.prototype, 'getContext') - .callsFake(() => { - return { - measureText: function () { - return {width: 0}; - }, - }; - }); - }); - - teardown(function () { - this.controller.dispose(); - window.cancelAnimationFrame = undefined; - this.jsdomCleanup(); - sinon.restore(); - }); - - // Test that toolbox key handlers call through to the right functions and - // transition correctly between toolbox, workspace, and flyout. - suite('Tests toolbox keys', function () { - setup(function () { - Blockly.defineBlocksWithJsonArray([ - { - type: 'basic_block', - message0: '%1', - args0: [ - { - type: 'field_input', - name: 'TEXTFIELD', - text: 'test', - }, - ], - }, - ]); - this.workspace = createNavigationWorkspace(this.navigation, true); - this.navigation.focusToolbox(this.workspace); - }); - - teardown(function () { - this.navigation.removeWorkspace(this.workspace); - this.workspace.dispose(); - sinon.restore(); - delete Blockly.Blocks['basic_block']; - }); - - const testCases = [ - [ - 'Calls toolbox selectNext', - createKeyDownEvent(Blockly.utils.KeyCodes.S, 'NotAField'), - 'selectNext_', - ], - [ - 'Calls toolbox selectPrevious', - createKeyDownEvent(Blockly.utils.KeyCodes.W, 'NotAField'), - 'selectPrevious_', - ], - [ - 'Calls toolbox selectParent', - createKeyDownEvent(Blockly.utils.KeyCodes.D, 'NotAField'), - 'selectChild_', - ], - [ - 'Calls toolbox selectChild', - createKeyDownEvent(Blockly.utils.KeyCodes.A, 'NotAField'), - 'selectParent_', - ], - ]; - - testCases.forEach(function (testCase) { - const testCaseName = testCase[0]; - const mockEvent = testCase[1]; - const stubName = testCase[2]; - test(testCaseName, function () { - const toolbox = this.workspace.getToolbox(); - const selectStub = sinon.stub(toolbox, stubName); - toolbox.selectedItem_ = toolbox.contents_[0]; - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); - sinon.assert.called(selectStub); - }); - }); - - test('Go to flyout', function () { - const navigation = this.navigation; - const mockEvent = createKeyDownEvent( - Blockly.utils.KeyCodes.D, - 'NotAField', - ); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); - - chai.assert.isTrue(keyDownSpy.returned(true)); - chai.assert.equal( - navigation.getState(this.workspace), - Constants.STATE.FLYOUT, - ); - - const flyoutCursor = navigation.getFlyoutCursor(this.workspace); - // See test_helper.js for hardcoded field values. - chai.assert.equal( - flyoutCursor.getCurNode().getLocation().getFieldValue('TEXTFIELD'), - 'first', - ); - }); - - test('Focuses workspace from toolbox (e)', function () { - const navigation = this.navigation; - navigation.setState(this.workspace, Constants.STATE.TOOLBOX); - const mockEvent = createKeyDownEvent( - Blockly.utils.KeyCodes.E, - 'NotAField', - ); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); - - chai.assert.isTrue(keyDownSpy.returned(true)); - chai.assert.equal( - navigation.getState(this.workspace), - Constants.STATE.WORKSPACE, - ); - }); - test('Focuses workspace from toolbox (escape)', function () { - const navigation = this.navigation; - navigation.setState(this.workspace, Constants.STATE.TOOLBOX); - const mockEvent = createKeyDownEvent( - Blockly.utils.KeyCodes.ESC, - 'NotAField', - ); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); - - chai.assert.isTrue(keyDownSpy.returned(true)); - chai.assert.equal( - navigation.getState(this.workspace), - Constants.STATE.WORKSPACE, - ); - }); - }); - - // Test that flyout key handlers call through to the right functions and - // transition correctly between toolbox, workspace, and flyout. - suite('Tests flyout keys', function () { - setup(function () { - Blockly.defineBlocksWithJsonArray([ - { - type: 'basic_block', - message0: '%1', - args0: [ - { - type: 'field_input', - name: 'TEXTFIELD', - text: 'test', - }, - ], - }, - ]); - this.workspace = createNavigationWorkspace(this.navigation, true); - this.navigation.focusToolbox(this.workspace); - this.navigation.focusFlyout(this.workspace); - }); - - teardown(function () { - this.navigation.removeWorkspace(this.workspace); - this.workspace.dispose(); - sinon.restore(); - delete Blockly.Blocks['basic_block']; - }); - // Should be a no-op - test('Previous at beginning', function () { - const mockEvent = createKeyDownEvent( - Blockly.utils.KeyCodes.W, - 'NotAField', - ); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); - - chai.assert.isTrue(keyDownSpy.returned(true)); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.FLYOUT, - ); - // See test_helper.js for hardcoded field values. - chai.assert.equal( - this.navigation - .getFlyoutCursor(this.workspace) - .getCurNode() - .getLocation() - .getFieldValue('TEXTFIELD'), - 'first', - ); - }); - test('Previous', function () { - const flyoutBlocks = this.workspace - .getFlyout() - .getWorkspace() - .getTopBlocks(); - this.navigation - .getFlyoutCursor(this.workspace) - .setCurNode(Blockly.ASTNode.createStackNode(flyoutBlocks[1])); - let flyoutBlock = this.navigation - .getFlyoutCursor(this.workspace) - .getCurNode() - .getLocation(); - // See test_helper.js for hardcoded field values. - chai.assert.equal(flyoutBlock.getFieldValue('TEXTFIELD'), 'second'); - - const mockEvent = createKeyDownEvent( - Blockly.utils.KeyCodes.W, - 'NotAField', - ); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); - - chai.assert.isTrue(keyDownSpy.returned(true)); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.FLYOUT, - ); - flyoutBlock = this.navigation - .getFlyoutCursor(this.workspace) - .getCurNode() - .getLocation(); - // See test_helper.js for hardcoded field values. - chai.assert.equal(flyoutBlock.getFieldValue('TEXTFIELD'), 'first'); - }); - - test('Next', function () { - const mockEvent = createKeyDownEvent( - Blockly.utils.KeyCodes.S, - 'NotAField', - ); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); - - chai.assert.isTrue(keyDownSpy.returned(true)); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.FLYOUT, - ); - const flyoutBlock = this.navigation - .getFlyoutCursor(this.workspace) - .getCurNode() - .getLocation(); - // See test_helper.js for hardcoded field values. - chai.assert.equal(flyoutBlock.getFieldValue('TEXTFIELD'), 'second'); - }); - - test('Out', function () { - const mockEvent = createKeyDownEvent( - Blockly.utils.KeyCodes.A, - 'NotAField', - ); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); - - chai.assert.isTrue(keyDownSpy.returned(true)); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.TOOLBOX, - ); - }); - - test('Mark', function () { - const mockEvent = createKeyDownEvent( - Blockly.utils.KeyCodes.ENTER, - 'NotAField', - ); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); - - chai.assert.isTrue(keyDownSpy.returned(true)); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.WORKSPACE, - ); - chai.assert.equal(this.workspace.getTopBlocks().length, 1); - }); - - test('Mark - Disabled Block', function () { - this.navigation.loggingCallback = function (type, msg) { - chai.assert.equal(msg, "Can't insert a disabled block."); - }; - const flyout = this.workspace.getFlyout(); - const topBlock = flyout.getWorkspace().getTopBlocks()[0]; - topBlock.setEnabled(false); - const mockEvent = createKeyDownEvent( - Blockly.utils.KeyCodes.ENTER, - 'NotAField', - ); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); - - chai.assert.isTrue(keyDownSpy.returned(true)); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.FLYOUT, - ); - chai.assert.equal(this.workspace.getTopBlocks().length, 0); - this.navigation.loggingCallback = null; - }); - - test('Exit', function () { - const mockEvent = createKeyDownEvent( - Blockly.utils.KeyCodes.ESC, - 'NotAField', - ); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); - - chai.assert.isTrue(keyDownSpy.returned(true)); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.WORKSPACE, - ); - }); - }); - // Test that workspace key handlers call through to the right functions and - // transition correctly between toolbox, workspace, and flyout. - suite('Tests workspace keys', function () { - setup(function () { - Blockly.defineBlocksWithJsonArray([ - { - type: 'basic_block', - message0: '%1', - args0: [ - { - type: 'field_input', - name: 'TEXTFIELD', - text: 'test', - }, - ], - previousStatement: null, - nextStatement: null, - }, - ]); - this.workspace = createNavigationWorkspace(this.navigation, true); - this.basicBlock = this.workspace.newBlock('basic_block'); - }); - - teardown(function () { - this.navigation.removeWorkspace(this.workspace); - this.workspace.dispose(); - sinon.restore(); - delete Blockly.Blocks['basic_block']; - }); - - test('Previous', function () { - const prevSpy = sinon.spy(this.workspace.getCursor(), 'prev'); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - const wEvent = createKeyDownEvent(Blockly.utils.KeyCodes.W, ''); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, wEvent); - - chai.assert.isTrue(keyDownSpy.returned(true)); - sinon.assert.calledOnce(prevSpy); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.WORKSPACE, - ); - }); - - test('Next', function () { - const nextSpy = sinon.spy(this.workspace.getCursor(), 'next'); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - const sEvent = createKeyDownEvent(Blockly.utils.KeyCodes.S, ''); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, sEvent); - - chai.assert.isTrue(keyDownSpy.returned(true)); - sinon.assert.calledOnce(nextSpy); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.WORKSPACE, - ); - }); - - test('Out', function () { - const outSpy = sinon.spy(this.workspace.getCursor(), 'out'); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - const aEvent = createKeyDownEvent(Blockly.utils.KeyCodes.A, ''); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, aEvent); - - chai.assert.isTrue(keyDownSpy.returned(true)); - sinon.assert.calledOnce(outSpy); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.WORKSPACE, - ); - }); - - test('In', function () { - const inSpy = sinon.spy(this.workspace.getCursor(), 'in'); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - const dEvent = createKeyDownEvent(Blockly.utils.KeyCodes.D, ''); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, dEvent); - - chai.assert.isTrue(keyDownSpy.returned(true)); - sinon.assert.calledOnce(inSpy); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.WORKSPACE, - ); - }); - - test('Insert', function () { - const blockNode = Blockly.ASTNode.createBlockNode(this.basicBlock); - this.navigation.getMarker(this.workspace).setCurNode(blockNode); - // Stub modify as we are not testing its behavior, only if it was called. - // Otherwise, there is a warning because there is no marked node. - const modifyStub = sinon - .stub(this.navigation, 'tryToConnectMarkerAndCursor') - .returns(true); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - const iEvent = createKeyDownEvent(Blockly.utils.KeyCodes.I, ''); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, iEvent); - - chai.assert.isTrue(keyDownSpy.returned(true)); - sinon.assert.calledOnce(modifyStub); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.WORKSPACE, - ); - }); - - test('Mark', function () { - this.workspace - .getCursor() - .setCurNode( - Blockly.ASTNode.createConnectionNode( - this.basicBlock.previousConnection, - ), - ); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - const enterEvent = createKeyDownEvent(Blockly.utils.KeyCodes.ENTER, ''); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, enterEvent); - - const markedNode = this.workspace - .getMarker(this.navigation.MARKER_NAME) - .getCurNode(); - chai.assert.isTrue(keyDownSpy.returned(true)); - chai.assert.equal( - markedNode.getLocation(), - this.basicBlock.previousConnection, - ); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.WORKSPACE, - ); - }); - - test('Toolbox', function () { - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - const tEvent = createKeyDownEvent(Blockly.utils.KeyCodes.T, ''); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, tEvent); - - const firstCategory = this.workspace.getToolbox().contents_[0]; - chai.assert.isTrue(keyDownSpy.returned(true)); - chai.assert.equal( - this.workspace.getToolbox().getSelectedItem(), - firstCategory, - ); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.TOOLBOX, - ); - }); - }); - - suite('Test key press', function () { - setup(function () { - Blockly.defineBlocksWithJsonArray([ - { - type: 'basic_block', - message0: '%1', - args0: [ - { - type: 'field_input', - name: 'TEXTFIELD', - text: 'test', - }, - ], - }, - ]); - this.workspace = createNavigationWorkspace(this.navigation, true); - - this.workspace.getCursor().drawer_ = null; - this.basicBlock = this.workspace.newBlock('basic_block'); - this.basicBlock.initSvg(); - this.basicBlock.render(); - }); - teardown(function () { - this.navigation.removeWorkspace(this.workspace); - this.workspace.dispose(); - sinon.restore(); - delete Blockly.Blocks['basic_block']; - }); - - test('Action does not exist', function () { - const block = this.workspace.getTopBlocks()[0]; - const field = block.inputList[0].fieldRow[0]; - const fieldSpy = sinon.spy(field, 'onShortcut'); - const mockEvent = createKeyDownEvent(Blockly.utils.KeyCodes.N, ''); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - this.workspace - .getCursor() - .setCurNode(Blockly.ASTNode.createFieldNode(field)); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); - - chai.assert.isFalse(keyDownSpy.returned(true)); - sinon.assert.notCalled(fieldSpy); - }); - - test('Action exists - field handles action', function () { - const block = this.workspace.getTopBlocks()[0]; - const field = block.inputList[0].fieldRow[0]; - const mockEvent = createKeyDownEvent(Blockly.utils.KeyCodes.A, ''); - const fieldSpy = sinon.stub(field, 'onShortcut').returns(true); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - this.workspace - .getCursor() - .setCurNode(Blockly.ASTNode.createFieldNode(field)); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); - - chai.assert.isTrue(keyDownSpy.returned(true)); - sinon.assert.calledOnce(fieldSpy); - }); - - test('Action exists - field does not handle action', function () { - const block = this.workspace.getTopBlocks()[0]; - const field = block.inputList[0].fieldRow[0]; - const mockEvent = createKeyDownEvent(Blockly.utils.KeyCodes.A, ''); - const fieldSpy = sinon.spy(field, 'onShortcut'); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - this.workspace - .getCursor() - .setCurNode(Blockly.ASTNode.createFieldNode(field)); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); - - chai.assert.isTrue(keyDownSpy.returned(true)); - sinon.assert.calledOnce(fieldSpy); - }); - - test('Toggle Action Off', function () { - const mockEvent = createKeyDownEvent(Blockly.utils.KeyCodes.K, '', [ - Blockly.utils.KeyCodes.SHIFT, - Blockly.utils.KeyCodes.CTRL, - ]); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - this.workspace.keyboardAccessibilityMode = true; - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); - - chai.assert.isTrue(keyDownSpy.returned(true)); - chai.assert.isFalse(this.workspace.keyboardAccessibilityMode); - }); - - test('Toggle Action On', function () { - const mockEvent = createKeyDownEvent(Blockly.utils.KeyCodes.K, '', [ - Blockly.utils.KeyCodes.SHIFT, - Blockly.utils.KeyCodes.CTRL, - ]); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - this.workspace.keyboardAccessibilityMode = false; - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); - - chai.assert.isTrue(keyDownSpy.returned(true)); - chai.assert.isTrue(this.workspace.keyboardAccessibilityMode); - }); - - suite('Test key press in read only mode', function () { - setup(function () { - Blockly.defineBlocksWithJsonArray([ - { - type: 'field_block', - message0: '%1 %2', - args0: [ - { - type: 'field_input', - name: 'TEXTFIELD', - text: 'test', - }, - { - type: 'input_value', - name: 'NAME', - }, - ], - previousStatement: null, - nextStatement: null, - colour: 230, - tooltip: '', - helpUrl: '', - }, - ]); - this.workspace = createNavigationWorkspace(this.navigation, true, true); - Blockly.common.setMainWorkspace(this.workspace); - this.workspace.getCursor().drawer_ = null; - - this.fieldBlock1 = this.workspace.newBlock('field_block'); - this.fieldBlock1.initSvg(); - this.fieldBlock1.render(); - }); - - teardown(function () { - this.navigation.removeWorkspace(this.workspace); - this.workspace.dispose(); - sinon.restore(); - delete Blockly.Blocks['field_block']; - }); - - test('Perform valid action for read only', function () { - const astNode = Blockly.ASTNode.createBlockNode(this.fieldBlock1); - const mockEvent = createKeyDownEvent(Blockly.utils.KeyCodes.S, ''); - this.workspace.getCursor().setCurNode(astNode); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); - - chai.assert.isTrue(keyDownSpy.returned(true)); - }); - - test('Perform invalid action for read only', function () { - const astNode = Blockly.ASTNode.createBlockNode(this.fieldBlock1); - const mockEvent = createKeyDownEvent(Blockly.utils.KeyCodes.I, ''); - this.workspace.getCursor().setCurNode(astNode); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); - - chai.assert.isTrue(keyDownSpy.returned(false)); - }); - - test('Try to perform action on a field', function () { - const field = this.fieldBlock1.inputList[0].fieldRow[0]; - const astNode = Blockly.ASTNode.createFieldNode(field); - const mockEvent = createKeyDownEvent(Blockly.utils.KeyCodes.ENTER, ''); - this.workspace.getCursor().setCurNode(astNode); - const keyDownSpy = sinon.spy( - Blockly.ShortcutRegistry.registry, - 'onKeyDown', - ); - - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); - - chai.assert.isTrue(keyDownSpy.returned(false)); - }); - }); - }); - suite('Insert Functions', function () { - setup(function () { - Blockly.defineBlocksWithJsonArray([ - { - type: 'basic_block', - message0: '%1', - args0: [ - { - type: 'field_input', - name: 'TEXTFIELD', - text: 'test', - }, - ], - previousStatement: null, - nextStatement: null, - }, - ]); - - this.workspace = createNavigationWorkspace(this.navigation, true); - - const basicBlock = this.workspace.newBlock('basic_block'); - const basicBlock2 = this.workspace.newBlock('basic_block'); - - this.basicBlock = basicBlock; - this.basicBlock2 = basicBlock2; - }); - - teardown(function () { - this.navigation.removeWorkspace(this.workspace); - this.workspace.dispose(); - sinon.restore(); - delete Blockly.Blocks['basic_block']; - }); - - test('Insert from flyout with a valid connection marked', function () { - const previousConnection = this.basicBlock.previousConnection; - const prevNode = Blockly.ASTNode.createConnectionNode(previousConnection); - this.workspace - .getMarker(this.navigation.MARKER_NAME) - .setCurNode(prevNode); - - this.navigation.focusToolbox(this.workspace); - this.navigation.focusFlyout(this.workspace); - this.navigation.insertFromFlyout(this.workspace); - - const insertedBlock = this.basicBlock.previousConnection.targetBlock(); - - chai.assert.isTrue(insertedBlock !== null); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.WORKSPACE, - ); - }); - - test('Insert Block from flyout without marking a connection', function () { - this.navigation.focusToolbox(this.workspace); - this.navigation.focusFlyout(this.workspace); - this.navigation.insertFromFlyout(this.workspace); - - const numBlocks = this.workspace.getTopBlocks().length; - - // Make sure the block was not connected to anything - chai.assert.isNull(this.basicBlock.previousConnection.targetConnection); - chai.assert.isNull(this.basicBlock.nextConnection.targetConnection); - - // Make sure that the block was added to the workspace - chai.assert.equal(numBlocks, 3); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.WORKSPACE, - ); - }); - - test('Connect two blocks that are on the workspace', function () { - const targetNode = Blockly.ASTNode.createConnectionNode( - this.basicBlock.previousConnection, - ); - const sourceNode = Blockly.ASTNode.createConnectionNode( - this.basicBlock2.nextConnection, - ); - - this.navigation.tryToConnectMarkerAndCursor( - this.workspace, - targetNode, - sourceNode, - ); - const insertedBlock = this.basicBlock.previousConnection.targetBlock(); - - chai.assert.isNotNull(insertedBlock); - }); - }); - suite('Connect Blocks', function () { - setup(function () { - Blockly.defineBlocksWithJsonArray([ - { - type: 'basic_block', - message0: '', - previousStatement: null, - nextStatement: null, - }, - { - type: 'inline_block', - message0: '%1 %2', - args0: [ - { - type: 'input_value', - name: 'NAME', - }, - { - type: 'input_value', - name: 'NAME', - }, - ], - inputsInline: true, - output: null, - tooltip: '', - helpUrl: '', - }, - ]); - - this.workspace = createNavigationWorkspace(this.navigation, true); - - const basicBlock = this.workspace.newBlock('basic_block'); - const basicBlock2 = this.workspace.newBlock('basic_block'); - const basicBlock3 = this.workspace.newBlock('basic_block'); - const basicBlock4 = this.workspace.newBlock('basic_block'); - - const inlineBlock1 = this.workspace.newBlock('inline_block'); - const inlineBlock2 = this.workspace.newBlock('inline_block'); - const inlineBlock3 = this.workspace.newBlock('inline_block'); - - this.basicBlock = basicBlock; - this.basicBlock2 = basicBlock2; - this.basicBlock3 = basicBlock3; - this.basicBlock4 = basicBlock4; - - this.inlineBlock1 = inlineBlock1; - this.inlineBlock2 = inlineBlock2; - this.inlineBlock3 = inlineBlock3; - - this.basicBlock.nextConnection.connect( - this.basicBlock2.previousConnection, - ); - - this.basicBlock3.nextConnection.connect( - this.basicBlock4.previousConnection, - ); - - this.inlineBlock1.inputList[0].connection.connect( - this.inlineBlock2.outputConnection, - ); - }); - - teardown(function () { - this.navigation.removeWorkspace(this.workspace); - this.workspace.dispose(); - sinon.restore(); - delete Blockly.Blocks['basic_block']; - delete Blockly.Blocks['inline_block']; - }); - - test('Connect cursor on previous into stack', function () { - const markedLocation = this.basicBlock2.previousConnection; - const cursorLocation = this.basicBlock3.previousConnection; - - this.navigation.connect(cursorLocation, markedLocation); - - chai.assert.equal( - this.basicBlock.nextConnection.targetBlock(), - this.basicBlock3, - ); - chai.assert.equal( - this.basicBlock2.previousConnection.targetBlock(), - this.basicBlock4, - ); - }); - - test('Connect marker on previous into stack', function () { - const markedLocation = this.basicBlock3.previousConnection; - const cursorLocation = this.basicBlock2.previousConnection; - - this.navigation.connect(cursorLocation, markedLocation); - - chai.assert.equal( - this.basicBlock.nextConnection.targetBlock(), - this.basicBlock3, - ); - chai.assert.equal( - this.basicBlock2.previousConnection.targetBlock(), - this.basicBlock4, - ); - }); - - test('Connect cursor on next into stack', function () { - const markedLocation = this.basicBlock2.previousConnection; - const cursorLocation = this.basicBlock4.nextConnection; - - this.navigation.connect(cursorLocation, markedLocation); - - chai.assert.equal( - this.basicBlock.nextConnection.targetBlock(), - this.basicBlock4, - ); - chai.assert.isNull(this.basicBlock3.nextConnection.targetConnection); - }); - - test('Connect cursor with parents', function () { - const markedLocation = this.basicBlock3.previousConnection; - const cursorLocation = this.basicBlock2.nextConnection; - - this.navigation.connect(cursorLocation, markedLocation); - - chai.assert.equal( - this.basicBlock3.previousConnection.targetBlock(), - this.basicBlock2, - ); - }); - - test('Try to connect input that is descendant of output', function () { - const markedLocation = this.inlineBlock2.inputList[0].connection; - const cursorLocation = this.inlineBlock1.outputConnection; - - this.navigation.connect(cursorLocation, markedLocation); - - chai.assert.isNull(this.inlineBlock2.outputConnection.targetBlock()); - chai.assert.equal( - this.inlineBlock1.outputConnection.targetBlock(), - this.inlineBlock2, - ); - }); - test.skip('Do not connect a shadow block', function () { - // TODO(https://github.com/google/blockly-samples/issues/538): Update - // tests after this bug is fixed. - this.inlineBlock2.setShadow(true); - - const markedLocation = this.inlineBlock2.outputConnection; - const cursorLocation = this.inlineBlock3.inputList[0].connection; - const didConnect = this.navigation.connect( - cursorLocation, - markedLocation, - ); - chai.assert.isFalse(didConnect); - chai.assert.isNull(this.inlineBlock2.outputConnection.targetBlock()); - chai.assert.equal( - this.inlineBlock1.outputConnection.targetBlock(), - this.inlineBlock2, - ); - }); - }); - - suite('Test cursor move on block delete', function () { - setup(function () { - Blockly.defineBlocksWithJsonArray([ - { - type: 'basic_block', - message0: '', - previousStatement: null, - nextStatement: null, - }, - ]); - this.workspace = createNavigationWorkspace(this.navigation, true); - - this.basicBlockA = this.workspace.newBlock('basic_block'); - this.basicBlockB = this.workspace.newBlock('basic_block'); - }); - - teardown(function () { - this.navigation.removeWorkspace(this.workspace); - this.workspace.dispose(); - sinon.restore(); - delete Blockly.Blocks['basic_block']; - }); - - test('Delete block - has parent ', function () { - this.basicBlockA.nextConnection.connect( - this.basicBlockB.previousConnection, - ); - const astNode = Blockly.ASTNode.createBlockNode(this.basicBlockB); - // Set the cursor to be on the child block - this.workspace.getCursor().setCurNode(astNode); - // Remove the child block - const mockEvent = createKeyDownEvent(Blockly.utils.KeyCodes.DELETE, ''); - - // Actions that happen when a block is deleted were causing problems. - // Since this is not what we are trying to test and does not effect the - // feature, disable events. - Blockly.Events.disable(); - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); - Blockly.Events.enable(); - - chai.assert.equal( - this.workspace.getCursor().getCurNode().getType(), - Blockly.ASTNode.types.NEXT, - ); - }); - - test('Delete block - no parent ', function () { - const astNode = Blockly.ASTNode.createBlockNode(this.basicBlockB); - this.workspace.getCursor().setCurNode(astNode); - - const mockEvent = createKeyDownEvent(Blockly.utils.KeyCodes.DELETE, ''); - - // Actions that happen when a block is deleted were causing problems. - // Since this is not what we are trying to test and does not effect the - // feature, disable events. - Blockly.Events.disable(); - Blockly.ShortcutRegistry.registry.onKeyDown(this.workspace, mockEvent); - Blockly.Events.enable(); - - chai.assert.equal( - this.workspace.getCursor().getCurNode().getType(), - Blockly.ASTNode.types.WORKSPACE, - ); - }); - - test('Delete parent block', function () { - this.basicBlockA.nextConnection.connect( - this.basicBlockB.previousConnection, - ); - const astNode = Blockly.ASTNode.createBlockNode(this.basicBlockB); - const mockDeleteBlockEvent = { - blockId: this.basicBlockA, - ids: [this.basicBlockA.id, this.basicBlockB.id], - }; - // Set the cursor to be on the child block - this.workspace.getCursor().setCurNode(astNode); - // Remove the parent block - this.navigation.handleBlockDeleteByDrag( - this.workspace, - mockDeleteBlockEvent, - ); - chai.assert.equal( - this.workspace.getCursor().getCurNode().getType(), - Blockly.ASTNode.types.WORKSPACE, - ); - }); - - test('Delete top block in stack', function () { - this.basicBlockA.nextConnection.connect( - this.basicBlockB.previousConnection, - ); - const astNode = Blockly.ASTNode.createStackNode(this.basicBlockA); - const mockDeleteBlockEvent = { - blockId: this.basicBlockA.id, - ids: [this.basicBlockA.id, this.basicBlockB.id], - }; - // Set the cursor to be on the stack - this.workspace.getCursor().setCurNode(astNode); - // Remove the top block in the stack - this.navigation.handleBlockDeleteByDrag( - this.workspace, - mockDeleteBlockEvent, - ); - chai.assert.equal( - this.workspace.getCursor().getCurNode().getType(), - Blockly.ASTNode.types.WORKSPACE, - ); - }); - }); - - suite('Test workspace listener', function () { - setup(function () { - Blockly.defineBlocksWithJsonArray([ - { - type: 'basic_block', - message0: '%1', - args0: [ - { - type: 'field_input', - name: 'TEXTFIELD', - text: 'test', - }, - ], - previousStatement: null, - nextStatement: null, - }, - ]); - this.workspace = createNavigationWorkspace(this.navigation, true); - this.workspaceChangeListener = this.navigation.wsChangeWrapper; - this.basicBlockA = this.workspace.newBlock('basic_block'); - }); - - teardown(function () { - this.navigation.removeWorkspace(this.workspace); - this.workspace.dispose(); - delete Blockly.Blocks['basic_block']; - sinon.restore(); - }); - - test('Handle block mutation', function () { - const e = { - type: Blockly.Events.BLOCK_CHANGE, - element: 'mutation', - blockId: this.basicBlockA.id, - workspaceId: this.workspace.id, - }; - const cursor = this.workspace.getCursor(); - const nextNode = Blockly.ASTNode.createConnectionNode( - this.basicBlockA.nextConnection, - ); - cursor.setCurNode(nextNode); - this.workspaceChangeListener(e); - chai.assert.equal( - cursor.getCurNode().getType(), - Blockly.ASTNode.types.BLOCK, - ); - }); - test('Handle workspace click', function () { - const e = { - type: Blockly.Events.CLICK, - workspaceId: this.workspace.id, - }; - this.navigation.focusFlyout(this.workspace); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.FLYOUT, - ); - - this.workspaceChangeListener(e); - - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.WORKSPACE, - ); - }); - test('Focus toolbox if category clicked', function () { - const e = { - type: Blockly.Events.TOOLBOX_ITEM_SELECT, - workspaceId: this.workspace.id, - newItem: true, - }; - const toolboxFocusStub = sinon.spy(this.navigation, 'focusToolbox'); - - this.navigation.focusWorkspace(this.workspace); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.WORKSPACE, - ); - - this.workspaceChangeListener(e); - - sinon.assert.calledOnce(toolboxFocusStub); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.TOOLBOX, - ); - }); - test('Focus workspace if toolbox is unselected', function () { - const e = { - type: Blockly.Events.TOOLBOX_ITEM_SELECT, - workspaceId: this.workspace.id, - newItem: false, - }; - const resetFlyoutStub = sinon.spy(this.navigation, 'resetFlyout'); - this.navigation.setState(this.workspace, Constants.STATE.TOOLBOX); - - this.workspaceChangeListener(e); - - sinon.assert.calledOnce(resetFlyoutStub); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.WORKSPACE, - ); - }); - test('Focus workspace when block created on workspace', function () { - const e = { - type: Blockly.Events.BLOCK_CREATE, - workspaceId: this.workspace.id, - }; - const resetFlyoutStub = sinon.spy(this.navigation, 'resetFlyout'); - // Only works when someone is in the flyout. - this.navigation.setState(this.workspace, Constants.STATE.FLYOUT); - - this.workspaceChangeListener(e); - - sinon.assert.calledOnce(resetFlyoutStub); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.WORKSPACE, - ); - }); - }); - - suite('Test simple flyout listener', function () { - setup(function () { - Blockly.defineBlocksWithJsonArray([ - { - type: 'basic_block', - message0: '%1', - args0: [ - { - type: 'field_input', - name: 'TEXTFIELD', - text: 'test', - }, - ], - }, - ]); - this.workspace = createNavigationWorkspace(this.navigation, true); - this.flyoutChangeListener = this.navigation.flyoutChangeWrapper; - this.basicBlockA = this.workspace.newBlock('basic_block'); - - this.navigation.focusToolbox(this.workspace); - this.workspace.getFlyout().autoClose = false; - }); - - teardown(function () { - delete Blockly.Blocks['basic_block']; - this.navigation.removeWorkspace(this.workspace); - this.workspace.dispose(); - sinon.restore(); - }); - test('Handle block click in flyout - click event', function () { - const flyout = this.workspace.getFlyout(); - const flyoutWorkspace = flyout.getWorkspace(); - const firstFlyoutBlock = flyoutWorkspace.getTopBlocks()[0]; - const e = { - type: Blockly.Events.CLICK, - workspaceId: flyoutWorkspace.id, - targetType: 'block', - blockId: firstFlyoutBlock.id, - }; - const flyoutCursor = flyoutWorkspace.getCursor(); - this.navigation.focusWorkspace(this.workspace); - - this.flyoutChangeListener(e); - - chai.assert.equal( - flyoutCursor.getCurNode().getType(), - Blockly.ASTNode.types.STACK, - ); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.FLYOUT, - ); - }); - test('Handle block click in flyout - select event', function () { - const flyout = this.workspace.getFlyout(); - const flyoutWorkspace = flyout.getWorkspace(); - const firstFlyoutBlock = flyoutWorkspace.getTopBlocks()[0]; - const e = { - type: Blockly.Events.SELECTED, - workspaceId: flyoutWorkspace.id, - newElementId: firstFlyoutBlock.id, - }; - const flyoutCursor = flyoutWorkspace.getCursor(); - this.navigation.focusWorkspace(this.workspace); - - this.flyoutChangeListener(e); - - chai.assert.equal( - flyoutCursor.getCurNode().getType(), - Blockly.ASTNode.types.STACK, - ); - chai.assert.equal( - this.navigation.getState(this.workspace), - Constants.STATE.FLYOUT, - ); - }); - }); - - suite('Test clean up methods', function () { - setup(function () { - this.workspace = createNavigationWorkspace(this.navigation, true); - }); - test('All listeners and markers removed', function () { - const numListeners = this.workspace.listeners.length; - const markerName = this.navigation.MARKER_NAME; - this.navigation.removeWorkspace(this.workspace); - chai.assert.equal(this.workspace.listeners.length, numListeners - 1); - - const marker = this.workspace.getMarkerManager().getMarker(markerName); - chai.assert.isNull(marker); - }); - test('Keyboard accessibility mode can not be enabled', function () { - this.navigation.removeWorkspace(this.workspace); - this.navigation.enableKeyboardAccessibility(this.workspace); - chai.assert.isFalse(this.workspace.keyboardAccessibilityMode); - }); - test('Dispose', function () { - const numListeners = this.workspace.listeners.length; - const flyout = this.workspace.getFlyout(); - const numFlyoutListeners = flyout.getWorkspace().listeners.length; - this.navigation.dispose(); - chai.assert.equal(this.workspace.listeners.length, numListeners - 1); - chai.assert.equal( - flyout.getWorkspace().listeners.length, - numFlyoutListeners - 1, - ); - }); - }); -}); diff --git a/plugins/keyboard-navigation/test/shortcuts_test.mocha.js b/plugins/keyboard-navigation/test/shortcuts_test.mocha.js deleted file mode 100644 index 4e19095210..0000000000 --- a/plugins/keyboard-navigation/test/shortcuts_test.mocha.js +++ /dev/null @@ -1,531 +0,0 @@ -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -const sinon = require('sinon'); -const chai = require('chai'); - -const Blockly = require('blockly'); - -const {NavigationController} = require('../src/index'); -const { - createNavigationWorkspace, - createKeyDownEvent, -} = require('./test_helper'); - -suite('Shortcut Tests', function () { - setup(function () { - this.jsdomCleanup = require('jsdom-global')( - '
', - ); - // We are running these tests in node even thought they require a rendered - // workspace, which doesn't exactly work. The rendering system expects - // cancelAnimationFrame to be defined so we need to define it. - window.cancelAnimationFrame = function () {}; - - Blockly.utils.dom.getFastTextWidthWithSizeString = function () { - return 10; - }; - Blockly.defineBlocksWithJsonArray([ - { - type: 'basic_block', - message0: '', - previousStatement: null, - nextStatement: null, - }, - ]); - this.controller = new NavigationController(); - this.controller.init(); - this.navigation = this.controller.navigation; - this.workspace = createNavigationWorkspace(this.navigation, true); - this.controller.addWorkspace(this.workspace); - this.basicBlock = this.workspace.newBlock('basic_block'); - }); - - teardown(function () { - window.cancelAnimationFrame = undefined; - this.controller.dispose(); - this.workspace.dispose(); - this.jsdomCleanup(); - delete Blockly.Blocks['basic_block']; - }); - - suite('Deleting blocks', function () { - setup(function () { - const blockNode = Blockly.ASTNode.createBlockNode(this.basicBlock); - this.workspace.getCursor().setCurNode(blockNode); - }); - - teardown(function () { - sinon.restore(); - }); - - const testCases = [ - { - name: 'Delete', - deleteEvent: createKeyDownEvent( - Blockly.utils.KeyCodes.DELETE, - 'NotAField', - ), - }, - { - name: 'Backspace', - deleteEvent: createKeyDownEvent( - Blockly.utils.KeyCodes.BACKSPACE, - 'NotAField', - ), - }, - ]; - - suite('delete keybinds trigger deletion', function () { - testCases.forEach(function (testCase) { - test(testCase.name, function () { - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.deleteEvent, - ); - chai.assert.equal( - this.workspace.getTopBlocks().length, - 0, - 'Expected the block to be deleted.', - ); - }); - }); - }); - - suite( - 'delete keybinds do not trigger deletion if workspace is readonly', - function () { - testCases.forEach(function (testCase) { - test(testCase.name, function () { - this.workspace.options.readOnly = true; - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.deleteEvent, - ); - chai.assert.equal( - this.workspace.getTopBlocks().length, - 1, - 'Expected the block to not be deleted.', - ); - }); - }); - }, - ); - }); - - suite('Copy and paste', function () { - teardown(function () { - sinon.restore(); - }); - const testCases = [ - { - name: 'Control', - copyEvent: createKeyDownEvent(Blockly.utils.KeyCodes.C, 'NotAField', [ - Blockly.utils.KeyCodes.CTRL, - ]), - pasteEvent: createKeyDownEvent(Blockly.utils.KeyCodes.V, 'NotAField', [ - Blockly.utils.KeyCodes.CTRL, - ]), - }, - { - name: 'Meta', - copyEvent: createKeyDownEvent(Blockly.utils.KeyCodes.C, 'NotAField', [ - Blockly.utils.KeyCodes.META, - ]), - pasteEvent: createKeyDownEvent(Blockly.utils.KeyCodes.V, 'NotAField', [ - Blockly.utils.KeyCodes.META, - ]), - }, - { - name: 'Alt', - copyEvent: createKeyDownEvent(Blockly.utils.KeyCodes.C, 'NotAField', [ - Blockly.utils.KeyCodes.ALT, - ]), - pasteEvent: createKeyDownEvent(Blockly.utils.KeyCodes.V, 'NotAField', [ - Blockly.utils.KeyCodes.ALT, - ]), - }, - ]; - - suite('copy and paste keybinds duplicate blocks', function () { - setup(function () { - const blockNode = Blockly.ASTNode.createBlockNode(this.basicBlock); - this.workspace.getCursor().setCurNode(blockNode); - }); - - testCases.forEach(function (testCase) { - test(testCase.name, function () { - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.copyEvent, - ); - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.pasteEvent, - ); - chai.assert.equal( - this.workspace.getTopBlocks().length, - 2, - 'Expected the block to be duplicated.', - ); - }); - }); - }); - - suite( - 'copy and paste does nothing if the cursor is not on a block', - function () { - setup(function () { - const workspaceNode = Blockly.ASTNode.createWorkspaceNode( - this.workspace, - new Blockly.utils.Coordinate(100, 100), - ); - this.workspace.getCursor().setCurNode(workspaceNode); - }); - testCases.forEach(function (testCase) { - test(testCase.name, function () { - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.copyEvent, - ); - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.pasteEvent, - ); - chai.assert.equal( - this.workspace.getTopBlocks().length, - 1, - 'Expected the block to not be duplicated.', - ); - }); - }); - }, - ); - - suite( - 'copy and paste do nothing if the cursor is on a shadow block', - function () { - setup(function () { - this.basicBlock.setShadow(true); - const blockNode = Blockly.ASTNode.createBlockNode(this.basicBlock); - this.workspace.getCursor().setCurNode(blockNode); - }); - testCases.forEach(function (testCase) { - test(testCase.name, function () { - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.copyEvent, - ); - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.pasteEvent, - ); - chai.assert.equal( - this.workspace.getTopBlocks().length, - 1, - 'Expected the block to not be duplicated.', - ); - }); - }); - }, - ); - - suite( - 'copy and paste do nothing if the workspace is readonly', - function () { - setup(function () { - this.workspace.options.readonly = true; - }); - testCases.forEach(function (testCase) { - test(testCase.name, function () { - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.copyEvent, - ); - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.pasteEvent, - ); - chai.assert.equal( - this.workspace.getTopBlocks().length, - 1, - 'Expected the block to not be duplicated.', - ); - }); - }); - }, - ); - - suite('copy and paste do nothing if a gesture is in progress', function () { - setup(function () { - sinon.stub(Blockly.Gesture, 'inProgress').returns(true); - }); - testCases.forEach(function (testCase) { - test(testCase.name, function () { - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.copyEvent, - ); - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.pasteEvent, - ); - chai.assert.equal( - this.workspace.getTopBlocks().length, - 1, - 'Expected the block to not be duplicated.', - ); - }); - }); - }); - - suite( - 'copy and paste do nothing if the block is not deletable', - function () { - setup(function () { - this.basicBlock.setDeletable(false); - }); - testCases.forEach(function (testCase) { - test(testCase.name, function () { - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.copyEvent, - ); - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.pasteEvent, - ); - chai.assert.equal( - this.workspace.getTopBlocks().length, - 1, - 'Expected the block to not be duplicated.', - ); - }); - }); - }, - ); - }); - - suite('Cut and paste', function () { - teardown(function () { - sinon.restore(); - }); - const testCases = [ - { - name: 'Control', - cutEvent: createKeyDownEvent(Blockly.utils.KeyCodes.X, 'NotAField', [ - Blockly.utils.KeyCodes.CTRL, - ]), - pasteEvent: createKeyDownEvent(Blockly.utils.KeyCodes.V, 'NotAField', [ - Blockly.utils.KeyCodes.CTRL, - ]), - }, - { - name: 'Meta', - cutEvent: createKeyDownEvent(Blockly.utils.KeyCodes.X, 'NotAField', [ - Blockly.utils.KeyCodes.META, - ]), - pasteEvent: createKeyDownEvent(Blockly.utils.KeyCodes.V, 'NotAField', [ - Blockly.utils.KeyCodes.META, - ]), - }, - { - name: 'Alt', - cutEvent: createKeyDownEvent(Blockly.utils.KeyCodes.X, 'NotAField', [ - Blockly.utils.KeyCodes.ALT, - ]), - pasteEvent: createKeyDownEvent(Blockly.utils.KeyCodes.V, 'NotAField', [ - Blockly.utils.KeyCodes.ALT, - ]), - }, - ]; - - suite('cut and paste keybinds duplicate blocks', function () { - setup(function () { - const blockNode = Blockly.ASTNode.createBlockNode(this.basicBlock); - this.workspace.getCursor().setCurNode(blockNode); - }); - - testCases.forEach(function (testCase) { - test(testCase.name, function () { - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.cutEvent, - ); - chai.assert.equal( - this.workspace.getTopBlocks().length, - 0, - 'Expected the block to be deleted.', - ); - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.pasteEvent, - ); - chai.assert.equal( - this.workspace.getTopBlocks().length, - 1, - 'Expected the block to be duplicated.', - ); - }); - }); - }); - - suite( - 'cut and paste does nothing if the cursor is not on a block', - function () { - setup(function () { - const workspaceNode = Blockly.ASTNode.createWorkspaceNode( - this.workspace, - new Blockly.utils.Coordinate(100, 100), - ); - this.workspace.getCursor().setCurNode(workspaceNode); - }); - testCases.forEach(function (testCase) { - test(testCase.name, function () { - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.cutEvent, - ); - chai.assert.equal( - this.workspace.getTopBlocks().length, - 1, - 'Expected the block to not be deleted.', - ); - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.pasteEvent, - ); - chai.assert.equal( - this.workspace.getTopBlocks().length, - 1, - 'Expected the block to not be duplicated.', - ); - }); - }); - }, - ); - - suite( - 'cut and paste do nothing if the cursor is on a shadow block', - function () { - setup(function () { - this.basicBlock.setShadow(true); - const blockNode = Blockly.ASTNode.createBlockNode(this.basicBlock); - this.workspace.getCursor().setCurNode(blockNode); - }); - testCases.forEach(function (testCase) { - test(testCase.name, function () { - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.cutEvent, - ); - chai.assert.equal( - this.workspace.getTopBlocks().length, - 1, - 'Expected the block to not be deleted.', - ); - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.pasteEvent, - ); - chai.assert.equal( - this.workspace.getTopBlocks().length, - 1, - 'Expected the block to not be duplicated.', - ); - }); - }); - }, - ); - - suite('cut and paste do nothing if the workspace is readonly', function () { - setup(function () { - this.workspace.options.readonly = true; - }); - testCases.forEach(function (testCase) { - test(testCase.name, function () { - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.cutEvent, - ); - chai.assert.equal( - this.workspace.getTopBlocks().length, - 1, - 'Expected the block to not be deleted.', - ); - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.pasteEvent, - ); - chai.assert.equal( - this.workspace.getTopBlocks().length, - 1, - 'Expected the block to not be duplicated.', - ); - }); - }); - }); - - suite('cut and paste do nothing if a gesture is in progress', function () { - setup(function () { - sinon.stub(Blockly.Gesture, 'inProgress').returns(true); - }); - testCases.forEach(function (testCase) { - test(testCase.name, function () { - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.cutEvent, - ); - chai.assert.equal( - this.workspace.getTopBlocks().length, - 1, - 'Expected the block to not be deleted.', - ); - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.pasteEvent, - ); - chai.assert.equal( - this.workspace.getTopBlocks().length, - 1, - 'Expected the block to not be duplicated.', - ); - }); - }); - }); - - suite( - 'cut and paste do nothing if the block is not deletable', - function () { - setup(function () { - this.basicBlock.setDeletable(false); - }); - testCases.forEach(function (testCase) { - test(testCase.name, function () { - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.cutEvent, - ); - chai.assert.equal( - this.workspace.getTopBlocks().length, - 1, - 'Expected the block to not be deleted.', - ); - Blockly.ShortcutRegistry.registry.onKeyDown( - this.workspace, - testCase.pasteEvent, - ); - chai.assert.equal( - this.workspace.getTopBlocks().length, - 1, - 'Expected the block to not be duplicated.', - ); - }); - }); - }, - ); - }); -}); diff --git a/plugins/keyboard-navigation/test/test_helper.js b/plugins/keyboard-navigation/test/test_helper.js deleted file mode 100644 index 99abcb5fb3..0000000000 --- a/plugins/keyboard-navigation/test/test_helper.js +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -const {Constants} = require('../src/index'); -const {Navigation} = require('../src/index'); -const Blockly = require('blockly/core'); - -/** - * Creates a workspace for testing keyboard navigation. - * @param {Navigation} navigation Object holding navigation classes. - * @param {boolean} enableKeyboardNav True to enable keyboard navigation, false - * otherwise. - * @param {boolean} readOnly True for a read only workspace, false otherwise. - * @returns {Blockly.WorkspaceSvg} The created workspace. - */ -export function createNavigationWorkspace( - navigation, - enableKeyboardNav, - readOnly, -) { - const workspace = Blockly.inject('blocklyDiv', { - toolbox: ` - - `, - readOnly: readOnly, - }); - if (enableKeyboardNav) { - navigation.addWorkspace(workspace); - navigation.enableKeyboardAccessibility(workspace); - navigation.setState(workspace, Constants.STATE.WORKSPACE); - } - return workspace; -} - -/** - * Creates a key down event used for testing. - * @param {number} keyCode The keycode for the event. Use Blockly.utils.KeyCodes - * enum. - * @param {string} type The type of the target. This only matters for the - * Blockly.utils.isTargetInput method. - * @param {?Array} modifiers A list of modifiers. Use - * Blockly.utils.KeyCodes enum. - * @returns {Object} The mocked keydown - * event. - */ -export function createKeyDownEvent(keyCode, type, modifiers) { - const event = { - keyCode: keyCode, - target: {type: type}, - getModifierState: function (name) { - if (name == 'Shift' && this.shiftKey) { - return true; - } else if (name == 'Control' && this.ctrlKey) { - return true; - } else if (name == 'Meta' && this.metaKey) { - return true; - } else if (name == 'Alt' && this.altKey) { - return true; - } - return false; - }, - preventDefault: function () {}, - }; - if (modifiers && modifiers.length) { - event.altKey = modifiers.includes(Blockly.utils.KeyCodes.ALT); - event.ctrlKey = modifiers.includes(Blockly.utils.KeyCodes.CTRL); - event.metaKey = modifiers.includes(Blockly.utils.KeyCodes.META); - event.shiftKey = modifiers.includes(Blockly.utils.KeyCodes.SHIFT); - } - return event; -} diff --git a/plugins/keyboard-navigation/test/toolbox.js b/plugins/keyboard-navigation/test/toolbox.js deleted file mode 100644 index 95dd4ff7bd..0000000000 --- a/plugins/keyboard-navigation/test/toolbox.js +++ /dev/null @@ -1,218 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview A custom toolbox for the plugin test. - */ - -export const toolbox = { - kind: 'categoryToolbox', - contents: [ - { - kind: 'category', - name: 'Logic', - categorystyle: 'logic_category', - contents: [ - { - type: 'controls_if', - kind: 'block', - }, - { - type: 'logic_compare', - kind: 'block', - fields: { - OP: 'EQ', - }, - }, - { - type: 'logic_operation', - kind: 'block', - fields: { - OP: 'AND', - }, - }, - ], - }, - { - kind: 'category', - name: 'Loops', - categorystyle: 'loop_category', - contents: [ - { - type: 'controls_repeat_ext', - kind: 'block', - inputs: { - TIMES: { - shadow: { - type: 'math_number', - fields: { - NUM: 10, - }, - }, - }, - }, - }, - { - type: 'controls_repeat', - kind: 'block', - enabled: false, - fields: { - TIMES: 10, - }, - }, - { - type: 'controls_whileUntil', - kind: 'block', - fields: { - MODE: 'WHILE', - }, - }, - { - type: 'controls_for', - kind: 'block', - fields: { - VAR: { - name: 'i', - }, - }, - inputs: { - FROM: { - shadow: { - type: 'math_number', - fields: { - NUM: 1, - }, - }, - }, - TO: { - shadow: { - type: 'math_number', - fields: { - NUM: 10, - }, - }, - }, - BY: { - shadow: { - type: 'math_number', - fields: { - NUM: 1, - }, - }, - }, - }, - }, - { - type: 'controls_forEach', - kind: 'block', - fields: { - VAR: { - name: 'j', - }, - }, - }, - { - type: 'controls_flow_statements', - kind: 'block', - enabled: false, - fields: { - FLOW: 'BREAK', - }, - }, - ], - }, - { - kind: 'sep', - }, - { - kind: 'category', - name: 'Variables', - custom: 'VARIABLE', - categorystyle: 'variable_category', - }, - { - kind: 'category', - name: 'Buttons and Blocks', - categorystyle: 'loop_category', - contents: [ - { - type: 'controls_repeat', - kind: 'block', - fields: { - TIMES: 10, - }, - }, - { - kind: 'BUTTON', - text: 'Randomize Button Style', - callbackkey: 'setRandomStyle', - }, - { - kind: 'BUTTON', - text: 'Randomize Button Style', - callbackkey: 'setRandomStyle', - }, - { - type: 'controls_repeat', - kind: 'block', - fields: { - TIMES: 10, - }, - }, - { - kind: 'BUTTON', - text: 'Randomize Button Style', - callbackkey: 'setRandomStyle', - }, - ], - }, - { - kind: 'sep', - }, - { - kind: 'category', - name: 'Nested Categories', - contents: [ - { - kind: 'category', - name: 'sub-category 1', - contents: [ - { - kind: 'BUTTON', - text: 'Randomize Button Style', - callbackkey: 'setRandomStyle', - }, - { - type: 'logic_boolean', - kind: 'block', - fields: { - BOOL: 'TRUE', - }, - }, - ], - }, - { - kind: 'category', - name: 'sub-category 2', - contents: [ - { - type: 'logic_boolean', - kind: 'block', - fields: { - BOOL: 'FALSE', - }, - }, - { - kind: 'BUTTON', - text: 'Randomize Button Style', - callbackkey: 'setRandomStyle', - }, - ], - }, - ], - }, - ], -}; diff --git a/plugins/migration/CHANGELOG.md b/plugins/migration/CHANGELOG.md index d9a8438d55..33a5d899d8 100644 --- a/plugins/migration/CHANGELOG.md +++ b/plugins/migration/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [3.0.3](https://github.com/google/blockly-samples/compare/@blockly/migrate@3.0.2...@blockly/migrate@3.0.3) (2025-03-13) + +**Note:** Version bump only for package @blockly/migrate + + + + + ## [3.0.2](https://github.com/google/blockly-samples/compare/@blockly/migrate@3.0.1...@blockly/migrate@3.0.2) (2024-08-08) diff --git a/plugins/migration/bin/fix-imports.js b/plugins/migration/bin/fix-imports.js index abaa79bee7..642767c715 100644 --- a/plugins/migration/bin/fix-imports.js +++ b/plugins/migration/bin/fix-imports.js @@ -99,6 +99,13 @@ const database = [ newImport: `import * as libraryBlocks from 'blockly/blocks';`, newRequire: `const libraryBlocks = require('blockly/blocks');`, }, + { + import: 'blockly', + oldIdentifier: 'Blockly', + newIdentifier: 'Blockly', // no-op + newImport: `import * as Blockly from 'blockly';`, + newRequire: `const Blockly = require('blockly');`, // no-op + }, ]; /** @@ -125,9 +132,18 @@ function migrateContents(contents) { */ function fixImport(contents, migrationData) { const identifier = getIdentifier(contents, migrationData); + // Don't need to run if there are no references. if (!identifier) return contents; - const newContents = replaceReferences(contents, migrationData, identifier); - if (newContents !== contents) return addImport(newContents, migrationData); + // If the identifier changed, update all references to it and the import + if (migrationData.oldIdentifier !== migrationData.newIdentifier) { + const newContents = replaceReferences(contents, migrationData, identifier); + if (newContents !== contents) { + return addImport(newContents, migrationData); + } + } else { + // Just the import changed + return addImport(contents, migrationData); + } return contents; } diff --git a/plugins/migration/package-lock.json b/plugins/migration/package-lock.json index 24f0cfaea3..a485ded8aa 100644 --- a/plugins/migration/package-lock.json +++ b/plugins/migration/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/migrate", - "version": "3.0.2", + "version": "3.0.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/migrate", - "version": "3.0.2", + "version": "3.0.3", "license": "Apache-2.0", "dependencies": { "chalk": "^5.0.1", @@ -2062,4 +2062,4 @@ "dev": true } } -} +} \ No newline at end of file diff --git a/plugins/migration/package.json b/plugins/migration/package.json index 4f93c81182..d752897ff0 100644 --- a/plugins/migration/package.json +++ b/plugins/migration/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/migrate", - "version": "3.0.2", + "version": "3.0.3", "description": "A collection of tools that help with migrating apps using Blockly to new versions of BLockly.", "bin": "./bin/migrate.js", "author": "Blockly Team", diff --git a/plugins/migration/test/manual-test-data/fix-imports/import.txt b/plugins/migration/test/manual-test-data/fix-imports/import.js similarity index 85% rename from plugins/migration/test/manual-test-data/fix-imports/import.txt rename to plugins/migration/test/manual-test-data/fix-imports/import.js index 4344593a55..721272e09e 100644 --- a/plugins/migration/test/manual-test-data/fix-imports/import.txt +++ b/plugins/migration/test/manual-test-data/fix-imports/import.js @@ -1,11 +1,11 @@ // Manual test data for the renamings migration. // Run using: -// node ./bin/migrate fix-imports --from ./test/manual-test-data/fix-imports/import.txt +// node ./bin/migrate fix-imports --from ./test/manual-test-data/fix-imports/import.js import Blockly from 'blockly'; -import * as BlocklyDart from "blockly/dart"; +import * as BlocklyDart from 'blockly/dart'; import * as BlocklyLua from 'blockly/lua'; -import * as BlocklyPhp from "blockly/php"; +import * as BlocklyPhp from 'blockly/php'; import * as BlocklyPython from 'blockly/python'; Blockly.JavaScript.something; @@ -31,3 +31,5 @@ Some.Other.identifer; Blockly.libraryBlocks.something; const something = Blockly.libraryBlocks.something; Some.Other.identifer; + +Blockly.zelos; diff --git a/plugins/migration/test/manual-test-data/fix-imports/mixed-1.txt b/plugins/migration/test/manual-test-data/fix-imports/mixed-1.js similarity index 98% rename from plugins/migration/test/manual-test-data/fix-imports/mixed-1.txt rename to plugins/migration/test/manual-test-data/fix-imports/mixed-1.js index 1c45be79da..77ffed9a26 100644 --- a/plugins/migration/test/manual-test-data/fix-imports/mixed-1.txt +++ b/plugins/migration/test/manual-test-data/fix-imports/mixed-1.js @@ -31,3 +31,5 @@ Some.Other.identifer; Blockly.libraryBlocks.something; const something = Blockly.libraryBlocks.something; Some.Other.identifer; + +Blockly.zelos; diff --git a/plugins/migration/test/manual-test-data/fix-imports/mixed-2.txt b/plugins/migration/test/manual-test-data/fix-imports/mixed-2.js similarity index 89% rename from plugins/migration/test/manual-test-data/fix-imports/mixed-2.txt rename to plugins/migration/test/manual-test-data/fix-imports/mixed-2.js index 320ddd2fe0..d8b8ca3fdc 100644 --- a/plugins/migration/test/manual-test-data/fix-imports/mixed-2.txt +++ b/plugins/migration/test/manual-test-data/fix-imports/mixed-2.js @@ -3,9 +3,9 @@ // node ./bin/migrate fix-imports --from ./test/manual-test-data/fix-imports/mixed-1.txt const Blockly = require('blockly'); -import * as BlocklyDart from "blockly/dart"; +import * as BlocklyDart from 'blockly/dart'; const BlocklyLua = require('blockly/lua'); -import * as BlocklyPhp from "blockly/php"; +import * as BlocklyPhp from 'blockly/php'; const BlocklyPython = require('blockly/python'); Blockly.JavaScript.something; @@ -31,3 +31,5 @@ Some.Other.identifer; Blockly.libraryBlocks.something; const something = Blockly.libraryBlocks.something; Some.Other.identifer; + +Blockly.zelos; diff --git a/plugins/migration/test/manual-test-data/fix-imports/require.txt b/plugins/migration/test/manual-test-data/fix-imports/require.js similarity index 89% rename from plugins/migration/test/manual-test-data/fix-imports/require.txt rename to plugins/migration/test/manual-test-data/fix-imports/require.js index 58b8fa0d88..d6a9410582 100644 --- a/plugins/migration/test/manual-test-data/fix-imports/require.txt +++ b/plugins/migration/test/manual-test-data/fix-imports/require.js @@ -3,9 +3,9 @@ // node ./bin/migrate fix-imports --from ./test/manual-test-data/fix-imports/require.txt const Blockly = require('blockly'); -const BlocklyDart = require("blockly/dart"); +const BlocklyDart = require('blockly/dart'); const BlocklyLua = require('blockly/lua'); -let BlocklyPhp = require("blockly/php"); +let BlocklyPhp = require('blockly/php'); var BlocklyPython = require('blockly/python'); Blockly.JavaScript.something; @@ -31,3 +31,5 @@ Some.Other.identifer; Blockly.libraryBlocks.something; const something = Blockly.libraryBlocks.something; Some.Other.identifer; + +Blockly.zelos; diff --git a/plugins/migration/test/manual-test-data/rename.txt b/plugins/migration/test/manual-test-data/rename.js similarity index 99% rename from plugins/migration/test/manual-test-data/rename.txt rename to plugins/migration/test/manual-test-data/rename.js index 6ce4c46d61..55bb51b878 100644 --- a/plugins/migration/test/manual-test-data/rename.txt +++ b/plugins/migration/test/manual-test-data/rename.js @@ -25,4 +25,4 @@ class SubClass extends Blockly.moduleC { const thingA = /** @type {Blockly.moduleD} */ (new Blockly.moduleE()); return thingA.someMethod(paramA, paramB); } -}; +} diff --git a/plugins/modal/CHANGELOG.md b/plugins/modal/CHANGELOG.md index e537ac675e..a3e34e76c1 100644 --- a/plugins/modal/CHANGELOG.md +++ b/plugins/modal/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [7.0.14](https://github.com/google/blockly-samples/compare/@blockly/plugin-modal@7.0.13...@blockly/plugin-modal@7.0.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/plugin-modal + + + + + +## [7.0.13](https://github.com/google/blockly-samples/compare/@blockly/plugin-modal@7.0.12...@blockly/plugin-modal@7.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/plugin-modal + + + + + +## [7.0.12](https://github.com/google/blockly-samples/compare/@blockly/plugin-modal@7.0.11...@blockly/plugin-modal@7.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/plugin-modal + + + + + ## [7.0.11](https://github.com/google/blockly-samples/compare/@blockly/plugin-modal@7.0.10...@blockly/plugin-modal@7.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/plugin-modal diff --git a/plugins/modal/package-lock.json b/plugins/modal/package-lock.json index 56372b293b..91cfc1a495 100644 --- a/plugins/modal/package-lock.json +++ b/plugins/modal/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/plugin-modal", - "version": "7.0.11", + "version": "7.0.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/plugin-modal", - "version": "7.0.11", + "version": "7.0.14", "license": "Apache 2.0", "devDependencies": { "jsdom": "^19.0.0", diff --git a/plugins/modal/package.json b/plugins/modal/package.json index 74e2c988bc..8be8b25446 100644 --- a/plugins/modal/package.json +++ b/plugins/modal/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/plugin-modal", - "version": "7.0.11", + "version": "7.0.14", "description": "A Blockly plugin that creates a modal.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -39,8 +39,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "jsdom": "^19.0.0", "jsdom-global": "3.0.2", "mocha": "^10.1.0", diff --git a/plugins/scroll-options/CHANGELOG.md b/plugins/scroll-options/CHANGELOG.md index 37895e55b7..14602d7137 100644 --- a/plugins/scroll-options/CHANGELOG.md +++ b/plugins/scroll-options/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [6.0.14](https://github.com/google/blockly-samples/compare/@blockly/plugin-scroll-options@6.0.13...@blockly/plugin-scroll-options@6.0.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/plugin-scroll-options + + + + + +## [6.0.13](https://github.com/google/blockly-samples/compare/@blockly/plugin-scroll-options@6.0.12...@blockly/plugin-scroll-options@6.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/plugin-scroll-options + + + + + +## [6.0.12](https://github.com/google/blockly-samples/compare/@blockly/plugin-scroll-options@6.0.11...@blockly/plugin-scroll-options@6.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/plugin-scroll-options + + + + + ## [6.0.11](https://github.com/google/blockly-samples/compare/@blockly/plugin-scroll-options@6.0.10...@blockly/plugin-scroll-options@6.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/plugin-scroll-options diff --git a/plugins/scroll-options/package-lock.json b/plugins/scroll-options/package-lock.json index fd8ed5d868..1e5dbb7851 100644 --- a/plugins/scroll-options/package-lock.json +++ b/plugins/scroll-options/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/plugin-scroll-options", - "version": "6.0.11", + "version": "6.0.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/plugin-scroll-options", - "version": "6.0.11", + "version": "6.0.14", "license": "Apache-2.0", "devDependencies": { "typescript": "^5.4.5" diff --git a/plugins/scroll-options/package.json b/plugins/scroll-options/package.json index 38294a7f0d..56deab5ed2 100644 --- a/plugins/scroll-options/package.json +++ b/plugins/scroll-options/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/plugin-scroll-options", - "version": "6.0.11", + "version": "6.0.14", "description": "A Blockly plugin that adds advanced scroll options such as scroll-on-drag and scroll while holding a block.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -39,8 +39,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "typescript": "^5.4.5" }, "peerDependencies": { diff --git a/plugins/shadow-block-converter/CHANGELOG.md b/plugins/shadow-block-converter/CHANGELOG.md index e3bda47a3a..6f8f83874f 100644 --- a/plugins/shadow-block-converter/CHANGELOG.md +++ b/plugins/shadow-block-converter/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [6.0.15](https://github.com/google/blockly-samples/compare/@blockly/shadow-block-converter@6.0.14...@blockly/shadow-block-converter@6.0.15) (2025-02-13) + +**Note:** Version bump only for package @blockly/shadow-block-converter + + + + + +## [6.0.14](https://github.com/google/blockly-samples/compare/@blockly/shadow-block-converter@6.0.13...@blockly/shadow-block-converter@6.0.14) (2024-12-19) + +**Note:** Version bump only for package @blockly/shadow-block-converter + + + + + +## [6.0.13](https://github.com/google/blockly-samples/compare/@blockly/shadow-block-converter@6.0.12...@blockly/shadow-block-converter@6.0.13) (2024-12-03) + +**Note:** Version bump only for package @blockly/shadow-block-converter + + + + + ## [6.0.12](https://github.com/google/blockly-samples/compare/@blockly/shadow-block-converter@6.0.11...@blockly/shadow-block-converter@6.0.12) (2024-11-07) **Note:** Version bump only for package @blockly/shadow-block-converter diff --git a/plugins/shadow-block-converter/package-lock.json b/plugins/shadow-block-converter/package-lock.json index 693140389f..6de9e0efa3 100644 --- a/plugins/shadow-block-converter/package-lock.json +++ b/plugins/shadow-block-converter/package-lock.json @@ -1,16 +1,16 @@ { "name": "@blockly/shadow-block-converter", - "version": "6.0.12", + "version": "6.0.15", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/shadow-block-converter", - "version": "6.0.12", + "version": "6.0.15", "license": "Apache-2.0", "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "chai": "^4.2.0", "jsdom": "^19.0.0", "jsdom-global": "^3.0.2", diff --git a/plugins/shadow-block-converter/package.json b/plugins/shadow-block-converter/package.json index 41c6e8cd83..93fe936d09 100644 --- a/plugins/shadow-block-converter/package.json +++ b/plugins/shadow-block-converter/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/shadow-block-converter", - "version": "6.0.12", + "version": "6.0.15", "description": "A workspace change listener that converts shadow blocks to real blocks when the user edits them.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -39,8 +39,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "chai": "^4.2.0", "jsdom": "^19.0.0", "jsdom-global": "^3.0.2", diff --git a/plugins/strict-connection-checker/CHANGELOG.md b/plugins/strict-connection-checker/CHANGELOG.md index b33ff707c0..31a27ec151 100644 --- a/plugins/strict-connection-checker/CHANGELOG.md +++ b/plugins/strict-connection-checker/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [5.0.14](https://github.com/google/blockly-samples/compare/@blockly/plugin-strict-connection-checker@5.0.13...@blockly/plugin-strict-connection-checker@5.0.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/plugin-strict-connection-checker + + + + + +## [5.0.13](https://github.com/google/blockly-samples/compare/@blockly/plugin-strict-connection-checker@5.0.12...@blockly/plugin-strict-connection-checker@5.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/plugin-strict-connection-checker + + + + + +## [5.0.12](https://github.com/google/blockly-samples/compare/@blockly/plugin-strict-connection-checker@5.0.11...@blockly/plugin-strict-connection-checker@5.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/plugin-strict-connection-checker + + + + + ## [5.0.11](https://github.com/google/blockly-samples/compare/@blockly/plugin-strict-connection-checker@5.0.10...@blockly/plugin-strict-connection-checker@5.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/plugin-strict-connection-checker diff --git a/plugins/strict-connection-checker/package-lock.json b/plugins/strict-connection-checker/package-lock.json index edc591e1df..2b487deaa7 100644 --- a/plugins/strict-connection-checker/package-lock.json +++ b/plugins/strict-connection-checker/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/plugin-strict-connection-checker", - "version": "5.0.11", + "version": "5.0.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/plugin-strict-connection-checker", - "version": "5.0.11", + "version": "5.0.14", "license": "Apache 2.0", "devDependencies": { "chai": "^4.2.0" diff --git a/plugins/strict-connection-checker/package.json b/plugins/strict-connection-checker/package.json index cd6acf00d1..abd03b83c4 100644 --- a/plugins/strict-connection-checker/package.json +++ b/plugins/strict-connection-checker/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/plugin-strict-connection-checker", - "version": "5.0.11", + "version": "5.0.14", "description": "A connection checker that prevents blocks that don't provide type information from being connected to blocks that do.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -40,8 +40,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "chai": "^4.2.0" }, "peerDependencies": { diff --git a/plugins/suggested-blocks/CHANGELOG.md b/plugins/suggested-blocks/CHANGELOG.md index 7569bf71e9..8b31d6a7a7 100644 --- a/plugins/suggested-blocks/CHANGELOG.md +++ b/plugins/suggested-blocks/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [5.0.14](https://github.com/google/blockly-samples/compare/@blockly/suggested-blocks@5.0.13...@blockly/suggested-blocks@5.0.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/suggested-blocks + + + + + +## [5.0.13](https://github.com/google/blockly-samples/compare/@blockly/suggested-blocks@5.0.12...@blockly/suggested-blocks@5.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/suggested-blocks + + + + + +## [5.0.12](https://github.com/google/blockly-samples/compare/@blockly/suggested-blocks@5.0.11...@blockly/suggested-blocks@5.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/suggested-blocks + + + + + ## [5.0.11](https://github.com/google/blockly-samples/compare/@blockly/suggested-blocks@5.0.10...@blockly/suggested-blocks@5.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/suggested-blocks diff --git a/plugins/suggested-blocks/package-lock.json b/plugins/suggested-blocks/package-lock.json index 932fb8b3fc..b90f616abc 100644 --- a/plugins/suggested-blocks/package-lock.json +++ b/plugins/suggested-blocks/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/suggested-blocks", - "version": "5.0.11", + "version": "5.0.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/suggested-blocks", - "version": "5.0.11", + "version": "5.0.14", "license": "Apache-2.0", "devDependencies": { "chai": "^4.3.6", diff --git a/plugins/suggested-blocks/package.json b/plugins/suggested-blocks/package.json index 2c743f79e7..b0029974f4 100644 --- a/plugins/suggested-blocks/package.json +++ b/plugins/suggested-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/suggested-blocks", - "version": "5.0.11", + "version": "5.0.14", "description": "A plugin that adds toolbox panes with suggested blocks based on the user's past usage of blocks.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -40,8 +40,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "chai": "^4.3.6", "sinon": "^14.0.0" }, diff --git a/plugins/theme-dark/CHANGELOG.md b/plugins/theme-dark/CHANGELOG.md index 8bb46b9689..749e6d7653 100644 --- a/plugins/theme-dark/CHANGELOG.md +++ b/plugins/theme-dark/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [7.0.10](https://github.com/google/blockly-samples/compare/@blockly/theme-dark@7.0.9...@blockly/theme-dark@7.0.10) (2024-12-03) + +**Note:** Version bump only for package @blockly/theme-dark + + + + + ## [7.0.9](https://github.com/google/blockly-samples/compare/@blockly/theme-dark@7.0.8...@blockly/theme-dark@7.0.9) (2024-11-07) **Note:** Version bump only for package @blockly/theme-dark diff --git a/plugins/theme-dark/package-lock.json b/plugins/theme-dark/package-lock.json index de6b71c0d0..f10f30ece3 100644 --- a/plugins/theme-dark/package-lock.json +++ b/plugins/theme-dark/package-lock.json @@ -1,15 +1,15 @@ { "name": "@blockly/theme-dark", - "version": "7.0.9", + "version": "7.0.10", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/theme-dark", - "version": "7.0.9", + "version": "7.0.10", "license": "Apache-2.0", "devDependencies": { - "@blockly/dev-scripts": "^4.0.6" + "@blockly/dev-scripts": "^4.0.7" }, "engines": { "node": ">=8.17.0" diff --git a/plugins/theme-dark/package.json b/plugins/theme-dark/package.json index 131b65085e..cfeac6d660 100644 --- a/plugins/theme-dark/package.json +++ b/plugins/theme-dark/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/theme-dark", - "version": "7.0.9", + "version": "7.0.10", "description": "A Blockly dark theme.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -40,7 +40,7 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6" + "@blockly/dev-scripts": "^4.0.7" }, "peerDependencies": { "blockly": "^11.0.0" diff --git a/plugins/theme-deuteranopia/CHANGELOG.md b/plugins/theme-deuteranopia/CHANGELOG.md index 14a4149caa..9edc14361f 100644 --- a/plugins/theme-deuteranopia/CHANGELOG.md +++ b/plugins/theme-deuteranopia/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [6.0.10](https://github.com/google/blockly-samples/compare/@blockly/theme-deuteranopia@6.0.9...@blockly/theme-deuteranopia@6.0.10) (2024-12-03) + +**Note:** Version bump only for package @blockly/theme-deuteranopia + + + + + ## [6.0.9](https://github.com/google/blockly-samples/compare/@blockly/theme-deuteranopia@6.0.8...@blockly/theme-deuteranopia@6.0.9) (2024-11-07) **Note:** Version bump only for package @blockly/theme-deuteranopia diff --git a/plugins/theme-deuteranopia/package-lock.json b/plugins/theme-deuteranopia/package-lock.json index 6178e9d7cf..38cba68ab6 100644 --- a/plugins/theme-deuteranopia/package-lock.json +++ b/plugins/theme-deuteranopia/package-lock.json @@ -1,15 +1,15 @@ { "name": "@blockly/theme-deuteranopia", - "version": "6.0.9", + "version": "6.0.10", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/theme-deuteranopia", - "version": "6.0.9", + "version": "6.0.10", "license": "Apache-2.0", "devDependencies": { - "@blockly/dev-scripts": "^4.0.6" + "@blockly/dev-scripts": "^4.0.7" }, "engines": { "node": ">=8.17.0" diff --git a/plugins/theme-deuteranopia/package.json b/plugins/theme-deuteranopia/package.json index 0b95497730..ac9b0936b5 100644 --- a/plugins/theme-deuteranopia/package.json +++ b/plugins/theme-deuteranopia/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/theme-deuteranopia", - "version": "6.0.9", + "version": "6.0.10", "description": "A Blockly theme for people that have deuteranopia.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -40,7 +40,7 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6" + "@blockly/dev-scripts": "^4.0.7" }, "peerDependencies": { "blockly": "^11.0.0" diff --git a/plugins/theme-highcontrast/CHANGELOG.md b/plugins/theme-highcontrast/CHANGELOG.md index 1a86faa465..14aa9d636e 100644 --- a/plugins/theme-highcontrast/CHANGELOG.md +++ b/plugins/theme-highcontrast/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [6.0.10](https://github.com/google/blockly-samples/compare/@blockly/theme-highcontrast@6.0.9...@blockly/theme-highcontrast@6.0.10) (2024-12-03) + +**Note:** Version bump only for package @blockly/theme-highcontrast + + + + + ## [6.0.9](https://github.com/google/blockly-samples/compare/@blockly/theme-highcontrast@6.0.8...@blockly/theme-highcontrast@6.0.9) (2024-11-07) **Note:** Version bump only for package @blockly/theme-highcontrast diff --git a/plugins/theme-highcontrast/package-lock.json b/plugins/theme-highcontrast/package-lock.json index 9ba8d520f0..b99c1ec691 100644 --- a/plugins/theme-highcontrast/package-lock.json +++ b/plugins/theme-highcontrast/package-lock.json @@ -1,15 +1,15 @@ { "name": "@blockly/theme-highcontrast", - "version": "6.0.9", + "version": "6.0.10", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/theme-highcontrast", - "version": "6.0.9", + "version": "6.0.10", "license": "Apache-2.0", "devDependencies": { - "@blockly/dev-scripts": "^4.0.6" + "@blockly/dev-scripts": "^4.0.7" }, "engines": { "node": ">=8.17.0" diff --git a/plugins/theme-highcontrast/package.json b/plugins/theme-highcontrast/package.json index d35daf54cf..a264dcd52b 100644 --- a/plugins/theme-highcontrast/package.json +++ b/plugins/theme-highcontrast/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/theme-highcontrast", - "version": "6.0.9", + "version": "6.0.10", "description": "A Blockly high contrast theme.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -40,7 +40,7 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6" + "@blockly/dev-scripts": "^4.0.7" }, "peerDependencies": { "blockly": "^11.0.0" diff --git a/plugins/theme-modern/CHANGELOG.md b/plugins/theme-modern/CHANGELOG.md index 90ea69d3ba..0ed1f1a4de 100644 --- a/plugins/theme-modern/CHANGELOG.md +++ b/plugins/theme-modern/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [6.0.10](https://github.com/google/blockly-samples/compare/@blockly/theme-modern@6.0.9...@blockly/theme-modern@6.0.10) (2024-12-03) + +**Note:** Version bump only for package @blockly/theme-modern + + + + + ## [6.0.9](https://github.com/google/blockly-samples/compare/@blockly/theme-modern@6.0.8...@blockly/theme-modern@6.0.9) (2024-11-07) **Note:** Version bump only for package @blockly/theme-modern diff --git a/plugins/theme-modern/package-lock.json b/plugins/theme-modern/package-lock.json index bc79786b39..1da58cb6b6 100644 --- a/plugins/theme-modern/package-lock.json +++ b/plugins/theme-modern/package-lock.json @@ -1,15 +1,15 @@ { "name": "@blockly/theme-modern", - "version": "6.0.9", + "version": "6.0.10", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/theme-modern", - "version": "6.0.9", + "version": "6.0.10", "license": "Apache-2.0", "devDependencies": { - "@blockly/dev-scripts": "^4.0.6" + "@blockly/dev-scripts": "^4.0.7" }, "engines": { "node": ">=8.17.0" diff --git a/plugins/theme-modern/package.json b/plugins/theme-modern/package.json index c4c283f4ac..37862bc36e 100644 --- a/plugins/theme-modern/package.json +++ b/plugins/theme-modern/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/theme-modern", - "version": "6.0.9", + "version": "6.0.10", "description": "A Blockly modern theme with darker block borders.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -40,7 +40,7 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6" + "@blockly/dev-scripts": "^4.0.7" }, "peerDependencies": { "blockly": "^11.0.0" diff --git a/plugins/theme-tritanopia/CHANGELOG.md b/plugins/theme-tritanopia/CHANGELOG.md index d242843678..e70f985331 100644 --- a/plugins/theme-tritanopia/CHANGELOG.md +++ b/plugins/theme-tritanopia/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [6.0.10](https://github.com/google/blockly-samples/compare/@blockly/theme-tritanopia@6.0.9...@blockly/theme-tritanopia@6.0.10) (2024-12-03) + +**Note:** Version bump only for package @blockly/theme-tritanopia + + + + + ## [6.0.9](https://github.com/google/blockly-samples/compare/@blockly/theme-tritanopia@6.0.8...@blockly/theme-tritanopia@6.0.9) (2024-11-07) **Note:** Version bump only for package @blockly/theme-tritanopia diff --git a/plugins/theme-tritanopia/package-lock.json b/plugins/theme-tritanopia/package-lock.json index e5dde935da..d22bea9cb1 100644 --- a/plugins/theme-tritanopia/package-lock.json +++ b/plugins/theme-tritanopia/package-lock.json @@ -1,15 +1,15 @@ { "name": "@blockly/theme-tritanopia", - "version": "6.0.9", + "version": "6.0.10", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/theme-tritanopia", - "version": "6.0.9", + "version": "6.0.10", "license": "Apache-2.0", "devDependencies": { - "@blockly/dev-scripts": "^4.0.6" + "@blockly/dev-scripts": "^4.0.7" }, "engines": { "node": ">=8.17.0" diff --git a/plugins/theme-tritanopia/package.json b/plugins/theme-tritanopia/package.json index 70d1630294..965b77dc5d 100644 --- a/plugins/theme-tritanopia/package.json +++ b/plugins/theme-tritanopia/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/theme-tritanopia", - "version": "6.0.9", + "version": "6.0.10", "description": "A Blockly theme for people that have tritanopia.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -40,7 +40,7 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6" + "@blockly/dev-scripts": "^4.0.7" }, "peerDependencies": { "blockly": "^11.0.0" diff --git a/plugins/toolbox-search/CHANGELOG.md b/plugins/toolbox-search/CHANGELOG.md index 20df03c229..eab82421bf 100644 --- a/plugins/toolbox-search/CHANGELOG.md +++ b/plugins/toolbox-search/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.0.14](https://github.com/google/blockly-samples/compare/@blockly/toolbox-search@2.0.13...@blockly/toolbox-search@2.0.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/toolbox-search + + + + + +## [2.0.13](https://github.com/google/blockly-samples/compare/@blockly/toolbox-search@2.0.12...@blockly/toolbox-search@2.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/toolbox-search + + + + + +## [2.0.12](https://github.com/google/blockly-samples/compare/@blockly/toolbox-search@2.0.11...@blockly/toolbox-search@2.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/toolbox-search + + + + + ## [2.0.11](https://github.com/google/blockly-samples/compare/@blockly/toolbox-search@2.0.10...@blockly/toolbox-search@2.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/toolbox-search diff --git a/plugins/toolbox-search/package-lock.json b/plugins/toolbox-search/package-lock.json index c6776174aa..145c69b2ac 100644 --- a/plugins/toolbox-search/package-lock.json +++ b/plugins/toolbox-search/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/toolbox-search", - "version": "2.0.11", + "version": "2.0.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/toolbox-search", - "version": "2.0.11", + "version": "2.0.14", "license": "Apache-2.0", "devDependencies": { "chai": "^4.3.7", diff --git a/plugins/toolbox-search/package.json b/plugins/toolbox-search/package.json index 795cfc1b0f..92f3716999 100644 --- a/plugins/toolbox-search/package.json +++ b/plugins/toolbox-search/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/toolbox-search", - "version": "2.0.11", + "version": "2.0.14", "description": "A Blockly plugin that adds a toolbox category that allows searching for blocks.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -40,8 +40,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "chai": "^4.3.7", "typescript": "^5.4.5" }, diff --git a/plugins/typed-variable-modal/CHANGELOG.md b/plugins/typed-variable-modal/CHANGELOG.md index 025704d33c..9cba36691e 100644 --- a/plugins/typed-variable-modal/CHANGELOG.md +++ b/plugins/typed-variable-modal/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [8.0.14](https://github.com/google/blockly-samples/compare/@blockly/plugin-typed-variable-modal@8.0.13...@blockly/plugin-typed-variable-modal@8.0.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/plugin-typed-variable-modal + + + + + +## [8.0.13](https://github.com/google/blockly-samples/compare/@blockly/plugin-typed-variable-modal@8.0.12...@blockly/plugin-typed-variable-modal@8.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/plugin-typed-variable-modal + + + + + +## [8.0.12](https://github.com/google/blockly-samples/compare/@blockly/plugin-typed-variable-modal@8.0.11...@blockly/plugin-typed-variable-modal@8.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/plugin-typed-variable-modal + + + + + ## [8.0.11](https://github.com/google/blockly-samples/compare/@blockly/plugin-typed-variable-modal@8.0.10...@blockly/plugin-typed-variable-modal@8.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/plugin-typed-variable-modal diff --git a/plugins/typed-variable-modal/package-lock.json b/plugins/typed-variable-modal/package-lock.json index 7c0a428a86..b27ce0145f 100644 --- a/plugins/typed-variable-modal/package-lock.json +++ b/plugins/typed-variable-modal/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/plugin-typed-variable-modal", - "version": "8.0.11", + "version": "8.0.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/plugin-typed-variable-modal", - "version": "8.0.11", + "version": "8.0.14", "license": "Apache-2.0", "devDependencies": { "jsdom": "^19.0.0", diff --git a/plugins/typed-variable-modal/package.json b/plugins/typed-variable-modal/package.json index 3bab1ba27c..18bca88d7d 100644 --- a/plugins/typed-variable-modal/package.json +++ b/plugins/typed-variable-modal/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/plugin-typed-variable-modal", - "version": "8.0.11", + "version": "8.0.14", "description": "A Blockly plugin to create a modal for creating typed variables.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -39,8 +39,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "jsdom": "^19.0.0", "jsdom-global": "3.0.2", "mocha": "^10.1.0", @@ -50,7 +50,7 @@ "blockly": "^11.0.0" }, "dependencies": { - "@blockly/plugin-modal": "^7.0.11" + "@blockly/plugin-modal": "^7.0.14" }, "publishConfig": { "access": "public", diff --git a/plugins/workspace-backpack/CHANGELOG.md b/plugins/workspace-backpack/CHANGELOG.md index 7e25b368a0..a27e14b919 100644 --- a/plugins/workspace-backpack/CHANGELOG.md +++ b/plugins/workspace-backpack/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [6.0.14](https://github.com/google/blockly-samples/compare/@blockly/workspace-backpack@6.0.13...@blockly/workspace-backpack@6.0.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/workspace-backpack + + + + + +## [6.0.13](https://github.com/google/blockly-samples/compare/@blockly/workspace-backpack@6.0.12...@blockly/workspace-backpack@6.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/workspace-backpack + + + + + +## [6.0.12](https://github.com/google/blockly-samples/compare/@blockly/workspace-backpack@6.0.11...@blockly/workspace-backpack@6.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/workspace-backpack + + + + + ## [6.0.11](https://github.com/google/blockly-samples/compare/@blockly/workspace-backpack@6.0.10...@blockly/workspace-backpack@6.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/workspace-backpack diff --git a/plugins/workspace-backpack/package-lock.json b/plugins/workspace-backpack/package-lock.json index a4f56a628d..13ffe72b5d 100644 --- a/plugins/workspace-backpack/package-lock.json +++ b/plugins/workspace-backpack/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/workspace-backpack", - "version": "6.0.11", + "version": "6.0.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/workspace-backpack", - "version": "6.0.11", + "version": "6.0.14", "license": "Apache-2.0", "devDependencies": { "typescript": "^5.4.5" diff --git a/plugins/workspace-backpack/package.json b/plugins/workspace-backpack/package.json index 9216a40033..474968d045 100644 --- a/plugins/workspace-backpack/package.json +++ b/plugins/workspace-backpack/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/workspace-backpack", - "version": "6.0.11", + "version": "6.0.14", "description": "A Blockly plugin that adds Backpack support.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -40,8 +40,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "typescript": "^5.4.5" }, "peerDependencies": { diff --git a/plugins/workspace-minimap/CHANGELOG.md b/plugins/workspace-minimap/CHANGELOG.md index 67f3c8b886..65acd9b28a 100644 --- a/plugins/workspace-minimap/CHANGELOG.md +++ b/plugins/workspace-minimap/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.14](https://github.com/google/blockly-samples/compare/@blockly/workspace-minimap@0.2.13...@blockly/workspace-minimap@0.2.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/workspace-minimap + + + + + +## [0.2.13](https://github.com/google/blockly-samples/compare/@blockly/workspace-minimap@0.2.12...@blockly/workspace-minimap@0.2.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/workspace-minimap + + + + + +## [0.2.12](https://github.com/google/blockly-samples/compare/@blockly/workspace-minimap@0.2.11...@blockly/workspace-minimap@0.2.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/workspace-minimap + + + + + ## [0.2.11](https://github.com/google/blockly-samples/compare/@blockly/workspace-minimap@0.2.10...@blockly/workspace-minimap@0.2.11) (2024-11-07) **Note:** Version bump only for package @blockly/workspace-minimap diff --git a/plugins/workspace-minimap/package-lock.json b/plugins/workspace-minimap/package-lock.json index 5c9c59de53..f50f1003f6 100644 --- a/plugins/workspace-minimap/package-lock.json +++ b/plugins/workspace-minimap/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/workspace-minimap", - "version": "0.2.11", + "version": "0.2.14", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@blockly/workspace-minimap", - "version": "0.2.11", + "version": "0.2.14", "license": "Apache-2.0", "devDependencies": { "chai": "^4.2.0", diff --git a/plugins/workspace-minimap/package.json b/plugins/workspace-minimap/package.json index c7cd28ea46..6c00eb4d45 100644 --- a/plugins/workspace-minimap/package.json +++ b/plugins/workspace-minimap/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/workspace-minimap", - "version": "0.2.11", + "version": "0.2.14", "description": "A Blockly plugin.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -39,8 +39,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "chai": "^4.2.0", "typescript": "^5.4.5" }, diff --git a/plugins/workspace-search/CHANGELOG.md b/plugins/workspace-search/CHANGELOG.md index 831cd9fb88..cb7d6b86ee 100644 --- a/plugins/workspace-search/CHANGELOG.md +++ b/plugins/workspace-search/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [9.1.8](https://github.com/google/blockly-samples/compare/@blockly/plugin-workspace-search@9.1.7...@blockly/plugin-workspace-search@9.1.8) (2025-02-13) + +**Note:** Version bump only for package @blockly/plugin-workspace-search + + + + + +## [9.1.7](https://github.com/google/blockly-samples/compare/@blockly/plugin-workspace-search@9.1.6...@blockly/plugin-workspace-search@9.1.7) (2024-12-19) + +**Note:** Version bump only for package @blockly/plugin-workspace-search + + + + + +## [9.1.6](https://github.com/google/blockly-samples/compare/@blockly/plugin-workspace-search@9.1.5...@blockly/plugin-workspace-search@9.1.6) (2024-12-03) + +**Note:** Version bump only for package @blockly/plugin-workspace-search + + + + + ## [9.1.5](https://github.com/google/blockly-samples/compare/@blockly/plugin-workspace-search@9.1.4...@blockly/plugin-workspace-search@9.1.5) (2024-11-07) **Note:** Version bump only for package @blockly/plugin-workspace-search diff --git a/plugins/workspace-search/package-lock.json b/plugins/workspace-search/package-lock.json index dbe488bebb..82c30c72a2 100644 --- a/plugins/workspace-search/package-lock.json +++ b/plugins/workspace-search/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/plugin-workspace-search", - "version": "9.1.5", + "version": "9.1.8", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/plugin-workspace-search", - "version": "9.1.5", + "version": "9.1.8", "license": "Apache-2.0", "devDependencies": { "jsdom": "^19.0.0", diff --git a/plugins/workspace-search/package.json b/plugins/workspace-search/package.json index 0a44dc5479..f24519ba4e 100644 --- a/plugins/workspace-search/package.json +++ b/plugins/workspace-search/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/plugin-workspace-search", - "version": "9.1.5", + "version": "9.1.8", "description": "A Blockly plugin that adds workspace search support.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -39,8 +39,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "jsdom": "^19.0.0", "jsdom-global": "3.0.2", "sinon": "^9.0.1", diff --git a/plugins/zoom-to-fit/CHANGELOG.md b/plugins/zoom-to-fit/CHANGELOG.md index 9f79a278ae..bb32f3d93b 100644 --- a/plugins/zoom-to-fit/CHANGELOG.md +++ b/plugins/zoom-to-fit/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [6.0.14](https://github.com/google/blockly-samples/compare/@blockly/zoom-to-fit@6.0.13...@blockly/zoom-to-fit@6.0.14) (2025-02-13) + +**Note:** Version bump only for package @blockly/zoom-to-fit + + + + + +## [6.0.13](https://github.com/google/blockly-samples/compare/@blockly/zoom-to-fit@6.0.12...@blockly/zoom-to-fit@6.0.13) (2024-12-19) + +**Note:** Version bump only for package @blockly/zoom-to-fit + + + + + +## [6.0.12](https://github.com/google/blockly-samples/compare/@blockly/zoom-to-fit@6.0.11...@blockly/zoom-to-fit@6.0.12) (2024-12-03) + +**Note:** Version bump only for package @blockly/zoom-to-fit + + + + + ## [6.0.11](https://github.com/google/blockly-samples/compare/@blockly/zoom-to-fit@6.0.10...@blockly/zoom-to-fit@6.0.11) (2024-11-07) **Note:** Version bump only for package @blockly/zoom-to-fit diff --git a/plugins/zoom-to-fit/package-lock.json b/plugins/zoom-to-fit/package-lock.json index 040d020fb8..b3384a47e3 100644 --- a/plugins/zoom-to-fit/package-lock.json +++ b/plugins/zoom-to-fit/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockly/zoom-to-fit", - "version": "6.0.11", + "version": "6.0.14", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@blockly/zoom-to-fit", - "version": "6.0.11", + "version": "6.0.14", "license": "Apache-2.0", "devDependencies": { "typescript": "^5.4.5" diff --git a/plugins/zoom-to-fit/package.json b/plugins/zoom-to-fit/package.json index 7c5aab25b3..86b7fad92f 100644 --- a/plugins/zoom-to-fit/package.json +++ b/plugins/zoom-to-fit/package.json @@ -1,6 +1,6 @@ { "name": "@blockly/zoom-to-fit", - "version": "6.0.11", + "version": "6.0.14", "description": "A Blockly plugin that adds a zoom-to-fit control to the workspace.", "scripts": { "audit:fix": "blockly-scripts auditFix", @@ -38,8 +38,8 @@ "src" ], "devDependencies": { - "@blockly/dev-scripts": "^4.0.6", - "@blockly/dev-tools": "^8.0.11", + "@blockly/dev-scripts": "^4.0.7", + "@blockly/dev-tools": "^8.1.0", "typescript": "^5.4.5" }, "peerDependencies": {