diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 1430463fea6..00000000000 --- a/.eslintignore +++ /dev/null @@ -1,28 +0,0 @@ -# Build Artifacts -/msg/* -/build/* -/dist/* -/typings/* -/docs/* - -# Tests other than mocha unit tests -/tests/blocks/* -/tests/themes/* -/tests/compile/* -/tests/jsunit/* -/tests/generators/* -/tests/mocha/webdriver.js -/tests/screenshot/* -/tests/test_runner.js -/tests/workspace_svg/* - -# Demos, scripts, misc -/node_modules/* -/generators/* -/demos/* -/appengine/* -/externs/* -/closure/* -/scripts/gulpfiles/* -CHANGELOG.md -PULL_REQUEST_TEMPLATE.md \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 14d27ca1af9..00000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,187 +0,0 @@ -const rules = { - 'no-unused-vars': [ - 'error', - { - 'args': 'after-used', - // Ignore vars starting with an underscore. - 'varsIgnorePattern': '^_', - // Ignore arguments starting with an underscore. - 'argsIgnorePattern': '^_', - }, - ], - // Blockly uses for exporting symbols. no-self-assign added in eslint 5. - 'no-self-assign': ['off'], - // Blockly uses single quotes except for JSON blobs, which must use double - // quotes. - 'quotes': ['off'], - // Blockly uses 'use strict' in files. - 'strict': ['off'], - // Closure style allows redeclarations. - 'no-redeclare': ['off'], - 'valid-jsdoc': ['error'], - 'no-console': ['off'], - 'spaced-comment': [ - 'error', - 'always', - { - 'block': { - 'balanced': true, - }, - 'exceptions': ['*'], - }, - ], - // Blockly uses prefixes for optional arguments and test-only functions. - 'camelcase': [ - 'error', - { - 'properties': 'never', - 'allow': ['^opt_', '^_opt_', '^testOnly_'], - }, - ], - // Blockly uses capital letters for some non-constructor namespaces. - // Keep them for legacy reasons. - 'new-cap': ['off'], - // Blockly uses objects as maps, but uses Object.create(null) to - // instantiate them. - 'guard-for-in': ['off'], - 'prefer-spread': ['off'], -}; - -/** - * Build shared settings for TS linting and add in the config differences. - * @return {Object} The override TS linting for given files and a given - * tsconfig. - */ -function buildTSOverride({files, tsconfig}) { - return { - 'files': files, - 'plugins': ['@typescript-eslint/eslint-plugin', 'jsdoc'], - 'settings': { - 'jsdoc': { - 'mode': 'typescript', - }, - }, - 'parser': '@typescript-eslint/parser', - 'parserOptions': { - 'project': tsconfig, - 'tsconfigRootDir': '.', - 'ecmaVersion': 2020, - 'sourceType': 'module', - }, - 'extends': [ - 'plugin:@typescript-eslint/recommended', - 'plugin:jsdoc/recommended', - 'prettier', // Extend again so that these rules are applied last - ], - 'rules': { - // TS rules - // Blockly uses namespaces to do declaration merging in some cases. - '@typescript-eslint/no-namespace': ['off'], - // Use the updated TypeScript-specific rule. - 'no-invalid-this': ['off'], - '@typescript-eslint/no-invalid-this': ['error'], - // Needs decision. 601 problems. - '@typescript-eslint/no-non-null-assertion': ['off'], - // Use TS-specific rule. - 'no-unused-vars': ['off'], - '@typescript-eslint/no-unused-vars': [ - 'error', - { - 'argsIgnorePattern': '^_', - 'varsIgnorePattern': '^_', - }, - ], - // Temporarily disable. 23 problems. - '@typescript-eslint/no-explicit-any': ['off'], - // Temporarily disable. 128 problems. - 'require-jsdoc': ['off'], - // Temporarily disable. 55 problems. - '@typescript-eslint/ban-types': ['off'], - // Temporarily disable. 33 problems. - '@typescript-eslint/no-empty-function': ['off'], - // Temporarily disable. 3 problems. - '@typescript-eslint/no-empty-interface': ['off'], - - // TsDoc rules (using JsDoc plugin) - // Disable built-in jsdoc verifier. - 'valid-jsdoc': ['off'], - // Don't require types in params and returns docs. - 'jsdoc/require-param-type': ['off'], - 'jsdoc/require-returns-type': ['off'], - // params and returns docs are optional. - 'jsdoc/require-param-description': ['off'], - 'jsdoc/require-returns': ['off'], - // Disable for now (breaks on `this` which is not really a param). - 'jsdoc/require-param': ['off'], - // Don't auto-add missing jsdoc. Only required on exported items. - 'jsdoc/require-jsdoc': [ - 'warn', - { - 'enableFixer': false, - 'publicOnly': true, - }, - ], - 'jsdoc/check-tag-names': [ - 'error', - { - 'definedTags': [ - 'sealed', - 'typeParam', - 'remarks', - 'define', - 'nocollapse', - 'suppress', - ], - }, - ], - // Re-enable after Closure is removed. There shouldn't even be - // types in the TsDoc. - // These are "types" because of Closure's @suppress {warningName} - 'jsdoc/no-undefined-types': ['off'], - 'jsdoc/valid-types': ['off'], - // Disabled due to not handling `this`. If re-enabled, - // checkDestructured option - // should be left as false. - 'jsdoc/check-param-names': ['off', {'checkDestructured': false}], - // Allow any text in the license tag. Other checks are not relevant. - 'jsdoc/check-values': ['off'], - // Ensure there is a blank line between the body and any @tags, - // as required by the tsdoc spec (see #6353). - 'jsdoc/tag-lines': ['error', 'any', {'startLines': 1}], - }, - }; -} - -// NOTE: When this output is put directly in `module.exports`, the formatter -// does not align with the linter. -const eslintJSON = { - 'rules': rules, - 'env': { - 'es2020': true, - 'browser': true, - }, - 'globals': { - 'goog': true, - 'exports': true, - }, - 'extends': ['eslint:recommended', 'google', 'prettier'], - // TypeScript-specific config. Uses above rules plus these. - 'overrides': [ - buildTSOverride({ - files: ['./**/*.ts', './**/*.tsx'], - tsconfig: './tsconfig.json', - }), - buildTSOverride({ - files: ['./tests/typescript/**/*.ts', './tests/typescript/**/*.tsx'], - tsconfig: './tests/typescript/tsconfig.json', - }), - { - 'files': ['./.eslintrc.js'], - 'env': { - 'node': true, - }, - }, - ], -}; - -module.exports = eslintJSON; diff --git a/.github/workflows/appengine_deploy.yml b/.github/workflows/appengine_deploy.yml index f7098d53a7e..938a16fc714 100644 --- a/.github/workflows/appengine_deploy.yml +++ b/.github/workflows/appengine_deploy.yml @@ -42,7 +42,7 @@ jobs: path: _deploy/ - name: Deploy to App Engine - uses: google-github-actions/deploy-appengine@v2.1.0 + uses: google-github-actions/deploy-appengine@v2.1.4 # For parameters see: # https://github.com/google-github-actions/deploy-appengine#inputs with: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ad62722e1f7..c4ab688f8fd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,7 +18,7 @@ jobs: # TODO (#2114): re-enable osx build. # os: [ubuntu-latest, macos-latest] os: [ubuntu-latest] - node-version: [18.x, 20.x] + node-version: [18.x, 20.x, 22.x] # See supported Node.js release schedule at # https://nodejs.org/en/about/releases/ @@ -37,8 +37,8 @@ jobs: with: node-version: ${{ matrix.node-version }} - - name: Npm Install - run: npm install + - name: Npm Clean Install + run: npm ci - name: Linux Test Setup if: runner.os == 'Linux' diff --git a/.npmrc b/.npmrc index 214c29d1395..a4af34998fa 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1,2 @@ registry=https://registry.npmjs.org/ +legacy-peer-deps=true diff --git a/.prettierrc.js b/.prettierrc.js index bbfb466399d..84a85c1159e 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -10,4 +10,6 @@ module.exports = { bracketSpacing: false, // Put HTML tag closing brackets on same line as last attribute. bracketSameLine: true, + // Organise imports using a plugin. + 'plugins': ['prettier-plugin-organize-imports'], }; diff --git a/appengine/blockly_compressed.js b/appengine/blockly_compressed.js index dc118dfbe20..837d6bb3580 100644 --- a/appengine/blockly_compressed.js +++ b/appengine/blockly_compressed.js @@ -6,6 +6,6 @@ var msg = 'Compiled Blockly files should be loaded from https://unpkg.com/blockl console.log(msg); try { alert(msg); -} catch (_e) { +} catch { // Can't alert? Probably node.js. } diff --git a/blocks/blocks.ts b/blocks/blocks.ts index a9874e54df1..dc6ca386cd2 100644 --- a/blocks/blocks.ts +++ b/blocks/blocks.ts @@ -6,6 +6,7 @@ // Former goog.module ID: Blockly.libraryBlocks +import type {BlockDefinition} from '../core/blocks.js'; import * as lists from './lists.js'; import * as logic from './logic.js'; import * as loops from './loops.js'; @@ -14,7 +15,6 @@ import * as procedures from './procedures.js'; import * as texts from './text.js'; import * as variables from './variables.js'; import * as variablesDynamic from './variables_dynamic.js'; -import type {BlockDefinition} from '../core/blocks.js'; export { lists, diff --git a/blocks/lists.ts b/blocks/lists.ts index 3b468dc9d21..6754b6847db 100644 --- a/blocks/lists.ts +++ b/blocks/lists.ts @@ -6,22 +6,22 @@ // Former goog.module ID: Blockly.libraryBlocks.lists -import * as fieldRegistry from '../core/field_registry.js'; -import * as xmlUtils from '../core/utils/xml.js'; -import {Align} from '../core/inputs/align.js'; import type {Block} from '../core/block.js'; -import type {Connection} from '../core/connection.js'; import type {BlockSvg} from '../core/block_svg.js'; -import type {FieldDropdown} from '../core/field_dropdown.js'; -import {Msg} from '../core/msg.js'; -import {MutatorIcon} from '../core/icons/mutator_icon.js'; -import type {Workspace} from '../core/workspace.js'; import { createBlockDefinitionsFromJsonArray, defineBlocks, } from '../core/common.js'; +import type {Connection} from '../core/connection.js'; import '../core/field_dropdown.js'; +import type {FieldDropdown} from '../core/field_dropdown.js'; +import * as fieldRegistry from '../core/field_registry.js'; +import {MutatorIcon} from '../core/icons/mutator_icon.js'; +import {Align} from '../core/inputs/align.js'; import {ValueInput} from '../core/inputs/value_input.js'; +import {Msg} from '../core/msg.js'; +import * as xmlUtils from '../core/utils/xml.js'; +import type {Workspace} from '../core/workspace.js'; /** * A dictionary of the block definitions provided by this module. @@ -412,6 +412,24 @@ const LISTS_GETINDEX = { this.appendDummyInput() .appendField(modeMenu, 'MODE') .appendField('', 'SPACE'); + const menu = fieldRegistry.fromJson({ + type: 'field_dropdown', + options: this.WHERE_OPTIONS, + }) as FieldDropdown; + menu.setValidator( + /** @param value The input value. */ + function (this: FieldDropdown, value: string) { + const oldValue: string | null = this.getValue(); + const oldAt = oldValue === 'FROM_START' || oldValue === 'FROM_END'; + const newAt = value === 'FROM_START' || value === 'FROM_END'; + if (newAt !== oldAt) { + const block = this.getSourceBlock() as GetIndexBlock; + block.updateAt_(newAt); + } + return undefined; + }, + ); + this.appendDummyInput().appendField(menu, 'WHERE'); this.appendDummyInput('AT'); if (Msg['LISTS_GET_INDEX_TAIL']) { this.appendDummyInput('TAIL').appendField(Msg['LISTS_GET_INDEX_TAIL']); @@ -577,31 +595,6 @@ const LISTS_GETINDEX = { } else { this.appendDummyInput('AT'); } - const menu = fieldRegistry.fromJson({ - type: 'field_dropdown', - options: this.WHERE_OPTIONS, - }) as FieldDropdown; - menu.setValidator( - /** - * @param value The input value. - * @returns Null if the field has been replaced; otherwise undefined. - */ - function (this: FieldDropdown, value: string) { - const newAt = value === 'FROM_START' || value === 'FROM_END'; - // The 'isAt' variable is available due to this function being a - // closure. - if (newAt !== isAt) { - const block = this.getSourceBlock() as GetIndexBlock; - block.updateAt_(newAt); - // This menu has been destroyed and replaced. Update the - // replacement. - block.setFieldValue(value, 'WHERE'); - return null; - } - return undefined; - }, - ); - this.getInput('AT')!.appendField(menu, 'WHERE'); if (Msg['LISTS_GET_INDEX_TAIL']) { this.moveInputBefore('TAIL', null); } @@ -644,6 +637,24 @@ const LISTS_SETINDEX = { this.appendDummyInput() .appendField(operationDropdown, 'MODE') .appendField('', 'SPACE'); + const menu = fieldRegistry.fromJson({ + type: 'field_dropdown', + options: this.WHERE_OPTIONS, + }) as FieldDropdown; + menu.setValidator( + /** @param value The input value. */ + function (this: FieldDropdown, value: string) { + const oldValue: string | null = this.getValue(); + const oldAt = oldValue === 'FROM_START' || oldValue === 'FROM_END'; + const newAt = value === 'FROM_START' || value === 'FROM_END'; + if (newAt !== oldAt) { + const block = this.getSourceBlock() as SetIndexBlock; + block.updateAt_(newAt); + } + return undefined; + }, + ); + this.appendDummyInput().appendField(menu, 'WHERE'); this.appendDummyInput('AT'); this.appendValueInput('TO').appendField(Msg['LISTS_SET_INDEX_INPUT_TO']); this.setInputsInline(true); @@ -756,36 +767,10 @@ const LISTS_SETINDEX = { } else { this.appendDummyInput('AT'); } - const menu = fieldRegistry.fromJson({ - type: 'field_dropdown', - options: this.WHERE_OPTIONS, - }) as FieldDropdown; - menu.setValidator( - /** - * @param value The input value. - * @returns Null if the field has been replaced; otherwise undefined. - */ - function (this: FieldDropdown, value: string) { - const newAt = value === 'FROM_START' || value === 'FROM_END'; - // The 'isAt' variable is available due to this function being a - // closure. - if (newAt !== isAt) { - const block = this.getSourceBlock() as SetIndexBlock; - block.updateAt_(newAt); - // This menu has been destroyed and replaced. Update the - // replacement. - block.setFieldValue(value, 'WHERE'); - return null; - } - return undefined; - }, - ); this.moveInputBefore('AT', 'TO'); if (this.getInput('ORDINAL')) { this.moveInputBefore('ORDINAL', 'TO'); } - - this.getInput('AT')!.appendField(menu, 'WHERE'); }, }; blocks['lists_setIndex'] = LISTS_SETINDEX; @@ -818,7 +803,30 @@ const LISTS_GETSUBLIST = { this.appendValueInput('LIST') .setCheck('Array') .appendField(Msg['LISTS_GET_SUBLIST_INPUT_IN_LIST']); + const createMenu = (n: 1 | 2): FieldDropdown => { + const menu = fieldRegistry.fromJson({ + type: 'field_dropdown', + options: + this[('WHERE_OPTIONS_' + n) as 'WHERE_OPTIONS_1' | 'WHERE_OPTIONS_2'], + }) as FieldDropdown; + menu.setValidator( + /** @param value The input value. */ + function (this: FieldDropdown, value: string) { + const oldValue: string | null = this.getValue(); + const oldAt = oldValue === 'FROM_START' || oldValue === 'FROM_END'; + const newAt = value === 'FROM_START' || value === 'FROM_END'; + if (newAt !== oldAt) { + const block = this.getSourceBlock() as GetSublistBlock; + block.updateAt_(n, newAt); + } + return undefined; + }, + ); + return menu; + }; + this.appendDummyInput('WHERE1_INPUT').appendField(createMenu(1), 'WHERE1'); this.appendDummyInput('AT1'); + this.appendDummyInput('WHERE2_INPUT').appendField(createMenu(2), 'WHERE2'); this.appendDummyInput('AT2'); if (Msg['LISTS_GET_SUBLIST_TAIL']) { this.appendDummyInput('TAIL').appendField(Msg['LISTS_GET_SUBLIST_TAIL']); @@ -896,35 +904,10 @@ const LISTS_GETSUBLIST = { } else { this.appendDummyInput('AT' + n); } - const menu = fieldRegistry.fromJson({ - type: 'field_dropdown', - options: - this[('WHERE_OPTIONS_' + n) as 'WHERE_OPTIONS_1' | 'WHERE_OPTIONS_2'], - }) as FieldDropdown; - menu.setValidator( - /** - * @param value The input value. - * @returns Null if the field has been replaced; otherwise undefined. - */ - function (this: FieldDropdown, value: string) { - const newAt = value === 'FROM_START' || value === 'FROM_END'; - // The 'isAt' variable is available due to this function being a - // closure. - if (newAt !== isAt) { - const block = this.getSourceBlock() as GetSublistBlock; - block.updateAt_(n, newAt); - // This menu has been destroyed and replaced. - // Update the replacement. - block.setFieldValue(value, 'WHERE' + n); - return null; - } - }, - ); - this.getInput('AT' + n)!.appendField(menu, 'WHERE' + n); if (n === 1) { - this.moveInputBefore('AT1', 'AT2'); + this.moveInputBefore('AT1', 'WHERE2_INPUT'); if (this.getInput('ORDINAL1')) { - this.moveInputBefore('ORDINAL1', 'AT2'); + this.moveInputBefore('ORDINAL1', 'WHERE2_INPUT'); } } if (Msg['LISTS_GET_SUBLIST_TAIL']) { diff --git a/blocks/logic.ts b/blocks/logic.ts index 3e5b807ebcf..d2a7405fffa 100644 --- a/blocks/logic.ts +++ b/blocks/logic.ts @@ -6,22 +6,22 @@ // Former goog.module ID: Blockly.libraryBlocks.logic -import * as Events from '../core/events/events.js'; -import * as Extensions from '../core/extensions.js'; -import * as xmlUtils from '../core/utils/xml.js'; -import type {Abstract as AbstractEvent} from '../core/events/events_abstract.js'; import type {Block} from '../core/block.js'; import type {BlockSvg} from '../core/block_svg.js'; -import type {Connection} from '../core/connection.js'; -import {Msg} from '../core/msg.js'; -import type {Workspace} from '../core/workspace.js'; import { createBlockDefinitionsFromJsonArray, defineBlocks, } from '../core/common.js'; +import type {Connection} from '../core/connection.js'; +import * as Events from '../core/events/events.js'; +import type {Abstract as AbstractEvent} from '../core/events/events_abstract.js'; +import * as Extensions from '../core/extensions.js'; import '../core/field_dropdown.js'; import '../core/field_label.js'; import '../core/icons/mutator_icon.js'; +import {Msg} from '../core/msg.js'; +import * as xmlUtils from '../core/utils/xml.js'; +import type {Workspace} from '../core/workspace.js'; /** * A dictionary of the block definitions provided by this module. diff --git a/blocks/loops.ts b/blocks/loops.ts index c7cb710d770..dd5a8116211 100644 --- a/blocks/loops.ts +++ b/blocks/loops.ts @@ -6,27 +6,27 @@ // Former goog.module ID: Blockly.libraryBlocks.loops -import type {Abstract as AbstractEvent} from '../core/events/events_abstract.js'; import type {Block} from '../core/block.js'; +import { + createBlockDefinitionsFromJsonArray, + defineBlocks, +} from '../core/common.js'; import * as ContextMenu from '../core/contextmenu.js'; import type { ContextMenuOption, LegacyContextMenuOption, } from '../core/contextmenu_registry.js'; import * as Events from '../core/events/events.js'; -import * as Extensions from '../core/extensions.js'; -import {Msg} from '../core/msg.js'; -import { - createBlockDefinitionsFromJsonArray, - defineBlocks, -} from '../core/common.js'; +import type {Abstract as AbstractEvent} from '../core/events/events_abstract.js'; import * as eventUtils from '../core/events/utils.js'; +import * as Extensions from '../core/extensions.js'; import '../core/field_dropdown.js'; import '../core/field_label.js'; import '../core/field_number.js'; import '../core/field_variable.js'; -import '../core/icons/warning_icon.js'; import {FieldVariable} from '../core/field_variable.js'; +import '../core/icons/warning_icon.js'; +import {Msg} from '../core/msg.js'; import {WorkspaceSvg} from '../core/workspace_svg.js'; /** diff --git a/blocks/math.ts b/blocks/math.ts index c96aef3c23b..e5aef5fbb6e 100644 --- a/blocks/math.ts +++ b/blocks/math.ts @@ -6,18 +6,18 @@ // Former goog.module ID: Blockly.libraryBlocks.math -import * as Extensions from '../core/extensions.js'; -import type {FieldDropdown} from '../core/field_dropdown.js'; -import * as xmlUtils from '../core/utils/xml.js'; import type {Block} from '../core/block.js'; import { createBlockDefinitionsFromJsonArray, defineBlocks, } from '../core/common.js'; +import * as Extensions from '../core/extensions.js'; import '../core/field_dropdown.js'; +import type {FieldDropdown} from '../core/field_dropdown.js'; import '../core/field_label.js'; import '../core/field_number.js'; import '../core/field_variable.js'; +import * as xmlUtils from '../core/utils/xml.js'; /** * A dictionary of the block definitions provided by this module. diff --git a/blocks/procedures.ts b/blocks/procedures.ts index 1214eb55eda..20d8fa36bb0 100644 --- a/blocks/procedures.ts +++ b/blocks/procedures.ts @@ -6,40 +6,40 @@ // Former goog.module ID: Blockly.libraryBlocks.procedures -import * as ContextMenu from '../core/contextmenu.js'; -import * as Events from '../core/events/events.js'; -import * as Procedures from '../core/procedures.js'; -import * as Variables from '../core/variables.js'; -import * as Xml from '../core/xml.js'; -import * as fieldRegistry from '../core/field_registry.js'; -import * as xmlUtils from '../core/utils/xml.js'; -import type {Abstract as AbstractEvent} from '../core/events/events_abstract.js'; -import {Align} from '../core/inputs/align.js'; import type {Block} from '../core/block.js'; import type {BlockSvg} from '../core/block_svg.js'; -import type {BlockCreate} from '../core/events/events_block_create.js'; -import type {BlockChange} from '../core/events/events_block_change.js'; import type {BlockDefinition} from '../core/blocks.js'; +import * as common from '../core/common.js'; +import {defineBlocks} from '../core/common.js'; +import {config} from '../core/config.js'; import type {Connection} from '../core/connection.js'; +import * as ContextMenu from '../core/contextmenu.js'; import type { ContextMenuOption, LegacyContextMenuOption, } from '../core/contextmenu_registry.js'; +import * as Events from '../core/events/events.js'; +import type {Abstract as AbstractEvent} from '../core/events/events_abstract.js'; +import type {BlockChange} from '../core/events/events_block_change.js'; +import type {BlockCreate} from '../core/events/events_block_create.js'; import * as eventUtils from '../core/events/utils.js'; import {FieldCheckbox} from '../core/field_checkbox.js'; import {FieldLabel} from '../core/field_label.js'; +import * as fieldRegistry from '../core/field_registry.js'; import {FieldTextInput} from '../core/field_textinput.js'; -import {Msg} from '../core/msg.js'; +import '../core/icons/comment_icon.js'; import {MutatorIcon as Mutator} from '../core/icons/mutator_icon.js'; +import '../core/icons/warning_icon.js'; +import {Align} from '../core/inputs/align.js'; +import {Msg} from '../core/msg.js'; import {Names} from '../core/names.js'; +import * as Procedures from '../core/procedures.js'; +import * as xmlUtils from '../core/utils/xml.js'; import type {VariableModel} from '../core/variable_model.js'; +import * as Variables from '../core/variables.js'; import type {Workspace} from '../core/workspace.js'; import type {WorkspaceSvg} from '../core/workspace_svg.js'; -import {config} from '../core/config.js'; -import {defineBlocks} from '../core/common.js'; -import '../core/icons/comment_icon.js'; -import '../core/icons/warning_icon.js'; -import * as common from '../core/common.js'; +import * as Xml from '../core/xml.js'; /** A dictionary of the block definitions provided by this module. */ export const blocks: {[key: string]: BlockDefinition} = {}; @@ -1099,6 +1099,14 @@ const PROCEDURE_CALL_COMMON = { xml.appendChild(block); Xml.domToWorkspace(xml, this.workspace); Events.setGroup(false); + } else if (!def.isEnabled()) { + this.setDisabledReason( + true, + DISABLED_PROCEDURE_DEFINITION_DISABLED_REASON, + ); + this.setWarningText( + Msg['PROCEDURES_CALL_DISABLED_DEF_WARNING'].replace('%1', name), + ); } } else if (event.type === Events.BLOCK_DELETE) { // Look for the case where a procedure definition has been deleted, @@ -1206,7 +1214,7 @@ blocks['procedures_callreturn'] = { this.appendDummyInput('TOPROW').appendField('', 'NAME'); this.setOutput(true); this.setStyle('procedure_blocks'); - // Tooltip is set in domToMutation. + // Tooltip is set in renameProcedure. this.setHelpUrl(Msg['PROCEDURES_CALLRETURN_HELPURL']); this.arguments_ = []; this.argumentVarModels_ = []; diff --git a/blocks/text.ts b/blocks/text.ts index 91a27005a92..a7ad5374ac4 100644 --- a/blocks/text.ts +++ b/blocks/text.ts @@ -6,25 +6,25 @@ // Former goog.module ID: Blockly.libraryBlocks.texts -import * as Extensions from '../core/extensions.js'; -import * as fieldRegistry from '../core/field_registry.js'; -import * as xmlUtils from '../core/utils/xml.js'; -import {Align} from '../core/inputs/align.js'; import type {Block} from '../core/block.js'; import type {BlockSvg} from '../core/block_svg.js'; -import {Connection} from '../core/connection.js'; -import {FieldImage} from '../core/field_image.js'; -import {FieldDropdown} from '../core/field_dropdown.js'; -import {FieldTextInput} from '../core/field_textinput.js'; -import {Msg} from '../core/msg.js'; -import {MutatorIcon} from '../core/icons/mutator_icon.js'; -import type {Workspace} from '../core/workspace.js'; import { createBlockDefinitionsFromJsonArray, defineBlocks, } from '../core/common.js'; +import {Connection} from '../core/connection.js'; +import * as Extensions from '../core/extensions.js'; +import {FieldDropdown} from '../core/field_dropdown.js'; +import {FieldImage} from '../core/field_image.js'; +import * as fieldRegistry from '../core/field_registry.js'; +import {FieldTextInput} from '../core/field_textinput.js'; import '../core/field_variable.js'; +import {MutatorIcon} from '../core/icons/mutator_icon.js'; +import {Align} from '../core/inputs/align.js'; import {ValueInput} from '../core/inputs/value_input.js'; +import {Msg} from '../core/msg.js'; +import * as xmlUtils from '../core/utils/xml.js'; +import type {Workspace} from '../core/workspace.js'; /** * A dictionary of the block definitions provided by this module. @@ -216,7 +216,30 @@ const GET_SUBSTRING_BLOCK = { this.appendValueInput('STRING') .setCheck('String') .appendField(Msg['TEXT_GET_SUBSTRING_INPUT_IN_TEXT']); + const createMenu = (n: 1 | 2): FieldDropdown => { + const menu = fieldRegistry.fromJson({ + type: 'field_dropdown', + options: + this[('WHERE_OPTIONS_' + n) as 'WHERE_OPTIONS_1' | 'WHERE_OPTIONS_2'], + }) as FieldDropdown; + menu.setValidator( + /** @param value The input value. */ + function (this: FieldDropdown, value: any): null | undefined { + const oldValue: string | null = this.getValue(); + const oldAt = oldValue === 'FROM_START' || oldValue === 'FROM_END'; + const newAt = value === 'FROM_START' || value === 'FROM_END'; + if (newAt !== oldAt) { + const block = this.getSourceBlock() as GetSubstringBlock; + block.updateAt_(n, newAt); + } + return undefined; + }, + ); + return menu; + }; + this.appendDummyInput('WHERE1_INPUT').appendField(createMenu(1), 'WHERE1'); this.appendDummyInput('AT1'); + this.appendDummyInput('WHERE2_INPUT').appendField(createMenu(2), 'WHERE2'); this.appendDummyInput('AT2'); if (Msg['TEXT_GET_SUBSTRING_TAIL']) { this.appendDummyInput('TAIL').appendField(Msg['TEXT_GET_SUBSTRING_TAIL']); @@ -288,37 +311,10 @@ const GET_SUBSTRING_BLOCK = { this.removeInput('TAIL', true); this.appendDummyInput('TAIL').appendField(Msg['TEXT_GET_SUBSTRING_TAIL']); } - const menu = fieldRegistry.fromJson({ - type: 'field_dropdown', - options: - this[('WHERE_OPTIONS_' + n) as 'WHERE_OPTIONS_1' | 'WHERE_OPTIONS_2'], - }) as FieldDropdown; - menu.setValidator( - /** - * @param value The input value. - * @returns Null if the field has been replaced; otherwise undefined. - */ - function (this: FieldDropdown, value: any): null | undefined { - const newAt = value === 'FROM_START' || value === 'FROM_END'; - // The 'isAt' variable is available due to this function being a - // closure. - if (newAt !== isAt) { - const block = this.getSourceBlock() as GetSubstringBlock; - block.updateAt_(n, newAt); - // This menu has been destroyed and replaced. - // Update the replacement. - block.setFieldValue(value, 'WHERE' + n); - return null; - } - return undefined; - }, - ); - - this.getInput('AT' + n)!.appendField(menu, 'WHERE' + n); if (n === 1) { - this.moveInputBefore('AT1', 'AT2'); + this.moveInputBefore('AT1', 'WHERE2_INPUT'); if (this.getInput('ORDINAL1')) { - this.moveInputBefore('ORDINAL1', 'AT2'); + this.moveInputBefore('ORDINAL1', 'WHERE2_INPUT'); } } }, @@ -438,6 +434,11 @@ const PROMPT_COMMON = { domToMutation: function (this: PromptCommonBlock, xmlElement: Element) { this.updateType_(xmlElement.getAttribute('type')!); }, + + // These blocks do not need JSO serialization hooks (saveExtraState + // and loadExtraState) because the state of this object is already + // encoded in the dropdown values. + // XML hooks are kept for backwards compatibility. }; blocks['text_prompt_ext'] = { @@ -468,16 +469,11 @@ blocks['text_prompt_ext'] = { : Msg['TEXT_PROMPT_TOOLTIP_NUMBER']; }); }, - - // This block does not need JSO serialization hooks (saveExtraState and - // loadExtraState) because the state of this object is already encoded in the - // dropdown values. - // XML hooks are kept for backwards compatibility. }; type PromptBlock = Block & PromptCommonMixin & QuoteImageMixin; -const TEXT_PROMPT_BLOCK = { +blocks['text_prompt'] = { ...PROMPT_COMMON, /** * Block for prompt function (internal message). @@ -520,8 +516,6 @@ const TEXT_PROMPT_BLOCK = { }, }; -blocks['text_prompt'] = TEXT_PROMPT_BLOCK; - blocks['text_count'] = { /** * Block for counting how many times one string appears within another string. @@ -666,7 +660,7 @@ const QUOTE_IMAGE_MIXIN = { * closing double quote. The selected quote will be adapted for RTL blocks. * * @param open If the image should be open quote (“ in LTR). - * Otherwise, a closing quote is used (” in LTR). + * Otherwise, a closing quote is used (” in LTR). * @returns The new field. */ newQuote_: function (this: QuoteImageBlock, open: boolean): FieldImage { diff --git a/blocks/variables.ts b/blocks/variables.ts index 8ac038fb2ce..0ec9112a3d6 100644 --- a/blocks/variables.ts +++ b/blocks/variables.ts @@ -6,22 +6,22 @@ // Former goog.module ID: Blockly.libraryBlocks.variables -import * as ContextMenu from '../core/contextmenu.js'; -import * as Extensions from '../core/extensions.js'; -import * as Variables from '../core/variables.js'; import type {Block} from '../core/block.js'; +import { + createBlockDefinitionsFromJsonArray, + defineBlocks, +} from '../core/common.js'; +import * as ContextMenu from '../core/contextmenu.js'; import type { ContextMenuOption, LegacyContextMenuOption, } from '../core/contextmenu_registry.js'; +import * as Extensions from '../core/extensions.js'; +import '../core/field_label.js'; import {FieldVariable} from '../core/field_variable.js'; import {Msg} from '../core/msg.js'; +import * as Variables from '../core/variables.js'; import type {WorkspaceSvg} from '../core/workspace_svg.js'; -import { - createBlockDefinitionsFromJsonArray, - defineBlocks, -} from '../core/common.js'; -import '../core/field_label.js'; /** * A dictionary of the block definitions provided by this module. diff --git a/blocks/variables_dynamic.ts b/blocks/variables_dynamic.ts index e74cae423ab..8e4ce290e09 100644 --- a/blocks/variables_dynamic.ts +++ b/blocks/variables_dynamic.ts @@ -6,23 +6,23 @@ // Former goog.module ID: Blockly.libraryBlocks.variablesDynamic -import * as ContextMenu from '../core/contextmenu.js'; -import * as Extensions from '../core/extensions.js'; -import * as Variables from '../core/variables.js'; -import {Abstract as AbstractEvent} from '../core/events/events_abstract.js'; import type {Block} from '../core/block.js'; +import { + createBlockDefinitionsFromJsonArray, + defineBlocks, +} from '../core/common.js'; +import * as ContextMenu from '../core/contextmenu.js'; import type { ContextMenuOption, LegacyContextMenuOption, } from '../core/contextmenu_registry.js'; +import {Abstract as AbstractEvent} from '../core/events/events_abstract.js'; +import * as Extensions from '../core/extensions.js'; +import '../core/field_label.js'; import {FieldVariable} from '../core/field_variable.js'; import {Msg} from '../core/msg.js'; +import * as Variables from '../core/variables.js'; import type {WorkspaceSvg} from '../core/workspace_svg.js'; -import { - createBlockDefinitionsFromJsonArray, - defineBlocks, -} from '../core/common.js'; -import '../core/field_label.js'; /** * A dictionary of the block definitions provided by this module. diff --git a/core/block.ts b/core/block.ts index 52191d63c3c..0face8f8c9b 100644 --- a/core/block.ts +++ b/core/block.ts @@ -23,35 +23,36 @@ import * as common from './common.js'; import {Connection} from './connection.js'; import {ConnectionType} from './connection_type.js'; import * as constants from './constants.js'; -import {DuplicateIconType} from './icons/exceptions.js'; import type {Abstract} from './events/events_abstract.js'; import type {BlockChange} from './events/events_block_change.js'; import type {BlockMove} from './events/events_block_move.js'; -import * as deprecation from './utils/deprecation.js'; +import {EventType} from './events/type.js'; import * as eventUtils from './events/utils.js'; import * as Extensions from './extensions.js'; import type {Field} from './field.js'; import * as fieldRegistry from './field_registry.js'; -import {Input} from './inputs/input.js'; +import {DuplicateIconType} from './icons/exceptions.js'; +import {IconType} from './icons/icon_types.js'; +import type {MutatorIcon} from './icons/mutator_icon.js'; import {Align} from './inputs/align.js'; +import {DummyInput} from './inputs/dummy_input.js'; +import {EndRowInput} from './inputs/end_row_input.js'; +import {Input} from './inputs/input.js'; +import {StatementInput} from './inputs/statement_input.js'; +import {ValueInput} from './inputs/value_input.js'; import type {IASTNodeLocation} from './interfaces/i_ast_node_location.js'; -import {type IIcon} from './interfaces/i_icon.js'; import {isCommentIcon} from './interfaces/i_comment_icon.js'; -import type {MutatorIcon} from './icons/mutator_icon.js'; +import {type IIcon} from './interfaces/i_icon.js'; +import * as registry from './registry.js'; import * as Tooltip from './tooltip.js'; import * as arrayUtils from './utils/array.js'; import {Coordinate} from './utils/coordinate.js'; +import * as deprecation from './utils/deprecation.js'; import * as idGenerator from './utils/idgenerator.js'; import * as parsing from './utils/parsing.js'; -import * as registry from './registry.js'; import {Size} from './utils/size.js'; import type {VariableModel} from './variable_model.js'; import type {Workspace} from './workspace.js'; -import {DummyInput} from './inputs/dummy_input.js'; -import {EndRowInput} from './inputs/end_row_input.js'; -import {ValueInput} from './inputs/value_input.js'; -import {StatementInput} from './inputs/statement_input.js'; -import {IconType} from './icons/icon_types.js'; /** * Class for one block. @@ -88,7 +89,7 @@ export class Block implements IASTNodeLocation { * Colour of the block as HSV hue value (0-360) * This may be null if the block colour was not set via a hue number. */ - private hue_: number | null = null; + private hue: number | null = null; /** Colour of the block in '#RRGGBB' format. */ protected colour_ = '#000000'; @@ -143,24 +144,31 @@ export class Block implements IASTNodeLocation { suppressPrefixSuffix: boolean | null = false; /** - * An optional property for declaring developer variables. Return a list of - * variable names for use by generators. Developer variables are never - * shown to the user, but are declared as global variables in the generated - * code. + * An optional method for declaring developer variables, to be used + * by generators. Developer variables are never shown to the user, + * but are declared as global variables in the generated code. + * + * @returns a list of developer variable names. */ getDeveloperVariables?: () => string[]; /** - * An optional function that reconfigures the block based on the contents of - * the mutator dialog. + * An optional method that reconfigures the block based on the + * contents of the mutator dialog. + * + * @param rootBlock The root block in the mutator flyout. */ - compose?: (p1: Block) => void; + compose?: (rootBlock: Block) => void; /** - * An optional function that populates the mutator's dialog with - * this block's components. + * An optional function that populates the mutator flyout with + * blocks representing this block's configuration. + * + * @param workspace The mutator flyout's workspace. + * @returns The root block created in the flyout's workspace. */ - decompose?: (p1: Workspace) => Block; + decompose?: (workspace: Workspace) => Block; + id: string; outputConnection: Connection | null = null; nextConnection: Connection | null = null; @@ -176,13 +184,13 @@ export class Block implements IASTNodeLocation { protected childBlocks_: this[] = []; - private deletable_ = true; + private deletable = true; - private movable_ = true; + private movable = true; - private editable_ = true; + private editable = true; - private isShadow_ = false; + private shadow = false; protected collapsed_ = false; protected outputShape_: number | null = null; @@ -199,7 +207,7 @@ export class Block implements IASTNodeLocation { */ initialized = false; - private readonly xy_: Coordinate; + private readonly xy: Coordinate; isInFlyout: boolean; isInMutator: boolean; RTL: boolean; @@ -216,10 +224,10 @@ export class Block implements IASTNodeLocation { /** * String for block help, or function that returns a URL. Null for no help. */ - helpUrl: string | Function | null = null; + helpUrl: string | (() => string) | null = null; /** A bound callback function to use when the parent workspace changes. */ - private onchangeWrapper_: ((p1: Abstract) => void) | null = null; + private onchangeWrapper: ((p1: Abstract) => void) | null = null; /** * A count of statement inputs on the block. @@ -252,7 +260,7 @@ export class Block implements IASTNodeLocation { * The block's position in workspace units. (0, 0) is at the workspace's * origin; scale does not change this value. */ - this.xy_ = new Coordinate(0, 0); + this.xy = new Coordinate(0, 0); this.isInFlyout = workspace.isFlyout; this.isInMutator = workspace.isMutator; @@ -297,7 +305,7 @@ export class Block implements IASTNodeLocation { // Fire a create event. if (eventUtils.isEnabled()) { - eventUtils.fire(new (eventUtils.get(eventUtils.BLOCK_CREATE))(this)); + eventUtils.fire(new (eventUtils.get(EventType.BLOCK_CREATE))(this)); } } finally { eventUtils.setGroup(existingGroup); @@ -325,14 +333,14 @@ export class Block implements IASTNodeLocation { // Dispose of this change listener before unplugging. // Technically not necessary due to the event firing delay. // But future-proofing. - if (this.onchangeWrapper_) { - this.workspace.removeChangeListener(this.onchangeWrapper_); + if (this.onchangeWrapper) { + this.workspace.removeChangeListener(this.onchangeWrapper); } this.unplug(healStack); if (eventUtils.isEnabled()) { // Constructing the delete event is costly. Only perform if necessary. - eventUtils.fire(new (eventUtils.get(eventUtils.BLOCK_DELETE))(this)); + eventUtils.fire(new (eventUtils.get(EventType.BLOCK_DELETE))(this)); } this.workspace.removeTopBlock(this); this.disposeInternal(); @@ -344,8 +352,8 @@ export class Block implements IASTNodeLocation { */ protected disposeInternal() { this.disposing = true; - if (this.onchangeWrapper_) { - this.workspace.removeChangeListener(this.onchangeWrapper_); + if (this.onchangeWrapper) { + this.workspace.removeChangeListener(this.onchangeWrapper); } this.workspace.removeTypedBlock(this); @@ -395,10 +403,10 @@ export class Block implements IASTNodeLocation { */ unplug(opt_healStack?: boolean) { if (this.outputConnection) { - this.unplugFromRow_(opt_healStack); + this.unplugFromRow(opt_healStack); } if (this.previousConnection) { - this.unplugFromStack_(opt_healStack); + this.unplugFromStack(opt_healStack); } } @@ -409,7 +417,7 @@ export class Block implements IASTNodeLocation { * @param opt_healStack Disconnect right-side block and connect to left-side * block. Defaults to false. */ - private unplugFromRow_(opt_healStack?: boolean) { + private unplugFromRow(opt_healStack?: boolean) { let parentConnection = null; if (this.outputConnection?.isConnected()) { parentConnection = this.outputConnection.targetConnection; @@ -422,7 +430,7 @@ export class Block implements IASTNodeLocation { return; } - const thisConnection = this.getOnlyValueConnection_(); + const thisConnection = this.getOnlyValueConnection(); if ( !thisConnection || !thisConnection.isConnected() || @@ -459,7 +467,7 @@ export class Block implements IASTNodeLocation { * * @returns The connection on the value input, or null. */ - private getOnlyValueConnection_(): Connection | null { + private getOnlyValueConnection(): Connection | null { let connection = null; for (let i = 0; i < this.inputList.length; i++) { const thisConnection = this.inputList[i].connection; @@ -484,7 +492,7 @@ export class Block implements IASTNodeLocation { * @param opt_healStack Disconnect child statement and reconnect stack. * Defaults to false. */ - private unplugFromStack_(opt_healStack?: boolean) { + private unplugFromStack(opt_healStack?: boolean) { let previousTarget = null; if (this.previousConnection?.isConnected()) { // Remember the connection that any next statements need to connect to. @@ -716,7 +724,7 @@ export class Block implements IASTNodeLocation { } // Check that block is connected to new parent if new parent is not null and - // that block is not connected to superior one if new parent is null. + // that block is not connected to superior one if new parent is null. const targetBlock = (this.previousConnection && this.previousConnection.targetBlock()) || (this.outputConnection && this.outputConnection.targetBlock()); @@ -734,14 +742,13 @@ export class Block implements IASTNodeLocation { } // This block hasn't actually moved on-screen, so there's no need to - // update - // its connection locations. + // update its connection locations. if (this.parentBlock_) { // Remove this block from the old parent's child list. arrayUtils.removeElem(this.parentBlock_.childBlocks_, this); } else { - // New parent must be non-null so remove this block from the workspace's - // list of top-most blocks. + // New parent must be non-null so remove this block from the + // workspace's list of top-most blocks. this.workspace.removeTopBlock(this); } @@ -782,8 +789,8 @@ export class Block implements IASTNodeLocation { */ isDeletable(): boolean { return ( - this.deletable_ && - !this.isShadow_ && + this.deletable && + !this.shadow && !this.isDeadOrDying() && !this.workspace.options.readOnly ); @@ -795,7 +802,7 @@ export class Block implements IASTNodeLocation { * @returns True if the block's deletable property is true, false otherwise. */ isOwnDeletable(): boolean { - return this.deletable_; + return this.deletable; } /** @@ -804,7 +811,7 @@ export class Block implements IASTNodeLocation { * @param deletable True if deletable. */ setDeletable(deletable: boolean) { - this.deletable_ = deletable; + this.deletable = deletable; } /** @@ -815,8 +822,8 @@ export class Block implements IASTNodeLocation { */ isMovable(): boolean { return ( - this.movable_ && - !this.isShadow_ && + this.movable && + !this.shadow && !this.isDeadOrDying() && !this.workspace.options.readOnly ); @@ -829,7 +836,7 @@ export class Block implements IASTNodeLocation { * @internal */ isOwnMovable(): boolean { - return this.movable_; + return this.movable; } /** @@ -838,7 +845,7 @@ export class Block implements IASTNodeLocation { * @param movable True if movable. */ setMovable(movable: boolean) { - this.movable_ = movable; + this.movable = movable; } /** @@ -864,7 +871,7 @@ export class Block implements IASTNodeLocation { * @returns True if a shadow. */ isShadow(): boolean { - return this.isShadow_; + return this.shadow; } /** @@ -876,7 +883,7 @@ export class Block implements IASTNodeLocation { * @internal */ setShadow(shadow: boolean) { - this.isShadow_ = shadow; + this.shadow = shadow; } /** @@ -907,9 +914,7 @@ export class Block implements IASTNodeLocation { */ isEditable(): boolean { return ( - this.editable_ && - !this.isDeadOrDying() && - !this.workspace.options.readOnly + this.editable && !this.isDeadOrDying() && !this.workspace.options.readOnly ); } @@ -919,7 +924,7 @@ export class Block implements IASTNodeLocation { * @returns True if the block's editable property is true, false otherwise. */ isOwnEditable(): boolean { - return this.editable_; + return this.editable; } /** @@ -928,7 +933,7 @@ export class Block implements IASTNodeLocation { * @param editable True if editable. */ setEditable(editable: boolean) { - this.editable_ = editable; + this.editable = editable; for (let i = 0, input; (input = this.inputList[i]); i++) { for (let j = 0, field; (field = input.fieldRow[j]); j++) { field.updateEditable(); @@ -991,7 +996,7 @@ export class Block implements IASTNodeLocation { * @param url URL string for block help, or function that returns a URL. Null * for no help. */ - setHelpUrl(url: string | Function) { + setHelpUrl(url: string | (() => string)) { this.helpUrl = url; } @@ -1039,7 +1044,7 @@ export class Block implements IASTNodeLocation { * @returns Hue value (0-360). */ getHue(): number | null { - return this.hue_; + return this.hue; } /** @@ -1050,7 +1055,7 @@ export class Block implements IASTNodeLocation { */ setColour(colour: number | string) { const parsed = parsing.parseBlockColour(colour); - this.hue_ = parsed.hue; + this.hue = parsed.hue; this.colour_ = parsed.hex; } @@ -1076,12 +1081,12 @@ export class Block implements IASTNodeLocation { if (onchangeFn && typeof onchangeFn !== 'function') { throw Error('onchange must be a function.'); } - if (this.onchangeWrapper_) { - this.workspace.removeChangeListener(this.onchangeWrapper_); + if (this.onchangeWrapper) { + this.workspace.removeChangeListener(this.onchangeWrapper); } this.onchange = onchangeFn; - this.onchangeWrapper_ = onchangeFn.bind(this); - this.workspace.addChangeListener(this.onchangeWrapper_); + this.onchangeWrapper = onchangeFn.bind(this); + this.workspace.addChangeListener(this.onchangeWrapper); } /** @@ -1323,7 +1328,7 @@ export class Block implements IASTNodeLocation { setInputsInline(newBoolean: boolean) { if (this.inputsInline !== newBoolean) { eventUtils.fire( - new (eventUtils.get(eventUtils.BLOCK_CHANGE))( + new (eventUtils.get(EventType.BLOCK_CHANGE))( this, 'inline', null, @@ -1460,13 +1465,32 @@ export class Block implements IASTNodeLocation { * update whether the block is currently disabled for this reason. */ setDisabledReason(disabled: boolean, reason: string): void { + // Workspaces that were serialized before the reason for being disabled + // could be specified may have blocks that are disabled without a known + // reason. On being loaded, these blocks will default to having the manually + // disabled reason. However, if the user isn't allowed to manually disable + // or enable blocks, then this manually disabled reason cannot be removed. + // For backward compatibility with these legacy workspaces, when removing + // any disabled reason and the workspace does not allow manually disabling + // but the block is manually disabled, then remove the manually disabled + // reason in addition to the more specific reason. For example, when an + // orphaned block is no longer orphaned, the block should be enabled again. + if ( + !disabled && + !this.workspace.options.disable && + this.hasDisabledReason(constants.MANUALLY_DISABLED) && + reason != constants.MANUALLY_DISABLED + ) { + this.setDisabledReason(false, constants.MANUALLY_DISABLED); + } + if (this.disabledReasons.has(reason) !== disabled) { if (disabled) { this.disabledReasons.add(reason); } else { this.disabledReasons.delete(reason); } - const blockChangeEvent = new (eventUtils.get(eventUtils.BLOCK_CHANGE))( + const blockChangeEvent = new (eventUtils.get(EventType.BLOCK_CHANGE))( this, 'disabled', /* name= */ null, @@ -1534,7 +1558,7 @@ export class Block implements IASTNodeLocation { setCollapsed(collapsed: boolean) { if (this.collapsed_ !== collapsed) { eventUtils.fire( - new (eventUtils.get(eventUtils.BLOCK_CHANGE))( + new (eventUtils.get(EventType.BLOCK_CHANGE))( this, 'collapsed', null, @@ -1748,15 +1772,15 @@ export class Block implements IASTNodeLocation { if (json['style'] && json['colour']) { throw Error(warningPrefix + 'Must not have both a colour and a style.'); } else if (json['style']) { - this.jsonInitStyle_(json, warningPrefix); + this.jsonInitStyle(json, warningPrefix); } else { - this.jsonInitColour_(json, warningPrefix); + this.jsonInitColour(json, warningPrefix); } // Interpolate the message blocks. let i = 0; while (json['message' + i] !== undefined) { - this.interpolate_( + this.interpolate( json['message' + i], json['args' + i] || [], // Backwards compatibility: lastDummyAlign aliases implicitAlign. @@ -1831,7 +1855,7 @@ export class Block implements IASTNodeLocation { * @param json Structured data describing the block. * @param warningPrefix Warning prefix string identifying block. */ - private jsonInitColour_(json: AnyDuringMigration, warningPrefix: string) { + private jsonInitColour(json: AnyDuringMigration, warningPrefix: string) { if ('colour' in json) { if (json['colour'] === undefined) { console.warn(warningPrefix + 'Undefined colour value.'); @@ -1839,7 +1863,7 @@ export class Block implements IASTNodeLocation { const rawValue = json['colour']; try { this.setColour(rawValue); - } catch (e) { + } catch { console.warn(warningPrefix + 'Illegal colour value: ', rawValue); } } @@ -1852,11 +1876,11 @@ export class Block implements IASTNodeLocation { * @param json Structured data describing the block. * @param warningPrefix Warning prefix string identifying block. */ - private jsonInitStyle_(json: AnyDuringMigration, warningPrefix: string) { + private jsonInitStyle(json: AnyDuringMigration, warningPrefix: string) { const blockStyleName = json['style']; try { this.setStyle(blockStyleName); - } catch (styleError) { + } catch { console.warn(warningPrefix + 'Style does not exist: ', blockStyleName); } } @@ -1904,21 +1928,21 @@ export class Block implements IASTNodeLocation { * of newline tokens, how should it be aligned? * @param warningPrefix Warning prefix string identifying block. */ - private interpolate_( + private interpolate( message: string, args: AnyDuringMigration[], implicitAlign: string | undefined, warningPrefix: string, ) { const tokens = parsing.tokenizeInterpolation(message); - this.validateTokens_(tokens, args.length); - const elements = this.interpolateArguments_(tokens, args, implicitAlign); + this.validateTokens(tokens, args.length); + const elements = this.interpolateArguments(tokens, args, implicitAlign); // An array of [field, fieldName] tuples. const fieldStack = []; for (let i = 0, element; (element = elements[i]); i++) { - if (this.isInputKeyword_(element['type'])) { - const input = this.inputFromJson_(element, warningPrefix); + if (this.isInputKeyword(element['type'])) { + const input = this.inputFromJson(element, warningPrefix); // Should never be null, but just in case. if (input) { for (let j = 0, tuple; (tuple = fieldStack[j]); j++) { @@ -1929,7 +1953,7 @@ export class Block implements IASTNodeLocation { } else { // All other types, including ones starting with 'input_' get routed // here. - const field = this.fieldFromJson_(element); + const field = this.fieldFromJson(element); if (field) { fieldStack.push([field, element['name']]); } @@ -1945,7 +1969,7 @@ export class Block implements IASTNodeLocation { * @param tokens An array of tokens to validate * @param argsCount The number of args that need to be referred to. */ - private validateTokens_(tokens: Array, argsCount: number) { + private validateTokens(tokens: Array, argsCount: number) { const visitedArgsHash = []; let visitedArgsCount = 0; for (let i = 0; i < tokens.length; i++) { @@ -2000,7 +2024,7 @@ export class Block implements IASTNodeLocation { * or dummy inputs, if necessary. * @returns The JSON definitions of field and inputs to add to the block. */ - private interpolateArguments_( + private interpolateArguments( tokens: Array, args: Array, implicitAlign: string | undefined, @@ -2023,7 +2047,7 @@ export class Block implements IASTNodeLocation { } else { // AnyDuringMigration because: Type '{ text: string; type: string; } // | null' is not assignable to type 'string | number'. - element = this.stringToFieldJson_(element) as AnyDuringMigration; + element = this.stringToFieldJson(element) as AnyDuringMigration; if (!element) { continue; } @@ -2035,9 +2059,7 @@ export class Block implements IASTNodeLocation { const length = elements.length; if ( length && - !this.isInputKeyword_( - (elements as AnyDuringMigration)[length - 1]['type'], - ) + !this.isInputKeyword((elements as AnyDuringMigration)[length - 1]['type']) ) { const dummyInput = {'type': 'input_dummy'}; if (implicitAlign) { @@ -2057,7 +2079,7 @@ export class Block implements IASTNodeLocation { * @param element The element to try to turn into a field. * @returns The field defined by the JSON, or null if one couldn't be created. */ - private fieldFromJson_(element: { + private fieldFromJson(element: { alt?: string; type: string; text?: string; @@ -2065,10 +2087,10 @@ export class Block implements IASTNodeLocation { const field = fieldRegistry.fromJson(element); if (!field && element['alt']) { if (typeof element['alt'] === 'string') { - const json = this.stringToFieldJson_(element['alt']); - return json ? this.fieldFromJson_(json) : null; + const json = this.stringToFieldJson(element['alt']); + return json ? this.fieldFromJson(json) : null; } - return this.fieldFromJson_(element['alt']); + return this.fieldFromJson(element['alt']); } return field; } @@ -2083,7 +2105,7 @@ export class Block implements IASTNodeLocation { * @returns The input that has been created, or null if one could not be * created for some reason (should never happen). */ - private inputFromJson_( + private inputFromJson( element: AnyDuringMigration, warningPrefix: string, ): Input | null { @@ -2141,7 +2163,7 @@ export class Block implements IASTNodeLocation { * @returns True if the given string matches one of the input keywords, false * otherwise. */ - private isInputKeyword_(str: string): boolean { + private isInputKeyword(str: string): boolean { return ( str === 'input_value' || str === 'input_statement' || @@ -2158,7 +2180,7 @@ export class Block implements IASTNodeLocation { * @param str String to turn into the JSON definition of a label field. * @returns The JSON definition or null. */ - private stringToFieldJson_(str: string): {text: string; type: string} | null { + private stringToFieldJson(str: string): {text: string; type: string} | null { str = str.trim(); if (str) { return { @@ -2333,7 +2355,7 @@ export class Block implements IASTNodeLocation { } eventUtils.fire( - new (eventUtils.get(eventUtils.BLOCK_CHANGE))( + new (eventUtils.get(EventType.BLOCK_CHANGE))( this, 'comment', null, @@ -2419,7 +2441,7 @@ export class Block implements IASTNodeLocation { * @returns Object with .x and .y properties. */ getRelativeToSurfaceXY(): Coordinate { - return this.xy_; + return this.xy; } /** @@ -2433,11 +2455,9 @@ export class Block implements IASTNodeLocation { if (this.parentBlock_) { throw Error('Block has parent'); } - const event = new (eventUtils.get(eventUtils.BLOCK_MOVE))( - this, - ) as BlockMove; - reason && event.setReason(reason); - this.xy_.translate(dx, dy); + const event = new (eventUtils.get(EventType.BLOCK_MOVE))(this) as BlockMove; + if (reason) event.setReason(reason); + this.xy.translate(dx, dy); event.recordNew(); eventUtils.fire(event); } diff --git a/core/block_svg.ts b/core/block_svg.ts index 54a5bfaaab7..1c1de49ec2b 100644 --- a/core/block_svg.ts +++ b/core/block_svg.ts @@ -16,7 +16,9 @@ import './events/events_selected.js'; import {Block} from './block.js'; import * as blockAnimations from './block_animations.js'; +import {IDeletable} from './blockly.js'; import * as browserEvents from './browser_events.js'; +import {BlockCopyData, BlockPaster} from './clipboard/block_paster.js'; import * as common from './common.js'; import {config} from './config.js'; import type {Connection} from './connection.js'; @@ -28,11 +30,15 @@ import { ContextMenuRegistry, LegacyContextMenuOption, } from './contextmenu_registry.js'; +import {BlockDragStrategy} from './dragging/block_drag_strategy.js'; import type {BlockMove} from './events/events_block_move.js'; -import * as deprecation from './utils/deprecation.js'; +import {EventType} from './events/type.js'; import * as eventUtils from './events/utils.js'; import type {Field} from './field.js'; import {FieldLabel} from './field_label.js'; +import {IconType} from './icons/icon_types.js'; +import {MutatorIcon} from './icons/mutator_icon.js'; +import {WarningIcon} from './icons/warning_icon.js'; import type {Input} from './inputs/input.js'; import type {IASTNodeLocationSvg} from './interfaces/i_ast_node_location_svg.js'; import type {IBoundedElement} from './interfaces/i_bounded_element.js'; @@ -44,26 +50,21 @@ import {ASTNode} from './keyboard_nav/ast_node.js'; import {TabNavigateCursor} from './keyboard_nav/tab_navigate_cursor.js'; import {MarkerManager} from './marker_manager.js'; import {Msg} from './msg.js'; -import {MutatorIcon} from './icons/mutator_icon.js'; +import * as renderManagement from './render_management.js'; import {RenderedConnection} from './rendered_connection.js'; import type {IPathObject} from './renderers/common/i_path_object.js'; import * as blocks from './serialization/blocks.js'; import type {BlockStyle} from './theme.js'; import * as Tooltip from './tooltip.js'; import {Coordinate} from './utils/coordinate.js'; +import * as deprecation from './utils/deprecation.js'; import * as dom from './utils/dom.js'; import {Rect} from './utils/rect.js'; import {Svg} from './utils/svg.js'; import * as svgMath from './utils/svg_math.js'; -import {WarningIcon} from './icons/warning_icon.js'; +import {FlyoutItemInfo} from './utils/toolbox.js'; import type {Workspace} from './workspace.js'; import type {WorkspaceSvg} from './workspace_svg.js'; -import * as renderManagement from './render_management.js'; -import {IconType} from './icons/icon_types.js'; -import {BlockCopyData, BlockPaster} from './clipboard/block_paster.js'; -import {BlockDragStrategy} from './dragging/block_drag_strategy.js'; -import {IDeletable} from './blockly.js'; -import {FlyoutItemInfo} from './utils/toolbox.js'; /** * Class for a block's SVG representation. @@ -92,7 +93,25 @@ export class BlockSvg static readonly COLLAPSED_WARNING_ID = 'TEMP_COLLAPSED_WARNING_'; override decompose?: (p1: Workspace) => BlockSvg; // override compose?: ((p1: BlockSvg) => void)|null; - saveConnections?: (p1: BlockSvg) => void; + + /** + * An optional method which saves a record of blocks connected to + * this block so they can be later restored after this block is + * recoomposed (reconfigured). Typically records the connected + * blocks on properties on blocks in the mutator flyout, so that + * rearranging those component blocks will automatically rearrange + * the corresponding connected blocks on this block after this block + * is recomposed. + * + * To keep the saved connection information up-to-date, MutatorIcon + * arranges for an event listener to call this method any time the + * mutator flyout is open and a change occurs on this block's + * workspace. + * + * @param rootBlock The root block in the mutator flyout. + */ + saveConnections?: (rootBlock: BlockSvg) => void; + customContextMenu?: ( p1: Array, ) => void; @@ -109,6 +128,14 @@ export class BlockSvg */ width = 0; + /** + * Width of this block, not including any connected value blocks. + * Width is in workspace units. + * + * @internal + */ + childlessWidth = 0; + /** * Map from IDs for warnings text to PIDs of functions to apply them. * Used to be able to maintain multiple warnings. @@ -118,7 +145,7 @@ export class BlockSvg /** Block's mutator icon (if any). */ mutator: MutatorIcon | null = null; - private svgGroup_: SVGGElement; + private svgGroup: SVGGElement; style: BlockStyle; /** @internal */ pathObject: IPathObject; @@ -128,15 +155,6 @@ export class BlockSvg private visuallyDisabled = false; - /** - * Is this block currently rendering? Used to stop recursive render calls - * from actually triggering a re-render. - */ - private renderIsInProgress_ = false; - - /** Whether mousedown events have been bound yet. */ - private eventsInit_ = false; - override workspace: WorkspaceSvg; // TODO(b/109816955): remove '!', see go/strict-prop-init-fix. override outputConnection!: RenderedConnection; @@ -174,7 +192,7 @@ export class BlockSvg throw TypeError('Cannot create a rendered block in a headless workspace'); } this.workspace = workspace; - this.svgGroup_ = dom.createSvgElement(Svg.G, {}); + this.svgGroup = dom.createSvgElement(Svg.G, {}); /** A block style object. */ this.style = workspace.getRenderer().getConstants().getBlockStyle(null); @@ -182,14 +200,14 @@ export class BlockSvg /** The renderer's path object. */ this.pathObject = workspace .getRenderer() - .makePathObject(this.svgGroup_, this.style); + .makePathObject(this.svgGroup, this.style); const svgPath = this.pathObject.svgPath; (svgPath as any).tooltip = this; Tooltip.bindMouseEvents(svgPath); // Expose this block's ID on its top-level SVG group. - this.svgGroup_.setAttribute('data-id', this.id); + this.svgGroup.setAttribute('data-id', this.id); this.doInit_(); } @@ -211,12 +229,7 @@ export class BlockSvg this.pathObject.updateMovable(this.isMovable() || this.isInFlyout); const svg = this.getSvgRoot(); if (!this.workspace.options.readOnly && svg) { - browserEvents.conditionalBind( - svg, - 'pointerdown', - this, - this.onMouseDown_, - ); + browserEvents.conditionalBind(svg, 'pointerdown', this, this.onMouseDown); } if (!svg.parentNode) { @@ -252,7 +265,7 @@ export class BlockSvg this.addSelect(); } - /** Unselects this block. Unhighlights the blockv visually. */ + /** Unselects this block. Unhighlights the block visually. */ unselect() { if (this.isShadow()) { this.getParent()?.unselect(); @@ -351,8 +364,8 @@ export class BlockSvg const eventsEnabled = eventUtils.isEnabled(); let event: BlockMove | null = null; if (eventsEnabled) { - event = new (eventUtils.get(eventUtils.BLOCK_MOVE)!)(this) as BlockMove; - reason && event.setReason(reason); + event = new (eventUtils.get(EventType.BLOCK_MOVE)!)(this) as BlockMove; + if (reason) event.setReason(reason); } const delta = new Coordinate(dx, dy); @@ -436,8 +449,28 @@ export class BlockSvg * @returns Object with coordinates of the bounding box. */ getBoundingRectangle(): Rect { + return this.getBoundingRectangleWithDimensions(this.getHeightWidth()); + } + + /** + * Returns the coordinates of a bounding box describing the dimensions of this + * block alone. + * Coordinate system: workspace coordinates. + * + * @returns Object with coordinates of the bounding box. + */ + getBoundingRectangleWithoutChildren(): Rect { + return this.getBoundingRectangleWithDimensions({ + height: this.height, + width: this.childlessWidth, + }); + } + + private getBoundingRectangleWithDimensions(blockBounds: { + height: number; + width: number; + }) { const blockXY = this.getRelativeToSurfaceXY(); - const blockBounds = this.getHeightWidth(); let left; let right; if (this.RTL) { @@ -471,14 +504,14 @@ export class BlockSvg return; } super.setCollapsed(collapsed); - this.updateCollapsed_(); + this.updateCollapsed(); } /** * Makes sure that when the block is collapsed, it is rendered correctly * for that state. */ - private updateCollapsed_() { + private updateCollapsed() { const collapsed = this.isCollapsed(); const collapsedInputName = constants.COLLAPSED_INPUT_NAME; const collapsedFieldName = constants.COLLAPSED_FIELD_NAME; @@ -545,7 +578,7 @@ export class BlockSvg * * @param e Pointer down event. */ - private onMouseDown_(e: PointerEvent) { + private onMouseDown(e: PointerEvent) { const gesture = this.workspace.getGesture(e); if (gesture) { gesture.handleBlockStart(e, this); @@ -655,10 +688,10 @@ export class BlockSvg if (adding) { this.translation = ''; common.draggingConnections.push(...this.getConnections_(true)); - dom.addClass(this.svgGroup_, 'blocklyDragging'); + dom.addClass(this.svgGroup, 'blocklyDragging'); } else { common.draggingConnections.length = 0; - dom.removeClass(this.svgGroup_, 'blocklyDragging'); + dom.removeClass(this.svgGroup, 'blocklyDragging'); } // Recurse through all blocks attached under this one. for (let i = 0; i < this.childBlocks_.length; i++) { @@ -728,7 +761,7 @@ export class BlockSvg * @returns The root SVG node (probably a group). */ getSvgRoot(): SVGGElement { - return this.svgGroup_; + return this.svgGroup; } /** @@ -750,8 +783,27 @@ export class BlockSvg blockAnimations.disposeUiEffect(this); } + // Selecting a shadow block highlights an ancestor block, but that highlight + // should be removed if the shadow block will be deleted. So, before + // deleting blocks and severing the connections between them, check whether + // doing so would delete a selected block and make sure that any associated + // parent is updated. + const selection = common.getSelected(); + if (selection instanceof Block) { + let selectionAncestor: Block | null = selection; + while (selectionAncestor !== null) { + if (selectionAncestor === this) { + // The block to be deleted contains the selected block, so remove any + // selection highlight associated with the selected block before + // deleting them. + selection.unselect(); + } + selectionAncestor = selectionAncestor.getParent(); + } + } + super.dispose(!!healStack); - dom.removeNode(this.svgGroup_); + dom.removeNode(this.svgGroup); } /** @@ -1125,10 +1177,11 @@ export class BlockSvg * tags do not respect z-index so SVG renders them in the * order that they are in the DOM. By placing this block first within the * block group's , it will render on top of any other blocks. + * Use sparingly, this method is expensive because it reorders the DOM + * nodes. * - * @param blockOnly: True to only move this block to the front without + * @param blockOnly True to only move this block to the front without * adjusting its parents. - * @internal */ bringToFront(blockOnly = false) { /* eslint-disable-next-line @typescript-eslint/no-this-alias */ @@ -1405,9 +1458,9 @@ export class BlockSvg if (conn.isConnected() && neighbour.isConnected()) continue; if (conn.isSuperior()) { - neighbour.bumpAwayFrom(conn); + neighbour.bumpAwayFrom(conn, /* initiatedByThis = */ false); } else { - conn.bumpAwayFrom(neighbour); + conn.bumpAwayFrom(neighbour, /* initiatedByThis = */ true); } } } @@ -1498,7 +1551,7 @@ export class BlockSvg dom.startTextWidthCache(); if (this.isCollapsed()) { - this.updateCollapsed_(); + this.updateCollapsed(); } if (!this.isEnabled()) { diff --git a/core/blockly.ts b/core/blockly.ts index cee509480c2..01490dbb694 100644 --- a/core/blockly.ts +++ b/core/blockly.ts @@ -22,8 +22,10 @@ import {BlocklyOptions} from './blockly_options.js'; import {Blocks} from './blocks.js'; import * as browserEvents from './browser_events.js'; import * as bubbles from './bubbles.js'; +import {MiniWorkspaceBubble} from './bubbles/mini_workspace_bubble.js'; import * as bumpObjects from './bump_objects.js'; import * as clipboard from './clipboard.js'; +import * as comments from './comments.js'; import * as common from './common.js'; import {ComponentManager} from './component_manager.js'; import {config} from './config.js'; @@ -31,15 +33,15 @@ import {Connection} from './connection.js'; import {ConnectionChecker} from './connection_checker.js'; import {ConnectionDB} from './connection_db.js'; import {ConnectionType} from './connection_type.js'; +import * as constants from './constants.js'; import * as ContextMenu from './contextmenu.js'; import * as ContextMenuItems from './contextmenu_items.js'; import {ContextMenuRegistry} from './contextmenu_registry.js'; -import * as comments from './comments.js'; import * as Css from './css.js'; import {DeleteArea} from './delete_area.js'; import * as dialog from './dialog.js'; -import * as dragging from './dragging.js'; import {DragTarget} from './drag_target.js'; +import * as dragging from './dragging.js'; import * as dropDownDiv from './dropdowndiv.js'; import * as Events from './events/events.js'; import * as Extensions from './extensions.js'; @@ -104,8 +106,8 @@ import {Gesture} from './gesture.js'; import {Grid} from './grid.js'; import * as icons from './icons.js'; import {inject} from './inject.js'; -import {Input} from './inputs/input.js'; import * as inputs from './inputs.js'; +import {Input} from './inputs/input.js'; import {InsertionMarkerManager} from './insertion_marker_manager.js'; import {InsertionMarkerPreviewer} from './insertion_marker_previewer.js'; import {IASTNodeLocation} from './interfaces/i_ast_node_location.js'; @@ -119,16 +121,16 @@ import {IComponent} from './interfaces/i_component.js'; import {IConnectionChecker} from './interfaces/i_connection_checker.js'; import {IConnectionPreviewer} from './interfaces/i_connection_previewer.js'; import {IContextMenu} from './interfaces/i_contextmenu.js'; -import {ICopyable, isCopyable, ICopyData} from './interfaces/i_copyable.js'; +import {ICopyData, ICopyable, isCopyable} from './interfaces/i_copyable.js'; import {IDeletable, isDeletable} from './interfaces/i_deletable.js'; import {IDeleteArea} from './interfaces/i_delete_area.js'; import {IDragTarget} from './interfaces/i_drag_target.js'; -import {IDragger} from './interfaces/i_dragger.js'; import { + IDragStrategy, IDraggable, isDraggable, - IDragStrategy, } from './interfaces/i_draggable.js'; +import {IDragger} from './interfaces/i_dragger.js'; import {IFlyout} from './interfaces/i_flyout.js'; import {IHasBubble, hasBubble} from './interfaces/i_has_bubble.js'; import {IIcon, isIcon} from './interfaces/i_icon.js'; @@ -159,22 +161,21 @@ import {BasicCursor} from './keyboard_nav/basic_cursor.js'; import {Cursor} from './keyboard_nav/cursor.js'; import {Marker} from './keyboard_nav/marker.js'; import {TabNavigateCursor} from './keyboard_nav/tab_navigate_cursor.js'; -import {MarkerManager} from './marker_manager.js'; import type {LayerManager} from './layer_manager.js'; +import * as layers from './layers.js'; +import {MarkerManager} from './marker_manager.js'; import {Menu} from './menu.js'; import {MenuItem} from './menuitem.js'; import {MetricsManager} from './metrics_manager.js'; import {Msg, setLocale} from './msg.js'; -import {MiniWorkspaceBubble} from './bubbles/mini_workspace_bubble.js'; import {Names} from './names.js'; import {Options} from './options.js'; import * as uiPosition from './positionable_helpers.js'; import * as Procedures from './procedures.js'; import * as registry from './registry.js'; -import {RenderedConnection} from './rendered_connection.js'; import * as renderManagement from './render_management.js'; +import {RenderedConnection} from './rendered_connection.js'; import * as blockRendering from './renderers/common/block_rendering.js'; -import * as constants from './constants.js'; import * as geras from './renderers/geras/geras.js'; import * as thrasos from './renderers/thrasos/thrasos.js'; import * as zelos from './renderers/zelos/zelos.js'; @@ -417,171 +418,187 @@ Names.prototype.populateProcedures = function ( // clang-format on // Re-export submodules that no longer declareLegacyNamespace. -export {browserEvents}; -export {ContextMenu}; -export {ContextMenuItems}; -export {Css}; -export {Events}; -export {Extensions}; -export {Procedures}; -export {Procedures as procedures}; -export {ShortcutItems}; -export {Themes}; -export {Tooltip}; -export {Touch}; -export {Variables}; -export {VariablesDynamic}; -export {WidgetDiv}; -export {Xml}; -export {blockAnimations}; -export {blockRendering}; -export {bumpObjects}; -export {clipboard}; -export {common}; -export {constants}; -export {dialog}; -export {fieldRegistry}; -export {geras}; -export {registry}; -export {thrasos}; -export {uiPosition}; -export {utils}; -export {zelos}; -export {ASTNode}; -export {BasicCursor}; -export {Block}; -export {BlocklyOptions}; -export {BlockSvg}; -export {Blocks}; -export {bubbles}; -export {CollapsibleToolboxCategory}; -export {ComponentManager}; -export {Connection}; -export {ConnectionType}; -export {ConnectionChecker}; -export {ConnectionDB}; -export {ContextMenuRegistry}; -export {comments}; -export {Cursor}; -export {DeleteArea}; -export {dragging}; -export {DragTarget}; +export { + ASTNode, + BasicCursor, + Block, + BlockSvg, + BlocklyOptions, + Blocks, + CollapsibleToolboxCategory, + ComponentManager, + Connection, + ConnectionChecker, + ConnectionDB, + ConnectionType, + ContextMenu, + ContextMenuItems, + ContextMenuRegistry, + Css, + Cursor, + DeleteArea, + DragTarget, + Events, + Extensions, + Procedures, + ShortcutItems, + Themes, + Tooltip, + Touch, + Variables, + VariablesDynamic, + WidgetDiv, + Xml, + blockAnimations, + blockRendering, + browserEvents, + bubbles, + bumpObjects, + clipboard, + comments, + common, + constants, + dialog, + dragging, + fieldRegistry, + geras, + Procedures as procedures, + registry, + thrasos, + uiPosition, + utils, + zelos, +}; export const DropDownDiv = dropDownDiv; -export {Field, FieldConfig, FieldValidator, UnattachedFieldError}; export { + CodeGenerator, + Field, FieldCheckbox, FieldCheckboxConfig, FieldCheckboxFromJsonConfig, FieldCheckboxValidator, -}; -export { + FieldConfig, FieldDropdown, FieldDropdownConfig, FieldDropdownFromJsonConfig, FieldDropdownValidator, - MenuGenerator, - MenuGeneratorFunction, - MenuOption, -}; -export {FieldImage, FieldImageConfig, FieldImageFromJsonConfig}; -export {FieldLabel, FieldLabelConfig, FieldLabelFromJsonConfig}; -export {FieldLabelSerializable}; -export { + FieldImage, + FieldImageConfig, + FieldImageFromJsonConfig, + FieldLabel, + FieldLabelConfig, + FieldLabelFromJsonConfig, + FieldLabelSerializable, FieldNumber, FieldNumberConfig, FieldNumberFromJsonConfig, FieldNumberValidator, -}; -export { FieldTextInput, FieldTextInputConfig, FieldTextInputFromJsonConfig, FieldTextInputValidator, -}; -export { + FieldValidator, FieldVariable, FieldVariableConfig, FieldVariableFromJsonConfig, FieldVariableValidator, + Flyout, + FlyoutButton, + FlyoutMetricsManager, + CodeGenerator as Generator, + Gesture, + Grid, + HorizontalFlyout, + IASTNodeLocation, + IASTNodeLocationSvg, + IASTNodeLocationWithBlock, + IAutoHideable, + IBoundedElement, + IBubble, + ICollapsibleToolboxItem, + IComponent, + IConnectionChecker, + IConnectionPreviewer, + IContextMenu, + ICopyData, + ICopyable, + IDeletable, + IDeleteArea, + IDragStrategy, + IDragTarget, + IDraggable, + IDragger, + IFlyout, + IHasBubble, + IIcon, + IKeyboardAccessible, + IMetricsManager, + IMovable, + IObservable, + IPaster, + IPositionable, + IRegistrable, + IRenderedElement, + ISelectable, + ISelectableToolboxItem, + ISerializable, + IStyleable, + IToolbox, + IToolboxItem, + IVariableBackedParameterModel, + Input, + InsertionMarkerManager, + InsertionMarkerPreviewer, + LayerManager, + Marker, + MarkerManager, + Menu, + MenuGenerator, + MenuGeneratorFunction, + MenuItem, + MenuOption, + MetricsManager, + Msg, + Names, + Options, + RenderedConnection, + Scrollbar, + ScrollbarPair, + ShortcutRegistry, + TabNavigateCursor, + Theme, + ThemeManager, + Toolbox, + ToolboxCategory, + ToolboxItem, + ToolboxSeparator, + Trashcan, + UnattachedFieldError, + VariableMap, + VariableModel, + VerticalFlyout, + Workspace, + WorkspaceAudio, + WorkspaceDragger, + WorkspaceSvg, + ZoomControls, + config, + hasBubble, + icons, + inject, + inputs, + isCopyable, + isDeletable, + isDraggable, + isIcon, + isObservable, + isPaster, + isRenderedElement, + isSelectable, + isSerializable, + isVariableBackedParameterModel, + layers, + renderManagement, + serialization, + setLocale, }; -export {Flyout}; -export {FlyoutButton}; -export {FlyoutMetricsManager}; -export {CodeGenerator}; -export {CodeGenerator as Generator}; // Deprecated name, October 2022. -export {Gesture}; -export {Grid}; -export {HorizontalFlyout}; -export {IASTNodeLocation}; -export {IASTNodeLocationSvg}; -export {IASTNodeLocationWithBlock}; -export {IAutoHideable}; -export {IBoundedElement}; -export {IBubble}; -export {ICollapsibleToolboxItem}; -export {IComponent}; -export {IConnectionChecker}; -export {IConnectionPreviewer}; -export {IContextMenu}; -export {icons}; -export {ICopyable, isCopyable, ICopyData}; -export {IDeletable, isDeletable}; -export {IDeleteArea}; -export {IDragTarget}; -export {IDragger}; -export {IDraggable, isDraggable, IDragStrategy}; -export {IFlyout}; -export {IHasBubble, hasBubble}; -export {IIcon, isIcon}; -export {IKeyboardAccessible}; -export {IMetricsManager}; -export {IMovable}; -export {Input}; -export {inputs}; -export {InsertionMarkerManager}; -export {InsertionMarkerPreviewer}; -export {IObservable, isObservable}; -export {IPaster, isPaster}; -export {IPositionable}; -export {IRegistrable}; -export {IRenderedElement, isRenderedElement}; -export {ISelectable, isSelectable}; -export {ISelectableToolboxItem}; -export {ISerializable, isSerializable}; -export {IStyleable}; -export {IToolbox}; -export {IToolboxItem}; -export {IVariableBackedParameterModel, isVariableBackedParameterModel}; -export {Marker}; -export {MarkerManager}; -export {LayerManager}; -export {Menu}; -export {MenuItem}; -export {MetricsManager}; -export {Msg, setLocale}; -export {Names}; -export {Options}; -export {RenderedConnection}; -export {renderManagement}; -export {Scrollbar}; -export {ScrollbarPair}; -export {ShortcutRegistry}; -export {TabNavigateCursor}; -export {Theme}; -export {ThemeManager}; -export {Toolbox}; -export {ToolboxCategory}; -export {ToolboxItem}; -export {ToolboxSeparator}; -export {Trashcan}; -export {VariableMap}; -export {VariableModel}; -export {VerticalFlyout}; -export {Workspace}; -export {WorkspaceAudio}; -export {WorkspaceDragger}; -export {WorkspaceSvg}; -export {ZoomControls}; -export {config}; -export {inject}; -export {serialization}; diff --git a/core/blockly_options.ts b/core/blockly_options.ts index e3ed0b91296..dd18dbfee5d 100644 --- a/core/blockly_options.ts +++ b/core/blockly_options.ts @@ -6,9 +6,9 @@ // Former goog.module ID: Blockly.BlocklyOptions -import type {Theme, ITheme} from './theme.js'; -import type {WorkspaceSvg} from './workspace_svg.js'; +import type {ITheme, Theme} from './theme.js'; import type {ToolboxDefinition} from './utils/toolbox.js'; +import type {WorkspaceSvg} from './workspace_svg.js'; /** * Blockly options. diff --git a/core/browser_events.ts b/core/browser_events.ts index 54fec307ec4..8176fe10ff3 100644 --- a/core/browser_events.ts +++ b/core/browser_events.ts @@ -6,6 +6,10 @@ // Former goog.module ID: Blockly.browserEvents +// Theoretically we could figure out a way to type the event params correctly, +// but it's not high priority. +/* eslint-disable @typescript-eslint/no-unsafe-function-type */ + import * as Touch from './touch.js'; import * as userAgent from './utils/useragent.js'; @@ -47,7 +51,7 @@ const PAGE_MODE_MULTIPLIER = 125; export function conditionalBind( node: EventTarget, name: string, - thisObject: Object | null, + thisObject: object | null, func: Function, opt_noCaptureIdentifier?: boolean, ): Data { @@ -96,7 +100,7 @@ export function conditionalBind( export function bind( node: EventTarget, name: string, - thisObject: Object | null, + thisObject: object | null, func: Function, ): Data { /** diff --git a/core/bubbles.ts b/core/bubbles.ts index 0c61741f92d..a49c2ae3581 100644 --- a/core/bubbles.ts +++ b/core/bubbles.ts @@ -5,8 +5,8 @@ */ import {Bubble} from './bubbles/bubble.js'; +import {MiniWorkspaceBubble} from './bubbles/mini_workspace_bubble.js'; import {TextBubble} from './bubbles/text_bubble.js'; import {TextInputBubble} from './bubbles/textinput_bubble.js'; -import {MiniWorkspaceBubble} from './bubbles/mini_workspace_bubble.js'; -export {Bubble, TextBubble, TextInputBubble, MiniWorkspaceBubble}; +export {Bubble, MiniWorkspaceBubble, TextBubble, TextInputBubble}; diff --git a/core/bubbles/bubble.ts b/core/bubbles/bubble.ts index 35b9e7dde0a..bac94dbc8a0 100644 --- a/core/bubbles/bubble.ts +++ b/core/bubbles/bubble.ts @@ -4,21 +4,21 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {ISelectable} from '../blockly.js'; import * as browserEvents from '../browser_events.js'; +import * as common from '../common.js'; import {BubbleDragStrategy} from '../dragging/bubble_drag_strategy.js'; import {IBubble} from '../interfaces/i_bubble.js'; import {ContainerRegion} from '../metrics_manager.js'; import {Scrollbar} from '../scrollbar.js'; import {Coordinate} from '../utils/coordinate.js'; import * as dom from '../utils/dom.js'; +import * as idGenerator from '../utils/idgenerator.js'; import * as math from '../utils/math.js'; import {Rect} from '../utils/rect.js'; import {Size} from '../utils/size.js'; import {Svg} from '../utils/svg.js'; import {WorkspaceSvg} from '../workspace_svg.js'; -import * as common from '../common.js'; -import {ISelectable} from '../blockly.js'; -import * as idGenerator from '../utils/idgenerator.js'; /** * The abstract pop-up bubble class. This creates a UI that looks like a speech @@ -212,9 +212,10 @@ export abstract class Bubble implements IBubble, ISelectable { this.background.setAttribute('fill', colour); } - /** Passes the pointer event off to the gesture system. */ + /** Brings the bubble to the front and passes the pointer event off to the gesture system. */ private onMouseDown(e: PointerEvent) { this.workspace.getGesture(e)?.handleBubbleStart(e, this); + this.bringToFront(); common.setSelected(this); } diff --git a/core/bubbles/mini_workspace_bubble.ts b/core/bubbles/mini_workspace_bubble.ts index 74317d57bc1..f4ad96c8c00 100644 --- a/core/bubbles/mini_workspace_bubble.ts +++ b/core/bubbles/mini_workspace_bubble.ts @@ -4,16 +4,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {Abstract as AbstractEvent} from '../events/events_abstract.js'; import type {BlocklyOptions} from '../blockly_options.js'; -import {Bubble} from './bubble.js'; +import {Abstract as AbstractEvent} from '../events/events_abstract.js'; +import {Options} from '../options.js'; import {Coordinate} from '../utils/coordinate.js'; import * as dom from '../utils/dom.js'; -import {Options} from '../options.js'; -import {Svg} from '../utils/svg.js'; import type {Rect} from '../utils/rect.js'; import {Size} from '../utils/size.js'; +import {Svg} from '../utils/svg.js'; import type {WorkspaceSvg} from '../workspace_svg.js'; +import {Bubble} from './bubble.js'; /** * A bubble that contains a mini-workspace which can hold arbitrary blocks. diff --git a/core/bubbles/text_bubble.ts b/core/bubbles/text_bubble.ts index 020ab4f2ec1..7ac5fa02965 100644 --- a/core/bubbles/text_bubble.ts +++ b/core/bubbles/text_bubble.ts @@ -4,13 +4,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {Bubble} from './bubble.js'; import {Coordinate} from '../utils/coordinate.js'; import * as dom from '../utils/dom.js'; import {Rect} from '../utils/rect.js'; import {Size} from '../utils/size.js'; import {Svg} from '../utils/svg.js'; import {WorkspaceSvg} from '../workspace_svg.js'; +import {Bubble} from './bubble.js'; /** * A bubble that displays non-editable text. Used by the warning icon. diff --git a/core/bubbles/textinput_bubble.ts b/core/bubbles/textinput_bubble.ts index d7d1f5ae7db..5b5278b91ff 100644 --- a/core/bubbles/textinput_bubble.ts +++ b/core/bubbles/textinput_bubble.ts @@ -4,16 +4,17 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {Bubble} from './bubble.js'; -import {Coordinate} from '../utils/coordinate.js'; import * as Css from '../css.js'; +import * as touch from '../touch.js'; +import {browserEvents} from '../utils.js'; +import {Coordinate} from '../utils/coordinate.js'; import * as dom from '../utils/dom.js'; +import * as drag from '../utils/drag.js'; import {Rect} from '../utils/rect.js'; import {Size} from '../utils/size.js'; import {Svg} from '../utils/svg.js'; -import * as touch from '../touch.js'; import {WorkspaceSvg} from '../workspace_svg.js'; -import {browserEvents} from '../utils.js'; +import {Bubble} from './bubble.js'; /** * A bubble that displays editable text. It can also be resized by the user. @@ -62,6 +63,8 @@ export class TextInputBubble extends Bubble { 20 + Bubble.DOUBLE_BORDER, ); + private editable = true; + /** * @param workspace The workspace this bubble belongs to. * @param anchor The anchor location of the thing this bubble is attached to. @@ -95,6 +98,21 @@ export class TextInputBubble extends Bubble { this.onTextChange(); } + /** Sets whether or not the text in the bubble is editable. */ + setEditable(editable: boolean) { + this.editable = editable; + if (this.editable) { + this.textArea.removeAttribute('readonly'); + } else { + this.textArea.setAttribute('readonly', ''); + } + } + + /** Returns whether or not the text in the bubble is editable. */ + isEditable(): boolean { + return this.editable; + } + /** Adds a change listener to be notified when this bubble's text changes. */ addTextChangeListener(listener: () => void) { this.textChangeListeners.push(listener); @@ -224,7 +242,8 @@ export class TextInputBubble extends Bubble { return; } - this.workspace.startDrag( + drag.start( + this.workspace, e, new Coordinate( this.workspace.RTL ? -this.getSize().width : this.getSize().width, @@ -264,7 +283,7 @@ export class TextInputBubble extends Bubble { /** Handles pointer move events on the resize target. */ private onResizePointerMove(e: PointerEvent) { - const delta = this.workspace.moveDrag(e); + const delta = drag.move(this.workspace, e); this.setSize( new Size(this.workspace.RTL ? -delta.x : delta.x, delta.y), false, diff --git a/core/bump_objects.ts b/core/bump_objects.ts index 3ceae2dbcfd..2aae257dde3 100644 --- a/core/bump_objects.ts +++ b/core/bump_objects.ts @@ -12,7 +12,9 @@ import type {BlockCreate} from './events/events_block_create.js'; import type {BlockMove} from './events/events_block_move.js'; import type {CommentCreate} from './events/events_comment_create.js'; import type {CommentMove} from './events/events_comment_move.js'; -import type {ViewportChange} from './events/events_viewport.js'; +import type {CommentResize} from './events/events_comment_resize.js'; +import {isViewportChange} from './events/predicates.js'; +import {BUMP_EVENTS, EventType} from './events/type.js'; import * as eventUtils from './events/utils.js'; import type {IBoundedElement} from './interfaces/i_bounded_element.js'; import type {ContainerRegion} from './metrics_manager.js'; @@ -98,7 +100,7 @@ export function bumpIntoBoundsHandler( return; } - if (eventUtils.BUMP_EVENTS.includes(e.type ?? '')) { + if (BUMP_EVENTS.includes(e.type ?? '')) { const scrollMetricsInWsCoords = metricsManager.getScrollMetrics(true); // Triggered by move/create event @@ -126,13 +128,8 @@ export function bumpIntoBoundsHandler( ); } eventUtils.setGroup(existingGroup); - } else if (e.type === eventUtils.VIEWPORT_CHANGE) { - const viewportEvent = e as ViewportChange; - if ( - viewportEvent.scale && - viewportEvent.oldScale && - viewportEvent.scale > viewportEvent.oldScale - ) { + } else if (isViewportChange(e)) { + if (e.scale && e.oldScale && e.scale > e.oldScale) { bumpTopObjectsIntoBounds(workspace); } } @@ -154,17 +151,18 @@ function extractObjectFromEvent( ): IBoundedElement | null { let object = null; switch (e.type) { - case eventUtils.BLOCK_CREATE: - case eventUtils.BLOCK_MOVE: + case EventType.BLOCK_CREATE: + case EventType.BLOCK_MOVE: object = workspace.getBlockById((e as BlockCreate | BlockMove).blockId!); if (object) { object = object.getRootBlock(); } break; - case eventUtils.COMMENT_CREATE: - case eventUtils.COMMENT_MOVE: + case EventType.COMMENT_CREATE: + case EventType.COMMENT_MOVE: + case EventType.COMMENT_RESIZE: object = workspace.getCommentById( - (e as CommentCreate | CommentMove).commentId!, + (e as CommentCreate | CommentMove | CommentResize).commentId!, ) as RenderedWorkspaceComment; break; } diff --git a/core/clipboard.ts b/core/clipboard.ts index ed574d11287..62e23fd24a3 100644 --- a/core/clipboard.ts +++ b/core/clipboard.ts @@ -6,12 +6,12 @@ // Former goog.module ID: Blockly.clipboard -import type {ICopyData, ICopyable} from './interfaces/i_copyable.js'; import {BlockPaster} from './clipboard/block_paster.js'; -import * as globalRegistry from './registry.js'; -import {WorkspaceSvg} from './workspace_svg.js'; import * as registry from './clipboard/registry.js'; +import type {ICopyData, ICopyable} from './interfaces/i_copyable.js'; +import * as globalRegistry from './registry.js'; import {Coordinate} from './utils/coordinate.js'; +import {WorkspaceSvg} from './workspace_svg.js'; /** Metadata about the object that is currently on the clipboard. */ let stashedCopyData: ICopyData | null = null; diff --git a/core/clipboard/block_paster.ts b/core/clipboard/block_paster.ts index f82adf2b385..08ff220ee91 100644 --- a/core/clipboard/block_paster.ts +++ b/core/clipboard/block_paster.ts @@ -5,15 +5,16 @@ */ import {BlockSvg} from '../block_svg.js'; -import * as registry from './registry.js'; +import * as common from '../common.js'; +import {config} from '../config.js'; +import {EventType} from '../events/type.js'; +import * as eventUtils from '../events/utils.js'; import {ICopyData} from '../interfaces/i_copyable.js'; import {IPaster} from '../interfaces/i_paster.js'; import {State, append} from '../serialization/blocks.js'; import {Coordinate} from '../utils/coordinate.js'; import {WorkspaceSvg} from '../workspace_svg.js'; -import * as eventUtils from '../events/utils.js'; -import {config} from '../config.js'; -import * as common from '../common.js'; +import * as registry from './registry.js'; export class BlockPaster implements IPaster { static TYPE = 'block'; @@ -52,7 +53,7 @@ export class BlockPaster implements IPaster { if (!block) return block; if (eventUtils.isEnabled() && !block.isShadow()) { - eventUtils.fire(new (eventUtils.get(eventUtils.BLOCK_CREATE))(block)); + eventUtils.fire(new (eventUtils.get(EventType.BLOCK_CREATE))(block)); } common.setSelected(block); return block; diff --git a/core/clipboard/workspace_comment_paster.ts b/core/clipboard/workspace_comment_paster.ts index c7e5eed68b0..fdfbf0a8419 100644 --- a/core/clipboard/workspace_comment_paster.ts +++ b/core/clipboard/workspace_comment_paster.ts @@ -4,15 +4,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {IPaster} from '../interfaces/i_paster.js'; +import {RenderedWorkspaceComment} from '../comments/rendered_workspace_comment.js'; +import * as common from '../common.js'; +import {EventType} from '../events/type.js'; +import * as eventUtils from '../events/utils.js'; import {ICopyData} from '../interfaces/i_copyable.js'; +import {IPaster} from '../interfaces/i_paster.js'; +import * as commentSerialiation from '../serialization/workspace_comments.js'; import {Coordinate} from '../utils/coordinate.js'; import {WorkspaceSvg} from '../workspace_svg.js'; import * as registry from './registry.js'; -import * as commentSerialiation from '../serialization/workspace_comments.js'; -import * as eventUtils from '../events/utils.js'; -import * as common from '../common.js'; -import {RenderedWorkspaceComment} from '../comments/rendered_workspace_comment.js'; export class WorkspaceCommentPaster implements IPaster @@ -46,7 +47,7 @@ export class WorkspaceCommentPaster if (!comment) return null; if (eventUtils.isEnabled()) { - eventUtils.fire(new (eventUtils.get(eventUtils.COMMENT_CREATE))(comment)); + eventUtils.fire(new (eventUtils.get(EventType.COMMENT_CREATE))(comment)); } common.setSelected(comment); return comment; diff --git a/core/comments.ts b/core/comments.ts index 368db0e7783..ee85919873a 100644 --- a/core/comments.ts +++ b/core/comments.ts @@ -5,5 +5,5 @@ */ export {CommentView} from './comments/comment_view.js'; -export {WorkspaceComment} from './comments/workspace_comment.js'; export {RenderedWorkspaceComment} from './comments/rendered_workspace_comment.js'; +export {WorkspaceComment} from './comments/workspace_comment.js'; diff --git a/core/comments/comment_view.ts b/core/comments/comment_view.ts index 52f92b56776..99c14aaa8f2 100644 --- a/core/comments/comment_view.ts +++ b/core/comments/comment_view.ts @@ -4,16 +4,17 @@ * SPDX-License-Identifier: Apache-2.0 */ +import * as browserEvents from '../browser_events.js'; +import * as css from '../css.js'; import {IRenderedElement} from '../interfaces/i_rendered_element.js'; -import {WorkspaceSvg} from '../workspace_svg.js'; -import * as dom from '../utils/dom.js'; -import {Svg} from '../utils/svg.js'; import * as layers from '../layers.js'; -import * as css from '../css.js'; +import * as touch from '../touch.js'; import {Coordinate} from '../utils/coordinate.js'; +import * as dom from '../utils/dom.js'; +import * as drag from '../utils/drag.js'; import {Size} from '../utils/size.js'; -import * as browserEvents from '../browser_events.js'; -import * as touch from '../touch.js'; +import {Svg} from '../utils/svg.js'; +import {WorkspaceSvg} from '../workspace_svg.js'; export class CommentView implements IRenderedElement { /** The root group element of the comment view. */ @@ -99,9 +100,12 @@ export class CommentView implements IRenderedElement { /** Whether this comment view has been disposed or not. */ private disposed = false; + /** Size of this comment when the resize drag was initiated. */ + private preResizeSize?: Size; + constructor(private readonly workspace: WorkspaceSvg) { this.svgRoot = dom.createSvgElement(Svg.G, { - 'class': 'blocklyComment blocklyEditable', + 'class': 'blocklyComment blocklyEditable blocklyDraggable', }); this.highlightRect = this.createHighlightRect(this.svgRoot); @@ -125,7 +129,7 @@ export class CommentView implements IRenderedElement { workspace.getLayerManager()?.append(this, layers.BLOCK); // Set size to the default size. - this.setSize(this.size); + this.setSizeWithoutFiringEvents(this.size); // Set default transform (including inverted scale for RTL). this.moveTo(new Coordinate(0, 0)); @@ -298,7 +302,7 @@ export class CommentView implements IRenderedElement { * Sets the size of the comment in workspace units, and updates the view * elements to reflect the new size. */ - setSize(size: Size) { + setSizeWithoutFiringEvents(size: Size) { const topBarSize = this.topBarBackground.getBBox(); const deleteSize = this.deleteIcon.getBBox(); const foldoutSize = this.foldoutIcon.getBBox(); @@ -309,7 +313,6 @@ export class CommentView implements IRenderedElement { size, this.calcMinSize(topBarSize, foldoutSize, deleteSize), ); - const oldSize = this.size; this.size = size; this.svgRoot.setAttribute('height', `${size.height}`); @@ -328,7 +331,15 @@ export class CommentView implements IRenderedElement { resizeSize, ); this.updateResizeHandlePosition(size, resizeSize); + } + /** + * Sets the size of the comment in workspace units, updates the view + * elements to reflect the new size, and triggers size change listeners. + */ + setSize(size: Size) { + const oldSize = this.preResizeSize || this.size; + this.setSizeWithoutFiringEvents(size); this.onSizeChange(oldSize, this.size); } @@ -472,7 +483,7 @@ export class CommentView implements IRenderedElement { /** * Triggers listeners when the size of the comment changes, either - * progrmatically or manually by the user. + * programmatically or manually by the user. */ private onSizeChange(oldSize: Size, newSize: Size) { // Loop through listeners backwards in case they remove themselves. @@ -512,8 +523,10 @@ export class CommentView implements IRenderedElement { return; } - // TODO(#7926): Move this into a utils file. - this.workspace.startDrag( + this.preResizeSize = this.getSize(); + + drag.start( + this.workspace, e, new Coordinate( this.workspace.RTL ? -this.getSize().width : this.getSize().width, @@ -550,13 +563,17 @@ export class CommentView implements IRenderedElement { browserEvents.unbind(this.resizePointerMoveListener); this.resizePointerMoveListener = null; } + // When ending a resize drag, notify size change listeners to fire an event. + this.setSize(this.size); + this.preResizeSize = undefined; } /** Resizes the comment in response to a drag on the resize handle. */ private onResizePointerMove(e: PointerEvent) { - // TODO(#7926): Move this into a utils file. - const delta = this.workspace.moveDrag(e); - this.setSize(new Size(this.workspace.RTL ? -delta.x : delta.x, delta.y)); + const size = drag.move(this.workspace, e); + this.setSizeWithoutFiringEvents( + new Size(this.workspace.RTL ? -size.x : size.x, size.y), + ); } /** Returns true if the comment is currently collapsed. */ @@ -573,7 +590,7 @@ export class CommentView implements IRenderedElement { dom.removeClass(this.svgRoot, 'blocklyCollapsed'); } // Repositions resize handle and such. - this.setSize(this.size); + this.setSizeWithoutFiringEvents(this.size); this.onCollapse(); } @@ -606,6 +623,7 @@ export class CommentView implements IRenderedElement { * event on the foldout icon. */ private onFoldoutDown(e: PointerEvent) { + touch.clearTouchIdentifier(); this.bringToFront(); if (browserEvents.isRightButton(e)) { e.stopPropagation(); @@ -682,7 +700,7 @@ export class CommentView implements IRenderedElement { /** * Triggers listeners when the text of the comment changes, either - * progrmatically or manually by the user. + * programmatically or manually by the user. */ private onTextChange() { const oldText = this.text; @@ -721,6 +739,7 @@ export class CommentView implements IRenderedElement { * delete icon. */ private onDeleteDown(e: PointerEvent) { + touch.clearTouchIdentifier(); if (browserEvents.isRightButton(e)) { e.stopPropagation(); return; @@ -810,7 +829,6 @@ css.register(` } .blocklyCommentTopbarBackground { - cursor: grab; fill: var(--commentBorderColour); height: 24px; } diff --git a/core/comments/rendered_workspace_comment.ts b/core/comments/rendered_workspace_comment.ts index 1234d6ef8e9..ff21335741b 100644 --- a/core/comments/rendered_workspace_comment.ts +++ b/core/comments/rendered_workspace_comment.ts @@ -4,30 +4,31 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {WorkspaceComment} from './workspace_comment.js'; -import {WorkspaceSvg} from '../workspace_svg.js'; -import {CommentView} from './comment_view.js'; -import {Coordinate} from '../utils/coordinate.js'; -import {Rect} from '../utils/rect.js'; -import {Size} from '../utils/size.js'; -import {IBoundedElement} from '../interfaces/i_bounded_element.js'; -import {IRenderedElement} from '../interfaces/i_rendered_element.js'; -import * as dom from '../utils/dom.js'; -import {IDraggable} from '../interfaces/i_draggable.js'; -import {CommentDragStrategy} from '../dragging/comment_drag_strategy.js'; import * as browserEvents from '../browser_events.js'; -import * as common from '../common.js'; -import {ISelectable} from '../interfaces/i_selectable.js'; -import {IDeletable} from '../interfaces/i_deletable.js'; -import {ICopyable} from '../interfaces/i_copyable.js'; -import * as commentSerialization from '../serialization/workspace_comments.js'; import { - WorkspaceCommentPaster, WorkspaceCommentCopyData, + WorkspaceCommentPaster, } from '../clipboard/workspace_comment_paster.js'; -import {IContextMenu} from '../interfaces/i_contextmenu.js'; +import * as common from '../common.js'; import * as contextMenu from '../contextmenu.js'; import {ContextMenuRegistry} from '../contextmenu_registry.js'; +import {CommentDragStrategy} from '../dragging/comment_drag_strategy.js'; +import {IBoundedElement} from '../interfaces/i_bounded_element.js'; +import {IContextMenu} from '../interfaces/i_contextmenu.js'; +import {ICopyable} from '../interfaces/i_copyable.js'; +import {IDeletable} from '../interfaces/i_deletable.js'; +import {IDraggable} from '../interfaces/i_draggable.js'; +import {IRenderedElement} from '../interfaces/i_rendered_element.js'; +import {ISelectable} from '../interfaces/i_selectable.js'; +import * as layers from '../layers.js'; +import * as commentSerialization from '../serialization/workspace_comments.js'; +import {Coordinate} from '../utils/coordinate.js'; +import * as dom from '../utils/dom.js'; +import {Rect} from '../utils/rect.js'; +import {Size} from '../utils/size.js'; +import {WorkspaceSvg} from '../workspace_svg.js'; +import {CommentView} from './comment_view.js'; +import {WorkspaceComment} from './workspace_comment.js'; export class RenderedWorkspaceComment extends WorkspaceComment @@ -57,6 +58,7 @@ export class RenderedWorkspaceComment // Set the size to the default size as defined in the superclass. this.view.setSize(this.getSize()); this.view.setEditable(this.isEditable()); + this.view.getSvgRoot().setAttribute('data-id', this.id); this.addModelUpdateBindings(); @@ -207,6 +209,7 @@ export class RenderedWorkspaceComment const gesture = this.workspace.getGesture(e); if (gesture) { gesture.handleCommentStart(e, this); + this.workspace.getLayerManager()?.append(this, layers.BLOCK); common.setSelected(this); } } diff --git a/core/comments/workspace_comment.ts b/core/comments/workspace_comment.ts index 3c23aba86a2..2d59c715edd 100644 --- a/core/comments/workspace_comment.ts +++ b/core/comments/workspace_comment.ts @@ -4,12 +4,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {Workspace} from '../workspace.js'; -import {Size} from '../utils/size.js'; +import {CommentMove} from '../events/events_comment_move.js'; +import {CommentResize} from '../events/events_comment_resize.js'; +import {EventType} from '../events/type.js'; +import * as eventUtils from '../events/utils.js'; import {Coordinate} from '../utils/coordinate.js'; import * as idGenerator from '../utils/idgenerator.js'; -import * as eventUtils from '../events/utils.js'; -import {CommentMove} from '../events/events_comment_move.js'; +import {Size} from '../utils/size.js'; +import {Workspace} from '../workspace.js'; export class WorkspaceComment { /** The unique identifier for this comment. */ @@ -62,13 +64,13 @@ export class WorkspaceComment { private fireCreateEvent() { if (eventUtils.isEnabled()) { - eventUtils.fire(new (eventUtils.get(eventUtils.COMMENT_CREATE))(this)); + eventUtils.fire(new (eventUtils.get(EventType.COMMENT_CREATE))(this)); } } private fireDeleteEvent() { if (eventUtils.isEnabled()) { - eventUtils.fire(new (eventUtils.get(eventUtils.COMMENT_DELETE))(this)); + eventUtils.fire(new (eventUtils.get(EventType.COMMENT_DELETE))(this)); } } @@ -76,7 +78,7 @@ export class WorkspaceComment { private fireChangeEvent(oldText: string, newText: string) { if (eventUtils.isEnabled()) { eventUtils.fire( - new (eventUtils.get(eventUtils.COMMENT_CHANGE))(this, oldText, newText), + new (eventUtils.get(EventType.COMMENT_CHANGE))(this, oldText, newText), ); } } @@ -85,7 +87,7 @@ export class WorkspaceComment { private fireCollapseEvent(newCollapsed: boolean) { if (eventUtils.isEnabled()) { eventUtils.fire( - new (eventUtils.get(eventUtils.COMMENT_COLLAPSE))(this, newCollapsed), + new (eventUtils.get(EventType.COMMENT_COLLAPSE))(this, newCollapsed), ); } } @@ -104,7 +106,14 @@ export class WorkspaceComment { /** Sets the comment's size in workspace units. */ setSize(size: Size) { + const event = new (eventUtils.get(EventType.COMMENT_RESIZE))( + this, + ) as CommentResize; + this.size = size; + + event.recordCurrentSizeAsNewSize(); + eventUtils.fire(event); } /** Returns the comment's size in workspace units. */ @@ -175,7 +184,11 @@ export class WorkspaceComment { * workspace is read-only. */ isDeletable(): boolean { - return this.isOwnDeletable() && !this.workspace.options.readOnly; + return ( + this.isOwnDeletable() && + !this.isDeadOrDying() && + !this.workspace.options.readOnly + ); } /** @@ -188,7 +201,7 @@ export class WorkspaceComment { /** Moves the comment to the given location in workspace coordinates. */ moveTo(location: Coordinate, reason?: string[] | undefined) { - const event = new (eventUtils.get(eventUtils.COMMENT_MOVE))( + const event = new (eventUtils.get(EventType.COMMENT_MOVE))( this, ) as CommentMove; if (reason) event.setReason(reason); @@ -196,7 +209,7 @@ export class WorkspaceComment { this.location = location; event.recordNew(); - if (eventUtils.isEnabled()) eventUtils.fire(event); + eventUtils.fire(event); } /** Returns the position of the comment in workspace coordinates. */ diff --git a/core/common.ts b/core/common.ts index fba960a5b5a..bc31bf17eea 100644 --- a/core/common.ts +++ b/core/common.ts @@ -6,14 +6,14 @@ // Former goog.module ID: Blockly.common -/* eslint-disable-next-line no-unused-vars */ import type {Block} from './block.js'; import {ISelectable} from './blockly.js'; import {BlockDefinition, Blocks} from './blocks.js'; import type {Connection} from './connection.js'; +import {EventType} from './events/type.js'; +import * as eventUtils from './events/utils.js'; import type {Workspace} from './workspace.js'; import type {WorkspaceSvg} from './workspace_svg.js'; -import * as eventUtils from './events/utils.js'; /** Database of all workspaces. */ const WorkspaceDB_ = Object.create(null); @@ -108,7 +108,7 @@ export function getSelected(): ISelectable | null { export function setSelected(newSelection: ISelectable | null) { if (selected === newSelection) return; - const event = new (eventUtils.get(eventUtils.SELECTED))( + const event = new (eventUtils.get(EventType.SELECTED))( selected?.id ?? null, newSelection?.id ?? null, newSelection?.workspace.id ?? selected?.workspace.id ?? '', diff --git a/core/component_manager.ts b/core/component_manager.ts index b9654c94ec5..8363d6fb4a0 100644 --- a/core/component_manager.ts +++ b/core/component_manager.ts @@ -23,10 +23,10 @@ class Capability<_T> { static DRAG_TARGET = new Capability('drag_target'); static DELETE_AREA = new Capability('delete_area'); static AUTOHIDEABLE = new Capability('autohideable'); - private readonly name_: string; + private readonly name: string; /** @param name The name of the component capability. */ constructor(name: string) { - this.name_ = name; + this.name = name; } /** @@ -35,7 +35,7 @@ class Capability<_T> { * @returns The name. */ toString(): string { - return this.name_; + return this.name; } } @@ -224,6 +224,16 @@ export class ComponentManager { } export namespace ComponentManager { + export enum ComponentWeight { + // The toolbox weight is lower (higher precedence) than the flyout, so that + // if both are under the pointer, the toolbox takes precedence even though + // the flyout's drag target area is large enough to include the toolbox. + TOOLBOX_WEIGHT = 0, + FLYOUT_WEIGHT = 1, + TRASHCAN_WEIGHT = 2, + ZOOM_CONTROLS_WEIGHT = 3, + } + /** An object storing component information. */ export interface ComponentDatum { component: IComponent; @@ -232,4 +242,6 @@ export namespace ComponentManager { } } +export type ComponentWeight = ComponentManager.ComponentWeight; +export const ComponentWeight = ComponentManager.ComponentWeight; export type ComponentDatum = ComponentManager.ComponentDatum; diff --git a/core/connection.ts b/core/connection.ts index 1dd8dc1ea55..9cc2c28a923 100644 --- a/core/connection.ts +++ b/core/connection.ts @@ -14,6 +14,7 @@ import type {Block} from './block.js'; import {ConnectionType} from './connection_type.js'; import type {BlockMove} from './events/events_block_move.js'; +import {EventType} from './events/type.js'; import * as eventUtils from './events/utils.js'; import type {Input} from './inputs/input.js'; import type {IASTNodeLocationWithBlock} from './interfaces/i_ast_node_location_with_block.js'; @@ -114,7 +115,7 @@ export class Connection implements IASTNodeLocationWithBlock { // Connect the new connection to the parent. let event; if (eventUtils.isEnabled()) { - event = new (eventUtils.get(eventUtils.BLOCK_MOVE))( + event = new (eventUtils.get(EventType.BLOCK_MOVE))( childBlock, ) as BlockMove; event.setReason(['connect']); @@ -213,11 +214,11 @@ export class Connection implements IASTNodeLocationWithBlock { * Called when an attempted connection fails. NOP by default (i.e. for * headless workspaces). * - * @param _otherConnection Connection that this connection failed to connect - * to. + * @param _superiorConnection Connection that this connection failed to connect + * to. The provided connection should be the superior connection. * @internal */ - onFailedConnect(_otherConnection: Connection) {} + onFailedConnect(_superiorConnection: Connection) {} // NOP /** @@ -281,7 +282,7 @@ export class Connection implements IASTNodeLocationWithBlock { let event; if (eventUtils.isEnabled()) { - event = new (eventUtils.get(eventUtils.BLOCK_MOVE))( + event = new (eventUtils.get(EventType.BLOCK_MOVE))( childConnection.getSourceBlock(), ) as BlockMove; event.setReason(['disconnect']); diff --git a/core/contextmenu.ts b/core/contextmenu.ts index e469c4335a1..b49dcba51c0 100644 --- a/core/contextmenu.ts +++ b/core/contextmenu.ts @@ -9,23 +9,24 @@ import type {Block} from './block.js'; import type {BlockSvg} from './block_svg.js'; import * as browserEvents from './browser_events.js'; +import * as common from './common.js'; import {config} from './config.js'; -import * as dom from './utils/dom.js'; import type { ContextMenuOption, LegacyContextMenuOption, } from './contextmenu_registry.js'; +import {EventType} from './events/type.js'; import * as eventUtils from './events/utils.js'; import {Menu} from './menu.js'; import {MenuItem} from './menuitem.js'; +import * as serializationBlocks from './serialization/blocks.js'; import * as aria from './utils/aria.js'; +import * as dom from './utils/dom.js'; import {Rect} from './utils/rect.js'; -import * as serializationBlocks from './serialization/blocks.js'; import * as svgMath from './utils/svg_math.js'; import * as WidgetDiv from './widgetdiv.js'; import type {WorkspaceSvg} from './workspace_svg.js'; import * as Xml from './xml.js'; -import * as common from './common.js'; /** * Which block is the context menu attached to? @@ -260,7 +261,7 @@ export function callbackFactory( eventUtils.enable(); } if (eventUtils.isEnabled() && !newBlock.isShadow()) { - eventUtils.fire(new (eventUtils.get(eventUtils.BLOCK_CREATE))(newBlock)); + eventUtils.fire(new (eventUtils.get(EventType.BLOCK_CREATE))(newBlock)); } common.setSelected(newBlock); return newBlock; diff --git a/core/contextmenu_items.ts b/core/contextmenu_items.ts index 254906ce7ff..25ffab59b8b 100644 --- a/core/contextmenu_items.ts +++ b/core/contextmenu_items.ts @@ -9,12 +9,13 @@ import type {BlockSvg} from './block_svg.js'; import * as clipboard from './clipboard.js'; import {RenderedWorkspaceComment} from './comments/rendered_workspace_comment.js'; +import * as common from './common.js'; +import {MANUALLY_DISABLED} from './constants.js'; import { ContextMenuRegistry, RegistryItem, Scope, } from './contextmenu_registry.js'; -import {MANUALLY_DISABLED} from './constants.js'; import * as dialog from './dialog.js'; import * as Events from './events/events.js'; import * as eventUtils from './events/utils.js'; @@ -23,7 +24,6 @@ import {Msg} from './msg.js'; import {StatementInput} from './renderers/zelos/zelos.js'; import {Coordinate} from './utils/coordinate.js'; import type {WorkspaceSvg} from './workspace_svg.js'; -import * as common from './common.js'; /** * Option to undo previous action. diff --git a/core/contextmenu_registry.ts b/core/contextmenu_registry.ts index abbd0f9756d..fb0d899d141 100644 --- a/core/contextmenu_registry.ts +++ b/core/contextmenu_registry.ts @@ -23,7 +23,7 @@ import type {WorkspaceSvg} from './workspace_svg.js'; export class ContextMenuRegistry { static registry: ContextMenuRegistry; /** Registry of all registered RegistryItems, keyed by ID. */ - private registry_ = new Map(); + private registeredItems = new Map(); /** Resets the existing singleton instance of ContextMenuRegistry. */ constructor() { @@ -32,7 +32,7 @@ export class ContextMenuRegistry { /** Clear and recreate the registry. */ reset() { - this.registry_.clear(); + this.registeredItems.clear(); } /** @@ -42,10 +42,10 @@ export class ContextMenuRegistry { * @throws {Error} if an item with the given ID already exists. */ register(item: RegistryItem) { - if (this.registry_.has(item.id)) { + if (this.registeredItems.has(item.id)) { throw Error('Menu item with ID "' + item.id + '" is already registered.'); } - this.registry_.set(item.id, item); + this.registeredItems.set(item.id, item); } /** @@ -55,10 +55,10 @@ export class ContextMenuRegistry { * @throws {Error} if an item with the given ID does not exist. */ unregister(id: string) { - if (!this.registry_.has(id)) { + if (!this.registeredItems.has(id)) { throw new Error('Menu item with ID "' + id + '" not found.'); } - this.registry_.delete(id); + this.registeredItems.delete(id); } /** @@ -66,7 +66,7 @@ export class ContextMenuRegistry { * @returns RegistryItem or null if not found */ getItem(id: string): RegistryItem | null { - return this.registry_.get(id) ?? null; + return this.registeredItems.get(id) ?? null; } /** @@ -85,7 +85,7 @@ export class ContextMenuRegistry { scope: Scope, ): ContextMenuOption[] { const menuOptions: ContextMenuOption[] = []; - for (const item of this.registry_.values()) { + for (const item of this.registeredItems.values()) { if (scopeType === item.scopeType) { const precondition = item.preconditionFn(scope); if (precondition !== 'hidden') { diff --git a/core/css.ts b/core/css.ts index 20c5730935e..c7443e5f06d 100644 --- a/core/css.ts +++ b/core/css.ts @@ -79,6 +79,8 @@ let content = ` position: relative; overflow: hidden; /* So blocks in drag surface disappear at edges */ touch-action: none; + user-select: none; + -webkit-user-select: none; } .blocklyNonSelectable { @@ -249,10 +251,6 @@ let content = ` stroke: none; } -.blocklyMultilineText { - font-family: monospace; -} - .blocklyNonEditableText>text { pointer-events: none; } @@ -266,17 +264,6 @@ let content = ` cursor: default; } -/* - Don't allow users to select text. It gets annoying when trying to - drag a block and selected text moves instead. -*/ -.blocklySvg text { - user-select: none; - -ms-user-select: none; - -webkit-user-select: none; - cursor: inherit; -} - .blocklyHidden { display: none; } diff --git a/core/delete_area.ts b/core/delete_area.ts index 4967927c42c..405084db9b1 100644 --- a/core/delete_area.ts +++ b/core/delete_area.ts @@ -14,9 +14,9 @@ import {BlockSvg} from './block_svg.js'; import {DragTarget} from './drag_target.js'; +import {isDeletable} from './interfaces/i_deletable.js'; import type {IDeleteArea} from './interfaces/i_delete_area.js'; import type {IDraggable} from './interfaces/i_draggable.js'; -import {isDeletable} from './interfaces/i_deletable.js'; /** * Abstract class for a component that can delete a block or bubble that is diff --git a/core/dragging.ts b/core/dragging.ts index a7e46fc27da..4ba85c49f7d 100644 --- a/core/dragging.ts +++ b/core/dragging.ts @@ -4,9 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {Dragger} from './dragging/dragger.js'; import {BlockDragStrategy} from './dragging/block_drag_strategy.js'; import {BubbleDragStrategy} from './dragging/bubble_drag_strategy.js'; import {CommentDragStrategy} from './dragging/comment_drag_strategy.js'; +import {Dragger} from './dragging/dragger.js'; -export {Dragger, BlockDragStrategy, BubbleDragStrategy, CommentDragStrategy}; +export {BlockDragStrategy, BubbleDragStrategy, CommentDragStrategy, Dragger}; diff --git a/core/dragging/block_drag_strategy.ts b/core/dragging/block_drag_strategy.ts index dc136d814c9..c9a1ea0abf7 100644 --- a/core/dragging/block_drag_strategy.ts +++ b/core/dragging/block_drag_strategy.ts @@ -4,24 +4,25 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {WorkspaceSvg} from '../workspace_svg.js'; -import {IDragStrategy} from '../interfaces/i_draggable.js'; -import {Coordinate} from '../utils.js'; -import * as eventUtils from '../events/utils.js'; -import {BlockSvg} from '../block_svg.js'; -import {RenderedConnection} from '../rendered_connection.js'; -import * as dom from '../utils/dom.js'; +import type {Block} from '../block.js'; import * as blockAnimation from '../block_animations.js'; -import {ConnectionType} from '../connection_type.js'; +import {BlockSvg} from '../block_svg.js'; import * as bumpObjects from '../bump_objects.js'; -import * as registry from '../registry.js'; -import {IConnectionPreviewer} from '../interfaces/i_connection_previewer.js'; -import {Connection} from '../connection.js'; -import type {Block} from '../block.js'; import {config} from '../config.js'; +import {Connection} from '../connection.js'; +import {ConnectionType} from '../connection_type.js'; import type {BlockMove} from '../events/events_block_move.js'; -import {finishQueuedRenders} from '../render_management.js'; +import {EventType} from '../events/type.js'; +import * as eventUtils from '../events/utils.js'; +import {IConnectionPreviewer} from '../interfaces/i_connection_previewer.js'; +import {IDragStrategy} from '../interfaces/i_draggable.js'; import * as layers from '../layers.js'; +import * as registry from '../registry.js'; +import {finishQueuedRenders} from '../render_management.js'; +import {RenderedConnection} from '../rendered_connection.js'; +import {Coordinate} from '../utils.js'; +import * as dom from '../utils/dom.js'; +import {WorkspaceSvg} from '../workspace_svg.js'; /** Represents a nearby valid connection. */ interface ConnectionCandidate { @@ -61,6 +62,9 @@ export class BlockDragStrategy implements IDragStrategy { */ private dragOffset = new Coordinate(0, 0); + /** Was there already an event group in progress when the drag started? */ + private inGroup: boolean = false; + constructor(private block: BlockSvg) { this.workspace = block.workspace; } @@ -92,7 +96,8 @@ export class BlockDragStrategy implements IDragStrategy { } this.dragging = true; - if (!eventUtils.getGroup()) { + this.inGroup = !!eventUtils.getGroup(); + if (!this.inGroup) { eventUtils.setGroup(true); } this.fireDragStartEvent(); @@ -173,7 +178,7 @@ export class BlockDragStrategy implements IDragStrategy { /** Fire a UI event at the start of a block drag. */ private fireDragStartEvent() { - const event = new (eventUtils.get(eventUtils.BLOCK_DRAG))( + const event = new (eventUtils.get(EventType.BLOCK_DRAG))( this.block, true, this.block.getDescendants(false), @@ -183,7 +188,7 @@ export class BlockDragStrategy implements IDragStrategy { /** Fire a UI event at the end of a block drag. */ private fireDragEndEvent() { - const event = new (eventUtils.get(eventUtils.BLOCK_DRAG))( + const event = new (eventUtils.get(EventType.BLOCK_DRAG))( this.block, false, this.block.getDescendants(false), @@ -194,7 +199,7 @@ export class BlockDragStrategy implements IDragStrategy { /** Fire a move event at the end of a block drag. */ private fireMoveEvent() { if (this.block.isDeadOrDying()) return; - const event = new (eventUtils.get(eventUtils.BLOCK_MOVE))( + const event = new (eventUtils.get(EventType.BLOCK_MOVE))( this.block, ) as BlockMove; event.setReason(['drag']); @@ -379,17 +384,24 @@ export class BlockDragStrategy implements IDragStrategy { if (this.connectionCandidate) { // Applying connections also rerenders the relevant blocks. this.applyConnections(this.connectionCandidate); + this.disposeStep(); } else { - this.block.queueRender(); + this.block.queueRender().then(() => this.disposeStep()); + } + + if (!this.inGroup) { + eventUtils.setGroup(false); } + } + + /** Disposes of any state at the end of the drag. */ + private disposeStep() { this.block.snapToGrid(); // Must dispose after connections are applied to not break the dynamic // connections plugin. See #7859 this.connectionPreviewer!.dispose(); this.workspace.setResizesEnabled(true); - - eventUtils.setGroup(false); } /** Connects the given candidate connections. */ diff --git a/core/dragging/bubble_drag_strategy.ts b/core/dragging/bubble_drag_strategy.ts index 7ffccddc1e5..c2a5c58f4a2 100644 --- a/core/dragging/bubble_drag_strategy.ts +++ b/core/dragging/bubble_drag_strategy.ts @@ -4,15 +4,18 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {IDragStrategy} from '../interfaces/i_draggable.js'; -import {Coordinate} from '../utils.js'; -import * as eventUtils from '../events/utils.js'; import {IBubble, WorkspaceSvg} from '../blockly.js'; +import * as eventUtils from '../events/utils.js'; +import {IDragStrategy} from '../interfaces/i_draggable.js'; import * as layers from '../layers.js'; +import {Coordinate} from '../utils.js'; export class BubbleDragStrategy implements IDragStrategy { private startLoc: Coordinate | null = null; + /** Was there already an event group in progress when the drag started? */ + private inGroup: boolean = false; + constructor( private bubble: IBubble, private workspace: WorkspaceSvg, @@ -23,13 +26,16 @@ export class BubbleDragStrategy implements IDragStrategy { } startDrag(): void { - if (!eventUtils.getGroup()) { + this.inGroup = !!eventUtils.getGroup(); + if (!this.inGroup) { eventUtils.setGroup(true); } this.startLoc = this.bubble.getRelativeToSurfaceXY(); this.workspace.setResizesEnabled(false); this.workspace.getLayerManager()?.moveToDragLayer(this.bubble); - this.bubble.setDragging && this.bubble.setDragging(true); + if (this.bubble.setDragging) { + this.bubble.setDragging(true); + } } drag(newLoc: Coordinate): void { @@ -38,7 +44,9 @@ export class BubbleDragStrategy implements IDragStrategy { endDrag(): void { this.workspace.setResizesEnabled(true); - eventUtils.setGroup(false); + if (!this.inGroup) { + eventUtils.setGroup(false); + } this.workspace .getLayerManager() diff --git a/core/dragging/comment_drag_strategy.ts b/core/dragging/comment_drag_strategy.ts index 804ad2e9c9e..dd8b10fc2f9 100644 --- a/core/dragging/comment_drag_strategy.ts +++ b/core/dragging/comment_drag_strategy.ts @@ -4,31 +4,41 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {IDragStrategy} from '../interfaces/i_draggable.js'; -import {Coordinate} from '../utils.js'; +import {RenderedWorkspaceComment} from '../comments.js'; +import {CommentMove} from '../events/events_comment_move.js'; +import {EventType} from '../events/type.js'; import * as eventUtils from '../events/utils.js'; +import {IDragStrategy} from '../interfaces/i_draggable.js'; import * as layers from '../layers.js'; -import {RenderedWorkspaceComment} from '../comments.js'; +import {Coordinate} from '../utils.js'; import {WorkspaceSvg} from '../workspace_svg.js'; -import {CommentMove} from '../events/events_comment_move.js'; export class CommentDragStrategy implements IDragStrategy { private startLoc: Coordinate | null = null; private workspace: WorkspaceSvg; + /** Was there already an event group in progress when the drag started? */ + private inGroup: boolean = false; + constructor(private comment: RenderedWorkspaceComment) { this.workspace = comment.workspace; } isMovable(): boolean { - return this.comment.isOwnMovable() && !this.workspace.options.readOnly; + return ( + this.comment.isOwnMovable() && + !this.comment.isDeadOrDying() && + !this.workspace.options.readOnly + ); } startDrag(): void { - if (!eventUtils.getGroup()) { + this.inGroup = !!eventUtils.getGroup(); + if (!this.inGroup) { eventUtils.setGroup(true); } + this.fireDragStartEvent(); this.startLoc = this.comment.getRelativeToSurfaceXY(); this.workspace.setResizesEnabled(false); this.workspace.getLayerManager()?.moveToDragLayer(this.comment); @@ -40,6 +50,7 @@ export class CommentDragStrategy implements IDragStrategy { } endDrag(): void { + this.fireDragEndEvent(); this.fireMoveEvent(); this.workspace @@ -50,12 +61,33 @@ export class CommentDragStrategy implements IDragStrategy { this.comment.snapToGrid(); this.workspace.setResizesEnabled(true); - eventUtils.setGroup(false); + if (!this.inGroup) { + eventUtils.setGroup(false); + } + } + + /** Fire a UI event at the start of a comment drag. */ + private fireDragStartEvent() { + const event = new (eventUtils.get(EventType.COMMENT_DRAG))( + this.comment, + true, + ); + eventUtils.fire(event); + } + + /** Fire a UI event at the end of a comment drag. */ + private fireDragEndEvent() { + const event = new (eventUtils.get(EventType.COMMENT_DRAG))( + this.comment, + false, + ); + eventUtils.fire(event); } + /** Fire a move event at the end of a comment drag. */ private fireMoveEvent() { if (this.comment.isDeadOrDying()) return; - const event = new (eventUtils.get(eventUtils.COMMENT_MOVE))( + const event = new (eventUtils.get(EventType.COMMENT_MOVE))( this.comment, ) as CommentMove; event.setReason(['drag']); diff --git a/core/dragging/dragger.ts b/core/dragging/dragger.ts index 66d447a6fca..8a9ac87c6a9 100644 --- a/core/dragging/dragger.ts +++ b/core/dragging/dragger.ts @@ -4,18 +4,18 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {IDragTarget} from '../interfaces/i_drag_target.js'; +import * as blockAnimations from '../block_animations.js'; +import {BlockSvg} from '../block_svg.js'; +import {ComponentManager} from '../component_manager.js'; +import * as eventUtils from '../events/utils.js'; import {IDeletable, isDeletable} from '../interfaces/i_deletable.js'; -import {IDragger} from '../interfaces/i_dragger.js'; +import {IDeleteArea} from '../interfaces/i_delete_area.js'; +import {IDragTarget} from '../interfaces/i_drag_target.js'; import {IDraggable} from '../interfaces/i_draggable.js'; +import {IDragger} from '../interfaces/i_dragger.js'; +import * as registry from '../registry.js'; import {Coordinate} from '../utils/coordinate.js'; import {WorkspaceSvg} from '../workspace_svg.js'; -import {ComponentManager} from '../component_manager.js'; -import {IDeleteArea} from '../interfaces/i_delete_area.js'; -import * as registry from '../registry.js'; -import * as eventUtils from '../events/utils.js'; -import * as blockAnimations from '../block_animations.js'; -import {BlockSvg} from '../block_svg.js'; export class Dragger implements IDragger { protected startLoc: Coordinate; diff --git a/core/dropdowndiv.ts b/core/dropdowndiv.ts index c90661c4ea7..f9af02ac9f7 100644 --- a/core/dropdowndiv.ts +++ b/core/dropdowndiv.ts @@ -14,8 +14,8 @@ import type {BlockSvg} from './block_svg.js'; import * as common from './common.js'; -import * as dom from './utils/dom.js'; import type {Field} from './field.js'; +import * as dom from './utils/dom.js'; import * as math from './utils/math.js'; import {Rect} from './utils/rect.js'; import type {Size} from './utils/size.js'; @@ -53,7 +53,7 @@ export const ANIMATION_TIME = 0.25; let animateOutTimer: ReturnType | null = null; /** Callback for when the drop-down is hidden. */ -let onHide: Function | null = null; +let onHide: (() => void) | null = null; /** A class name representing the current owner's workspace renderer. */ let renderedClassName = ''; @@ -202,7 +202,7 @@ export function setColour(backgroundColour: string, borderColour: string) { export function showPositionedByBlock( field: Field, block: BlockSvg, - opt_onHide?: Function, + opt_onHide?: () => void, opt_secondaryYOffset?: number, ): boolean { return showPositionedByRect( @@ -226,7 +226,7 @@ export function showPositionedByBlock( */ export function showPositionedByField( field: Field, - opt_onHide?: Function, + opt_onHide?: () => void, opt_secondaryYOffset?: number, ): boolean { positionToField = true; @@ -278,7 +278,7 @@ function getScaledBboxOfField(field: Field): Rect { function showPositionedByRect( bBox: Rect, field: Field, - opt_onHide?: Function, + opt_onHide?: () => void, opt_secondaryYOffset?: number, ): boolean { // If we can fit it, render below the block. @@ -334,7 +334,7 @@ export function show( primaryY: number, secondaryX: number, secondaryY: number, - opt_onHide?: Function, + opt_onHide?: () => void, ): boolean { owner = newOwner as Field; onHide = opt_onHide || null; diff --git a/core/events/events.ts b/core/events/events.ts index bb8011755fc..86899565381 100644 --- a/core/events/events.ts +++ b/core/events/events.ts @@ -6,146 +6,103 @@ // Former goog.module ID: Blockly.Events -import {Abstract, AbstractEventJson} from './events_abstract.js'; -import {BlockBase, BlockBaseJson} from './events_block_base.js'; -import {BlockChange, BlockChangeJson} from './events_block_change.js'; -import {BlockCreate, BlockCreateJson} from './events_block_create.js'; -import {BlockDelete, BlockDeleteJson} from './events_block_delete.js'; -import {BlockDrag, BlockDragJson} from './events_block_drag.js'; -import { +import {EventType} from './type.js'; + +// Events. +export {Abstract, AbstractEventJson} from './events_abstract.js'; +export {BlockBase, BlockBaseJson} from './events_block_base.js'; +export {BlockChange, BlockChangeJson} from './events_block_change.js'; +export {BlockCreate, BlockCreateJson} from './events_block_create.js'; +export {BlockDelete, BlockDeleteJson} from './events_block_delete.js'; +export {BlockDrag, BlockDragJson} from './events_block_drag.js'; +export { BlockFieldIntermediateChange, BlockFieldIntermediateChangeJson, } from './events_block_field_intermediate_change.js'; -import {BlockMove, BlockMoveJson} from './events_block_move.js'; -import {BubbleOpen, BubbleOpenJson, BubbleType} from './events_bubble_open.js'; -import {Click, ClickJson, ClickTarget} from './events_click.js'; -import {CommentBase, CommentBaseJson} from './events_comment_base.js'; -import {CommentChange, CommentChangeJson} from './events_comment_change.js'; -import {CommentCreate, CommentCreateJson} from './events_comment_create.js'; -import {CommentDelete} from './events_comment_delete.js'; -import {CommentMove, CommentMoveJson} from './events_comment_move.js'; -import { +export {BlockMove, BlockMoveJson} from './events_block_move.js'; +export {BubbleOpen, BubbleOpenJson, BubbleType} from './events_bubble_open.js'; +export {Click, ClickJson, ClickTarget} from './events_click.js'; +export {CommentBase, CommentBaseJson} from './events_comment_base.js'; +export {CommentChange, CommentChangeJson} from './events_comment_change.js'; +export { CommentCollapse, CommentCollapseJson, } from './events_comment_collapse.js'; -import {MarkerMove, MarkerMoveJson} from './events_marker_move.js'; -import {Selected, SelectedJson} from './events_selected.js'; -import {ThemeChange, ThemeChangeJson} from './events_theme_change.js'; -import { +export {CommentCreate, CommentCreateJson} from './events_comment_create.js'; +export {CommentDelete} from './events_comment_delete.js'; +export {CommentDrag, CommentDragJson} from './events_comment_drag.js'; +export {CommentMove, CommentMoveJson} from './events_comment_move.js'; +export {CommentResize, CommentResizeJson} from './events_comment_resize.js'; +export {MarkerMove, MarkerMoveJson} from './events_marker_move.js'; +export {Selected, SelectedJson} from './events_selected.js'; +export {ThemeChange, ThemeChangeJson} from './events_theme_change.js'; +export { ToolboxItemSelect, ToolboxItemSelectJson, } from './events_toolbox_item_select.js'; -import {TrashcanOpen, TrashcanOpenJson} from './events_trashcan_open.js'; -import {UiBase} from './events_ui_base.js'; -import {VarBase, VarBaseJson} from './events_var_base.js'; -import {VarCreate, VarCreateJson} from './events_var_create.js'; -import {VarDelete, VarDeleteJson} from './events_var_delete.js'; -import {VarRename, VarRenameJson} from './events_var_rename.js'; -import {ViewportChange, ViewportChangeJson} from './events_viewport.js'; -import * as eventUtils from './utils.js'; -import {FinishedLoading} from './workspace_events.js'; +export {TrashcanOpen, TrashcanOpenJson} from './events_trashcan_open.js'; +export {UiBase} from './events_ui_base.js'; +export {VarBase, VarBaseJson} from './events_var_base.js'; +export {VarCreate, VarCreateJson} from './events_var_create.js'; +export {VarDelete, VarDeleteJson} from './events_var_delete.js'; +export {VarRename, VarRenameJson} from './events_var_rename.js'; +export {ViewportChange, ViewportChangeJson} from './events_viewport.js'; +export {FinishedLoading} from './workspace_events.js'; -// Events. -export {Abstract}; -export {AbstractEventJson}; -export {BubbleOpen}; -export {BubbleOpenJson}; -export {BubbleType}; -export {BlockBase}; -export {BlockBaseJson}; -export {BlockChange}; -export {BlockChangeJson}; -export {BlockCreate}; -export {BlockCreateJson}; -export {BlockDelete}; -export {BlockDeleteJson}; -export {BlockDrag}; -export {BlockDragJson}; -export {BlockFieldIntermediateChange}; -export {BlockFieldIntermediateChangeJson}; -export {BlockMove}; -export {BlockMoveJson}; -export {Click}; -export {ClickJson}; -export {ClickTarget}; -export {CommentBase}; -export {CommentBaseJson}; -export {CommentChange}; -export {CommentChangeJson}; -export {CommentCreate}; -export {CommentCreateJson}; -export {CommentDelete}; -export {CommentMove}; -export {CommentMoveJson}; -export {CommentCollapse}; -export {CommentCollapseJson}; -export {FinishedLoading}; -export {MarkerMove}; -export {MarkerMoveJson}; -export {Selected}; -export {SelectedJson}; -export {ThemeChange}; -export {ThemeChangeJson}; -export {ToolboxItemSelect}; -export {ToolboxItemSelectJson}; -export {TrashcanOpen}; -export {TrashcanOpenJson}; -export {UiBase}; -export {VarBase}; -export {VarBaseJson}; -export {VarCreate}; -export {VarCreateJson}; -export {VarDelete}; -export {VarDeleteJson}; -export {VarRename}; -export {VarRenameJson}; -export {ViewportChange}; -export {ViewportChangeJson}; +export type {BumpEvent} from './utils.js'; // Event types. -export const BLOCK_CHANGE = eventUtils.BLOCK_CHANGE; -export const BLOCK_CREATE = eventUtils.BLOCK_CREATE; -export const BLOCK_DELETE = eventUtils.BLOCK_DELETE; -export const BLOCK_DRAG = eventUtils.BLOCK_DRAG; -export const BLOCK_MOVE = eventUtils.BLOCK_MOVE; +export const BLOCK_CHANGE = EventType.BLOCK_CHANGE; +export const BLOCK_CREATE = EventType.BLOCK_CREATE; +export const BLOCK_DELETE = EventType.BLOCK_DELETE; +export const BLOCK_DRAG = EventType.BLOCK_DRAG; +export const BLOCK_MOVE = EventType.BLOCK_MOVE; export const BLOCK_FIELD_INTERMEDIATE_CHANGE = - eventUtils.BLOCK_FIELD_INTERMEDIATE_CHANGE; -export const BUBBLE_OPEN = eventUtils.BUBBLE_OPEN; -export type BumpEvent = eventUtils.BumpEvent; -export const BUMP_EVENTS = eventUtils.BUMP_EVENTS; -export const CHANGE = eventUtils.CHANGE; -export const CLICK = eventUtils.CLICK; -export const COMMENT_CHANGE = eventUtils.COMMENT_CHANGE; -export const COMMENT_CREATE = eventUtils.COMMENT_CREATE; -export const COMMENT_DELETE = eventUtils.COMMENT_DELETE; -export const COMMENT_MOVE = eventUtils.COMMENT_MOVE; -export const CREATE = eventUtils.CREATE; -export const DELETE = eventUtils.DELETE; -export const FINISHED_LOADING = eventUtils.FINISHED_LOADING; -export const MARKER_MOVE = eventUtils.MARKER_MOVE; -export const MOVE = eventUtils.MOVE; -export const SELECTED = eventUtils.SELECTED; -export const THEME_CHANGE = eventUtils.THEME_CHANGE; -export const TOOLBOX_ITEM_SELECT = eventUtils.TOOLBOX_ITEM_SELECT; -export const TRASHCAN_OPEN = eventUtils.TRASHCAN_OPEN; -export const UI = eventUtils.UI; -export const VAR_CREATE = eventUtils.VAR_CREATE; -export const VAR_DELETE = eventUtils.VAR_DELETE; -export const VAR_RENAME = eventUtils.VAR_RENAME; -export const VIEWPORT_CHANGE = eventUtils.VIEWPORT_CHANGE; + EventType.BLOCK_FIELD_INTERMEDIATE_CHANGE; +export const BUBBLE_OPEN = EventType.BUBBLE_OPEN; +/** @deprecated Use BLOCK_CHANGE instead */ +export const CHANGE = EventType.BLOCK_CHANGE; +export const CLICK = EventType.CLICK; +export const COMMENT_CHANGE = EventType.COMMENT_CHANGE; +export const COMMENT_CREATE = EventType.COMMENT_CREATE; +export const COMMENT_DELETE = EventType.COMMENT_DELETE; +export const COMMENT_MOVE = EventType.COMMENT_MOVE; +export const COMMENT_RESIZE = EventType.COMMENT_RESIZE; +export const COMMENT_DRAG = EventType.COMMENT_DRAG; +/** @deprecated Use BLOCK_CREATE instead */ +export const CREATE = EventType.BLOCK_CREATE; +/** @deprecated Use BLOCK_DELETE instead */ +export const DELETE = EventType.BLOCK_DELETE; +export const FINISHED_LOADING = EventType.FINISHED_LOADING; +export const MARKER_MOVE = EventType.MARKER_MOVE; +/** @deprecated Use BLOCK_MOVE instead */ +export const MOVE = EventType.BLOCK_MOVE; +export const SELECTED = EventType.SELECTED; +export const THEME_CHANGE = EventType.THEME_CHANGE; +export const TOOLBOX_ITEM_SELECT = EventType.TOOLBOX_ITEM_SELECT; +export const TRASHCAN_OPEN = EventType.TRASHCAN_OPEN; +export const UI = EventType.UI; +export const VAR_CREATE = EventType.VAR_CREATE; +export const VAR_DELETE = EventType.VAR_DELETE; +export const VAR_RENAME = EventType.VAR_RENAME; +export const VIEWPORT_CHANGE = EventType.VIEWPORT_CHANGE; + +export {BUMP_EVENTS} from './type.js'; // Event utils. -export const clearPendingUndo = eventUtils.clearPendingUndo; -export const disable = eventUtils.disable; -export const enable = eventUtils.enable; -export const filter = eventUtils.filter; -export const fire = eventUtils.fire; -export const fromJson = eventUtils.fromJson; -export const getDescendantIds = eventUtils.getDescendantIds; -export const get = eventUtils.get; -export const getGroup = eventUtils.getGroup; -export const getRecordUndo = eventUtils.getRecordUndo; -export const isEnabled = eventUtils.isEnabled; -export const setGroup = eventUtils.setGroup; -export const setRecordUndo = eventUtils.setRecordUndo; -export const disableOrphans = eventUtils.disableOrphans; +export { + clearPendingUndo, + disable, + disableOrphans, + enable, + filter, + fire, + fromJson, + get, + getDescendantIds, + getGroup, + getRecordUndo, + isEnabled, + setGroup, + setRecordUndo, +} from './utils.js'; diff --git a/core/events/events_abstract.ts b/core/events/events_abstract.ts index 31ff0a924dd..e5a77dc7d6b 100644 --- a/core/events/events_abstract.ts +++ b/core/events/events_abstract.ts @@ -14,8 +14,7 @@ import * as common from '../common.js'; import type {Workspace} from '../workspace.js'; - -import * as eventUtils from './utils.js'; +import {getGroup, getRecordUndo} from './utils.js'; /** * Abstract class for an event. @@ -48,8 +47,8 @@ export abstract class Abstract { type = ''; constructor() { - this.group = eventUtils.getGroup(); - this.recordUndo = eventUtils.getRecordUndo(); + this.group = getGroup(); + this.recordUndo = getRecordUndo(); } /** @@ -108,7 +107,6 @@ export abstract class Abstract { * * @returns The workspace the event belongs to. * @throws {Error} if workspace is null. - * @internal */ getEventWorkspace_(): Workspace { let workspace; diff --git a/core/events/events_block_base.ts b/core/events/events_block_base.ts index 350985428a3..d15b8e439ed 100644 --- a/core/events/events_block_base.ts +++ b/core/events/events_block_base.ts @@ -13,7 +13,6 @@ import type {Block} from '../block.js'; import type {Workspace} from '../workspace.js'; - import { Abstract as AbstractEvent, AbstractEventJson, diff --git a/core/events/events_block_change.ts b/core/events/events_block_change.ts index 570b7f58e2c..e71eabb1747 100644 --- a/core/events/events_block_change.ts +++ b/core/events/events_block_change.ts @@ -13,15 +13,15 @@ import type {Block} from '../block.js'; import type {BlockSvg} from '../block_svg.js'; +import {MANUALLY_DISABLED} from '../constants.js'; import {IconType} from '../icons/icon_types.js'; import {hasBubble} from '../interfaces/i_has_bubble.js'; -import {MANUALLY_DISABLED} from '../constants.js'; import * as registry from '../registry.js'; import * as utilsXml from '../utils/xml.js'; import {Workspace} from '../workspace.js'; import * as Xml from '../xml.js'; - import {BlockBase, BlockBaseJson} from './events_block_base.js'; +import {EventType} from './type.js'; import * as eventUtils from './utils.js'; /** @@ -29,7 +29,7 @@ import * as eventUtils from './utils.js'; * field values, comments, etc). */ export class BlockChange extends BlockBase { - override type = eventUtils.BLOCK_CHANGE; + override type = EventType.BLOCK_CHANGE; /** * The element that changed; one of 'field', 'comment', 'collapsed', * 'disabled', 'inline', or 'mutation' @@ -256,4 +256,4 @@ export interface BlockChangeJson extends BlockBaseJson { disabledReason?: string; } -registry.register(registry.Type.EVENT, eventUtils.CHANGE, BlockChange); +registry.register(registry.Type.EVENT, EventType.BLOCK_CHANGE, BlockChange); diff --git a/core/events/events_block_create.ts b/core/events/events_block_create.ts index cbabc9332de..ca697945488 100644 --- a/core/events/events_block_create.ts +++ b/core/events/events_block_create.ts @@ -15,18 +15,18 @@ import type {Block} from '../block.js'; import * as registry from '../registry.js'; import * as blocks from '../serialization/blocks.js'; import * as utilsXml from '../utils/xml.js'; +import {Workspace} from '../workspace.js'; import * as Xml from '../xml.js'; - import {BlockBase, BlockBaseJson} from './events_block_base.js'; +import {EventType} from './type.js'; import * as eventUtils from './utils.js'; -import {Workspace} from '../workspace.js'; /** * Notifies listeners when a block (or connected stack of blocks) is * created. */ export class BlockCreate extends BlockBase { - override type = eventUtils.BLOCK_CREATE; + override type = EventType.BLOCK_CREATE; /** The XML representation of the created block(s). */ xml?: Element | DocumentFragment; @@ -182,4 +182,4 @@ export interface BlockCreateJson extends BlockBaseJson { recordUndo?: boolean; } -registry.register(registry.Type.EVENT, eventUtils.CREATE, BlockCreate); +registry.register(registry.Type.EVENT, EventType.BLOCK_CREATE, BlockCreate); diff --git a/core/events/events_block_delete.ts b/core/events/events_block_delete.ts index 3375a78dda3..5dd23160642 100644 --- a/core/events/events_block_delete.ts +++ b/core/events/events_block_delete.ts @@ -15,11 +15,11 @@ import type {Block} from '../block.js'; import * as registry from '../registry.js'; import * as blocks from '../serialization/blocks.js'; import * as utilsXml from '../utils/xml.js'; +import {Workspace} from '../workspace.js'; import * as Xml from '../xml.js'; - import {BlockBase, BlockBaseJson} from './events_block_base.js'; +import {EventType} from './type.js'; import * as eventUtils from './utils.js'; -import {Workspace} from '../workspace.js'; /** * Notifies listeners when a block (or connected stack of blocks) is @@ -38,7 +38,7 @@ export class BlockDelete extends BlockBase { /** True if the deleted block was a shadow block, false otherwise. */ wasShadow?: boolean; - override type = eventUtils.BLOCK_DELETE; + override type = EventType.BLOCK_DELETE; /** @param opt_block The deleted block. Undefined for a blank event. */ constructor(opt_block?: Block) { @@ -179,4 +179,4 @@ export interface BlockDeleteJson extends BlockBaseJson { recordUndo?: boolean; } -registry.register(registry.Type.EVENT, eventUtils.DELETE, BlockDelete); +registry.register(registry.Type.EVENT, EventType.BLOCK_DELETE, BlockDelete); diff --git a/core/events/events_block_drag.ts b/core/events/events_block_drag.ts index 3729ab77756..4a91c4d112d 100644 --- a/core/events/events_block_drag.ts +++ b/core/events/events_block_drag.ts @@ -13,10 +13,10 @@ import type {Block} from '../block.js'; import * as registry from '../registry.js'; +import {Workspace} from '../workspace.js'; import {AbstractEventJson} from './events_abstract.js'; import {UiBase} from './events_ui_base.js'; -import * as eventUtils from './utils.js'; -import {Workspace} from '../workspace.js'; +import {EventType} from './type.js'; /** * Notifies listeners when a block is being manually dragged/dropped. @@ -34,7 +34,7 @@ export class BlockDrag extends UiBase { */ blocks?: Block[]; - override type = eventUtils.BLOCK_DRAG; + override type = EventType.BLOCK_DRAG; /** * @param opt_block The top block in the stack that is being dragged. @@ -113,4 +113,4 @@ export interface BlockDragJson extends AbstractEventJson { blocks?: Block[]; } -registry.register(registry.Type.EVENT, eventUtils.BLOCK_DRAG, BlockDrag); +registry.register(registry.Type.EVENT, EventType.BLOCK_DRAG, BlockDrag); diff --git a/core/events/events_block_field_intermediate_change.ts b/core/events/events_block_field_intermediate_change.ts index 264f910a8a2..49280cf2b4a 100644 --- a/core/events/events_block_field_intermediate_change.ts +++ b/core/events/events_block_field_intermediate_change.ts @@ -15,9 +15,8 @@ import type {Block} from '../block.js'; import * as registry from '../registry.js'; import {Workspace} from '../workspace.js'; - import {BlockBase, BlockBaseJson} from './events_block_base.js'; -import * as eventUtils from './utils.js'; +import {EventType} from './type.js'; /** * Notifies listeners when the value of a block's field has changed but the @@ -25,7 +24,7 @@ import * as eventUtils from './utils.js'; * event. */ export class BlockFieldIntermediateChange extends BlockBase { - override type = eventUtils.BLOCK_FIELD_INTERMEDIATE_CHANGE; + override type = EventType.BLOCK_FIELD_INTERMEDIATE_CHANGE; // Intermediate events do not undo or redo. They may be fired frequently while // the field editor widget is open. A separate BLOCK_CHANGE event is fired @@ -162,6 +161,6 @@ export interface BlockFieldIntermediateChangeJson extends BlockBaseJson { registry.register( registry.Type.EVENT, - eventUtils.BLOCK_FIELD_INTERMEDIATE_CHANGE, + EventType.BLOCK_FIELD_INTERMEDIATE_CHANGE, BlockFieldIntermediateChange, ); diff --git a/core/events/events_block_move.ts b/core/events/events_block_move.ts index 6c05ab2af28..99e1622896e 100644 --- a/core/events/events_block_move.ts +++ b/core/events/events_block_move.ts @@ -15,10 +15,9 @@ import type {Block} from '../block.js'; import {ConnectionType} from '../connection_type.js'; import * as registry from '../registry.js'; import {Coordinate} from '../utils/coordinate.js'; - -import {BlockBase, BlockBaseJson} from './events_block_base.js'; -import * as eventUtils from './utils.js'; import type {Workspace} from '../workspace.js'; +import {BlockBase, BlockBaseJson} from './events_block_base.js'; +import {EventType} from './type.js'; interface BlockLocation { parentId?: string; @@ -31,7 +30,7 @@ interface BlockLocation { * connection to another, or from one location on the workspace to another. */ export class BlockMove extends BlockBase { - override type = eventUtils.BLOCK_MOVE; + override type = EventType.BLOCK_MOVE; /** The ID of the old parent block. Undefined if it was a top-level block. */ oldParentId?: string; @@ -90,7 +89,7 @@ export class BlockMove extends BlockBase { this.recordUndo = false; } - const location = this.currentLocation_(); + const location = this.currentLocation(); this.oldParentId = location.parentId; this.oldInputName = location.inputName; this.oldCoordinate = location.coordinate; @@ -168,7 +167,7 @@ export class BlockMove extends BlockBase { /** Record the block's new location. Called after the move. */ recordNew() { - const location = this.currentLocation_(); + const location = this.currentLocation(); this.newParentId = location.parentId; this.newInputName = location.inputName; this.newCoordinate = location.coordinate; @@ -189,7 +188,7 @@ export class BlockMove extends BlockBase { * * @returns Collection of location info. */ - private currentLocation_(): BlockLocation { + private currentLocation(): BlockLocation { const workspace = this.getEventWorkspace_(); if (!this.blockId) { throw new Error( @@ -304,4 +303,4 @@ export interface BlockMoveJson extends BlockBaseJson { recordUndo?: boolean; } -registry.register(registry.Type.EVENT, eventUtils.MOVE, BlockMove); +registry.register(registry.Type.EVENT, EventType.BLOCK_MOVE, BlockMove); diff --git a/core/events/events_bubble_open.ts b/core/events/events_bubble_open.ts index 023e16a17e7..a36bbcd6a93 100644 --- a/core/events/events_bubble_open.ts +++ b/core/events/events_bubble_open.ts @@ -9,14 +9,15 @@ * * @class */ + // Former goog.module ID: Blockly.Events.BubbleOpen -import type {AbstractEventJson} from './events_abstract.js'; import type {BlockSvg} from '../block_svg.js'; import * as registry from '../registry.js'; -import {UiBase} from './events_ui_base.js'; -import * as eventUtils from './utils.js'; import type {Workspace} from '../workspace.js'; +import type {AbstractEventJson} from './events_abstract.js'; +import {UiBase} from './events_ui_base.js'; +import {EventType} from './type.js'; /** * Class for a bubble open event. @@ -31,7 +32,7 @@ export class BubbleOpen extends UiBase { /** The type of bubble; one of 'mutator', 'comment', or 'warning'. */ bubbleType?: BubbleType; - override type = eventUtils.BUBBLE_OPEN; + override type = EventType.BUBBLE_OPEN; /** * @param opt_block The associated block. Undefined for a blank event. @@ -117,4 +118,4 @@ export interface BubbleOpenJson extends AbstractEventJson { blockId: string; } -registry.register(registry.Type.EVENT, eventUtils.BUBBLE_OPEN, BubbleOpen); +registry.register(registry.Type.EVENT, EventType.BUBBLE_OPEN, BubbleOpen); diff --git a/core/events/events_click.ts b/core/events/events_click.ts index 1b15560695d..c023f20f152 100644 --- a/core/events/events_click.ts +++ b/core/events/events_click.ts @@ -9,15 +9,15 @@ * * @class */ + // Former goog.module ID: Blockly.Events.Click import type {Block} from '../block.js'; import * as registry from '../registry.js'; +import {Workspace} from '../workspace.js'; import {AbstractEventJson} from './events_abstract.js'; - import {UiBase} from './events_ui_base.js'; -import * as eventUtils from './utils.js'; -import {Workspace} from '../workspace.js'; +import {EventType} from './type.js'; /** * Notifies listeners that some blockly element was clicked. @@ -31,7 +31,7 @@ export class Click extends UiBase { * or 'zoom_controls'. */ targetType?: ClickTarget; - override type = eventUtils.CLICK; + override type = EventType.CLICK; /** * @param opt_block The affected block. Null for click events that do not have @@ -107,4 +107,4 @@ export interface ClickJson extends AbstractEventJson { blockId?: string; } -registry.register(registry.Type.EVENT, eventUtils.CLICK, Click); +registry.register(registry.Type.EVENT, EventType.CLICK, Click); diff --git a/core/events/events_comment_base.ts b/core/events/events_comment_base.ts index 6fbc95c4d60..e4b76c8e547 100644 --- a/core/events/events_comment_base.ts +++ b/core/events/events_comment_base.ts @@ -13,14 +13,14 @@ import type {WorkspaceComment} from '../comments/workspace_comment.js'; import * as comments from '../serialization/workspace_comments.js'; +import type {Workspace} from '../workspace.js'; import { Abstract as AbstractEvent, AbstractEventJson, } from './events_abstract.js'; import type {CommentCreate} from './events_comment_create.js'; import type {CommentDelete} from './events_comment_delete.js'; -import * as eventUtils from './utils.js'; -import type {Workspace} from '../workspace.js'; +import {getGroup, getRecordUndo} from './utils.js'; /** * Abstract class for a comment event. @@ -44,8 +44,8 @@ export class CommentBase extends AbstractEvent { this.commentId = opt_comment.id; this.workspaceId = opt_comment.workspace.id; - this.group = eventUtils.getGroup(); - this.recordUndo = eventUtils.getRecordUndo(); + this.group = getGroup(); + this.recordUndo = getRecordUndo(); } /** diff --git a/core/events/events_comment_change.ts b/core/events/events_comment_change.ts index eb39d929de9..4d944ea39af 100644 --- a/core/events/events_comment_change.ts +++ b/core/events/events_comment_change.ts @@ -11,18 +11,17 @@ */ // Former goog.module ID: Blockly.Events.CommentChange -import * as registry from '../registry.js'; import type {WorkspaceComment} from '../comments/workspace_comment.js'; - -import {CommentBase, CommentBaseJson} from './events_comment_base.js'; -import * as eventUtils from './utils.js'; +import * as registry from '../registry.js'; import type {Workspace} from '../workspace.js'; +import {CommentBase, CommentBaseJson} from './events_comment_base.js'; +import {EventType} from './type.js'; /** * Notifies listeners that the contents of a workspace comment has changed. */ export class CommentChange extends CommentBase { - override type = eventUtils.COMMENT_CHANGE; + override type = EventType.COMMENT_CHANGE; // TODO(#6774): We should remove underscores. /** The previous contents of the comment. */ @@ -154,8 +153,4 @@ export interface CommentChangeJson extends CommentBaseJson { newContents: string; } -registry.register( - registry.Type.EVENT, - eventUtils.COMMENT_CHANGE, - CommentChange, -); +registry.register(registry.Type.EVENT, EventType.COMMENT_CHANGE, CommentChange); diff --git a/core/events/events_comment_collapse.ts b/core/events/events_comment_collapse.ts index 6646b1df296..0f718a040bf 100644 --- a/core/events/events_comment_collapse.ts +++ b/core/events/events_comment_collapse.ts @@ -4,14 +4,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -import * as registry from '../registry.js'; import {WorkspaceComment} from '../comments/workspace_comment.js'; -import {CommentBase, CommentBaseJson} from './events_comment_base.js'; -import * as eventUtils from './utils.js'; +import * as registry from '../registry.js'; import type {Workspace} from '../workspace.js'; +import {CommentBase, CommentBaseJson} from './events_comment_base.js'; +import {EventType} from './type.js'; export class CommentCollapse extends CommentBase { - override type = eventUtils.COMMENT_COLLAPSE; + override type = EventType.COMMENT_COLLAPSE; constructor( comment?: WorkspaceComment, @@ -98,6 +98,6 @@ export interface CommentCollapseJson extends CommentBaseJson { registry.register( registry.Type.EVENT, - eventUtils.COMMENT_COLLAPSE, + EventType.COMMENT_COLLAPSE, CommentCollapse, ); diff --git a/core/events/events_comment_create.ts b/core/events/events_comment_create.ts index 692397df683..637107e3f55 100644 --- a/core/events/events_comment_create.ts +++ b/core/events/events_comment_create.ts @@ -11,20 +11,20 @@ */ // Former goog.module ID: Blockly.Events.CommentCreate -import * as registry from '../registry.js'; import type {WorkspaceComment} from '../comments/workspace_comment.js'; +import * as registry from '../registry.js'; import * as comments from '../serialization/workspace_comments.js'; import * as utilsXml from '../utils/xml.js'; +import type {Workspace} from '../workspace.js'; import * as Xml from '../xml.js'; import {CommentBase, CommentBaseJson} from './events_comment_base.js'; -import * as eventUtils from './utils.js'; -import type {Workspace} from '../workspace.js'; +import {EventType} from './type.js'; /** * Notifies listeners that a workspace comment was created. */ export class CommentCreate extends CommentBase { - override type = eventUtils.COMMENT_CREATE; + override type = EventType.COMMENT_CREATE; /** The XML representation of the created workspace comment. */ xml?: Element | DocumentFragment; @@ -111,8 +111,4 @@ export interface CommentCreateJson extends CommentBaseJson { json: object; } -registry.register( - registry.Type.EVENT, - eventUtils.COMMENT_CREATE, - CommentCreate, -); +registry.register(registry.Type.EVENT, EventType.COMMENT_CREATE, CommentCreate); diff --git a/core/events/events_comment_delete.ts b/core/events/events_comment_delete.ts index 62f8916fb3b..579131e5033 100644 --- a/core/events/events_comment_delete.ts +++ b/core/events/events_comment_delete.ts @@ -11,20 +11,20 @@ */ // Former goog.module ID: Blockly.Events.CommentDelete -import * as registry from '../registry.js'; import type {WorkspaceComment} from '../comments/workspace_comment.js'; +import * as registry from '../registry.js'; import * as comments from '../serialization/workspace_comments.js'; -import {CommentBase, CommentBaseJson} from './events_comment_base.js'; -import * as eventUtils from './utils.js'; import * as utilsXml from '../utils/xml.js'; -import * as Xml from '../xml.js'; import type {Workspace} from '../workspace.js'; +import * as Xml from '../xml.js'; +import {CommentBase, CommentBaseJson} from './events_comment_base.js'; +import {EventType} from './type.js'; /** * Notifies listeners that a workspace comment has been deleted. */ export class CommentDelete extends CommentBase { - override type = eventUtils.COMMENT_DELETE; + override type = EventType.COMMENT_DELETE; /** The XML representation of the deleted workspace comment. */ xml?: Element; @@ -110,8 +110,4 @@ export interface CommentDeleteJson extends CommentBaseJson { json: object; } -registry.register( - registry.Type.EVENT, - eventUtils.COMMENT_DELETE, - CommentDelete, -); +registry.register(registry.Type.EVENT, EventType.COMMENT_DELETE, CommentDelete); diff --git a/core/events/events_comment_drag.ts b/core/events/events_comment_drag.ts new file mode 100644 index 00000000000..b25ca5b7382 --- /dev/null +++ b/core/events/events_comment_drag.ts @@ -0,0 +1,99 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * Events fired when a workspace comment is dragged. + */ + +import type {WorkspaceComment} from '../comments/workspace_comment.js'; +import * as registry from '../registry.js'; +import {Workspace} from '../workspace.js'; +import {AbstractEventJson} from './events_abstract.js'; +import {UiBase} from './events_ui_base.js'; +import {EventType} from './type.js'; + +/** + * Notifies listeners when a comment is being manually dragged/dropped. + */ +export class CommentDrag extends UiBase { + /** The ID of the top-level comment being dragged. */ + commentId?: string; + + /** True if this is the start of a drag, false if this is the end of one. */ + isStart?: boolean; + + override type = EventType.COMMENT_DRAG; + + /** + * @param opt_comment The comment that is being dragged. + * Undefined for a blank event. + * @param opt_isStart Whether this is the start of a comment drag. + * Undefined for a blank event. + */ + constructor(opt_comment?: WorkspaceComment, opt_isStart?: boolean) { + const workspaceId = opt_comment ? opt_comment.workspace.id : undefined; + super(workspaceId); + if (!opt_comment) return; + + this.commentId = opt_comment.id; + this.isStart = opt_isStart; + } + + /** + * Encode the event as JSON. + * + * @returns JSON representation. + */ + override toJson(): CommentDragJson { + const json = super.toJson() as CommentDragJson; + if (this.isStart === undefined) { + throw new Error( + 'Whether this event is the start of a drag is undefined. ' + + 'Either pass the value to the constructor, or call fromJson', + ); + } + if (this.commentId === undefined) { + throw new Error( + 'The comment ID is undefined. Either pass a comment to ' + + 'the constructor, or call fromJson', + ); + } + json['isStart'] = this.isStart; + json['commentId'] = this.commentId; + return json; + } + + /** + * Deserializes the JSON event. + * + * @param event The event to append new properties to. Should be a subclass + * of CommentDrag, but we can't specify that due to the fact that parameters + * to static methods in subclasses must be supertypes of parameters to + * static methods in superclasses. + * @internal + */ + static fromJson( + json: CommentDragJson, + workspace: Workspace, + event?: any, + ): CommentDrag { + const newEvent = super.fromJson( + json, + workspace, + event ?? new CommentDrag(), + ) as CommentDrag; + newEvent.isStart = json['isStart']; + newEvent.commentId = json['commentId']; + return newEvent; + } +} + +export interface CommentDragJson extends AbstractEventJson { + isStart: boolean; + commentId: string; +} + +registry.register(registry.Type.EVENT, EventType.COMMENT_DRAG, CommentDrag); diff --git a/core/events/events_comment_move.ts b/core/events/events_comment_move.ts index 502ca032f4c..af5e336165d 100644 --- a/core/events/events_comment_move.ts +++ b/core/events/events_comment_move.ts @@ -11,19 +11,18 @@ */ // Former goog.module ID: Blockly.Events.CommentMove +import type {WorkspaceComment} from '../comments/workspace_comment.js'; import * as registry from '../registry.js'; import {Coordinate} from '../utils/coordinate.js'; -import type {WorkspaceComment} from '../comments/workspace_comment.js'; - -import {CommentBase, CommentBaseJson} from './events_comment_base.js'; -import * as eventUtils from './utils.js'; import type {Workspace} from '../workspace.js'; +import {CommentBase, CommentBaseJson} from './events_comment_base.js'; +import {EventType} from './type.js'; /** * Notifies listeners that a workspace comment has moved. */ export class CommentMove extends CommentBase { - override type = eventUtils.COMMENT_MOVE; + override type = EventType.COMMENT_MOVE; /** The comment that is being moved. */ comment_?: WorkspaceComment; @@ -204,4 +203,4 @@ export interface CommentMoveJson extends CommentBaseJson { newCoordinate: string; } -registry.register(registry.Type.EVENT, eventUtils.COMMENT_MOVE, CommentMove); +registry.register(registry.Type.EVENT, EventType.COMMENT_MOVE, CommentMove); diff --git a/core/events/events_comment_resize.ts b/core/events/events_comment_resize.ts new file mode 100644 index 00000000000..0c59177d9c4 --- /dev/null +++ b/core/events/events_comment_resize.ts @@ -0,0 +1,169 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * Class for comment resize event. + */ + +import type {WorkspaceComment} from '../comments/workspace_comment.js'; +import * as registry from '../registry.js'; +import {Size} from '../utils/size.js'; +import type {Workspace} from '../workspace.js'; +import {CommentBase, CommentBaseJson} from './events_comment_base.js'; +import {EventType} from './type.js'; + +/** + * Notifies listeners that a workspace comment has resized. + */ +export class CommentResize extends CommentBase { + override type = EventType.COMMENT_RESIZE; + + /** The size of the comment before the resize. */ + oldSize?: Size; + + /** The size of the comment after the resize. */ + newSize?: Size; + + /** + * @param opt_comment The comment that is being resized. Undefined for a blank + * event. + */ + constructor(opt_comment?: WorkspaceComment) { + super(opt_comment); + + if (!opt_comment) { + return; // Blank event to be populated by fromJson. + } + + this.oldSize = opt_comment.getSize(); + } + + /** + * Record the comment's new size. Called after the resize. Can only be + * called once. + */ + recordCurrentSizeAsNewSize() { + if (this.newSize) { + throw Error( + 'Tried to record the new size of a comment on the ' + + 'same event twice.', + ); + } + const workspace = this.getEventWorkspace_(); + if (!this.commentId) { + throw new Error( + 'The comment ID is undefined. Either pass a comment to ' + + 'the constructor, or call fromJson', + ); + } + const comment = workspace.getCommentById(this.commentId); + if (!comment) { + throw new Error( + 'The comment associated with the comment resize event ' + + 'could not be found', + ); + } + this.newSize = comment.getSize(); + } + + /** + * Encode the event as JSON. + * + * @returns JSON representation. + */ + override toJson(): CommentResizeJson { + const json = super.toJson() as CommentResizeJson; + if (!this.oldSize) { + throw new Error( + 'The old comment size is undefined. Either pass a comment to ' + + 'the constructor, or call fromJson', + ); + } + if (!this.newSize) { + throw new Error( + 'The new comment size is undefined. Either call ' + + 'recordCurrentSizeAsNewSize, or call fromJson', + ); + } + json['oldWidth'] = Math.round(this.oldSize.width); + json['oldHeight'] = Math.round(this.oldSize.height); + json['newWidth'] = Math.round(this.newSize.width); + json['newHeight'] = Math.round(this.newSize.height); + return json; + } + + /** + * Deserializes the JSON event. + * + * @param event The event to append new properties to. Should be a subclass + * of CommentResize, but we can't specify that due to the fact that + * parameters to static methods in subclasses must be supertypes of + * parameters to static methods in superclasses. + * @internal + */ + static fromJson( + json: CommentResizeJson, + workspace: Workspace, + event?: any, + ): CommentResize { + const newEvent = super.fromJson( + json, + workspace, + event ?? new CommentResize(), + ) as CommentResize; + newEvent.oldSize = new Size(json['oldWidth'], json['oldHeight']); + newEvent.newSize = new Size(json['newWidth'], json['newHeight']); + return newEvent; + } + + /** + * Does this event record any change of state? + * + * @returns False if something changed. + */ + override isNull(): boolean { + return Size.equals(this.oldSize, this.newSize); + } + + /** + * Run a resize event. + * + * @param forward True if run forward, false if run backward (undo). + */ + override run(forward: boolean) { + const workspace = this.getEventWorkspace_(); + if (!this.commentId) { + throw new Error( + 'The comment ID is undefined. Either pass a comment to ' + + 'the constructor, or call fromJson', + ); + } + const comment = workspace.getCommentById(this.commentId); + if (!comment) { + console.warn("Can't resize non-existent comment: " + this.commentId); + return; + } + + const size = forward ? this.newSize : this.oldSize; + if (!size) { + throw new Error( + 'Either oldSize or newSize is undefined. ' + + 'Either pass a comment to the constructor and call ' + + 'recordCurrentSizeAsNewSize, or call fromJson', + ); + } + comment.setSize(size); + } +} + +export interface CommentResizeJson extends CommentBaseJson { + oldWidth: number; + oldHeight: number; + newWidth: number; + newHeight: number; +} + +registry.register(registry.Type.EVENT, EventType.COMMENT_RESIZE, CommentResize); diff --git a/core/events/events_marker_move.ts b/core/events/events_marker_move.ts index f162eeca9a8..58309df5896 100644 --- a/core/events/events_marker_move.ts +++ b/core/events/events_marker_move.ts @@ -16,9 +16,8 @@ import {ASTNode} from '../keyboard_nav/ast_node.js'; import * as registry from '../registry.js'; import type {Workspace} from '../workspace.js'; import {AbstractEventJson} from './events_abstract.js'; - import {UiBase} from './events_ui_base.js'; -import * as eventUtils from './utils.js'; +import {EventType} from './type.js'; /** * Notifies listeners that a marker (used for keyboard navigation) has @@ -41,7 +40,7 @@ export class MarkerMove extends UiBase { */ isCursor?: boolean; - override type = eventUtils.MARKER_MOVE; + override type = EventType.MARKER_MOVE; /** * @param opt_block The affected block. Null if current node is of type @@ -131,4 +130,4 @@ export interface MarkerMoveJson extends AbstractEventJson { newNode: ASTNode; } -registry.register(registry.Type.EVENT, eventUtils.MARKER_MOVE, MarkerMove); +registry.register(registry.Type.EVENT, EventType.MARKER_MOVE, MarkerMove); diff --git a/core/events/events_selected.ts b/core/events/events_selected.ts index c320c67462b..e4a7774966b 100644 --- a/core/events/events_selected.ts +++ b/core/events/events_selected.ts @@ -12,11 +12,10 @@ // Former goog.module ID: Blockly.Events.Selected import * as registry from '../registry.js'; +import type {Workspace} from '../workspace.js'; import {AbstractEventJson} from './events_abstract.js'; - import {UiBase} from './events_ui_base.js'; -import * as eventUtils from './utils.js'; -import type {Workspace} from '../workspace.js'; +import {EventType} from './type.js'; /** * Class for a selected event. @@ -32,7 +31,7 @@ export class Selected extends UiBase { */ newElementId?: string; - override type = eventUtils.SELECTED; + override type = EventType.SELECTED; /** * @param opt_oldElementId The ID of the previously selected element. Null if @@ -95,4 +94,4 @@ export interface SelectedJson extends AbstractEventJson { newElementId?: string; } -registry.register(registry.Type.EVENT, eventUtils.SELECTED, Selected); +registry.register(registry.Type.EVENT, EventType.SELECTED, Selected); diff --git a/core/events/events_theme_change.ts b/core/events/events_theme_change.ts index c0267ac6caa..b142b9f148b 100644 --- a/core/events/events_theme_change.ts +++ b/core/events/events_theme_change.ts @@ -12,10 +12,10 @@ // Former goog.module ID: Blockly.Events.ThemeChange import * as registry from '../registry.js'; +import type {Workspace} from '../workspace.js'; import {AbstractEventJson} from './events_abstract.js'; import {UiBase} from './events_ui_base.js'; -import * as eventUtils from './utils.js'; -import type {Workspace} from '../workspace.js'; +import {EventType} from './type.js'; /** * Notifies listeners that the workspace theme has changed. @@ -24,7 +24,7 @@ export class ThemeChange extends UiBase { /** The name of the new theme that has been set. */ themeName?: string; - override type = eventUtils.THEME_CHANGE; + override type = EventType.THEME_CHANGE; /** * @param opt_themeName The theme name. Undefined for a blank event. @@ -81,4 +81,4 @@ export interface ThemeChangeJson extends AbstractEventJson { themeName: string; } -registry.register(registry.Type.EVENT, eventUtils.THEME_CHANGE, ThemeChange); +registry.register(registry.Type.EVENT, EventType.THEME_CHANGE, ThemeChange); diff --git a/core/events/events_toolbox_item_select.ts b/core/events/events_toolbox_item_select.ts index f1810deadc2..6a93dbfde2f 100644 --- a/core/events/events_toolbox_item_select.ts +++ b/core/events/events_toolbox_item_select.ts @@ -12,10 +12,10 @@ // Former goog.module ID: Blockly.Events.ToolboxItemSelect import * as registry from '../registry.js'; +import type {Workspace} from '../workspace.js'; import {AbstractEventJson} from './events_abstract.js'; import {UiBase} from './events_ui_base.js'; -import * as eventUtils from './utils.js'; -import type {Workspace} from '../workspace.js'; +import {EventType} from './type.js'; /** * Notifies listeners that a toolbox item has been selected. @@ -27,7 +27,7 @@ export class ToolboxItemSelect extends UiBase { /** The newly selected toolbox item. */ newItem?: string; - override type = eventUtils.TOOLBOX_ITEM_SELECT; + override type = EventType.TOOLBOX_ITEM_SELECT; /** * @param opt_oldItem The previously selected toolbox item. @@ -91,6 +91,6 @@ export interface ToolboxItemSelectJson extends AbstractEventJson { registry.register( registry.Type.EVENT, - eventUtils.TOOLBOX_ITEM_SELECT, + EventType.TOOLBOX_ITEM_SELECT, ToolboxItemSelect, ); diff --git a/core/events/events_trashcan_open.ts b/core/events/events_trashcan_open.ts index 745e7459cf8..af06d9f8f4f 100644 --- a/core/events/events_trashcan_open.ts +++ b/core/events/events_trashcan_open.ts @@ -12,11 +12,10 @@ // Former goog.module ID: Blockly.Events.TrashcanOpen import * as registry from '../registry.js'; +import type {Workspace} from '../workspace.js'; import {AbstractEventJson} from './events_abstract.js'; - import {UiBase} from './events_ui_base.js'; -import * as eventUtils from './utils.js'; -import type {Workspace} from '../workspace.js'; +import {EventType} from './type.js'; /** * Notifies listeners when the trashcan is opening or closing. @@ -27,7 +26,7 @@ export class TrashcanOpen extends UiBase { * False if it is currently closing (previously open). */ isOpen?: boolean; - override type = eventUtils.TRASHCAN_OPEN; + override type = EventType.TRASHCAN_OPEN; /** * @param opt_isOpen Whether the trashcan flyout is opening (false if @@ -85,4 +84,4 @@ export interface TrashcanOpenJson extends AbstractEventJson { isOpen: boolean; } -registry.register(registry.Type.EVENT, eventUtils.TRASHCAN_OPEN, TrashcanOpen); +registry.register(registry.Type.EVENT, EventType.TRASHCAN_OPEN, TrashcanOpen); diff --git a/core/events/events_var_base.ts b/core/events/events_var_base.ts index 74537f144ff..8e359de517f 100644 --- a/core/events/events_var_base.ts +++ b/core/events/events_var_base.ts @@ -12,12 +12,11 @@ // Former goog.module ID: Blockly.Events.VarBase import type {VariableModel} from '../variable_model.js'; - +import type {Workspace} from '../workspace.js'; import { Abstract as AbstractEvent, AbstractEventJson, } from './events_abstract.js'; -import type {Workspace} from '../workspace.js'; /** * Abstract class for a variable event. diff --git a/core/events/events_var_create.ts b/core/events/events_var_create.ts index a719cad985a..b3ae548aa0d 100644 --- a/core/events/events_var_create.ts +++ b/core/events/events_var_create.ts @@ -13,16 +13,15 @@ import * as registry from '../registry.js'; import type {VariableModel} from '../variable_model.js'; - -import {VarBase, VarBaseJson} from './events_var_base.js'; -import * as eventUtils from './utils.js'; import type {Workspace} from '../workspace.js'; +import {VarBase, VarBaseJson} from './events_var_base.js'; +import {EventType} from './type.js'; /** * Notifies listeners that a variable model has been created. */ export class VarCreate extends VarBase { - override type = eventUtils.VAR_CREATE; + override type = EventType.VAR_CREATE; /** The type of the variable that was created. */ varType?: string; @@ -123,4 +122,4 @@ export interface VarCreateJson extends VarBaseJson { varName: string; } -registry.register(registry.Type.EVENT, eventUtils.VAR_CREATE, VarCreate); +registry.register(registry.Type.EVENT, EventType.VAR_CREATE, VarCreate); diff --git a/core/events/events_var_delete.ts b/core/events/events_var_delete.ts index fc19461d4cd..caaa1f4874a 100644 --- a/core/events/events_var_delete.ts +++ b/core/events/events_var_delete.ts @@ -8,10 +8,9 @@ import * as registry from '../registry.js'; import type {VariableModel} from '../variable_model.js'; - -import {VarBase, VarBaseJson} from './events_var_base.js'; -import * as eventUtils from './utils.js'; import type {Workspace} from '../workspace.js'; +import {VarBase, VarBaseJson} from './events_var_base.js'; +import {EventType} from './type.js'; /** * Notifies listeners that a variable model has been deleted. @@ -19,7 +18,7 @@ import type {Workspace} from '../workspace.js'; * @class */ export class VarDelete extends VarBase { - override type = eventUtils.VAR_DELETE; + override type = EventType.VAR_DELETE; /** The type of the variable that was deleted. */ varType?: string; /** The name of the variable that was deleted. */ @@ -118,4 +117,4 @@ export interface VarDeleteJson extends VarBaseJson { varName: string; } -registry.register(registry.Type.EVENT, eventUtils.VAR_DELETE, VarDelete); +registry.register(registry.Type.EVENT, EventType.VAR_DELETE, VarDelete); diff --git a/core/events/events_var_rename.ts b/core/events/events_var_rename.ts index 3bb1e90eb56..b461184cab1 100644 --- a/core/events/events_var_rename.ts +++ b/core/events/events_var_rename.ts @@ -8,10 +8,9 @@ import * as registry from '../registry.js'; import type {VariableModel} from '../variable_model.js'; - -import {VarBase, VarBaseJson} from './events_var_base.js'; -import * as eventUtils from './utils.js'; import type {Workspace} from '../workspace.js'; +import {VarBase, VarBaseJson} from './events_var_base.js'; +import {EventType} from './type.js'; /** * Notifies listeners that a variable model was renamed. @@ -19,7 +18,7 @@ import type {Workspace} from '../workspace.js'; * @class */ export class VarRename extends VarBase { - override type = eventUtils.VAR_RENAME; + override type = EventType.VAR_RENAME; /** The previous name of the variable. */ oldName?: string; @@ -127,4 +126,4 @@ export interface VarRenameJson extends VarBaseJson { newName: string; } -registry.register(registry.Type.EVENT, eventUtils.VAR_RENAME, VarRename); +registry.register(registry.Type.EVENT, EventType.VAR_RENAME, VarRename); diff --git a/core/events/events_viewport.ts b/core/events/events_viewport.ts index aff236e48a2..b7a05b8d61e 100644 --- a/core/events/events_viewport.ts +++ b/core/events/events_viewport.ts @@ -12,10 +12,10 @@ // Former goog.module ID: Blockly.Events.ViewportChange import * as registry from '../registry.js'; +import type {Workspace} from '../workspace.js'; import {AbstractEventJson} from './events_abstract.js'; import {UiBase} from './events_ui_base.js'; -import * as eventUtils from './utils.js'; -import type {Workspace} from '../workspace.js'; +import {EventType} from './type.js'; /** * Notifies listeners that the workspace surface's position or scale has @@ -42,7 +42,7 @@ export class ViewportChange extends UiBase { /** The previous scale of the workspace. */ oldScale?: number; - override type = eventUtils.VIEWPORT_CHANGE; + override type = EventType.VIEWPORT_CHANGE; /** * @param opt_top Top-edge of the visible portion of the workspace, relative @@ -144,6 +144,6 @@ export interface ViewportChangeJson extends AbstractEventJson { registry.register( registry.Type.EVENT, - eventUtils.VIEWPORT_CHANGE, + EventType.VIEWPORT_CHANGE, ViewportChange, ); diff --git a/core/events/predicates.ts b/core/events/predicates.ts new file mode 100644 index 00000000000..79d8ca284e4 --- /dev/null +++ b/core/events/predicates.ts @@ -0,0 +1,172 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file Predicates for testing Abstract event subclasses based on + * their .type properties. These are useful because there are places + * where it is not possible to use instanceof tests + * for type narrowing due to load ordering issues that would be caused + * by the need to import (rather than just import type) the class + * constructors in question. + */ + +import type {Abstract} from './events_abstract.js'; +import type {BlockChange} from './events_block_change.js'; +import type {BlockCreate} from './events_block_create.js'; +import type {BlockDelete} from './events_block_delete.js'; +import type {BlockDrag} from './events_block_drag.js'; +import type {BlockFieldIntermediateChange} from './events_block_field_intermediate_change.js'; +import type {BlockMove} from './events_block_move.js'; +import type {BubbleOpen} from './events_bubble_open.js'; +import type {Click} from './events_click.js'; +import type {CommentChange} from './events_comment_change.js'; +import type {CommentCollapse} from './events_comment_collapse.js'; +import type {CommentCreate} from './events_comment_create.js'; +import type {CommentDelete} from './events_comment_delete.js'; +import type {CommentDrag} from './events_comment_drag.js'; +import type {CommentMove} from './events_comment_move.js'; +import type {CommentResize} from './events_comment_resize.js'; +import type {MarkerMove} from './events_marker_move.js'; +import type {Selected} from './events_selected.js'; +import type {ThemeChange} from './events_theme_change.js'; +import type {ToolboxItemSelect} from './events_toolbox_item_select.js'; +import type {TrashcanOpen} from './events_trashcan_open.js'; +import type {VarCreate} from './events_var_create.js'; +import type {VarDelete} from './events_var_delete.js'; +import type {VarRename} from './events_var_rename.js'; +import type {ViewportChange} from './events_viewport.js'; +import type {FinishedLoading} from './workspace_events.js'; + +import {EventType} from './type.js'; + +/** @returns true iff event.type is EventType.BLOCK_CREATE */ +export function isBlockCreate(event: Abstract): event is BlockCreate { + return event.type === EventType.BLOCK_CREATE; +} + +/** @returns true iff event.type is EventType.BLOCK_DELETE */ +export function isBlockDelete(event: Abstract): event is BlockDelete { + return event.type === EventType.BLOCK_DELETE; +} + +/** @returns true iff event.type is EventType.BLOCK_CHANGE */ +export function isBlockChange(event: Abstract): event is BlockChange { + return event.type === EventType.BLOCK_CHANGE; +} + +/** @returns true iff event.type is EventType.BLOCK_FIELD_INTERMEDIATE_CHANGE */ +export function isBlockFieldIntermediateChange( + event: Abstract, +): event is BlockFieldIntermediateChange { + return event.type === EventType.BLOCK_FIELD_INTERMEDIATE_CHANGE; +} + +/** @returns true iff event.type is EventType.BLOCK_MOVE */ +export function isBlockMove(event: Abstract): event is BlockMove { + return event.type === EventType.BLOCK_MOVE; +} + +/** @returns true iff event.type is EventType.VAR_CREATE */ +export function isVarCreate(event: Abstract): event is VarCreate { + return event.type === EventType.VAR_CREATE; +} + +/** @returns true iff event.type is EventType.VAR_DELETE */ +export function isVarDelete(event: Abstract): event is VarDelete { + return event.type === EventType.VAR_DELETE; +} + +/** @returns true iff event.type is EventType.VAR_RENAME */ +export function isVarRename(event: Abstract): event is VarRename { + return event.type === EventType.VAR_RENAME; +} + +/** @returns true iff event.type is EventType.BLOCK_DRAG */ +export function isBlockDrag(event: Abstract): event is BlockDrag { + return event.type === EventType.BLOCK_DRAG; +} + +/** @returns true iff event.type is EventType.SELECTED */ +export function isSelected(event: Abstract): event is Selected { + return event.type === EventType.SELECTED; +} + +/** @returns true iff event.type is EventType.CLICK */ +export function isClick(event: Abstract): event is Click { + return event.type === EventType.CLICK; +} + +/** @returns true iff event.type is EventType.MARKER_MOVE */ +export function isMarkerMove(event: Abstract): event is MarkerMove { + return event.type === EventType.MARKER_MOVE; +} + +/** @returns true iff event.type is EventType.BUBBLE_OPEN */ +export function isBubbleOpen(event: Abstract): event is BubbleOpen { + return event.type === EventType.BUBBLE_OPEN; +} + +/** @returns true iff event.type is EventType.TRASHCAN_OPEN */ +export function isTrashcanOpen(event: Abstract): event is TrashcanOpen { + return event.type === EventType.TRASHCAN_OPEN; +} + +/** @returns true iff event.type is EventType.TOOLBOX_ITEM_SELECT */ +export function isToolboxItemSelect( + event: Abstract, +): event is ToolboxItemSelect { + return event.type === EventType.TOOLBOX_ITEM_SELECT; +} + +/** @returns true iff event.type is EventType.THEME_CHANGE */ +export function isThemeChange(event: Abstract): event is ThemeChange { + return event.type === EventType.THEME_CHANGE; +} + +/** @returns true iff event.type is EventType.VIEWPORT_CHANGE */ +export function isViewportChange(event: Abstract): event is ViewportChange { + return event.type === EventType.VIEWPORT_CHANGE; +} + +/** @returns true iff event.type is EventType.COMMENT_CREATE */ +export function isCommentCreate(event: Abstract): event is CommentCreate { + return event.type === EventType.COMMENT_CREATE; +} + +/** @returns true iff event.type is EventType.COMMENT_DELETE */ +export function isCommentDelete(event: Abstract): event is CommentDelete { + return event.type === EventType.COMMENT_DELETE; +} + +/** @returns true iff event.type is EventType.COMMENT_CHANGE */ +export function isCommentChange(event: Abstract): event is CommentChange { + return event.type === EventType.COMMENT_CHANGE; +} + +/** @returns true iff event.type is EventType.COMMENT_MOVE */ +export function isCommentMove(event: Abstract): event is CommentMove { + return event.type === EventType.COMMENT_MOVE; +} + +/** @returns true iff event.type is EventType.COMMENT_RESIZE */ +export function isCommentResize(event: Abstract): event is CommentResize { + return event.type === EventType.COMMENT_RESIZE; +} + +/** @returns true iff event.type is EventType.COMMENT_DRAG */ +export function isCommentDrag(event: Abstract): event is CommentDrag { + return event.type === EventType.COMMENT_DRAG; +} + +/** @returns true iff event.type is EventType.COMMENT_COLLAPSE */ +export function isCommentCollapse(event: Abstract): event is CommentCollapse { + return event.type === EventType.COMMENT_COLLAPSE; +} + +/** @returns true iff event.type is EventType.FINISHED_LOADING */ +export function isFinishedLoading(event: Abstract): event is FinishedLoading { + return event.type === EventType.FINISHED_LOADING; +} diff --git a/core/events/type.ts b/core/events/type.ts new file mode 100644 index 00000000000..db9ad6c96a3 --- /dev/null +++ b/core/events/type.ts @@ -0,0 +1,85 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * Enum of values for the .type property for event classes (concrete subclasses + * of Abstract). + */ +export enum EventType { + /** Type of event that creates a block. */ + BLOCK_CREATE = 'create', + /** Type of event that deletes a block. */ + BLOCK_DELETE = 'delete', + /** Type of event that changes a block. */ + BLOCK_CHANGE = 'change', + /** + * Type of event representing an in-progress change to a field of a + * block, which is expected to be followed by a block change event. + */ + BLOCK_FIELD_INTERMEDIATE_CHANGE = 'block_field_intermediate_change', + /** Type of event that moves a block. */ + BLOCK_MOVE = 'move', + /** Type of event that creates a variable. */ + VAR_CREATE = 'var_create', + /** Type of event that deletes a variable. */ + VAR_DELETE = 'var_delete', + /** Type of event that renames a variable. */ + VAR_RENAME = 'var_rename', + /** + * Type of generic event that records a UI change. + * + * @deprecated Was only ever intended for internal use. + */ + UI = 'ui', + /** Type of event that drags a block. */ + BLOCK_DRAG = 'drag', + /** Type of event that records a change in selected element. */ + SELECTED = 'selected', + /** Type of event that records a click. */ + CLICK = 'click', + /** Type of event that records a marker move. */ + MARKER_MOVE = 'marker_move', + /** Type of event that records a bubble open. */ + BUBBLE_OPEN = 'bubble_open', + /** Type of event that records a trashcan open. */ + TRASHCAN_OPEN = 'trashcan_open', + /** Type of event that records a toolbox item select. */ + TOOLBOX_ITEM_SELECT = 'toolbox_item_select', + /** Type of event that records a theme change. */ + THEME_CHANGE = 'theme_change', + /** Type of event that records a viewport change. */ + VIEWPORT_CHANGE = 'viewport_change', + /** Type of event that creates a comment. */ + COMMENT_CREATE = 'comment_create', + /** Type of event that deletes a comment. */ + COMMENT_DELETE = 'comment_delete', + /** Type of event that changes a comment. */ + COMMENT_CHANGE = 'comment_change', + /** Type of event that moves a comment. */ + COMMENT_MOVE = 'comment_move', + /** Type of event that resizes a comment. */ + COMMENT_RESIZE = 'comment_resize', + /** Type of event that drags a comment. */ + COMMENT_DRAG = 'comment_drag', + /** Type of event that collapses a comment. */ + COMMENT_COLLAPSE = 'comment_collapse', + /** Type of event that records a workspace load. */ + FINISHED_LOADING = 'finished_loading', +} + +/** + * List of events that cause objects to be bumped back into the visible + * portion of the workspace. + * + * Not to be confused with bumping so that disconnected connections do not + * appear connected. + */ +export const BUMP_EVENTS: string[] = [ + EventType.BLOCK_CREATE, + EventType.BLOCK_MOVE, + EventType.COMMENT_CREATE, + EventType.COMMENT_MOVE, +]; diff --git a/core/events/utils.ts b/core/events/utils.ts index eacf0490673..4753e7783d9 100644 --- a/core/events/utils.ts +++ b/core/events/utils.ts @@ -9,17 +9,24 @@ import type {Block} from '../block.js'; import * as common from '../common.js'; import * as registry from '../registry.js'; +import * as deprecation from '../utils/deprecation.js'; import * as idGenerator from '../utils/idgenerator.js'; import type {Workspace} from '../workspace.js'; import type {WorkspaceSvg} from '../workspace_svg.js'; - import type {Abstract} from './events_abstract.js'; -import type {BlockChange} from './events_block_change.js'; import type {BlockCreate} from './events_block_create.js'; import type {BlockMove} from './events_block_move.js'; import type {CommentCreate} from './events_comment_create.js'; import type {CommentMove} from './events_comment_move.js'; -import type {ViewportChange} from './events_viewport.js'; +import type {CommentResize} from './events_comment_resize.js'; +import { + isBlockChange, + isBlockCreate, + isBlockMove, + isBubbleOpen, + isClick, + isViewportChange, +} from './predicates.js'; /** Group ID for new events. Grouped events are indivisible. */ let group = ''; @@ -48,146 +55,6 @@ export function getRecordUndo(): boolean { /** Allow change events to be created and fired. */ let disabled = 0; -/** - * Name of event that creates a block. Will be deprecated for BLOCK_CREATE. - */ -export const CREATE = 'create'; - -/** - * Name of event that creates a block. - */ -export const BLOCK_CREATE = CREATE; - -/** - * Name of event that deletes a block. Will be deprecated for BLOCK_DELETE. - */ -export const DELETE = 'delete'; - -/** - * Name of event that deletes a block. - */ -export const BLOCK_DELETE = DELETE; - -/** - * Name of event that changes a block. Will be deprecated for BLOCK_CHANGE. - */ -export const CHANGE = 'change'; - -/** - * Name of event that changes a block. - */ -export const BLOCK_CHANGE = CHANGE; - -/** - * Name of event representing an in-progress change to a field of a block, which - * is expected to be followed by a block change event. - */ -export const BLOCK_FIELD_INTERMEDIATE_CHANGE = - 'block_field_intermediate_change'; - -/** - * Name of event that moves a block. Will be deprecated for BLOCK_MOVE. - */ -export const MOVE = 'move'; - -/** - * Name of event that moves a block. - */ -export const BLOCK_MOVE = MOVE; - -/** - * Name of event that creates a variable. - */ -export const VAR_CREATE = 'var_create'; - -/** - * Name of event that deletes a variable. - */ -export const VAR_DELETE = 'var_delete'; - -/** - * Name of event that renames a variable. - */ -export const VAR_RENAME = 'var_rename'; - -/** - * Name of generic event that records a UI change. - */ -export const UI = 'ui'; - -/** - * Name of event that record a block drags a block. - */ -export const BLOCK_DRAG = 'drag'; - -/** - * Name of event that records a change in selected element. - */ -export const SELECTED = 'selected'; - -/** - * Name of event that records a click. - */ -export const CLICK = 'click'; - -/** - * Name of event that records a marker move. - */ -export const MARKER_MOVE = 'marker_move'; - -/** - * Name of event that records a bubble open. - */ -export const BUBBLE_OPEN = 'bubble_open'; - -/** - * Name of event that records a trashcan open. - */ -export const TRASHCAN_OPEN = 'trashcan_open'; - -/** - * Name of event that records a toolbox item select. - */ -export const TOOLBOX_ITEM_SELECT = 'toolbox_item_select'; - -/** - * Name of event that records a theme change. - */ -export const THEME_CHANGE = 'theme_change'; - -/** - * Name of event that records a viewport change. - */ -export const VIEWPORT_CHANGE = 'viewport_change'; - -/** - * Name of event that creates a comment. - */ -export const COMMENT_CREATE = 'comment_create'; - -/** - * Name of event that deletes a comment. - */ -export const COMMENT_DELETE = 'comment_delete'; - -/** - * Name of event that changes a comment. - */ -export const COMMENT_CHANGE = 'comment_change'; - -/** - * Name of event that moves a comment. - */ -export const COMMENT_MOVE = 'comment_move'; - -/** Type of event that moves a comment. */ -export const COMMENT_COLLAPSE = 'comment_collapse'; - -/** - * Name of event that records a workspace load. - */ -export const FINISHED_LOADING = 'finished_loading'; - /** * The language-neutral ID for when the reason why a block is disabled is * because the block is not descended from a root block. @@ -201,29 +68,31 @@ const ORPHANED_BLOCK_DISABLED_REASON = 'ORPHANED_BLOCK'; * Not to be confused with bumping so that disconnected connections do not * appear connected. */ -export type BumpEvent = BlockCreate | BlockMove | CommentCreate | CommentMove; - -/** - * List of events that cause objects to be bumped back into the visible - * portion of the workspace. - * - * Not to be confused with bumping so that disconnected connections do not - * appear connected. - */ -export const BUMP_EVENTS: string[] = [ - BLOCK_CREATE, - BLOCK_MOVE, - COMMENT_CREATE, - COMMENT_MOVE, -]; +export type BumpEvent = + | BlockCreate + | BlockMove + | CommentCreate + | CommentMove + | CommentResize; /** List of events queued for firing. */ const FIRE_QUEUE: Abstract[] = []; /** - * Create a custom event and fire it. + * Enqueue an event to be dispatched to change listeners. * - * @param event Custom data for event. + * Notes: + * + * - Events are enqueued until a timeout, generally after rendering is + * complete or at the end of the current microtask, if not running + * in a browser. + * - Queued events are subject to destructive modification by being + * combined with later-enqueued events, but only until they are + * fired. + * - Events are dispatched via the fireChangeListener method on the + * affected workspace. + * + * @param event Any Blockly event. */ export function fire(event: Abstract) { TEST_ONLY.fireInternal(event); @@ -244,166 +113,187 @@ function fireInternal(event: Abstract) { requestAnimationFrame(() => { setTimeout(fireNow, 0); }); - } catch (e) { + } catch { // Otherwise we just want to delay so events can be coallesced. // requestAnimationFrame will error triggering this. setTimeout(fireNow, 0); } } - FIRE_QUEUE.push(event); + enqueueEvent(event); } -/** Fire all queued events. */ +/** Dispatch all queued events. */ function fireNow() { const queue = filter(FIRE_QUEUE, true); FIRE_QUEUE.length = 0; - for (let i = 0, event; (event = queue[i]); i++) { - if (!event.workspaceId) { - continue; - } - const eventWorkspace = common.getWorkspaceById(event.workspaceId); - if (eventWorkspace) { - eventWorkspace.fireChangeListener(event); - } + for (const event of queue) { + if (!event.workspaceId) continue; + common.getWorkspaceById(event.workspaceId)?.fireChangeListener(event); } +} - // Post-filter the undo stack to squash and remove any events that result in - // a null event - - // 1. Determine which workspaces will need to have their undo stacks validated - const workspaceIds = new Set(queue.map((e) => e.workspaceId)); - for (const workspaceId of workspaceIds) { - // Only process valid workspaces - if (!workspaceId) { - continue; - } - const eventWorkspace = common.getWorkspaceById(workspaceId); - if (!eventWorkspace) { - continue; - } - - // Find the last contiguous group of events on the stack - const undoStack = eventWorkspace.getUndoStack(); +/** + * Enqueue an event on FIRE_QUEUE. + * + * Normally this is equivalent to FIRE_QUEUE.push(event), but if the + * enqueued event is a BlockChange event and the most recent event(s) + * on the queue are BlockMove events that (re)connect other blocks to + * the changed block (and belong to the same event group) then the + * enqueued event will be enqueued before those events rather than + * after. + * + * This is a workaround for a problem caused by the fact that + * MutatorIcon.prototype.recomposeSourceBlock can only fire a + * BlockChange event after the mutating block's compose method + * returns, meaning that if the compose method reconnects child blocks + * the corresponding BlockMove events are emitted _before_ the + * BlockChange event, causing issues with undo, mirroring, etc.; see + * https://github.com/google/blockly/issues/8225#issuecomment-2195751783 + * (and following) for details. + */ +function enqueueEvent(event: Abstract) { + if (isBlockChange(event) && event.element === 'mutation') { let i; - let group: string | undefined = undefined; - for (i = undoStack.length; i > 0; i--) { - const event = undoStack[i - 1]; - if (event.group === '') { - break; - } else if (group === undefined) { - group = event.group; - } else if (event.group !== group) { + for (i = FIRE_QUEUE.length; i > 0; i--) { + const otherEvent = FIRE_QUEUE[i - 1]; + if ( + otherEvent.group !== event.group || + otherEvent.workspaceId !== event.workspaceId || + !isBlockMove(otherEvent) || + otherEvent.newParentId !== event.blockId + ) { break; } } - if (!group || i == undoStack.length - 1) { - // Need a group of two or more events on the stack. Nothing to do here. - continue; - } - - // Extract the event group, filter, and add back to the undo stack - let events = undoStack.splice(i, undoStack.length - i); - events = filter(events, true); - undoStack.push(...events); + FIRE_QUEUE.splice(i, 0, event); + return; } + + FIRE_QUEUE.push(event); } /** - * Filter the queued events and merge duplicates. + * Filter the queued events by merging duplicates, removing null + * events and reording BlockChange events. + * + * History of this function: + * + * This function was originally added in commit cf257ea5 with the + * intention of dramatically reduing the total number of dispatched + * events. Initialy it affected only BlockMove events but others were + * added over time. + * + * Code was added to reorder BlockChange events added in commit + * 5578458, for uncertain reasons but most probably as part of an + * only-partially-successful attemp to fix problems with event + * ordering during block mutations. This code should probably have + * been added to the top of the function, before merging and + * null-removal, but was added at the bottom for now-forgotten + * reasons. See these bug investigations for a fuller discussion of + * the underlying issue and some of the failures that arose because of + * this incomplete/incorrect fix: + * + * https://github.com/google/blockly/issues/8225#issuecomment-2195751783 + * https://github.com/google/blockly/issues/2037#issuecomment-2209696351 + * + * Later, in PR #1205 the original O(n^2) implementation was replaced + * by a linear-time implementation, though additonal fixes were made + * subsequently. + * + * In August 2024 a number of significant simplifications were made: + * + * This function was previously called from Workspace.prototype.undo, + * but the mutation of events by this function was the cause of issue + * #7026 (note that events would combine differently in reverse order + * vs. forward order). The originally-chosen fix for this was the + * addition (in PR #7069) of code to fireNow to post-filter the + * .undoStack_ and .redoStack_ of any workspace that had just been + * involved in dispatching events; this apparently resolved the issue + * but added considerable additional complexity and made it difficult + * to reason about how events are processed for undo/redo, so both the + * call from undo and the post-processing code was removed, and + * forward=true was made the default while calling the function with + * forward=false was deprecated. + * + * At the same time, the buggy code to reorder BlockChange events was + * replaced by a less-buggy version of the same functionality in a new + * function, enqueueEvent, called from fireInternal, thus assuring + * that events will be in the correct order at the time filter is + * called. * - * @param queueIn Array of events. + * Additionally, the event merging code was modified so that only + * immediately adjacent events would be merged. This simplified the + * implementation while ensuring that the merging of events cannot + * cause them to be reordered. + * + * @param queue Array of events. * @param forward True if forward (redo), false if backward (undo). + * This parameter is deprecated: true is now the default and + * calling filter with it set to false will in future not be + * supported. * @returns Array of filtered events. */ -export function filter(queueIn: Abstract[], forward: boolean): Abstract[] { - let queue = queueIn.slice(); - // Shallow copy of queue. +export function filter(queue: Abstract[], forward = true): Abstract[] { if (!forward) { - // Undo is merged in reverse order. - queue.reverse(); + deprecation.warn('filter(queue, /*forward=*/false)', 'v11.2', 'v12'); + // Undo was merged in reverse order. + queue = queue.slice().reverse(); // Copy before reversing in place. } - const mergedQueue = []; - const hash = Object.create(null); + const mergedQueue: Abstract[] = []; // Merge duplicates. - for (let i = 0, event; (event = queue[i]); i++) { - if (!event.isNull()) { - // Treat all UI events as the same type in hash table. - const eventType = event.isUiEvent ? UI : event.type; - // TODO(#5927): Check whether `blockId` exists before accessing it. - const blockId = (event as AnyDuringMigration).blockId; - const key = [eventType, blockId, event.workspaceId].join(' '); - - const lastEntry = hash[key]; - const lastEvent = lastEntry ? lastEntry.event : null; - if (!lastEntry) { - // Each item in the hash table has the event and the index of that event - // in the input array. This lets us make sure we only merge adjacent - // move events. - hash[key] = {event, index: i}; - mergedQueue.push(event); - } else if (event.type === MOVE && lastEntry.index === i - 1) { - const moveEvent = event as BlockMove; - // Merge move events. - lastEvent.newParentId = moveEvent.newParentId; - lastEvent.newInputName = moveEvent.newInputName; - lastEvent.newCoordinate = moveEvent.newCoordinate; - if (moveEvent.reason) { - if (lastEvent.reason) { - // Concatenate reasons without duplicates. - const reasonSet = new Set( - moveEvent.reason.concat(lastEvent.reason), - ); - lastEvent.reason = Array.from(reasonSet); - } else { - lastEvent.reason = moveEvent.reason; - } - } - lastEntry.index = i; - } else if ( - event.type === CHANGE && - (event as BlockChange).element === lastEvent.element && - (event as BlockChange).name === lastEvent.name - ) { - const changeEvent = event as BlockChange; - // Merge change events. - lastEvent.newValue = changeEvent.newValue; - } else if (event.type === VIEWPORT_CHANGE) { - const viewportEvent = event as ViewportChange; - // Merge viewport change events. - lastEvent.viewTop = viewportEvent.viewTop; - lastEvent.viewLeft = viewportEvent.viewLeft; - lastEvent.scale = viewportEvent.scale; - lastEvent.oldScale = viewportEvent.oldScale; - } else if (event.type === CLICK && lastEvent.type === BUBBLE_OPEN) { - // Drop click events caused by opening/closing bubbles. - } else { - // Collision: newer events should merge into this event to maintain - // order. - hash[key] = {event, index: i}; - mergedQueue.push(event); + for (const event of queue) { + const lastEvent = mergedQueue[mergedQueue.length - 1]; + if (event.isNull()) continue; + if ( + !lastEvent || + lastEvent.workspaceId !== event.workspaceId || + lastEvent.group !== event.group + ) { + mergedQueue.push(event); + continue; + } + if ( + isBlockMove(event) && + isBlockMove(lastEvent) && + event.blockId === lastEvent.blockId + ) { + // Merge move events. + lastEvent.newParentId = event.newParentId; + lastEvent.newInputName = event.newInputName; + lastEvent.newCoordinate = event.newCoordinate; + // Concatenate reasons without duplicates. + if (lastEvent.reason || event.reason) { + lastEvent.reason = Array.from( + new Set((lastEvent.reason ?? []).concat(event.reason ?? [])), + ); } + } else if ( + isBlockChange(event) && + isBlockChange(lastEvent) && + event.blockId === lastEvent.blockId && + event.element === lastEvent.element && + event.name === lastEvent.name + ) { + // Merge change events. + lastEvent.newValue = event.newValue; + } else if (isViewportChange(event) && isViewportChange(lastEvent)) { + // Merge viewport change events. + lastEvent.viewTop = event.viewTop; + lastEvent.viewLeft = event.viewLeft; + lastEvent.scale = event.scale; + lastEvent.oldScale = event.oldScale; + } else if (isClick(event) && isBubbleOpen(lastEvent)) { + // Drop click events caused by opening/closing bubbles. + } else { + mergedQueue.push(event); } } // Filter out any events that have become null due to merging. - queue = mergedQueue.filter(function (e) { - return !e.isNull(); - }); + queue = mergedQueue.filter((e) => !e.isNull()); if (!forward) { // Restore undo order. queue.reverse(); } - // Move mutation events to the top of the queue. - // Intentionally skip first event. - for (let i = 1, event; (event = queue[i]); i++) { - // AnyDuringMigration because: Property 'element' does not exist on type - // 'Abstract'. - if ( - event.type === CHANGE && - (event as AnyDuringMigration).element === 'mutation' - ) { - queue.unshift(queue.splice(i, 1)[0]); - } - } return queue; } @@ -528,7 +418,7 @@ export function get( * @param event Custom data for event. */ export function disableOrphans(event: Abstract) { - if (event.type === MOVE || event.type === CREATE) { + if (isBlockMove(event) || isBlockCreate(event)) { const blockEvent = event as BlockMove | BlockCreate; if (!blockEvent.workspaceId) { return; @@ -572,6 +462,7 @@ export function disableOrphans(event: Abstract) { export const TEST_ONLY = { FIRE_QUEUE, + enqueueEvent, fireNow, fireInternal, setGroupInternal, diff --git a/core/events/workspace_events.ts b/core/events/workspace_events.ts index 225e342b4e8..1a2ff54735b 100644 --- a/core/events/workspace_events.ts +++ b/core/events/workspace_events.ts @@ -14,7 +14,7 @@ import * as registry from '../registry.js'; import type {Workspace} from '../workspace.js'; import {Abstract as AbstractEvent} from './events_abstract.js'; -import * as eventUtils from './utils.js'; +import {EventType} from './type.js'; /** * Notifies listeners when the workspace has finished deserializing from @@ -23,7 +23,7 @@ import * as eventUtils from './utils.js'; export class FinishedLoading extends AbstractEvent { override isBlank = true; override recordUndo = false; - override type = eventUtils.FINISHED_LOADING; + override type = EventType.FINISHED_LOADING; /** * @param opt_workspace The workspace that has finished loading. Undefined @@ -41,6 +41,6 @@ export class FinishedLoading extends AbstractEvent { registry.register( registry.Type.EVENT, - eventUtils.FINISHED_LOADING, + EventType.FINISHED_LOADING, FinishedLoading, ); diff --git a/core/extensions.ts b/core/extensions.ts index aa9a6a1860d..0957b7f86ca 100644 --- a/core/extensions.ts +++ b/core/extensions.ts @@ -27,7 +27,10 @@ export const TEST_ONLY = {allExtensions}; * @throws {Error} if the extension name is empty, the extension is already * registered, or extensionFn is not a function. */ -export function register(name: string, initFn: Function) { +export function register( + name: string, + initFn: (this: T) => void, +) { if (typeof name !== 'string' || name.trim() === '') { throw Error('Error: Invalid extension name "' + name + '"'); } diff --git a/core/field.ts b/core/field.ts index 51e006823d7..4c4b90cf55a 100644 --- a/core/field.ts +++ b/core/field.ts @@ -20,12 +20,14 @@ import type {Block} from './block.js'; import type {BlockSvg} from './block_svg.js'; import * as browserEvents from './browser_events.js'; import * as dropDownDiv from './dropdowndiv.js'; +import {EventType} from './events/type.js'; import * as eventUtils from './events/utils.js'; import type {Input} from './inputs/input.js'; import type {IASTNodeLocationSvg} from './interfaces/i_ast_node_location_svg.js'; import type {IASTNodeLocationWithBlock} from './interfaces/i_ast_node_location_with_block.js'; import type {IKeyboardAccessible} from './interfaces/i_keyboard_accessible.js'; import type {IRegistrable} from './interfaces/i_registrable.js'; +import {ISerializable} from './interfaces/i_serializable.js'; import {MarkerManager} from './marker_manager.js'; import type {ConstantProvider} from './renderers/common/constants.js'; import type {KeyboardShortcut} from './shortcut_registry.js'; @@ -41,7 +43,6 @@ import * as userAgent from './utils/useragent.js'; import * as utilsXml from './utils/xml.js'; import * as WidgetDiv from './widgetdiv.js'; import type {WorkspaceSvg} from './workspace_svg.js'; -import {ISerializable} from './interfaces/i_serializable.js'; /** * A function that is called to validate changes to the field's value before @@ -106,20 +107,20 @@ export abstract class Field * Used to cache the field's tooltip value if setTooltip is called when the * field is not yet initialized. Is *not* guaranteed to be accurate. */ - private tooltip_: Tooltip.TipInfo | null = null; + private tooltip: Tooltip.TipInfo | null = null; protected size_: Size; /** * Holds the cursors svg element when the cursor is attached to the field. * This is null if there is no cursor on the field. */ - private cursorSvg_: SVGElement | null = null; + private cursorSvg: SVGElement | null = null; /** * Holds the markers svg element when the marker is attached to the field. * This is null if there is no marker on the field. */ - private markerSvg_: SVGElement | null = null; + private markerSvg: SVGElement | null = null; /** The rendered field's SVG group element. */ protected fieldGroup_: SVGGElement | null = null; @@ -134,7 +135,7 @@ export abstract class Field protected textContent_: Text | null = null; /** Mouse down event listener data. */ - private mouseDownWrapper_: browserEvents.Data | null = null; + private mouseDownWrapper: browserEvents.Data | null = null; /** Constants associated with the source block's renderer. */ protected constants_: ConstantProvider | null = null; @@ -311,7 +312,7 @@ export abstract class Field sourceBlockSvg.getSvgRoot().appendChild(this.fieldGroup_); this.initView(); this.updateEditable(); - this.setTooltip(this.tooltip_); + this.setTooltip(this.tooltip); this.bindEvents_(); this.initModel(); this.applyColour(); @@ -392,7 +393,7 @@ export abstract class Field const clickTarget = this.getClickTarget_(); if (!clickTarget) throw new Error('A click target has not been set.'); Tooltip.bindMouseEvents(clickTarget); - this.mouseDownWrapper_ = browserEvents.conditionalBind( + this.mouseDownWrapper = browserEvents.conditionalBind( clickTarget, 'pointerdown', this, @@ -1080,62 +1081,73 @@ export abstract class Field setValue(newValue: AnyDuringMigration, fireChangeEvent = true) { const doLogging = false; if (newValue === null) { - doLogging && console.log('null, return'); + if (doLogging) console.log('null, return'); // Not a valid value to check. return; } - const classValidation = this.doClassValidation_(newValue); - const classValue = this.processValidation_( - newValue, - classValidation, - fireChangeEvent, - ); - if (classValue instanceof Error) { - doLogging && console.log('invalid class validation, return'); - return; + // Field validators are allowed to make changes to the workspace, which + // should get grouped with the field value change event. + const existingGroup = eventUtils.getGroup(); + if (!existingGroup) { + eventUtils.setGroup(true); } - const localValidation = this.getValidator()?.call(this, classValue); - const localValue = this.processValidation_( - classValue, - localValidation, - fireChangeEvent, - ); - if (localValue instanceof Error) { - doLogging && console.log('invalid local validation, return'); - return; - } + try { + const classValidation = this.doClassValidation_(newValue); + const classValue = this.processValidation( + newValue, + classValidation, + fireChangeEvent, + ); + if (classValue instanceof Error) { + if (doLogging) console.log('invalid class validation, return'); + return; + } - const source = this.sourceBlock_; - if (source && source.disposed) { - doLogging && console.log('source disposed, return'); - return; - } + const localValidation = this.getValidator()?.call(this, classValue); + const localValue = this.processValidation( + classValue, + localValidation, + fireChangeEvent, + ); + if (localValue instanceof Error) { + if (doLogging) console.log('invalid local validation, return'); + return; + } - const oldValue = this.getValue(); - if (oldValue === localValue) { - doLogging && console.log('same, doValueUpdate_, return'); - this.doValueUpdate_(localValue); - return; - } + const source = this.sourceBlock_; + if (source && source.disposed) { + if (doLogging) console.log('source disposed, return'); + return; + } - this.doValueUpdate_(localValue); - if (fireChangeEvent && source && eventUtils.isEnabled()) { - eventUtils.fire( - new (eventUtils.get(eventUtils.BLOCK_CHANGE))( - source, - 'field', - this.name || null, - oldValue, - localValue, - ), - ); - } - if (this.isDirty_) { - this.forceRerender(); + const oldValue = this.getValue(); + if (oldValue === localValue) { + if (doLogging) console.log('same, doValueUpdate_, return'); + this.doValueUpdate_(localValue); + return; + } + + this.doValueUpdate_(localValue); + if (fireChangeEvent && source && eventUtils.isEnabled()) { + eventUtils.fire( + new (eventUtils.get(EventType.BLOCK_CHANGE))( + source, + 'field', + this.name || null, + oldValue, + localValue, + ), + ); + } + if (this.isDirty_) { + this.forceRerender(); + } + if (doLogging) console.log(this.value_); + } finally { + eventUtils.setGroup(existingGroup); } - doLogging && console.log(this.value_); } /** @@ -1146,7 +1158,7 @@ export abstract class Field * @param fireChangeEvent Whether to fire a change event if the value changes. * @returns New value, or an Error object. */ - private processValidation_( + private processValidation( newValue: AnyDuringMigration, validatedValue: T | null | undefined, fireChangeEvent: boolean, @@ -1260,7 +1272,7 @@ export abstract class Field (clickTarget as AnyDuringMigration).tooltip = newTip; } else { // Field has not been initialized yet. - this.tooltip_ = newTip; + this.tooltip = newTip; } } @@ -1274,8 +1286,8 @@ export abstract class Field if (clickTarget) { return Tooltip.getTooltipOfObject(clickTarget); } - // Field has not been initialized yet. Return stashed this.tooltip_ value. - return Tooltip.getTooltipOfObject({tooltip: this.tooltip_}); + // Field has not been initialized yet. Return stashed this.tooltip value. + return Tooltip.getTooltipOfObject({tooltip: this.tooltip}); } /** @@ -1384,7 +1396,7 @@ export abstract class Field */ setCursorSvg(cursorSvg: SVGElement) { if (!cursorSvg) { - this.cursorSvg_ = null; + this.cursorSvg = null; return; } @@ -1392,7 +1404,7 @@ export abstract class Field throw new Error(`The field group is ${this.fieldGroup_}.`); } this.fieldGroup_.appendChild(cursorSvg); - this.cursorSvg_ = cursorSvg; + this.cursorSvg = cursorSvg; } /** @@ -1403,7 +1415,7 @@ export abstract class Field */ setMarkerSvg(markerSvg: SVGElement) { if (!markerSvg) { - this.markerSvg_ = null; + this.markerSvg = null; return; } @@ -1411,7 +1423,7 @@ export abstract class Field throw new Error(`The field group is ${this.fieldGroup_}.`); } this.fieldGroup_.appendChild(markerSvg); - this.markerSvg_ = markerSvg; + this.markerSvg = markerSvg; } /** @@ -1425,10 +1437,10 @@ export abstract class Field throw new UnattachedFieldError(); } const workspace = block.workspace as WorkspaceSvg; - if (workspace.keyboardAccessibilityMode && this.cursorSvg_) { + if (workspace.keyboardAccessibilityMode && this.cursorSvg) { workspace.getCursor()!.draw(); } - if (workspace.keyboardAccessibilityMode && this.markerSvg_) { + if (workspace.keyboardAccessibilityMode && this.markerSvg) { // TODO(#4592): Update all markers on the field. workspace.getMarker(MarkerManager.LOCAL_MARKER)!.draw(); } diff --git a/core/field_checkbox.ts b/core/field_checkbox.ts index 83f460bb9d2..5ae3dfda1ae 100644 --- a/core/field_checkbox.ts +++ b/core/field_checkbox.ts @@ -14,9 +14,9 @@ // Unused import preserved for side-effects. Remove if unneeded. import './events/events_block_change.js'; -import * as dom from './utils/dom.js'; import {Field, FieldConfig, FieldValidator} from './field.js'; import * as fieldRegistry from './field_registry.js'; +import * as dom from './utils/dom.js'; type BoolString = 'TRUE' | 'FALSE'; type CheckboxBool = BoolString | boolean; @@ -170,7 +170,7 @@ export class FieldCheckbox extends Field { * that this is a either 'TRUE' or 'FALSE'. */ protected override doValueUpdate_(newValue: BoolString) { - this.value_ = this.convertValueToBool_(newValue); + this.value_ = this.convertValueToBool(newValue); // Update visual. if (this.textElement_) { this.textElement_.style.display = this.value_ ? 'block' : 'none'; @@ -201,7 +201,7 @@ export class FieldCheckbox extends Field { * @returns Text representing the value of this field ('true' or 'false'). */ override getText(): string { - return String(this.convertValueToBool_(this.value_)); + return String(this.convertValueToBool(this.value_)); } /** @@ -213,7 +213,7 @@ export class FieldCheckbox extends Field { * @param value The value to convert. * @returns The converted value. */ - private convertValueToBool_(value: CheckboxBool | null): boolean { + private convertValueToBool(value: CheckboxBool | null): boolean { if (typeof value === 'string') return value === 'TRUE'; return !!value; } diff --git a/core/field_dropdown.ts b/core/field_dropdown.ts index 58a4b073218..b1e3b5af26c 100644 --- a/core/field_dropdown.ts +++ b/core/field_dropdown.ts @@ -24,12 +24,12 @@ import { import * as fieldRegistry from './field_registry.js'; import {Menu} from './menu.js'; import {MenuItem} from './menuitem.js'; -import * as style from './utils/style.js'; import * as aria from './utils/aria.js'; import {Coordinate} from './utils/coordinate.js'; import * as dom from './utils/dom.js'; import * as parsing from './utils/parsing.js'; import * as utilsString from './utils/string.js'; +import * as style from './utils/style.js'; import {Svg} from './utils/svg.js'; /** @@ -95,6 +95,15 @@ export class FieldDropdown extends Field { private selectedOption!: MenuOption; override clickTarget_: SVGElement | null = null; + /** + * The y offset from the top of the field to the top of the image, if an image + * is selected. + */ + protected static IMAGE_Y_OFFSET = 5; + + /** The total vertical padding above and below an image. */ + protected static IMAGE_Y_PADDING = FieldDropdown.IMAGE_Y_OFFSET * 2; + /** * @param menuGenerator A non-empty array of options for a dropdown list, or a * function which generates these options. Also accepts Field.SKIP_SETUP @@ -128,8 +137,8 @@ export class FieldDropdown extends Field { if (menuGenerator === Field.SKIP_SETUP) return; if (Array.isArray(menuGenerator)) { - validateOptions(menuGenerator); - const trimmed = trimOptions(menuGenerator); + this.validateOptions(menuGenerator); + const trimmed = this.trimOptions(menuGenerator); this.menuGenerator_ = trimmed.options; this.prefixField = trimmed.prefix || null; this.suffixField = trimmed.suffix || null; @@ -401,7 +410,7 @@ export class FieldDropdown extends Field { if (useCache && this.generatedOptions) return this.generatedOptions; this.generatedOptions = this.menuGenerator_(); - validateOptions(this.generatedOptions); + this.validateOptions(this.generatedOptions); return this.generatedOptions; } @@ -520,7 +529,7 @@ export class FieldDropdown extends Field { const hasBorder = !!this.borderRect_; const height = Math.max( hasBorder ? this.getConstants()!.FIELD_DROPDOWN_BORDER_RECT_HEIGHT : 0, - imageHeight + IMAGE_Y_PADDING, + imageHeight + FieldDropdown.IMAGE_Y_PADDING, ); const xPadding = hasBorder ? this.getConstants()!.FIELD_BORDER_RECT_X_PADDING @@ -661,6 +670,127 @@ export class FieldDropdown extends Field { // override the static fromJson method. return new this(options.options, undefined, options); } + + /** + * Factor out common words in statically defined options. + * Create prefix and/or suffix labels. + */ + protected trimOptions(options: MenuOption[]): { + options: MenuOption[]; + prefix?: string; + suffix?: string; + } { + let hasImages = false; + const trimmedOptions = options.map(([label, value]): MenuOption => { + if (typeof label === 'string') { + return [parsing.replaceMessageReferences(label), value]; + } + + hasImages = true; + // Copy the image properties so they're not influenced by the original. + // NOTE: No need to deep copy since image properties are only 1 level deep. + const imageLabel = + label.alt !== null + ? {...label, alt: parsing.replaceMessageReferences(label.alt)} + : {...label}; + return [imageLabel, value]; + }); + + if (hasImages || options.length < 2) return {options: trimmedOptions}; + + const stringOptions = trimmedOptions as [string, string][]; + const stringLabels = stringOptions.map(([label]) => label); + + const shortest = utilsString.shortestStringLength(stringLabels); + const prefixLength = utilsString.commonWordPrefix(stringLabels, shortest); + const suffixLength = utilsString.commonWordSuffix(stringLabels, shortest); + + if ( + (!prefixLength && !suffixLength) || + shortest <= prefixLength + suffixLength + ) { + // One or more strings will entirely vanish if we proceed. Abort. + return {options: stringOptions}; + } + + const prefix = prefixLength + ? stringLabels[0].substring(0, prefixLength - 1) + : undefined; + const suffix = suffixLength + ? stringLabels[0].substr(1 - suffixLength) + : undefined; + return { + options: this.applyTrim(stringOptions, prefixLength, suffixLength), + prefix, + suffix, + }; + } + + /** + * Use the calculated prefix and suffix lengths to trim all of the options in + * the given array. + * + * @param options Array of option tuples: + * (human-readable text or image, language-neutral name). + * @param prefixLength The length of the common prefix. + * @param suffixLength The length of the common suffix + * @returns A new array with all of the option text trimmed. + */ + private applyTrim( + options: [string, string][], + prefixLength: number, + suffixLength: number, + ): MenuOption[] { + return options.map(([text, value]) => [ + text.substring(prefixLength, text.length - suffixLength), + value, + ]); + } + + /** + * Validates the data structure to be processed as an options list. + * + * @param options The proposed dropdown options. + * @throws {TypeError} If proposed options are incorrectly structured. + */ + protected validateOptions(options: MenuOption[]) { + if (!Array.isArray(options)) { + throw TypeError('FieldDropdown options must be an array.'); + } + if (!options.length) { + throw TypeError('FieldDropdown options must not be an empty array.'); + } + let foundError = false; + for (let i = 0; i < options.length; i++) { + const tuple = options[i]; + if (!Array.isArray(tuple)) { + foundError = true; + console.error( + `Invalid option[${i}]: Each FieldDropdown option must be an array. + Found: ${tuple}`, + ); + } else if (typeof tuple[1] !== 'string') { + foundError = true; + console.error( + `Invalid option[${i}]: Each FieldDropdown option id must be a string. + Found ${tuple[1]} in: ${tuple}`, + ); + } else if ( + tuple[0] && + typeof tuple[0] !== 'string' && + typeof tuple[0].src !== 'string' + ) { + foundError = true; + console.error( + `Invalid option[${i}]: Each FieldDropdown option must have a string + label or image description. Found ${tuple[0]} in: ${tuple}`, + ); + } + } + if (foundError) { + throw TypeError('Found invalid FieldDropdown options.'); + } + } } /** @@ -721,147 +851,4 @@ export interface FieldDropdownFromJsonConfig extends FieldDropdownConfig { */ export type FieldDropdownValidator = FieldValidator; -/** - * The y offset from the top of the field to the top of the image, if an image - * is selected. - */ -const IMAGE_Y_OFFSET = 5; - -/** The total vertical padding above and below an image. */ -const IMAGE_Y_PADDING: number = IMAGE_Y_OFFSET * 2; - -/** - * Factor out common words in statically defined options. - * Create prefix and/or suffix labels. - */ -function trimOptions(options: MenuOption[]): { - options: MenuOption[]; - prefix?: string; - suffix?: string; -} { - let hasImages = false; - const trimmedOptions = options.map(([label, value]): MenuOption => { - if (typeof label === 'string') { - return [parsing.replaceMessageReferences(label), value]; - } - - hasImages = true; - // Copy the image properties so they're not influenced by the original. - // NOTE: No need to deep copy since image properties are only 1 level deep. - const imageLabel = - label.alt !== null - ? {...label, alt: parsing.replaceMessageReferences(label.alt)} - : {...label}; - return [imageLabel, value]; - }); - - if (hasImages || options.length < 2) return {options: trimmedOptions}; - - const stringOptions = trimmedOptions as [string, string][]; - const stringLabels = stringOptions.map(([label]) => label); - - const shortest = utilsString.shortestStringLength(stringLabels); - const prefixLength = utilsString.commonWordPrefix(stringLabels, shortest); - const suffixLength = utilsString.commonWordSuffix(stringLabels, shortest); - - if ( - (!prefixLength && !suffixLength) || - shortest <= prefixLength + suffixLength - ) { - // One or more strings will entirely vanish if we proceed. Abort. - return {options: stringOptions}; - } - - const prefix = prefixLength - ? stringLabels[0].substring(0, prefixLength - 1) - : undefined; - const suffix = suffixLength - ? stringLabels[0].substr(1 - suffixLength) - : undefined; - return { - options: applyTrim(stringOptions, prefixLength, suffixLength), - prefix, - suffix, - }; -} - -/** - * Use the calculated prefix and suffix lengths to trim all of the options in - * the given array. - * - * @param options Array of option tuples: - * (human-readable text or image, language-neutral name). - * @param prefixLength The length of the common prefix. - * @param suffixLength The length of the common suffix - * @returns A new array with all of the option text trimmed. - */ -function applyTrim( - options: [string, string][], - prefixLength: number, - suffixLength: number, -): MenuOption[] { - return options.map(([text, value]) => [ - text.substring(prefixLength, text.length - suffixLength), - value, - ]); -} - -/** - * Validates the data structure to be processed as an options list. - * - * @param options The proposed dropdown options. - * @throws {TypeError} If proposed options are incorrectly structured. - */ -function validateOptions(options: MenuOption[]) { - if (!Array.isArray(options)) { - throw TypeError('FieldDropdown options must be an array.'); - } - if (!options.length) { - throw TypeError('FieldDropdown options must not be an empty array.'); - } - let foundError = false; - for (let i = 0; i < options.length; i++) { - const tuple = options[i]; - if (!Array.isArray(tuple)) { - foundError = true; - console.error( - 'Invalid option[' + - i + - ']: Each FieldDropdown option must be an ' + - 'array. Found: ', - tuple, - ); - } else if (typeof tuple[1] !== 'string') { - foundError = true; - console.error( - 'Invalid option[' + - i + - ']: Each FieldDropdown option id must be ' + - 'a string. Found ' + - tuple[1] + - ' in: ', - tuple, - ); - } else if ( - tuple[0] && - typeof tuple[0] !== 'string' && - typeof tuple[0].src !== 'string' - ) { - foundError = true; - console.error( - 'Invalid option[' + - i + - ']: Each FieldDropdown option must have a ' + - 'string label or image description. Found' + - tuple[0] + - ' in: ', - tuple, - ); - } - } - if (foundError) { - throw TypeError('Found invalid FieldDropdown options.'); - } -} - fieldRegistry.register('field_dropdown', FieldDropdown); diff --git a/core/field_input.ts b/core/field_input.ts index 85431cc5b33..eecb4ec94e8 100644 --- a/core/field_input.ts +++ b/core/field_input.ts @@ -15,11 +15,11 @@ import './events/events_block_change.js'; import {BlockSvg} from './block_svg.js'; -import * as bumpObjects from './bump_objects.js'; import * as browserEvents from './browser_events.js'; +import * as bumpObjects from './bump_objects.js'; import * as dialog from './dialog.js'; -import * as dom from './utils/dom.js'; import * as dropDownDiv from './dropdowndiv.js'; +import {EventType} from './events/type.js'; import * as eventUtils from './events/utils.js'; import { Field, @@ -28,12 +28,13 @@ import { UnattachedFieldError, } from './field.js'; import {Msg} from './msg.js'; +import * as renderManagement from './render_management.js'; import * as aria from './utils/aria.js'; -import {Coordinate} from './utils/coordinate.js'; +import * as dom from './utils/dom.js'; +import {Size} from './utils/size.js'; import * as userAgent from './utils/useragent.js'; import * as WidgetDiv from './widgetdiv.js'; import type {WorkspaceSvg} from './workspace_svg.js'; -import {Size} from './utils/size.js'; /** * Supported types for FieldInput subclasses. @@ -79,10 +80,10 @@ export abstract class FieldInput extends Field< protected valueWhenEditorWasOpened_: string | T | null = null; /** Key down event data. */ - private onKeyDownWrapper_: browserEvents.Data | null = null; + private onKeyDownWrapper: browserEvents.Data | null = null; /** Key input event data. */ - private onKeyInputWrapper_: browserEvents.Data | null = null; + private onKeyInputWrapper: browserEvents.Data | null = null; /** * Whether the field should consider the whole parent block to be its click @@ -187,7 +188,7 @@ export abstract class FieldInput extends Field< fireChangeEvent ) { eventUtils.fire( - new (eventUtils.get(eventUtils.BLOCK_CHANGE))( + new (eventUtils.get(EventType.BLOCK_CHANGE))( this.sourceBlock_, 'field', this.name || null, @@ -337,9 +338,9 @@ export abstract class FieldInput extends Field< this.workspace_.options.modalInputs && (userAgent.MOBILE || userAgent.ANDROID || userAgent.IPAD) ) { - this.showPromptEditor_(); + this.showPromptEditor(); } else { - this.showInlineEditor_(quietInput); + this.showInlineEditor(quietInput); } } @@ -348,7 +349,7 @@ export abstract class FieldInput extends Field< * Mobile browsers may have issues with in-line textareas (focus and * keyboards). */ - private showPromptEditor_() { + private showPromptEditor() { dialog.prompt( Msg['CHANGE_VALUE_TITLE'], this.getText(), @@ -367,7 +368,7 @@ export abstract class FieldInput extends Field< * * @param quietInput True if editor should be created without focus. */ - private showInlineEditor_(quietInput: boolean) { + private showInlineEditor(quietInput: boolean) { const block = this.getSourceBlock(); if (!block) { throw new UnattachedFieldError(); @@ -475,7 +476,7 @@ export abstract class FieldInput extends Field< // multiple times while the editor was open, but this will fire an event // containing the value when the editor was opened as well as the new one. eventUtils.fire( - new (eventUtils.get(eventUtils.BLOCK_CHANGE))( + new (eventUtils.get(EventType.BLOCK_CHANGE))( this.sourceBlock_, 'field', this.name || null, @@ -517,30 +518,30 @@ export abstract class FieldInput extends Field< */ protected bindInputEvents_(htmlInput: HTMLElement) { // Trap Enter without IME and Esc to hide. - this.onKeyDownWrapper_ = browserEvents.conditionalBind( + this.onKeyDownWrapper = browserEvents.conditionalBind( htmlInput, 'keydown', this, this.onHtmlInputKeyDown_, ); // Resize after every input change. - this.onKeyInputWrapper_ = browserEvents.conditionalBind( + this.onKeyInputWrapper = browserEvents.conditionalBind( htmlInput, 'input', this, - this.onHtmlInputChange_, + this.onHtmlInputChange, ); } /** Unbind handlers for user input and workspace size changes. */ protected unbindInputEvents_() { - if (this.onKeyDownWrapper_) { - browserEvents.unbind(this.onKeyDownWrapper_); - this.onKeyDownWrapper_ = null; + if (this.onKeyDownWrapper) { + browserEvents.unbind(this.onKeyDownWrapper); + this.onKeyDownWrapper = null; } - if (this.onKeyInputWrapper_) { - browserEvents.unbind(this.onKeyInputWrapper_); - this.onKeyInputWrapper_ = null; + if (this.onKeyInputWrapper) { + browserEvents.unbind(this.onKeyInputWrapper); + this.onKeyInputWrapper = null; } } @@ -573,7 +574,7 @@ export abstract class FieldInput extends Field< * * @param _e Keyboard event. */ - private onHtmlInputChange_(_e: Event) { + private onHtmlInputChange(_e: Event) { // Intermediate value changes from user input are not confirmed until the // user closes the editor, and may be numerous. Inhibit reporting these as // normal block change events, and instead report them as special @@ -592,7 +593,7 @@ export abstract class FieldInput extends Field< // Fire a special event indicating that the value changed but the change // isn't complete yet and normal field change listeners can wait. eventUtils.fire( - new (eventUtils.get(eventUtils.BLOCK_FIELD_INTERMEDIATE_CHANGE))( + new (eventUtils.get(EventType.BLOCK_FIELD_INTERMEDIATE_CHANGE))( this.sourceBlock_, this.name || null, oldValue, @@ -629,22 +630,22 @@ export abstract class FieldInput extends Field< /** Resize the editor to fit the text. */ protected resizeEditor_() { - const block = this.getSourceBlock(); - if (!block) { - throw new UnattachedFieldError(); - } - const div = WidgetDiv.getDiv(); - const bBox = this.getScaledBBox(); - div!.style.width = bBox.right - bBox.left + 'px'; - div!.style.height = bBox.bottom - bBox.top + 'px'; + renderManagement.finishQueuedRenders().then(() => { + const block = this.getSourceBlock(); + if (!block) throw new UnattachedFieldError(); + const div = WidgetDiv.getDiv(); + const bBox = this.getScaledBBox(); + div!.style.width = bBox.right - bBox.left + 'px'; + div!.style.height = bBox.bottom - bBox.top + 'px'; - // In RTL mode block fields and LTR input fields the left edge moves, - // whereas the right edge is fixed. Reposition the editor. - const x = block.RTL ? bBox.right - div!.offsetWidth : bBox.left; - const xy = new Coordinate(x, bBox.top); + // In RTL mode block fields and LTR input fields the left edge moves, + // whereas the right edge is fixed. Reposition the editor. + const x = block.RTL ? bBox.right - div!.offsetWidth : bBox.left; + const y = bBox.top; - div!.style.left = xy.x + 'px'; - div!.style.top = xy.y + 'px'; + div!.style.left = `${x}px`; + div!.style.top = `${y}px`; + }); } /** @@ -656,7 +657,7 @@ export abstract class FieldInput extends Field< * div. */ override repositionForWindowResize(): boolean { - const block = this.getSourceBlock(); + const block = this.getSourceBlock()?.getRootBlock(); // This shouldn't be possible. We should never have a WidgetDiv if not using // rendered blocks. if (!(block instanceof BlockSvg)) return false; diff --git a/core/field_label.ts b/core/field_label.ts index 2b77b0d25ff..2b0ae1eba49 100644 --- a/core/field_label.ts +++ b/core/field_label.ts @@ -12,9 +12,9 @@ */ // Former goog.module ID: Blockly.FieldLabel -import * as dom from './utils/dom.js'; import {Field, FieldConfig} from './field.js'; import * as fieldRegistry from './field_registry.js'; +import * as dom from './utils/dom.js'; import * as parsing from './utils/parsing.js'; /** diff --git a/core/field_number.ts b/core/field_number.ts index e8e51d06007..0641b9ae32b 100644 --- a/core/field_number.ts +++ b/core/field_number.ts @@ -12,12 +12,12 @@ // Former goog.module ID: Blockly.FieldNumber import {Field} from './field.js'; -import * as fieldRegistry from './field_registry.js'; import { FieldInput, FieldInputConfig, FieldInputValidator, } from './field_input.js'; +import * as fieldRegistry from './field_registry.js'; import * as aria from './utils/aria.js'; /** diff --git a/core/flyout_base.ts b/core/flyout_base.ts index 18f84480c5d..96d2b27fdcb 100644 --- a/core/flyout_base.ts +++ b/core/flyout_base.ts @@ -11,19 +11,22 @@ */ // Former goog.module ID: Blockly.Flyout -import type {Abstract as AbstractEvent} from './events/events_abstract.js'; import type {Block} from './block.js'; import {BlockSvg} from './block_svg.js'; import * as browserEvents from './browser_events.js'; import * as common from './common.js'; import {ComponentManager} from './component_manager.js'; +import {MANUALLY_DISABLED} from './constants.js'; import {DeleteArea} from './delete_area.js'; +import type {Abstract as AbstractEvent} from './events/events_abstract.js'; +import {EventType} from './events/type.js'; import * as eventUtils from './events/utils.js'; import {FlyoutButton} from './flyout_button.js'; import {FlyoutMetricsManager} from './flyout_metrics_manager.js'; +import {IAutoHideable} from './interfaces/i_autohideable.js'; import type {IFlyout} from './interfaces/i_flyout.js'; -import {MANUALLY_DISABLED} from './constants.js'; import type {Options} from './options.js'; +import * as renderManagement from './render_management.js'; import {ScrollbarPair} from './scrollbar_pair.js'; import * as blocks from './serialization/blocks.js'; import * as Tooltip from './tooltip.js'; @@ -32,12 +35,10 @@ import * as dom from './utils/dom.js'; import * as idGenerator from './utils/idgenerator.js'; import {Svg} from './utils/svg.js'; import * as toolbox from './utils/toolbox.js'; +import * as utilsXml from './utils/xml.js'; import * as Variables from './variables.js'; import {WorkspaceSvg} from './workspace_svg.js'; -import * as utilsXml from './utils/xml.js'; import * as Xml from './xml.js'; -import * as renderManagement from './render_management.js'; -import {IAutoHideable} from './interfaces/i_autohideable.js'; enum FlyoutItemType { BLOCK = 'block', @@ -206,7 +207,7 @@ export abstract class Flyout /** * Whether the flyout is visible. */ - private isVisible_ = false; + private visible = false; /** * Whether the workspace containing this flyout is visible. @@ -285,7 +286,7 @@ export abstract class Flyout this.workspace_.internalIsFlyout = true; // Keep the workspace visibility consistent with the flyout's visibility. - this.workspace_.setVisible(this.isVisible_); + this.workspace_.setVisible(this.visible); /** * The unique id for this component that is used to register with the @@ -427,7 +428,7 @@ export abstract class Flyout targetWorkspace.getComponentManager().addComponent({ component: this, - weight: 1, + weight: ComponentManager.ComponentWeight.FLYOUT_WEIGHT, capabilities: [ ComponentManager.Capability.AUTOHIDEABLE, ComponentManager.Capability.DELETE_AREA, @@ -531,7 +532,7 @@ export abstract class Flyout * @returns True if visible. */ isVisible(): boolean { - return this.isVisible_; + return this.visible; } /** @@ -544,7 +545,7 @@ export abstract class Flyout setVisible(visible: boolean) { const visibilityChanged = visible !== this.isVisible(); - this.isVisible_ = visible; + this.visible = visible; if (visibilityChanged) { if (!this.autoClose) { // Auto-close flyouts are ignored as drag targets, so only non @@ -1070,7 +1071,7 @@ export abstract class Flyout * @param block The flyout block to copy. * @returns Function to call when block is clicked. */ - private blockMouseDown(block: BlockSvg): Function { + private blockMouseDown(block: BlockSvg) { return (e: PointerEvent) => { const gesture = this.targetWorkspace.getGesture(e); if (gesture) { @@ -1138,13 +1139,13 @@ export abstract class Flyout for (let i = 0; i < newVariables.length; i++) { const thisVariable = newVariables[i]; eventUtils.fire( - new (eventUtils.get(eventUtils.VAR_CREATE))(thisVariable), + new (eventUtils.get(EventType.VAR_CREATE))(thisVariable), ); } // Block events come after var events, in case they refer to newly created // variables. - eventUtils.fire(new (eventUtils.get(eventUtils.BLOCK_CREATE))(newBlock)); + eventUtils.fire(new (eventUtils.get(EventType.BLOCK_CREATE))(newBlock)); } if (this.autoClose) { this.hide(); diff --git a/core/flyout_button.ts b/core/flyout_button.ts index e73403d77a0..b03a8d9615c 100644 --- a/core/flyout_button.ts +++ b/core/flyout_button.ts @@ -11,6 +11,7 @@ */ // Former goog.module ID: Blockly.FlyoutButton +import type {IASTNodeLocationSvg} from './blockly.js'; import * as browserEvents from './browser_events.js'; import * as Css from './css.js'; import {Coordinate} from './utils/coordinate.js'; @@ -20,7 +21,6 @@ import * as style from './utils/style.js'; import {Svg} from './utils/svg.js'; import type * as toolbox from './utils/toolbox.js'; import type {WorkspaceSvg} from './workspace_svg.js'; -import type {IASTNodeLocationSvg} from './blockly.js'; /** * Class for a button or label in the flyout. diff --git a/core/flyout_metrics_manager.ts b/core/flyout_metrics_manager.ts index fadc5deb505..00f675caafa 100644 --- a/core/flyout_metrics_manager.ts +++ b/core/flyout_metrics_manager.ts @@ -38,13 +38,13 @@ export class FlyoutMetricsManager extends MetricsManager { * * @returns The bounding box of the blocks on the workspace. */ - private getBoundingBox_(): + private getBoundingBox(): | SVGRect | {height: number; y: number; width: number; x: number} { let blockBoundingBox; try { blockBoundingBox = this.workspace_.getCanvas().getBBox(); - } catch (e) { + } catch { // Firefox has trouble with hidden elements (Bug 528969). // 2021 Update: It looks like this was fixed around Firefox 77 released in // 2020. @@ -55,7 +55,7 @@ export class FlyoutMetricsManager extends MetricsManager { override getContentMetrics(opt_getWorkspaceCoordinates?: boolean) { // The bounding box is in workspace coordinates. - const blockBoundingBox = this.getBoundingBox_(); + const blockBoundingBox = this.getBoundingBox(); const scale = opt_getWorkspaceCoordinates ? 1 : this.workspace_.scale; return { diff --git a/core/generator.ts b/core/generator.ts index 7bb509f8ba3..5884b4e5449 100644 --- a/core/generator.ts +++ b/core/generator.ts @@ -24,7 +24,7 @@ import type {Workspace} from './workspace.js'; * @deprecated * @see {@link https://developers.google.com/blockly/guides/create-custom-blocks/generating-code} * @param block The Block instance to generate code for. - * @param genearator The CodeGenerator calling the function. + * @param generator The CodeGenerator calling the function. * @returns A string containing the generated code (for statement blocks), * or a [code, precedence] tuple (for value/expression blocks), or * null if no code should be emitted for block. @@ -295,8 +295,8 @@ export class CodeGenerator { * @param name The name of the input. * @param outerOrder The maximum binding strength (minimum order value) of any * operators adjacent to "block". - * @returns Generated code or '' if no blocks are connected or the specified - * input does not exist. + * @returns Generated code or '' if no blocks are connected. + * @throws ReferenceError if the specified input does not exist. */ valueToCode(block: Block, name: string, outerOrder: number): string { if (isNaN(outerOrder)) { @@ -381,6 +381,7 @@ export class CodeGenerator { * @param block The block containing the input. * @param name The name of the input. * @returns Generated code or '' if no blocks are connected. + * @throws ReferenceError if the specified input does not exist. */ statementToCode(block: Block, name: string): string { const targetBlock = block.getInputTargetBlock(name); diff --git a/core/gesture.ts b/core/gesture.ts index 7970ed00689..0b65299e578 100644 --- a/core/gesture.ts +++ b/core/gesture.ts @@ -18,23 +18,24 @@ import './events/events_click.js'; import * as blockAnimations from './block_animations.js'; import type {BlockSvg} from './block_svg.js'; import * as browserEvents from './browser_events.js'; +import {RenderedWorkspaceComment} from './comments.js'; import * as common from './common.js'; import {config} from './config.js'; import * as dropDownDiv from './dropdowndiv.js'; +import {EventType} from './events/type.js'; import * as eventUtils from './events/utils.js'; import type {Field} from './field.js'; import type {IBubble} from './interfaces/i_bubble.js'; +import {IDraggable, isDraggable} from './interfaces/i_draggable.js'; +import {IDragger} from './interfaces/i_dragger.js'; import type {IFlyout} from './interfaces/i_flyout.js'; +import type {IIcon} from './interfaces/i_icon.js'; +import * as registry from './registry.js'; import * as Tooltip from './tooltip.js'; import * as Touch from './touch.js'; import {Coordinate} from './utils/coordinate.js'; import {WorkspaceDragger} from './workspace_dragger.js'; import type {WorkspaceSvg} from './workspace_svg.js'; -import type {IIcon} from './interfaces/i_icon.js'; -import {IDragger} from './interfaces/i_dragger.js'; -import * as registry from './registry.js'; -import {IDraggable, isDraggable} from './interfaces/i_draggable.js'; -import {RenderedWorkspaceComment} from './comments.js'; /** * Note: In this file "start" refers to pointerdown @@ -145,7 +146,7 @@ export class Gesture { private mostRecentEvent: PointerEvent; /** Boolean for whether or not this gesture is a multi-touch gesture. */ - private isMultiTouch_ = false; + private multiTouch = false; /** A map of cached points used for tracking multi-touch gestures. */ private cachedPoints = new Map(); @@ -585,7 +586,7 @@ export class Gesture { const point0 = this.cachedPoints.get(pointers[0])!; const point1 = this.cachedPoints.get(pointers[1])!; this.startDistance = Coordinate.distance(point0, point1); - this.isMultiTouch_ = true; + this.multiTouch = true; e.preventDefault(); } } @@ -599,13 +600,20 @@ export class Gesture { */ handleTouchMove(e: PointerEvent) { const pointerId = Touch.getTouchIdentifierFromEvent(e); - // Update the cache this.cachedPoints.set(pointerId, this.getTouchPoint(e)); if (this.isPinchZoomEnabled && this.cachedPoints.size === 2) { this.handlePinch(e); } else { - this.handleMove(e); + // Handle the move directly instead of calling handleMove + this.updateFromEvent(e); + if (this.workspaceDragger) { + this.workspaceDragger.drag(this.currentDragDeltaXY); + } else if (this.dragger) { + this.dragger.onDrag(this.mostRecentEvent, this.currentDragDeltaXY); + } + e.preventDefault(); + e.stopPropagation(); } } @@ -683,7 +691,7 @@ export class Gesture { * @internal */ isMultiTouch(): boolean { - return this.isMultiTouch_; + return this.multiTouch; } /** @@ -769,7 +777,7 @@ export class Gesture { */ private fireWorkspaceClick(ws: WorkspaceSvg) { eventUtils.fire( - new (eventUtils.get(eventUtils.CLICK))(null, ws.id, 'workspace'), + new (eventUtils.get(EventType.CLICK))(null, ws.id, 'workspace'), ); } @@ -902,7 +910,7 @@ export class Gesture { ); } // Clicks events are on the start block, even if it was a shadow. - const event = new (eventUtils.get(eventUtils.CLICK))( + const event = new (eventUtils.get(EventType.CLICK))( this.startBlock, this.startWorkspace_.id, 'block', diff --git a/core/grid.ts b/core/grid.ts index 1a5de250e5c..e2fc054a262 100644 --- a/core/grid.ts +++ b/core/grid.ts @@ -12,10 +12,10 @@ */ // Former goog.module ID: Blockly.Grid -import * as dom from './utils/dom.js'; +import {GridOptions} from './options.js'; import {Coordinate} from './utils/coordinate.js'; +import * as dom from './utils/dom.js'; import {Svg} from './utils/svg.js'; -import {GridOptions} from './options.js'; /** * Class for a workspace's grid. diff --git a/core/icons.ts b/core/icons.ts index 61d1594b826..fcc7c98c663 100644 --- a/core/icons.ts +++ b/core/icons.ts @@ -4,21 +4,21 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {Icon} from './icons/icon.js'; import {CommentIcon, CommentState} from './icons/comment_icon.js'; -import {MutatorIcon} from './icons/mutator_icon.js'; -import {WarningIcon} from './icons/warning_icon.js'; -import {IconType} from './icons/icon_types.js'; import * as exceptions from './icons/exceptions.js'; +import {Icon} from './icons/icon.js'; +import {IconType} from './icons/icon_types.js'; +import {MutatorIcon} from './icons/mutator_icon.js'; import * as registry from './icons/registry.js'; +import {WarningIcon} from './icons/warning_icon.js'; export { - Icon, CommentIcon, CommentState, - MutatorIcon, - WarningIcon, - IconType, exceptions, + Icon, + IconType, + MutatorIcon, registry, + WarningIcon, }; diff --git a/core/icons/comment_icon.ts b/core/icons/comment_icon.ts index df54560c557..ea120ca1728 100644 --- a/core/icons/comment_icon.ts +++ b/core/icons/comment_icon.ts @@ -8,21 +8,21 @@ import type {Block} from '../block.js'; import type {BlockSvg} from '../block_svg.js'; -import {IconType} from './icon_types.js'; -import {Coordinate} from '../utils.js'; -import * as dom from '../utils/dom.js'; +import {TextInputBubble} from '../bubbles/textinput_bubble.js'; +import {EventType} from '../events/type.js'; import * as eventUtils from '../events/utils.js'; -import {Icon} from './icon.js'; import type {IHasBubble} from '../interfaces/i_has_bubble.js'; import type {ISerializable} from '../interfaces/i_serializable.js'; +import * as renderManagement from '../render_management.js'; +import {Coordinate} from '../utils.js'; +import * as dom from '../utils/dom.js'; import {Rect} from '../utils/rect.js'; -import * as registry from './registry.js'; import {Size} from '../utils/size.js'; import {Svg} from '../utils/svg.js'; -import {TextBubble} from '../bubbles/text_bubble.js'; -import {TextInputBubble} from '../bubbles/textinput_bubble.js'; import type {WorkspaceSvg} from '../workspace_svg.js'; -import * as renderManagement from '../render_management.js'; +import {Icon} from './icon.js'; +import {IconType} from './icon_types.js'; +import * as registry from './registry.js'; /** The size of the comment icon in workspace-scale units. */ const SIZE = 17; @@ -46,12 +46,9 @@ export class CommentIcon extends Icon implements IHasBubble, ISerializable { */ static readonly WEIGHT = 3; - /** The bubble used to show editable text to the user. */ + /** The bubble used to show comment text to the user. */ private textInputBubble: TextInputBubble | null = null; - /** The bubble used to show non-editable text to the user. */ - private textBubble: TextBubble | null = null; - /** The text of this comment. */ private text = ''; @@ -117,7 +114,6 @@ export class CommentIcon extends Icon implements IHasBubble, ISerializable { override dispose() { super.dispose(); this.textInputBubble?.dispose(); - this.textBubble?.dispose(); } override getWeight(): number { @@ -132,7 +128,6 @@ export class CommentIcon extends Icon implements IHasBubble, ISerializable { super.applyColour(); const colour = (this.sourceBlock as BlockSvg).style.colourPrimary; this.textInputBubble?.setColour(colour); - this.textBubble?.setColour(colour); } /** @@ -152,14 +147,13 @@ export class CommentIcon extends Icon implements IHasBubble, ISerializable { super.onLocationChange(blockOrigin); const anchorLocation = this.getAnchorLocation(); this.textInputBubble?.setAnchorLocation(anchorLocation); - this.textBubble?.setAnchorLocation(anchorLocation); } /** Sets the text of this comment. Updates any bubbles if they are visible. */ setText(text: string) { const oldText = this.text; eventUtils.fire( - new (eventUtils.get(eventUtils.BLOCK_CHANGE))( + new (eventUtils.get(EventType.BLOCK_CHANGE))( this.sourceBlock, 'comment', null, @@ -169,7 +163,6 @@ export class CommentIcon extends Icon implements IHasBubble, ISerializable { ); this.text = text; this.textInputBubble?.setText(this.text); - this.textBubble?.setText(this.text); } /** Returns the text of this comment. */ @@ -238,7 +231,7 @@ export class CommentIcon extends Icon implements IHasBubble, ISerializable { if (this.text === newText) return; eventUtils.fire( - new (eventUtils.get(eventUtils.BLOCK_CHANGE))( + new (eventUtils.get(EventType.BLOCK_CHANGE))( this.sourceBlock, 'comment', null, @@ -288,7 +281,7 @@ export class CommentIcon extends Icon implements IHasBubble, ISerializable { } eventUtils.fire( - new (eventUtils.get(eventUtils.BUBBLE_OPEN))( + new (eventUtils.get(EventType.BUBBLE_OPEN))( this.sourceBlock, visible, 'comment', @@ -301,33 +294,31 @@ export class CommentIcon extends Icon implements IHasBubble, ISerializable { * to update the state of this icon in response to changes in the bubble. */ private showEditableBubble() { - this.textInputBubble = new TextInputBubble( - this.sourceBlock.workspace as WorkspaceSvg, - this.getAnchorLocation(), - this.getBubbleOwnerRect(), - ); - this.textInputBubble.setText(this.getText()); - this.textInputBubble.setSize(this.bubbleSize, true); - this.textInputBubble.addTextChangeListener(() => this.onTextChange()); - this.textInputBubble.addSizeChangeListener(() => this.onSizeChange()); + this.createBubble(); + this.textInputBubble?.addTextChangeListener(() => this.onTextChange()); + this.textInputBubble?.addSizeChangeListener(() => this.onSizeChange()); } /** Shows the non editable text bubble for this comment. */ private showNonEditableBubble() { - this.textBubble = new TextBubble( - this.getText(), + this.createBubble(); + this.textInputBubble?.setEditable(false); + } + + protected createBubble() { + this.textInputBubble = new TextInputBubble( this.sourceBlock.workspace as WorkspaceSvg, this.getAnchorLocation(), this.getBubbleOwnerRect(), ); + this.textInputBubble.setText(this.getText()); + this.textInputBubble.setSize(this.bubbleSize, true); } /** Hides any open bubbles owned by this comment. */ private hideBubble() { this.textInputBubble?.dispose(); this.textInputBubble = null; - this.textBubble?.dispose(); - this.textBubble = null; } /** @@ -347,8 +338,7 @@ export class CommentIcon extends Icon implements IHasBubble, ISerializable { * I.E. the block that owns this icon. */ private getBubbleOwnerRect(): Rect { - const bbox = (this.sourceBlock as BlockSvg).getSvgRoot().getBBox(); - return new Rect(bbox.y, bbox.y + bbox.height, bbox.x, bbox.x + bbox.width); + return (this.sourceBlock as BlockSvg).getBoundingRectangleWithoutChildren(); } } diff --git a/core/icons/icon.ts b/core/icons/icon.ts index 6ad9532366e..30a6b538f6e 100644 --- a/core/icons/icon.ts +++ b/core/icons/icon.ts @@ -9,12 +9,12 @@ import type {BlockSvg} from '../block_svg.js'; import * as browserEvents from '../browser_events.js'; import {hasBubble} from '../interfaces/i_has_bubble.js'; import type {IIcon} from '../interfaces/i_icon.js'; +import * as tooltip from '../tooltip.js'; import {Coordinate} from '../utils/coordinate.js'; import * as dom from '../utils/dom.js'; import {Size} from '../utils/size.js'; import {Svg} from '../utils/svg.js'; import type {IconType} from './icon_types.js'; -import * as tooltip from '../tooltip.js'; /** * The abstract icon class. Icons are visual elements that live in the top-start diff --git a/core/icons/mutator_icon.ts b/core/icons/mutator_icon.ts index 7fb3fcf3b81..d02c7e1871b 100644 --- a/core/icons/mutator_icon.ts +++ b/core/icons/mutator_icon.ts @@ -6,22 +6,24 @@ // Former goog.module ID: Blockly.Mutator +import type {BlockSvg} from '../block_svg.js'; +import type {BlocklyOptions} from '../blockly_options.js'; +import {MiniWorkspaceBubble} from '../bubbles/mini_workspace_bubble.js'; import type {Abstract} from '../events/events_abstract.js'; import {BlockChange} from '../events/events_block_change.js'; -import type {BlocklyOptions} from '../blockly_options.js'; -import type {BlockSvg} from '../block_svg.js'; -import {Coordinate} from '../utils/coordinate.js'; -import * as dom from '../utils/dom.js'; +import {isBlockChange, isBlockCreate} from '../events/predicates.js'; +import {EventType} from '../events/type.js'; import * as eventUtils from '../events/utils.js'; import type {IHasBubble} from '../interfaces/i_has_bubble.js'; -import {Icon} from './icon.js'; -import {MiniWorkspaceBubble} from '../bubbles/mini_workspace_bubble.js'; +import * as renderManagement from '../render_management.js'; +import {Coordinate} from '../utils/coordinate.js'; +import * as dom from '../utils/dom.js'; import {Rect} from '../utils/rect.js'; import {Size} from '../utils/size.js'; import {Svg} from '../utils/svg.js'; import type {WorkspaceSvg} from '../workspace_svg.js'; +import {Icon} from './icon.js'; import {IconType} from './icon_types.js'; -import * as renderManagement from '../render_management.js'; /** The size of the mutator icon in workspace-scale units. */ const SIZE = 17; @@ -193,7 +195,7 @@ export class MutatorIcon extends Icon implements IHasBubble { } eventUtils.fire( - new (eventUtils.get(eventUtils.BUBBLE_OPEN))( + new (eventUtils.get(EventType.BUBBLE_OPEN))( this.sourceBlock, visible, 'mutator', @@ -307,9 +309,8 @@ export class MutatorIcon extends Icon implements IHasBubble { static isIgnorableMutatorEvent(e: Abstract) { return ( e.isUiEvent || - e.type === eventUtils.CREATE || - (e.type === eventUtils.CHANGE && - (e as BlockChange).element === 'disabled') + isBlockCreate(e) || + (isBlockChange(e) && e.element === 'disabled') ); } @@ -331,7 +332,7 @@ export class MutatorIcon extends Icon implements IHasBubble { if (oldExtraState !== newExtraState) { eventUtils.fire( - new (eventUtils.get(eventUtils.BLOCK_CHANGE))( + new (eventUtils.get(EventType.BLOCK_CHANGE))( this.sourceBlock, 'mutation', null, diff --git a/core/icons/warning_icon.ts b/core/icons/warning_icon.ts index 08f511a60b7..2744195f98d 100644 --- a/core/icons/warning_icon.ts +++ b/core/icons/warning_icon.ts @@ -7,17 +7,18 @@ // Former goog.module ID: Blockly.Warning import type {BlockSvg} from '../block_svg.js'; -import {Coordinate} from '../utils/coordinate.js'; -import * as dom from '../utils/dom.js'; +import {TextBubble} from '../bubbles/text_bubble.js'; +import {EventType} from '../events/type.js'; import * as eventUtils from '../events/utils.js'; -import {Icon} from './icon.js'; import type {IHasBubble} from '../interfaces/i_has_bubble.js'; -import {Rect} from '../utils/rect.js'; +import * as renderManagement from '../render_management.js'; import {Size} from '../utils.js'; +import {Coordinate} from '../utils/coordinate.js'; +import * as dom from '../utils/dom.js'; +import {Rect} from '../utils/rect.js'; import {Svg} from '../utils/svg.js'; -import {TextBubble} from '../bubbles/text_bubble.js'; +import {Icon} from './icon.js'; import {IconType} from './icon_types.js'; -import * as renderManagement from '../render_management.js'; /** The size of the warning icon in workspace-scale units. */ const SIZE = 17; @@ -188,7 +189,7 @@ export class WarningIcon extends Icon implements IHasBubble { } eventUtils.fire( - new (eventUtils.get(eventUtils.BUBBLE_OPEN))( + new (eventUtils.get(EventType.BUBBLE_OPEN))( this.sourceBlock, visible, 'warning', diff --git a/core/inject.ts b/core/inject.ts index 323191817ac..b425d77b74b 100644 --- a/core/inject.ts +++ b/core/inject.ts @@ -22,7 +22,6 @@ import * as Touch from './touch.js'; import * as aria from './utils/aria.js'; import * as dom from './utils/dom.js'; import {Svg} from './utils/svg.js'; -import * as userAgent from './utils/useragent.js'; import * as WidgetDiv from './widgetdiv.js'; import {WorkspaceSvg} from './workspace_svg.js'; @@ -77,6 +76,8 @@ export function inject( common.setMainWorkspace(workspace); }); + browserEvents.conditionalBind(subContainer, 'keydown', null, onKeyDown); + return workspace; } @@ -320,8 +321,6 @@ let documentEventsBound = false; * Most of these events should be bound to the SVG's surface. * However, 'mouseup' has to be on the whole document so that a block dragged * out of bounds and released will know that it has been released. - * Also, 'keydown' has to be on the whole document since the browser doesn't - * understand a concept of focus on the SVG image. */ function bindDocumentEvents() { if (!documentEventsBound) { @@ -333,23 +332,10 @@ function bindDocumentEvents() { } } }); - browserEvents.conditionalBind(document, 'keydown', null, onKeyDown); // longStop needs to run to stop the context menu from showing up. It // should run regardless of what other touch event handlers have run. browserEvents.bind(document, 'touchend', null, Touch.longStop); browserEvents.bind(document, 'touchcancel', null, Touch.longStop); - // Some iPad versions don't fire resize after portrait to landscape change. - if (userAgent.IPAD) { - browserEvents.conditionalBind( - window, - 'orientationchange', - document, - function () { - // TODO (#397): Fix for multiple Blockly workspaces. - common.svgResize(common.getMainWorkspace() as WorkspaceSvg); - }, - ); - } } documentEventsBound = true; } diff --git a/core/inputs.ts b/core/inputs.ts index 4b7bfa89750..064d37530a5 100644 --- a/core/inputs.ts +++ b/core/inputs.ts @@ -5,19 +5,19 @@ */ import {Align} from './inputs/align.js'; -import {Input} from './inputs/input.js'; import {DummyInput} from './inputs/dummy_input.js'; import {EndRowInput} from './inputs/end_row_input.js'; +import {Input} from './inputs/input.js'; +import {inputTypes} from './inputs/input_types.js'; import {StatementInput} from './inputs/statement_input.js'; import {ValueInput} from './inputs/value_input.js'; -import {inputTypes} from './inputs/input_types.js'; export { Align, - Input, DummyInput, EndRowInput, + Input, + inputTypes, StatementInput, ValueInput, - inputTypes, }; diff --git a/core/inputs/input.ts b/core/inputs/input.ts index da7cccad588..0907bf44939 100644 --- a/core/inputs/input.ts +++ b/core/inputs/input.ts @@ -21,8 +21,8 @@ import type {ConnectionType} from '../connection_type.js'; import type {Field} from '../field.js'; import * as fieldRegistry from '../field_registry.js'; import type {RenderedConnection} from '../rendered_connection.js'; -import {inputTypes} from './input_types.js'; import {Align} from './align.js'; +import {inputTypes} from './input_types.js'; /** Class for an input with optional fields. */ export class Input { diff --git a/core/insertion_marker_manager.ts b/core/insertion_marker_manager.ts index 376297f10e7..13d63042002 100644 --- a/core/insertion_marker_manager.ts +++ b/core/insertion_marker_manager.ts @@ -11,20 +11,20 @@ */ // Former goog.module ID: Blockly.InsertionMarkerManager -import {finishQueuedRenders} from './render_management.js'; import * as blockAnimations from './block_animations.js'; import type {BlockSvg} from './block_svg.js'; import * as common from './common.js'; import {ComponentManager} from './component_manager.js'; import {config} from './config.js'; -import * as blocks from './serialization/blocks.js'; import * as eventUtils from './events/utils.js'; import type {IDeleteArea} from './interfaces/i_delete_area.js'; import type {IDragTarget} from './interfaces/i_drag_target.js'; +import * as renderManagement from './render_management.js'; +import {finishQueuedRenders} from './render_management.js'; import type {RenderedConnection} from './rendered_connection.js'; +import * as blocks from './serialization/blocks.js'; import type {Coordinate} from './utils/coordinate.js'; import type {WorkspaceSvg} from './workspace_svg.js'; -import * as renderManagement from './render_management.js'; /** Represents a nearby valid connection. */ interface CandidateConnection { @@ -529,7 +529,7 @@ export class InsertionMarkerManager { local.getSourceBlock(), local, ); - } catch (e) { + } catch { // It's possible that the number of connections on the local block has // changed since the insertion marker was originally created. Let's // recreate the insertion marker and try again. In theory we could diff --git a/core/insertion_marker_previewer.ts b/core/insertion_marker_previewer.ts index 3cc9f1a049f..2343b9adc76 100644 --- a/core/insertion_marker_previewer.ts +++ b/core/insertion_marker_previewer.ts @@ -5,15 +5,15 @@ */ import {BlockSvg} from './block_svg.js'; -import {IConnectionPreviewer} from './interfaces/i_connection_previewer.js'; -import {RenderedConnection} from './rendered_connection.js'; -import {WorkspaceSvg} from './workspace_svg.js'; -import * as blocks from './serialization/blocks.js'; +import {ConnectionType} from './connection_type.js'; import * as eventUtils from './events/utils.js'; -import * as renderManagement from './render_management.js'; +import {IConnectionPreviewer} from './interfaces/i_connection_previewer.js'; import * as registry from './registry.js'; +import * as renderManagement from './render_management.js'; +import {RenderedConnection} from './rendered_connection.js'; import {Renderer as ZelosRenderer} from './renderers/zelos/renderer.js'; -import {ConnectionType} from './connection_type.js'; +import * as blocks from './serialization/blocks.js'; +import {WorkspaceSvg} from './workspace_svg.js'; export class InsertionMarkerPreviewer implements IConnectionPreviewer { private readonly workspace: WorkspaceSvg; diff --git a/core/interfaces/i_ast_node_location_with_block.ts b/core/interfaces/i_ast_node_location_with_block.ts index a00603864d3..b04234fd4a8 100644 --- a/core/interfaces/i_ast_node_location_with_block.ts +++ b/core/interfaces/i_ast_node_location_with_block.ts @@ -6,8 +6,8 @@ // Former goog.module ID: Blockly.IASTNodeLocationWithBlock -import type {IASTNodeLocation} from './i_ast_node_location.js'; import type {Block} from '../block.js'; +import type {IASTNodeLocation} from './i_ast_node_location.js'; /** * An AST node location that has an associated block. diff --git a/core/interfaces/i_bounded_element.ts b/core/interfaces/i_bounded_element.ts index a32df5985ef..aac26855bd6 100644 --- a/core/interfaces/i_bounded_element.ts +++ b/core/interfaces/i_bounded_element.ts @@ -4,9 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type {Rect} from '../utils/rect.js'; // Former goog.module ID: Blockly.IBoundedElement +import type {Rect} from '../utils/rect.js'; + /** * A bounded element interface. */ diff --git a/core/interfaces/i_bubble.ts b/core/interfaces/i_bubble.ts index e27fccafd48..d31ce9c9dce 100644 --- a/core/interfaces/i_bubble.ts +++ b/core/interfaces/i_bubble.ts @@ -4,9 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type {Coordinate} from '../utils/coordinate.js'; // Former goog.module ID: Blockly.IBubble +import type {Coordinate} from '../utils/coordinate.js'; import type {IContextMenu} from './i_contextmenu.js'; import type {IDraggable} from './i_draggable.js'; diff --git a/core/interfaces/i_comment_icon.ts b/core/interfaces/i_comment_icon.ts index 09b071110dd..9801a8d6e11 100644 --- a/core/interfaces/i_comment_icon.ts +++ b/core/interfaces/i_comment_icon.ts @@ -4,11 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {IconType} from '../icons/icon_types.js'; import {CommentState} from '../icons/comment_icon.js'; -import {IIcon, isIcon} from './i_icon.js'; +import {IconType} from '../icons/icon_types.js'; import {Size} from '../utils/size.js'; import {IHasBubble, hasBubble} from './i_has_bubble.js'; +import {IIcon, isIcon} from './i_icon.js'; import {ISerializable, isSerializable} from './i_serializable.js'; export interface ICommentIcon extends IIcon, IHasBubble, ISerializable { @@ -26,7 +26,7 @@ export interface ICommentIcon extends IIcon, IHasBubble, ISerializable { } /** Checks whether the given object is an ICommentIcon. */ -export function isCommentIcon(obj: Object): obj is ICommentIcon { +export function isCommentIcon(obj: object): obj is ICommentIcon { return ( isIcon(obj) && hasBubble(obj) && diff --git a/core/interfaces/i_connection_checker.ts b/core/interfaces/i_connection_checker.ts index 8bb0fcc7393..352b719d665 100644 --- a/core/interfaces/i_connection_checker.ts +++ b/core/interfaces/i_connection_checker.ts @@ -4,9 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +// Former goog.module ID: Blockly.IConnectionChecker + import type {Connection} from '../connection.js'; import type {RenderedConnection} from '../rendered_connection.js'; -// Former goog.module ID: Blockly.IConnectionChecker /** * Class for connection type checking logic. diff --git a/core/interfaces/i_drag_target.ts b/core/interfaces/i_drag_target.ts index 3fa060232be..395b2345123 100644 --- a/core/interfaces/i_drag_target.ts +++ b/core/interfaces/i_drag_target.ts @@ -4,13 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {Rect} from '../utils/rect.js'; - -import {IDraggable} from './i_draggable.js'; - // Former goog.module ID: Blockly.IDragTarget +import {Rect} from '../utils/rect.js'; import type {IComponent} from './i_component.js'; +import {IDraggable} from './i_draggable.js'; /** * Interface for a component with custom behaviour when a block or bubble is diff --git a/core/interfaces/i_flyout.ts b/core/interfaces/i_flyout.ts index 84067f755d2..c79be344c5a 100644 --- a/core/interfaces/i_flyout.ts +++ b/core/interfaces/i_flyout.ts @@ -6,13 +6,13 @@ // Former goog.module ID: Blockly.IFlyout -import type {WorkspaceSvg} from '../workspace_svg.js'; import type {BlockSvg} from '../block_svg.js'; +import {FlyoutItem} from '../flyout_base.js'; import type {Coordinate} from '../utils/coordinate.js'; -import type {FlyoutDefinition} from '../utils/toolbox.js'; import type {Svg} from '../utils/svg.js'; +import type {FlyoutDefinition} from '../utils/toolbox.js'; +import type {WorkspaceSvg} from '../workspace_svg.js'; import type {IRegistrable} from './i_registrable.js'; -import {FlyoutItem} from '../flyout_base.js'; /** * Interface for a flyout. diff --git a/core/interfaces/i_keyboard_accessible.ts b/core/interfaces/i_keyboard_accessible.ts index 50e85b08e9d..4d04e9d4f08 100644 --- a/core/interfaces/i_keyboard_accessible.ts +++ b/core/interfaces/i_keyboard_accessible.ts @@ -4,9 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {KeyboardShortcut} from '../shortcut_registry.js'; // Former goog.module ID: Blockly.IKeyboardAccessible +import {KeyboardShortcut} from '../shortcut_registry.js'; + /** * An interface for an object that handles keyboard shortcuts. */ diff --git a/core/interfaces/i_legacy_procedure_blocks.ts b/core/interfaces/i_legacy_procedure_blocks.ts index 3bd7e19bf21..d74eaec220a 100644 --- a/core/interfaces/i_legacy_procedure_blocks.ts +++ b/core/interfaces/i_legacy_procedure_blocks.ts @@ -28,7 +28,7 @@ export interface LegacyProcedureDefBlock { /** @internal */ export function isLegacyProcedureDefBlock( - block: Object, + block: object, ): block is LegacyProcedureDefBlock { return (block as any).getProcedureDef !== undefined; } @@ -41,7 +41,7 @@ export interface LegacyProcedureCallBlock { /** @internal */ export function isLegacyProcedureCallBlock( - block: Object, + block: object, ): block is LegacyProcedureCallBlock { return ( (block as any).getProcedureCall !== undefined && diff --git a/core/interfaces/i_metrics_manager.ts b/core/interfaces/i_metrics_manager.ts index 52b9644dfb6..bb4d54da440 100644 --- a/core/interfaces/i_metrics_manager.ts +++ b/core/interfaces/i_metrics_manager.ts @@ -4,15 +4,16 @@ * SPDX-License-Identifier: Apache-2.0 */ +// Former goog.module ID: Blockly.IMetricsManager + import type { + AbsoluteMetrics, ContainerRegion, ToolboxMetrics, - AbsoluteMetrics, UiMetrics, } from '../metrics_manager.js'; -import type {Size} from '../utils/size.js'; import type {Metrics} from '../utils/metrics.js'; -// Former goog.module ID: Blockly.IMetricsManager +import type {Size} from '../utils/size.js'; /** * Interface for a metrics manager. diff --git a/core/interfaces/i_positionable.ts b/core/interfaces/i_positionable.ts index 19843d15333..4ea7dafa08d 100644 --- a/core/interfaces/i_positionable.ts +++ b/core/interfaces/i_positionable.ts @@ -4,10 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type {Rect} from '../utils/rect.js'; -import type {UiMetrics} from '../metrics_manager.js'; // Former goog.module ID: Blockly.IPositionable +import type {UiMetrics} from '../metrics_manager.js'; +import type {Rect} from '../utils/rect.js'; import type {IComponent} from './i_component.js'; /** diff --git a/core/interfaces/i_procedure_block.ts b/core/interfaces/i_procedure_block.ts index 3744eb18336..f8538052749 100644 --- a/core/interfaces/i_procedure_block.ts +++ b/core/interfaces/i_procedure_block.ts @@ -4,9 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +// Former goog.module ID: Blockly.procedures.IProcedureBlock + import type {Block} from '../block.js'; import {IProcedureModel} from './i_procedure_model.js'; -// Former goog.module ID: Blockly.procedures.IProcedureBlock /** The interface for a block which models a procedure. */ export interface IProcedureBlock { diff --git a/core/interfaces/i_selectable.ts b/core/interfaces/i_selectable.ts index 7cf9ad98c6f..972b0adb107 100644 --- a/core/interfaces/i_selectable.ts +++ b/core/interfaces/i_selectable.ts @@ -24,7 +24,7 @@ export interface ISelectable { } /** Checks whether the given object is an ISelectable. */ -export function isSelectable(obj: Object): obj is ISelectable { +export function isSelectable(obj: object): obj is ISelectable { return ( typeof (obj as any).id === 'string' && (obj as any).workspace !== undefined && diff --git a/core/interfaces/i_selectable_toolbox_item.ts b/core/interfaces/i_selectable_toolbox_item.ts index b3267efd058..890d4e370af 100644 --- a/core/interfaces/i_selectable_toolbox_item.ts +++ b/core/interfaces/i_selectable_toolbox_item.ts @@ -4,9 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type {FlyoutItemInfoArray} from '../utils/toolbox'; // Former goog.module ID: Blockly.ISelectableToolboxItem +import type {FlyoutItemInfoArray} from '../utils/toolbox'; import type {IToolboxItem} from './i_toolbox_item.js'; /** diff --git a/core/interfaces/i_serializer.ts b/core/interfaces/i_serializer.ts index 29c25791550..f5fbb67d100 100644 --- a/core/interfaces/i_serializer.ts +++ b/core/interfaces/i_serializer.ts @@ -22,8 +22,6 @@ export interface ISerializer { */ priority: number; - /* eslint-disable no-unused-vars, valid-jsdoc */ - /** * Saves the state of the plugin or system. * @@ -31,8 +29,7 @@ export interface ISerializer { * @returns A JS object containing the system's state, or null if there is no * state to record. */ - save(workspace: Workspace): Object | null; - /* eslint-enable valid-jsdoc */ + save(workspace: Workspace): object | null; /** * Loads the state of the plugin or system. @@ -42,7 +39,7 @@ export interface ISerializer { * @param workspace The workspace the system to deserialize is associated * with. */ - load(state: Object, workspace: Workspace): void; + load(state: object, workspace: Workspace): void; /** * Clears the state of the plugin or system. @@ -52,4 +49,3 @@ export interface ISerializer { */ clear(workspace: Workspace): void; } -/* eslint-enable no-unused-vars */ diff --git a/core/interfaces/i_toolbox.ts b/core/interfaces/i_toolbox.ts index a236d4442ae..2756099ec34 100644 --- a/core/interfaces/i_toolbox.ts +++ b/core/interfaces/i_toolbox.ts @@ -6,11 +6,11 @@ // Former goog.module ID: Blockly.IToolbox -import type {IRegistrable} from './i_registrable.js'; -import type {IToolboxItem} from './i_toolbox_item.js'; import type {ToolboxInfo} from '../utils/toolbox.js'; -import type {IFlyout} from './i_flyout.js'; import type {WorkspaceSvg} from '../workspace_svg.js'; +import type {IFlyout} from './i_flyout.js'; +import type {IRegistrable} from './i_registrable.js'; +import type {IToolboxItem} from './i_toolbox_item.js'; /** * Interface for a toolbox. diff --git a/core/keyboard_nav/ast_node.ts b/core/keyboard_nav/ast_node.ts index 7985ac6dc24..3b0efae3fb3 100644 --- a/core/keyboard_nav/ast_node.ts +++ b/core/keyboard_nav/ast_node.ts @@ -16,14 +16,14 @@ import {Block} from '../block.js'; import type {Connection} from '../connection.js'; import {ConnectionType} from '../connection_type.js'; import type {Field} from '../field.js'; +import {FlyoutItem} from '../flyout_base.js'; +import {FlyoutButton} from '../flyout_button.js'; import type {Input} from '../inputs/input.js'; import type {IASTNodeLocation} from '../interfaces/i_ast_node_location.js'; import type {IASTNodeLocationWithBlock} from '../interfaces/i_ast_node_location_with_block.js'; import {Coordinate} from '../utils/coordinate.js'; import type {Workspace} from '../workspace.js'; -import {FlyoutButton} from '../flyout_button.js'; import {WorkspaceSvg} from '../workspace_svg.js'; -import {FlyoutItem} from '../flyout_base.js'; /** * Class for an AST node. diff --git a/core/keyboard_nav/basic_cursor.ts b/core/keyboard_nav/basic_cursor.ts index 95b5e2f4d51..7526141529e 100644 --- a/core/keyboard_nav/basic_cursor.ts +++ b/core/keyboard_nav/basic_cursor.ts @@ -13,7 +13,6 @@ // Former goog.module ID: Blockly.BasicCursor import * as registry from '../registry.js'; - import {ASTNode} from './ast_node.js'; import {Cursor} from './cursor.js'; diff --git a/core/keyboard_nav/cursor.ts b/core/keyboard_nav/cursor.ts index da0a50f1cb6..92279da562d 100644 --- a/core/keyboard_nav/cursor.ts +++ b/core/keyboard_nav/cursor.ts @@ -13,7 +13,6 @@ // Former goog.module ID: Blockly.Cursor import * as registry from '../registry.js'; - import {ASTNode} from './ast_node.js'; import {Marker} from './marker.js'; diff --git a/core/keyboard_nav/marker.ts b/core/keyboard_nav/marker.ts index 9653e6b8548..e3b438e6efe 100644 --- a/core/keyboard_nav/marker.ts +++ b/core/keyboard_nav/marker.ts @@ -12,9 +12,7 @@ */ // Former goog.module ID: Blockly.Marker -/* eslint-disable-next-line no-unused-vars */ import type {MarkerSvg} from '../renderers/common/marker_svg.js'; - import type {ASTNode} from './ast_node.js'; /** diff --git a/core/keyboard_nav/tab_navigate_cursor.ts b/core/keyboard_nav/tab_navigate_cursor.ts index 20fd3dabb38..0392887a1fd 100644 --- a/core/keyboard_nav/tab_navigate_cursor.ts +++ b/core/keyboard_nav/tab_navigate_cursor.ts @@ -13,7 +13,6 @@ // Former goog.module ID: Blockly.TabNavigateCursor import type {Field} from '../field.js'; - import {ASTNode} from './ast_node.js'; import {BasicCursor} from './basic_cursor.js'; diff --git a/core/layer_manager.ts b/core/layer_manager.ts index e181e680139..e7663b1b7ee 100644 --- a/core/layer_manager.ts +++ b/core/layer_manager.ts @@ -4,12 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {WorkspaceSvg} from './workspace_svg.js'; -import * as dom from './utils/dom.js'; -import {Svg} from './utils/svg.js'; import {IRenderedElement} from './interfaces/i_rendered_element.js'; import * as layerNums from './layers.js'; import {Coordinate} from './utils/coordinate.js'; +import * as dom from './utils/dom.js'; +import {Svg} from './utils/svg.js'; +import {WorkspaceSvg} from './workspace_svg.js'; /** @internal */ export class LayerManager { diff --git a/core/layers.ts b/core/layers.ts index 60a30c8f67a..c62c40f3e53 100644 --- a/core/layers.ts +++ b/core/layers.ts @@ -7,13 +7,11 @@ /** * The layer to place blocks on. * - * @internal */ export const BLOCK = 50; /** * The layer to place bubbles on. * - * @internal */ export const BUBBLE = 100; diff --git a/core/marker_manager.ts b/core/marker_manager.ts index bd243c005b3..d7035534da7 100644 --- a/core/marker_manager.ts +++ b/core/marker_manager.ts @@ -23,16 +23,16 @@ export class MarkerManager { static readonly LOCAL_MARKER = 'local_marker_1'; /** The cursor. */ - private cursor_: Cursor | null = null; + private cursor: Cursor | null = null; /** The cursor's SVG element. */ - private cursorSvg_: SVGElement | null = null; + private cursorSvg: SVGElement | null = null; /** The map of markers for the workspace. */ private markers = new Map(); /** The marker's SVG element. */ - private markerSvg_: SVGElement | null = null; + private markerSvg: SVGElement | null = null; /** * @param workspace The workspace for the marker manager. @@ -83,7 +83,7 @@ export class MarkerManager { * @returns The cursor for this workspace. */ getCursor(): Cursor | null { - return this.cursor_; + return this.cursor; } /** @@ -104,16 +104,16 @@ export class MarkerManager { * @param cursor The cursor used to move around this workspace. */ setCursor(cursor: Cursor) { - if (this.cursor_ && this.cursor_.getDrawer()) { - this.cursor_.getDrawer().dispose(); + if (this.cursor && this.cursor.getDrawer()) { + this.cursor.getDrawer().dispose(); } - this.cursor_ = cursor; - if (this.cursor_) { + this.cursor = cursor; + if (this.cursor) { const drawer = this.workspace .getRenderer() - .makeMarkerDrawer(this.workspace, this.cursor_); - this.cursor_.setDrawer(drawer); - this.setCursorSvg(this.cursor_.getDrawer().createDom()); + .makeMarkerDrawer(this.workspace, this.cursor); + this.cursor.setDrawer(drawer); + this.setCursorSvg(this.cursor.getDrawer().createDom()); } } @@ -126,12 +126,12 @@ export class MarkerManager { */ setCursorSvg(cursorSvg: SVGElement | null) { if (!cursorSvg) { - this.cursorSvg_ = null; + this.cursorSvg = null; return; } this.workspace.getBlockCanvas()!.appendChild(cursorSvg); - this.cursorSvg_ = cursorSvg; + this.cursorSvg = cursorSvg; } /** @@ -143,15 +143,15 @@ export class MarkerManager { */ setMarkerSvg(markerSvg: SVGElement | null) { if (!markerSvg) { - this.markerSvg_ = null; + this.markerSvg = null; return; } if (this.workspace.getBlockCanvas()) { - if (this.cursorSvg_) { + if (this.cursorSvg) { this.workspace .getBlockCanvas()! - .insertBefore(markerSvg, this.cursorSvg_); + .insertBefore(markerSvg, this.cursorSvg); } else { this.workspace.getBlockCanvas()!.appendChild(markerSvg); } @@ -164,7 +164,7 @@ export class MarkerManager { * @internal */ updateMarkers() { - if (this.workspace.keyboardAccessibilityMode && this.cursorSvg_) { + if (this.workspace.keyboardAccessibilityMode && this.cursorSvg) { this.workspace.getCursor()!.draw(); } } @@ -181,9 +181,9 @@ export class MarkerManager { this.unregisterMarker(markerId); } this.markers.clear(); - if (this.cursor_) { - this.cursor_.dispose(); - this.cursor_ = null; + if (this.cursor) { + this.cursor.dispose(); + this.cursor = null; } } } diff --git a/core/menuitem.ts b/core/menuitem.ts index aad914b6889..e9e7dc0dbca 100644 --- a/core/menuitem.ts +++ b/core/menuitem.ts @@ -41,7 +41,7 @@ export class MenuItem { private highlight = false; /** Bound function to call when this menu item is clicked. */ - private actionHandler: Function | null = null; + private actionHandler: ((obj: this) => void) | null = null; /** * @param content Text caption to display as the content of the item, or a diff --git a/core/observable_procedure_map.ts b/core/observable_procedure_map.ts index e8722bcbf89..2f10107557c 100644 --- a/core/observable_procedure_map.ts +++ b/core/observable_procedure_map.ts @@ -4,9 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {isObservable} from './interfaces/i_observable.js'; import {IProcedureMap} from './interfaces/i_procedure_map.js'; import type {IProcedureModel} from './interfaces/i_procedure_model.js'; -import {isObservable} from './interfaces/i_observable.js'; export class ObservableProcedureMap extends Map diff --git a/core/options.ts b/core/options.ts index 42d2b41de73..539fd3f6f92 100644 --- a/core/options.ts +++ b/core/options.ts @@ -167,7 +167,7 @@ export class Options { this.modalInputs = modalInputs; this.pathToMedia = pathToMedia; this.hasCategories = hasCategories; - this.moveOptions = Options.parseMoveOptions_(options, hasCategories); + this.moveOptions = Options.parseMoveOptions(options, hasCategories); this.hasScrollbars = !!this.moveOptions.scrollbars; this.hasTrashcan = hasTrashcan; this.maxTrashcanContents = maxTrashcanContents; @@ -175,10 +175,10 @@ export class Options { this.hasCss = hasCss; this.horizontalLayout = horizontalLayout; this.languageTree = toolboxJsonDef; - this.gridOptions = Options.parseGridOptions_(options); - this.zoomOptions = Options.parseZoomOptions_(options); + this.gridOptions = Options.parseGridOptions(options); + this.zoomOptions = Options.parseZoomOptions(options); this.toolboxPosition = toolboxPosition; - this.theme = Options.parseThemeOptions_(options); + this.theme = Options.parseThemeOptions(options); this.renderer = renderer; this.rendererOverrides = options['rendererOverrides'] ?? null; @@ -201,7 +201,7 @@ export class Options { * @param hasCategories Whether the workspace has categories or not. * @returns Normalized move options. */ - private static parseMoveOptions_( + private static parseMoveOptions( options: BlocklyOptions, hasCategories: boolean, ): MoveOptions { @@ -260,7 +260,7 @@ export class Options { * @param options Dictionary of options. * @returns Normalized zoom options. */ - private static parseZoomOptions_(options: BlocklyOptions): ZoomOptions { + private static parseZoomOptions(options: BlocklyOptions): ZoomOptions { const zoom = options['zoom'] || {}; const zoomOptions = {} as ZoomOptions; if (zoom['controls'] === undefined) { @@ -309,7 +309,7 @@ export class Options { * @param options Dictionary of options. * @returns Normalized grid options. */ - private static parseGridOptions_(options: BlocklyOptions): GridOptions { + private static parseGridOptions(options: BlocklyOptions): GridOptions { const grid = options['grid'] || {}; const gridOptions = {} as GridOptions; gridOptions.spacing = Number(grid['spacing']) || 0; @@ -327,7 +327,7 @@ export class Options { * @param options Dictionary of options. * @returns A Blockly Theme. */ - private static parseThemeOptions_(options: BlocklyOptions): Theme { + private static parseThemeOptions(options: BlocklyOptions): Theme { const theme = options['theme'] || Classic; if (typeof theme === 'string') { return registry.getObject(registry.Type.THEME, theme) as Theme; diff --git a/core/procedures.ts b/core/procedures.ts index 680abb8afd2..a16b0fce44a 100644 --- a/core/procedures.ts +++ b/core/procedures.ts @@ -15,29 +15,37 @@ import {Blocks} from './blocks.js'; import * as common from './common.js'; import type {Abstract} from './events/events_abstract.js'; import type {BubbleOpen} from './events/events_bubble_open.js'; +import { + isBlockChange, + isBlockCreate, + isBlockDelete, + isBlockFieldIntermediateChange, + isBubbleOpen, +} from './events/predicates.js'; +import {EventType} from './events/type.js'; import * as eventUtils from './events/utils.js'; import {Field, UnattachedFieldError} from './field.js'; -import {Msg} from './msg.js'; -import {Names} from './names.js'; -import {IParameterModel} from './interfaces/i_parameter_model.js'; -import {IProcedureMap} from './interfaces/i_procedure_map.js'; -import {IProcedureModel} from './interfaces/i_procedure_model.js'; -import { - IProcedureBlock, - isProcedureBlock, -} from './interfaces/i_procedure_block.js'; +import {MutatorIcon} from './icons.js'; import { isLegacyProcedureCallBlock, isLegacyProcedureDefBlock, ProcedureBlock, ProcedureTuple, } from './interfaces/i_legacy_procedure_blocks.js'; +import {IParameterModel} from './interfaces/i_parameter_model.js'; +import { + IProcedureBlock, + isProcedureBlock, +} from './interfaces/i_procedure_block.js'; +import {IProcedureMap} from './interfaces/i_procedure_map.js'; +import {IProcedureModel} from './interfaces/i_procedure_model.js'; +import {Msg} from './msg.js'; +import {Names} from './names.js'; import {ObservableProcedureMap} from './observable_procedure_map.js'; import * as utilsXml from './utils/xml.js'; import * as Variables from './variables.js'; import type {Workspace} from './workspace.js'; import type {WorkspaceSvg} from './workspace_svg.js'; -import {MutatorIcon} from './icons.js'; /** * String for use in the "custom" attribute of a category in toolbox XML. @@ -354,9 +362,8 @@ function updateMutatorFlyout(workspace: WorkspaceSvg) { * @internal */ export function mutatorOpenListener(e: Abstract) { - if (e.type !== eventUtils.BUBBLE_OPEN) { - return; - } + if (!isBubbleOpen(e)) return; + const bubbleEvent = e as BubbleOpen; if ( !(bubbleEvent.bubbleType === 'mutator' && bubbleEvent.isOpen) || @@ -386,10 +393,10 @@ export function mutatorOpenListener(e: Abstract) { */ function mutatorChangeListener(e: Abstract) { if ( - e.type !== eventUtils.BLOCK_CREATE && - e.type !== eventUtils.BLOCK_DELETE && - e.type !== eventUtils.BLOCK_CHANGE && - e.type !== eventUtils.BLOCK_FIELD_INTERMEDIATE_CHANGE + !isBlockCreate(e) && + !isBlockDelete(e) && + !isBlockChange(e) && + !isBlockFieldIntermediateChange(e) ) { return; } @@ -454,7 +461,7 @@ export function mutateCallers(defBlock: Block) { // definition mutation. eventUtils.setRecordUndo(false); eventUtils.fire( - new (eventUtils.get(eventUtils.BLOCK_CHANGE))( + new (eventUtils.get(EventType.BLOCK_CHANGE))( caller, 'mutation', null, @@ -500,11 +507,11 @@ export function getDefinition( } export { - ObservableProcedureMap, IParameterModel, IProcedureBlock, - isProcedureBlock, IProcedureMap, IProcedureModel, + isProcedureBlock, + ObservableProcedureMap, ProcedureTuple, }; diff --git a/core/registry.ts b/core/registry.ts index d46c36f4819..60e8049797c 100644 --- a/core/registry.ts +++ b/core/registry.ts @@ -8,11 +8,15 @@ import type {Abstract} from './events/events_abstract.js'; import type {Field} from './field.js'; +import type {Input} from './inputs/input.js'; import type {IConnectionChecker} from './interfaces/i_connection_checker.js'; +import type {IConnectionPreviewer} from './interfaces/i_connection_previewer.js'; +import type {ICopyData, ICopyable} from './interfaces/i_copyable.js'; +import type {IDragger} from './interfaces/i_dragger.js'; import type {IFlyout} from './interfaces/i_flyout.js'; -import type {IMetricsManager} from './interfaces/i_metrics_manager.js'; import type {IIcon} from './interfaces/i_icon.js'; -import type {Input} from './inputs/input.js'; +import type {IMetricsManager} from './interfaces/i_metrics_manager.js'; +import type {IPaster} from './interfaces/i_paster.js'; import type {ISerializer} from './interfaces/i_serializer.js'; import type {IToolbox} from './interfaces/i_toolbox.js'; import type {Cursor} from './keyboard_nav/cursor.js'; @@ -20,10 +24,6 @@ import type {Options} from './options.js'; import type {Renderer} from './renderers/common/renderer.js'; import type {Theme} from './theme.js'; import type {ToolboxItem} from './toolbox/toolbox_item.js'; -import type {IPaster} from './interfaces/i_paster.js'; -import type {ICopyData, ICopyable} from './interfaces/i_copyable.js'; -import type {IConnectionPreviewer} from './interfaces/i_connection_previewer.js'; -import type {IDragger} from './interfaces/i_dragger.js'; /** * A map of maps. With the keys being the type and name of the class we are @@ -193,7 +193,7 @@ export function register( * @param registryItem A class or object that we are checking for the required * properties. */ -function validate(type: string, registryItem: Function | AnyDuringMigration) { +function validate(type: string, registryItem: AnyDuringMigration) { switch (type) { case String(Type.FIELD): if (typeof registryItem.fromJson !== 'function') { diff --git a/core/render_management.ts b/core/render_management.ts index 3e84efead24..c3fe2e342ba 100644 --- a/core/render_management.ts +++ b/core/render_management.ts @@ -5,8 +5,8 @@ */ import {BlockSvg} from './block_svg.js'; -import * as userAgent from './utils/useragent.js'; import * as eventUtils from './events/utils.js'; +import * as userAgent from './utils/useragent.js'; import type {WorkspaceSvg} from './workspace_svg.js'; /** The set of all blocks in need of rendering which don't have parents. */ diff --git a/core/rendered_connection.ts b/core/rendered_connection.ts index 5aa6f7f7588..f73dc0628cc 100644 --- a/core/rendered_connection.ts +++ b/core/rendered_connection.ts @@ -117,59 +117,85 @@ export class RenderedConnection extends Connection { * Move the block(s) belonging to the connection to a point where they don't * visually interfere with the specified connection. * - * @param staticConnection The connection to move away from. + * @param superiorConnection The connection to move away from. The provided + * connection should be the superior connection and should not be + * connected to this connection. + * @param initiatedByThis Whether or not the block group that was manipulated + * recently causing bump checks is associated with the inferior + * connection. Defaults to false. * @internal */ - bumpAwayFrom(staticConnection: RenderedConnection) { + bumpAwayFrom( + superiorConnection: RenderedConnection, + initiatedByThis = false, + ) { if (this.sourceBlock_.workspace.isDragging()) { // Don't move blocks around while the user is doing the same. return; } - // Move the root block. - let rootBlock = this.sourceBlock_.getRootBlock(); - if (rootBlock.isInFlyout) { + let offsetX = + config.snapRadius + Math.floor(Math.random() * BUMP_RANDOMNESS); + let offsetY = + config.snapRadius + Math.floor(Math.random() * BUMP_RANDOMNESS); + /* eslint-disable-next-line @typescript-eslint/no-this-alias */ + const inferiorConnection = this; + const superiorRootBlock = superiorConnection.sourceBlock_.getRootBlock(); + const inferiorRootBlock = inferiorConnection.sourceBlock_.getRootBlock(); + + if (superiorRootBlock.isInFlyout || inferiorRootBlock.isInFlyout) { // Don't move blocks around in a flyout. return; } - let reverse = false; - if (!rootBlock.isMovable()) { - // Can't bump an uneditable block away. + let moveInferior = true; + if (!inferiorRootBlock.isMovable()) { + // Can't bump an immovable block away. // Check to see if the other block is movable. - rootBlock = staticConnection.getSourceBlock().getRootBlock(); - if (!rootBlock.isMovable()) { + if (!superiorRootBlock.isMovable()) { + // Neither block is movable, abort operation. return; + } else { + // Only the superior block group is movable. + moveInferior = false; + // The superior block group moves in the opposite direction. + offsetX = -offsetX; + offsetY = -offsetY; + } + } else if (superiorRootBlock.isMovable()) { + // Both block groups are movable. The one on the inferior side will be + // moved to make space for the superior one. However, it's possible that + // both groups of blocks have an inferior connection that bumps into a + // superior connection on the other group, which could result in both + // groups moving in the same direction and eventually bumping each other + // again. It would be better if one group of blocks could consistently + // move in an orthogonal direction from the other, so that they become + // separated in the end. We can designate one group the "initiator" if + // it's the one that was most recently manipulated, causing inputs to be + // checked for bumpable neighbors. As a useful heuristic, in the case + // where the inferior connection belongs to the initiator group, moving it + // in the orthogonal direction will separate the blocks better. + if (initiatedByThis) { + offsetY = -offsetY; } - // Swap the connections and move the 'static' connection instead. - /* eslint-disable-next-line @typescript-eslint/no-this-alias */ - staticConnection = this; - reverse = true; } + const staticConnection = moveInferior + ? superiorConnection + : inferiorConnection; + const dynamicConnection = moveInferior + ? inferiorConnection + : superiorConnection; + const dynamicRootBlock = moveInferior + ? inferiorRootBlock + : superiorRootBlock; // Raise it to the top for extra visibility. - const selected = common.getSelected() == rootBlock; - selected || rootBlock.addSelect(); - let dx = - staticConnection.x + - config.snapRadius + - Math.floor(Math.random() * BUMP_RANDOMNESS) - - this.x; - let dy = - staticConnection.y + - config.snapRadius + - Math.floor(Math.random() * BUMP_RANDOMNESS) - - this.y; - if (reverse) { - // When reversing a bump due to an uneditable block, bump up. - dy = -dy; - } - if (rootBlock.RTL) { - dx = - staticConnection.x - - config.snapRadius - - Math.floor(Math.random() * BUMP_RANDOMNESS) - - this.x; + const selected = common.getSelected() === dynamicRootBlock; + if (!selected) dynamicRootBlock.addSelect(); + if (dynamicRootBlock.RTL) { + offsetX = -offsetX; } - rootBlock.moveBy(dx, dy, ['bump']); - selected || rootBlock.removeSelect(); + const dx = staticConnection.x + offsetX - dynamicConnection.x; + const dy = staticConnection.y + offsetY - dynamicConnection.y; + dynamicRootBlock.moveBy(dx, dy, ['bump']); + if (!selected) dynamicRootBlock.removeSelect(); } /** @@ -389,9 +415,10 @@ export class RenderedConnection extends Connection { if (block.isCollapsed()) { // This block should only be partially revealed since it is collapsed. connections = []; - block.outputConnection && connections.push(block.outputConnection); - block.nextConnection && connections.push(block.nextConnection); - block.previousConnection && connections.push(block.previousConnection); + if (block.outputConnection) connections.push(block.outputConnection); + if (block.nextConnection) connections.push(block.nextConnection); + if (block.previousConnection) + connections.push(block.previousConnection); } else { // Show all connections of this block. connections = block.getConnections_(true); @@ -412,11 +439,11 @@ export class RenderedConnection extends Connection { * Bumps this connection away from the other connection. Called when an * attempted connection fails. * - * @param otherConnection Connection that this connection failed to connect - * to. + * @param superiorConnection Connection that this connection failed to connect + * to. The provided connection should be the superior connection. * @internal */ - override onFailedConnect(otherConnection: Connection) { + override onFailedConnect(superiorConnection: Connection) { const block = this.getSourceBlock(); if (eventUtils.getRecordUndo()) { const group = eventUtils.getGroup(); @@ -424,7 +451,7 @@ export class RenderedConnection extends Connection { function (this: RenderedConnection) { if (!block.isDisposed() && !block.getParent()) { eventUtils.setGroup(group); - this.bumpAwayFrom(otherConnection as RenderedConnection); + this.bumpAwayFrom(superiorConnection as RenderedConnection); eventUtils.setGroup(false); } }.bind(this), diff --git a/core/renderers/common/block_rendering.ts b/core/renderers/common/block_rendering.ts index 7c87a892873..27fbbd538c7 100644 --- a/core/renderers/common/block_rendering.ts +++ b/core/renderers/common/block_rendering.ts @@ -30,7 +30,6 @@ import {SquareCorner} from '../measurables/square_corner.js'; import {StatementInput} from '../measurables/statement_input.js'; import {TopRow} from '../measurables/top_row.js'; import {Types} from '../measurables/types.js'; - import {Drawer} from './drawer.js'; import type {IPathObject} from './i_path_object.js'; import {RenderInfo} from './info.js'; @@ -45,7 +44,10 @@ import {Renderer} from './renderer.js'; * @param rendererClass The new renderer class to register. * @throws {Error} if a renderer with the same name has already been registered. */ -export function register(name: string, rendererClass: Function) { +export function register( + name: string, + rendererClass: new (name: string) => Renderer, +) { registry.register(registry.Type.RENDERER, name, rendererClass); } @@ -78,43 +80,45 @@ export function init( renderer.init(theme, opt_rendererOverrides); return renderer; } -export {BottomRow}; -export {Connection}; -export {Drawer}; -export {ExternalValueInput}; -export {Field}; -export {Hat}; -export {Icon}; -export {InRowSpacer}; -export {InlineInput}; -export {InputConnection}; -export {InputRow}; -export {IPathObject}; -export {JaggedEdge}; -export {MarkerSvg}; -export {Measurable}; -export {NextConnection}; -export {OutputConnection}; -export {PathObject}; -export {PreviousConnection}; -export {Renderer}; -export {RenderInfo}; -export {RoundCorner}; -export {Row}; -export {SpacerRow}; -export {SquareCorner}; -export {StatementInput}; -export {TopRow}; -export {Types}; +export { + BottomRow, + Connection, + Drawer, + ExternalValueInput, + Field, + Hat, + Icon, + InlineInput, + InputConnection, + InputRow, + InRowSpacer, + IPathObject, + JaggedEdge, + MarkerSvg, + Measurable, + NextConnection, + OutputConnection, + PathObject, + PreviousConnection, + Renderer, + RenderInfo, + RoundCorner, + Row, + SpacerRow, + SquareCorner, + StatementInput, + TopRow, + Types, +}; export { - OutsideCorners, + BaseShape, + ConstantProvider, + DynamicShape, InsideCorners, - StartHat, + JaggedTeeth, Notch, + OutsideCorners, PuzzleTab, - JaggedTeeth, - BaseShape, - DynamicShape, - ConstantProvider, + StartHat, } from './constants.js'; diff --git a/core/renderers/common/drawer.ts b/core/renderers/common/drawer.ts index 5ded620b799..59a856011f2 100644 --- a/core/renderers/common/drawer.ts +++ b/core/renderers/common/drawer.ts @@ -7,6 +7,7 @@ // Former goog.module ID: Blockly.blockRendering.Drawer import type {BlockSvg} from '../../block_svg.js'; +import {ConnectionType} from '../../connection_type.js'; import {Coordinate} from '../../utils.js'; import * as svgPaths from '../../utils/svg_paths.js'; import {Connection} from '../measurables/connection.js'; @@ -17,11 +18,9 @@ import type {InlineInput} from '../measurables/inline_input.js'; import type {PreviousConnection} from '../measurables/previous_connection.js'; import type {Row} from '../measurables/row.js'; import {Types} from '../measurables/types.js'; - -import {isDynamicShape, isNotch, isPuzzleTab} from './constants.js'; import type {ConstantProvider, Notch, PuzzleTab} from './constants.js'; +import {isDynamicShape, isNotch, isPuzzleTab} from './constants.js'; import type {RenderInfo} from './info.js'; -import {ConnectionType} from '../../connection_type.js'; /** * An object that draws a block based on the given rendering information. @@ -80,6 +79,7 @@ export class Drawer { // The dark path adds to the size of the block in both X and Y. this.block_.height = this.info_.height; this.block_.width = this.info_.widthWithChildren; + this.block_.childlessWidth = this.info_.width; } /** Create the outline of the block. This is a single continuous path. */ diff --git a/core/renderers/common/i_path_object.ts b/core/renderers/common/i_path_object.ts index 30033f18e81..3a78035e156 100644 --- a/core/renderers/common/i_path_object.ts +++ b/core/renderers/common/i_path_object.ts @@ -6,11 +6,11 @@ // Former goog.module ID: Blockly.blockRendering.IPathObject -import type {BlockStyle} from '../../theme.js'; import type {BlockSvg} from '../../block_svg.js'; -import type {ConstantProvider} from './constants.js'; import type {RenderedConnection} from '../../rendered_connection.js'; +import type {BlockStyle} from '../../theme.js'; import type {Coordinate} from '../../utils/coordinate.js'; +import type {ConstantProvider} from './constants.js'; /** * An interface for a block's path object. diff --git a/core/renderers/common/info.ts b/core/renderers/common/info.ts index 995124c1b21..ff073ace48b 100644 --- a/core/renderers/common/info.ts +++ b/core/renderers/common/info.ts @@ -7,13 +7,16 @@ // Former goog.module ID: Blockly.blockRendering.RenderInfo import type {BlockSvg} from '../../block_svg.js'; -import {Input} from '../../inputs/input.js'; import {Align} from '../../inputs/align.js'; +import {DummyInput} from '../../inputs/dummy_input.js'; +import {EndRowInput} from '../../inputs/end_row_input.js'; +import {Input} from '../../inputs/input.js'; +import {StatementInput} from '../../inputs/statement_input.js'; +import {ValueInput} from '../../inputs/value_input.js'; import type {RenderedConnection} from '../../rendered_connection.js'; import type {Measurable} from '../measurables/base.js'; import {BottomRow} from '../measurables/bottom_row.js'; -import {DummyInput} from '../../inputs/dummy_input.js'; -import {EndRowInput} from '../../inputs/end_row_input.js'; +import {Connection} from '../measurables/connection.js'; import {ExternalValueInput} from '../measurables/external_value_input.js'; import {Field} from '../measurables/field.js'; import {Hat} from '../measurables/hat.js'; @@ -30,14 +33,10 @@ import type {Row} from '../measurables/row.js'; import {SpacerRow} from '../measurables/spacer_row.js'; import {SquareCorner} from '../measurables/square_corner.js'; import {StatementInput as StatementInputMeasurable} from '../measurables/statement_input.js'; -import {StatementInput} from '../../inputs/statement_input.js'; import {TopRow} from '../measurables/top_row.js'; import {Types} from '../measurables/types.js'; -import {ValueInput} from '../../inputs/value_input.js'; - import type {ConstantProvider} from './constants.js'; import type {Renderer} from './renderer.js'; -import {Connection} from '../measurables/connection.js'; /** * An object containing all sizing information needed to draw this block. diff --git a/core/renderers/common/marker_svg.ts b/core/renderers/common/marker_svg.ts index 995783576ef..057324f0346 100644 --- a/core/renderers/common/marker_svg.ts +++ b/core/renderers/common/marker_svg.ts @@ -12,8 +12,10 @@ import '../../events/events_marker_move.js'; import type {BlockSvg} from '../../block_svg.js'; import type {Connection} from '../../connection.js'; import {ConnectionType} from '../../connection_type.js'; +import {EventType} from '../../events/type.js'; import * as eventUtils from '../../events/utils.js'; import type {Field} from '../../field.js'; +import {FlyoutButton} from '../../flyout_button.js'; import type {IASTNodeLocationSvg} from '../../interfaces/i_ast_node_location_svg.js'; import {ASTNode} from '../../keyboard_nav/ast_node.js'; import type {Marker} from '../../keyboard_nav/marker.js'; @@ -22,9 +24,7 @@ import * as dom from '../../utils/dom.js'; import {Svg} from '../../utils/svg.js'; import * as svgPaths from '../../utils/svg_paths.js'; import type {WorkspaceSvg} from '../../workspace_svg.js'; - import type {ConstantProvider, Notch, PuzzleTab} from './constants.js'; -import {FlyoutButton} from '../../flyout_button.js'; /** The name of the CSS class for a cursor. */ const CURSOR_CLASS = 'blocklyCursor'; @@ -47,7 +47,7 @@ export class MarkerSvg { * The workspace, field, or block that the marker SVG element should be * attached to. */ - private parent: IASTNodeLocationSvg | null = null; + protected parent: IASTNodeLocationSvg | null = null; /** The current SVG element for the marker. */ currentMarkerSvg: SVGElement | null = null; @@ -73,9 +73,9 @@ export class MarkerSvg { * @param marker The marker to draw. */ constructor( - private readonly workspace: WorkspaceSvg, + protected readonly workspace: WorkspaceSvg, constants: ConstantProvider, - private readonly marker: Marker, + protected readonly marker: Marker, ) { this.constants_ = constants; @@ -176,9 +176,11 @@ export class MarkerSvg { // Ensures the marker will be visible immediately after the move. const animate = this.currentMarkerSvg!.childNodes[0]; - if (animate !== undefined) { - (animate as SVGAnimationElement).beginElement && - (animate as SVGAnimationElement).beginElement(); + if ( + animate !== undefined && + (animate as SVGAnimationElement).beginElement + ) { + (animate as SVGAnimationElement).beginElement(); } } @@ -221,7 +223,7 @@ export class MarkerSvg { * * @param curNode The node to draw the marker for. */ - private showWithBlockPrevOutput(curNode: ASTNode) { + protected showWithBlockPrevOutput(curNode: ASTNode) { const block = curNode.getSourceBlock() as BlockSvg; const width = block.width; const height = block.height; @@ -618,9 +620,9 @@ export class MarkerSvg { * @param oldNode The old node the marker used to be on. * @param curNode The new node the marker is currently on. */ - private fireMarkerEvent(oldNode: ASTNode, curNode: ASTNode) { + protected fireMarkerEvent(oldNode: ASTNode, curNode: ASTNode) { const curBlock = curNode.getSourceBlock(); - const event = new (eventUtils.get(eventUtils.MARKER_MOVE))( + const event = new (eventUtils.get(EventType.MARKER_MOVE))( curBlock, this.isCursor(), oldNode, diff --git a/core/renderers/common/path_object.ts b/core/renderers/common/path_object.ts index d5c0850a1b8..0f46cf3a423 100644 --- a/core/renderers/common/path_object.ts +++ b/core/renderers/common/path_object.ts @@ -13,7 +13,6 @@ import type {BlockStyle} from '../../theme.js'; import {Coordinate} from '../../utils/coordinate.js'; import * as dom from '../../utils/dom.js'; import {Svg} from '../../utils/svg.js'; - import type {ConstantProvider} from './constants.js'; import type {IPathObject} from './i_path_object.js'; diff --git a/core/renderers/common/renderer.ts b/core/renderers/common/renderer.ts index 15a958db463..d3bff56a702 100644 --- a/core/renderers/common/renderer.ts +++ b/core/renderers/common/renderer.ts @@ -18,15 +18,14 @@ import type {IRegistrable} from '../../interfaces/i_registrable.js'; import type {Marker} from '../../keyboard_nav/marker.js'; import type {RenderedConnection} from '../../rendered_connection.js'; import type {BlockStyle, Theme} from '../../theme.js'; +import * as deprecation from '../../utils/deprecation.js'; import type {WorkspaceSvg} from '../../workspace_svg.js'; - import {ConstantProvider} from './constants.js'; import {Drawer} from './drawer.js'; import type {IPathObject} from './i_path_object.js'; import {RenderInfo} from './info.js'; import {MarkerSvg} from './marker_svg.js'; import {PathObject} from './path_object.js'; -import * as deprecation from '../../utils/deprecation.js'; /** * The base class for a block renderer. diff --git a/core/renderers/geras/constants.ts b/core/renderers/geras/constants.ts index fc0b7ae7934..6d0c3dfbf34 100644 --- a/core/renderers/geras/constants.ts +++ b/core/renderers/geras/constants.ts @@ -31,16 +31,12 @@ export class ConstantProvider extends BaseConstantProvider { override getCSS_(selector: string) { return super.getCSS_(selector).concat([ - /* eslint-disable indent */ - /* clang-format off */ // Insertion marker. `${selector} .blocklyInsertionMarker>.blocklyPathLight,`, `${selector} .blocklyInsertionMarker>.blocklyPathDark {`, `fill-opacity: ${this.INSERTION_MARKER_OPACITY};`, `stroke: none;`, '}', - /* clang-format on */ - /* eslint-enable indent */ ]); } } diff --git a/core/renderers/geras/drawer.ts b/core/renderers/geras/drawer.ts index 29bcbfab433..542b21ff93b 100644 --- a/core/renderers/geras/drawer.ts +++ b/core/renderers/geras/drawer.ts @@ -10,7 +10,6 @@ import type {BlockSvg} from '../../block_svg.js'; import * as svgPaths from '../../utils/svg_paths.js'; import {Drawer as BaseDrawer} from '../common/drawer.js'; import type {Row} from '../measurables/row.js'; - import type {ConstantProvider} from './constants.js'; import {Highlighter} from './highlighter.js'; import type {RenderInfo} from './info.js'; diff --git a/core/renderers/geras/highlighter.ts b/core/renderers/geras/highlighter.ts index 664e74fb888..efcb4e2df03 100644 --- a/core/renderers/geras/highlighter.ts +++ b/core/renderers/geras/highlighter.ts @@ -13,7 +13,6 @@ import type {Row} from '../measurables/row.js'; import {SpacerRow} from '../measurables/spacer_row.js'; import type {TopRow} from '../measurables/top_row.js'; import {Types} from '../measurables/types.js'; - import type { HighlightConstantProvider, InsideCorner, diff --git a/core/renderers/geras/info.ts b/core/renderers/geras/info.ts index 6565f226b53..b9cc1c59c8c 100644 --- a/core/renderers/geras/info.ts +++ b/core/renderers/geras/info.ts @@ -7,22 +7,21 @@ // Former goog.module ID: Blockly.geras.RenderInfo import type {BlockSvg} from '../../block_svg.js'; +import {DummyInput} from '../../inputs/dummy_input.js'; +import {EndRowInput} from '../../inputs/end_row_input.js'; import type {Input} from '../../inputs/input.js'; +import {StatementInput} from '../../inputs/statement_input.js'; +import {ValueInput} from '../../inputs/value_input.js'; import {RenderInfo as BaseRenderInfo} from '../common/info.js'; import type {Measurable} from '../measurables/base.js'; import type {BottomRow} from '../measurables/bottom_row.js'; -import {DummyInput} from '../../inputs/dummy_input.js'; -import {EndRowInput} from '../../inputs/end_row_input.js'; import {ExternalValueInput} from '../measurables/external_value_input.js'; import type {Field} from '../measurables/field.js'; import {InRowSpacer} from '../measurables/in_row_spacer.js'; import type {InputRow} from '../measurables/input_row.js'; import type {Row} from '../measurables/row.js'; -import {StatementInput} from '../../inputs/statement_input.js'; import type {TopRow} from '../measurables/top_row.js'; import {Types} from '../measurables/types.js'; -import {ValueInput} from '../../inputs/value_input.js'; - import type {ConstantProvider} from './constants.js'; import {InlineInput} from './measurables/inline_input.js'; import {StatementInput as StatementInputMeasurable} from './measurables/statement_input.js'; diff --git a/core/renderers/geras/measurables/inline_input.ts b/core/renderers/geras/measurables/inline_input.ts index 9ed85ad5253..931b9e76262 100644 --- a/core/renderers/geras/measurables/inline_input.ts +++ b/core/renderers/geras/measurables/inline_input.ts @@ -6,7 +6,6 @@ // Former goog.module ID: Blockly.geras.InlineInput -/* eslint-disable-next-line no-unused-vars */ import type {Input} from '../../../inputs/input.js'; import type {ConstantProvider as BaseConstantProvider} from '../../../renderers/common/constants.js'; import {InlineInput as BaseInlineInput} from '../../../renderers/measurables/inline_input.js'; diff --git a/core/renderers/geras/measurables/statement_input.ts b/core/renderers/geras/measurables/statement_input.ts index 5ce3f854a45..c6eba8dc024 100644 --- a/core/renderers/geras/measurables/statement_input.ts +++ b/core/renderers/geras/measurables/statement_input.ts @@ -6,7 +6,6 @@ // Former goog.module ID: Blockly.geras.StatementInput -/* eslint-disable-next-line no-unused-vars */ import type {Input} from '../../../inputs/input.js'; import type {ConstantProvider as BaseConstantProvider} from '../../../renderers/common/constants.js'; import {StatementInput as BaseStatementInput} from '../../../renderers/measurables/statement_input.js'; diff --git a/core/renderers/geras/path_object.ts b/core/renderers/geras/path_object.ts index 6b058e5a752..c1d689535af 100644 --- a/core/renderers/geras/path_object.ts +++ b/core/renderers/geras/path_object.ts @@ -12,7 +12,6 @@ import * as colour from '../../utils/colour.js'; import * as dom from '../../utils/dom.js'; import {Svg} from '../../utils/svg.js'; import {PathObject as BasePathObject} from '../common/path_object.js'; - import type {ConstantProvider} from './constants.js'; /** diff --git a/core/renderers/geras/renderer.ts b/core/renderers/geras/renderer.ts index 06062e9bc30..aba8fc3eab1 100644 --- a/core/renderers/geras/renderer.ts +++ b/core/renderers/geras/renderer.ts @@ -11,7 +11,6 @@ import type {BlockStyle, Theme} from '../../theme.js'; import * as blockRendering from '../common/block_rendering.js'; import type {RenderInfo as BaseRenderInfo} from '../common/info.js'; import {Renderer as BaseRenderer} from '../common/renderer.js'; - import {ConstantProvider} from './constants.js'; import {Drawer} from './drawer.js'; import {HighlightConstantProvider} from './highlight_constants.js'; diff --git a/core/renderers/measurables/base.ts b/core/renderers/measurables/base.ts index e429a3a3ef5..15f4f36837e 100644 --- a/core/renderers/measurables/base.ts +++ b/core/renderers/measurables/base.ts @@ -7,7 +7,6 @@ // Former goog.module ID: Blockly.blockRendering.Measurable import type {ConstantProvider} from '../common/constants.js'; - import {Types} from './types.js'; /** diff --git a/core/renderers/measurables/bottom_row.ts b/core/renderers/measurables/bottom_row.ts index 66cbbd34ecd..2506610e7eb 100644 --- a/core/renderers/measurables/bottom_row.ts +++ b/core/renderers/measurables/bottom_row.ts @@ -8,7 +8,6 @@ import type {BlockSvg} from '../../block_svg.js'; import type {ConstantProvider} from '../common/constants.js'; - import type {NextConnection} from './next_connection.js'; import {Row} from './row.js'; import {Types} from './types.js'; diff --git a/core/renderers/measurables/connection.ts b/core/renderers/measurables/connection.ts index 5744eaab448..c5a3e4ce0d2 100644 --- a/core/renderers/measurables/connection.ts +++ b/core/renderers/measurables/connection.ts @@ -6,10 +6,8 @@ // Former goog.module ID: Blockly.blockRendering.Connection -/* eslint-disable-next-line no-unused-vars */ import type {RenderedConnection} from '../../rendered_connection.js'; import type {ConstantProvider, Shape} from '../common/constants.js'; - import {Measurable} from './base.js'; import {Types} from './types.js'; diff --git a/core/renderers/measurables/external_value_input.ts b/core/renderers/measurables/external_value_input.ts index 9b9dac15f80..4dea7541336 100644 --- a/core/renderers/measurables/external_value_input.ts +++ b/core/renderers/measurables/external_value_input.ts @@ -6,10 +6,8 @@ // Former goog.module ID: Blockly.blockRendering.ExternalValueInput -/* eslint-disable-next-line no-unused-vars */ import type {Input} from '../../inputs/input.js'; import type {ConstantProvider} from '../common/constants.js'; - import {InputConnection} from './input_connection.js'; import {Types} from './types.js'; diff --git a/core/renderers/measurables/field.ts b/core/renderers/measurables/field.ts index 8d6c4d60b75..2c080d2e39d 100644 --- a/core/renderers/measurables/field.ts +++ b/core/renderers/measurables/field.ts @@ -6,11 +6,9 @@ // Former goog.module ID: Blockly.blockRendering.Field -/* eslint-disable-next-line no-unused-vars */ import type {Field as BlocklyField} from '../../field.js'; import type {Input} from '../../inputs/input.js'; import type {ConstantProvider} from '../common/constants.js'; - import {Measurable} from './base.js'; import {Types} from './types.js'; diff --git a/core/renderers/measurables/hat.ts b/core/renderers/measurables/hat.ts index 2a0a5058652..477a2095b93 100644 --- a/core/renderers/measurables/hat.ts +++ b/core/renderers/measurables/hat.ts @@ -7,7 +7,6 @@ // Former goog.module ID: Blockly.blockRendering.Hat import type {ConstantProvider} from '../common/constants.js'; - import {Measurable} from './base.js'; import {Types} from './types.js'; diff --git a/core/renderers/measurables/icon.ts b/core/renderers/measurables/icon.ts index 98e3f722d00..424cc67bee8 100644 --- a/core/renderers/measurables/icon.ts +++ b/core/renderers/measurables/icon.ts @@ -6,10 +6,8 @@ // Former goog.module ID: Blockly.blockRendering.Icon -/* eslint-disable-next-line no-unused-vars */ import type {IIcon as BlocklyIcon} from '../../interfaces/i_icon.js'; import type {ConstantProvider} from '../common/constants.js'; - import {Measurable} from './base.js'; import {Types} from './types.js'; diff --git a/core/renderers/measurables/in_row_spacer.ts b/core/renderers/measurables/in_row_spacer.ts index 19b9efa67e2..ec64e71a23a 100644 --- a/core/renderers/measurables/in_row_spacer.ts +++ b/core/renderers/measurables/in_row_spacer.ts @@ -7,7 +7,6 @@ // Former goog.module ID: Blockly.blockRendering.InRowSpacer import type {ConstantProvider} from '../common/constants.js'; - import {Measurable} from './base.js'; import {Types} from './types.js'; diff --git a/core/renderers/measurables/inline_input.ts b/core/renderers/measurables/inline_input.ts index 9738ddfc24e..307daef8d56 100644 --- a/core/renderers/measurables/inline_input.ts +++ b/core/renderers/measurables/inline_input.ts @@ -6,10 +6,8 @@ // Former goog.module ID: Blockly.blockRendering.InlineInput -/* eslint-disable-next-line no-unused-vars */ import type {Input} from '../../inputs/input.js'; import type {ConstantProvider} from '../common/constants.js'; - import {InputConnection} from './input_connection.js'; import {Types} from './types.js'; diff --git a/core/renderers/measurables/input_connection.ts b/core/renderers/measurables/input_connection.ts index 69ac82d2172..e4e265b4edd 100644 --- a/core/renderers/measurables/input_connection.ts +++ b/core/renderers/measurables/input_connection.ts @@ -10,7 +10,6 @@ import type {BlockSvg} from '../../block_svg.js'; import type {Input} from '../../inputs/input.js'; import type {RenderedConnection} from '../../rendered_connection.js'; import type {ConstantProvider} from '../common/constants.js'; - import {Connection} from './connection.js'; import {Types} from './types.js'; diff --git a/core/renderers/measurables/input_row.ts b/core/renderers/measurables/input_row.ts index 229975cfe98..a9924246f38 100644 --- a/core/renderers/measurables/input_row.ts +++ b/core/renderers/measurables/input_row.ts @@ -7,7 +7,6 @@ // Former goog.module ID: Blockly.blockRendering.InputRow import type {ConstantProvider} from '../common/constants.js'; - import {ExternalValueInput} from './external_value_input.js'; import {InputConnection} from './input_connection.js'; import {Row} from './row.js'; diff --git a/core/renderers/measurables/jagged_edge.ts b/core/renderers/measurables/jagged_edge.ts index a7711dc283b..daca2512118 100644 --- a/core/renderers/measurables/jagged_edge.ts +++ b/core/renderers/measurables/jagged_edge.ts @@ -7,7 +7,6 @@ // Former goog.module ID: Blockly.blockRendering.JaggedEdge import type {ConstantProvider} from '../common/constants.js'; - import {Measurable} from './base.js'; import {Types} from './types.js'; diff --git a/core/renderers/measurables/next_connection.ts b/core/renderers/measurables/next_connection.ts index 50ac75ad25a..ea22001ed53 100644 --- a/core/renderers/measurables/next_connection.ts +++ b/core/renderers/measurables/next_connection.ts @@ -8,7 +8,6 @@ import type {RenderedConnection} from '../../rendered_connection.js'; import type {ConstantProvider} from '../common/constants.js'; - import {Connection} from './connection.js'; import {Types} from './types.js'; diff --git a/core/renderers/measurables/output_connection.ts b/core/renderers/measurables/output_connection.ts index 4a3f995f415..1fa07494945 100644 --- a/core/renderers/measurables/output_connection.ts +++ b/core/renderers/measurables/output_connection.ts @@ -8,7 +8,6 @@ import type {RenderedConnection} from '../../rendered_connection.js'; import type {ConstantProvider} from '../common/constants.js'; - import {Connection} from './connection.js'; import {Types} from './types.js'; diff --git a/core/renderers/measurables/previous_connection.ts b/core/renderers/measurables/previous_connection.ts index 44ebeebfaa5..1314eb6a45d 100644 --- a/core/renderers/measurables/previous_connection.ts +++ b/core/renderers/measurables/previous_connection.ts @@ -8,7 +8,6 @@ import type {RenderedConnection} from '../../rendered_connection.js'; import type {ConstantProvider} from '../common/constants.js'; - import {Connection} from './connection.js'; import {Types} from './types.js'; diff --git a/core/renderers/measurables/round_corner.ts b/core/renderers/measurables/round_corner.ts index 37fc0fb988d..60bbed70784 100644 --- a/core/renderers/measurables/round_corner.ts +++ b/core/renderers/measurables/round_corner.ts @@ -7,7 +7,6 @@ // Former goog.module ID: Blockly.blockRendering.RoundCorner import type {ConstantProvider} from '../common/constants.js'; - import {Measurable} from './base.js'; import {Types} from './types.js'; diff --git a/core/renderers/measurables/row.ts b/core/renderers/measurables/row.ts index 4208c84b775..613ec6ace74 100644 --- a/core/renderers/measurables/row.ts +++ b/core/renderers/measurables/row.ts @@ -7,7 +7,6 @@ // Former goog.module ID: Blockly.blockRendering.Row import type {ConstantProvider} from '../common/constants.js'; - import type {Measurable} from './base.js'; import type {InRowSpacer} from './in_row_spacer.js'; import type {InputConnection} from './input_connection.js'; diff --git a/core/renderers/measurables/spacer_row.ts b/core/renderers/measurables/spacer_row.ts index 6fae98d877d..0e49d30883d 100644 --- a/core/renderers/measurables/spacer_row.ts +++ b/core/renderers/measurables/spacer_row.ts @@ -7,7 +7,6 @@ // Former goog.module ID: Blockly.blockRendering.SpacerRow import type {ConstantProvider} from '../common/constants.js'; - import {InRowSpacer} from './in_row_spacer.js'; import {Row} from './row.js'; import {Types} from './types.js'; diff --git a/core/renderers/measurables/square_corner.ts b/core/renderers/measurables/square_corner.ts index 560f37b65fc..29749ac057d 100644 --- a/core/renderers/measurables/square_corner.ts +++ b/core/renderers/measurables/square_corner.ts @@ -7,7 +7,6 @@ // Former goog.module ID: Blockly.blockRendering.SquareCorner import type {ConstantProvider} from '../common/constants.js'; - import {Measurable} from './base.js'; import {Types} from './types.js'; diff --git a/core/renderers/measurables/statement_input.ts b/core/renderers/measurables/statement_input.ts index cdc7c6680de..91fe5b64a45 100644 --- a/core/renderers/measurables/statement_input.ts +++ b/core/renderers/measurables/statement_input.ts @@ -6,10 +6,8 @@ // Former goog.module ID: Blockly.blockRendering.StatementInput -/* eslint-disable-next-line no-unused-vars */ import type {Input} from '../../inputs/input.js'; import type {ConstantProvider} from '../common/constants.js'; - import {InputConnection} from './input_connection.js'; import {Types} from './types.js'; diff --git a/core/renderers/measurables/top_row.ts b/core/renderers/measurables/top_row.ts index b1490860611..b87ce4ad753 100644 --- a/core/renderers/measurables/top_row.ts +++ b/core/renderers/measurables/top_row.ts @@ -8,7 +8,6 @@ import type {BlockSvg} from '../../block_svg.js'; import type {ConstantProvider} from '../common/constants.js'; - import {Hat} from './hat.js'; import type {PreviousConnection} from './previous_connection.js'; import {Row} from './row.js'; diff --git a/core/renderers/measurables/types.ts b/core/renderers/measurables/types.ts index a378fc18efe..a145b156303 100644 --- a/core/renderers/measurables/types.ts +++ b/core/renderers/measurables/types.ts @@ -13,6 +13,9 @@ import type {Row} from './row.js'; * Types of rendering elements. */ class TypesContainer { + // This class is very non-idiomatic for typescript, so we have to use + // the Function type to make it happy. + // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type [index: string]: number | Function; NONE = 0; // None diff --git a/core/renderers/thrasos/info.ts b/core/renderers/thrasos/info.ts index 789897209a9..23772a9af0e 100644 --- a/core/renderers/thrasos/info.ts +++ b/core/renderers/thrasos/info.ts @@ -15,7 +15,6 @@ import {InRowSpacer} from '../measurables/in_row_spacer.js'; import type {Row} from '../measurables/row.js'; import type {TopRow} from '../measurables/top_row.js'; import {Types} from '../measurables/types.js'; - import type {Renderer} from './renderer.js'; /** diff --git a/core/renderers/thrasos/renderer.ts b/core/renderers/thrasos/renderer.ts index 513cadc7892..d12eaf941ab 100644 --- a/core/renderers/thrasos/renderer.ts +++ b/core/renderers/thrasos/renderer.ts @@ -9,7 +9,6 @@ import type {BlockSvg} from '../../block_svg.js'; import * as blockRendering from '../common/block_rendering.js'; import {Renderer as BaseRenderer} from '../common/renderer.js'; - import {RenderInfo} from './info.js'; /** diff --git a/core/renderers/zelos/constants.ts b/core/renderers/zelos/constants.ts index c50e66510a0..74df72aeb91 100644 --- a/core/renderers/zelos/constants.ts +++ b/core/renderers/zelos/constants.ts @@ -13,8 +13,8 @@ import * as utilsColour from '../../utils/colour.js'; import * as dom from '../../utils/dom.js'; import {Svg} from '../../utils/svg.js'; import * as svgPaths from '../../utils/svg_paths.js'; -import {ConstantProvider as BaseConstantProvider} from '../common/constants.js'; import type {Shape} from '../common/constants.js'; +import {ConstantProvider as BaseConstantProvider} from '../common/constants.js'; /** An object containing sizing and path information about inside corners. */ export interface InsideCorners { @@ -786,7 +786,6 @@ export class ConstantProvider extends BaseConstantProvider { override getCSS_(selector: string) { return [ - /* eslint-disable indent */ // Text. `${selector} .blocklyText,`, `${selector} .blocklyFlyoutLabelText {`, @@ -871,4 +870,3 @@ export class ConstantProvider extends BaseConstantProvider { ]; } } -/* eslint-enable indent */ diff --git a/core/renderers/zelos/drawer.ts b/core/renderers/zelos/drawer.ts index 009247aeae4..e5b91c1e607 100644 --- a/core/renderers/zelos/drawer.ts +++ b/core/renderers/zelos/drawer.ts @@ -17,7 +17,6 @@ import {OutputConnection} from '../measurables/output_connection.js'; import type {Row} from '../measurables/row.js'; import type {SpacerRow} from '../measurables/spacer_row.js'; import {Types} from '../measurables/types.js'; - import type {InsideCorners} from './constants.js'; import type {RenderInfo} from './info.js'; import type {StatementInput} from './measurables/inputs.js'; diff --git a/core/renderers/zelos/info.ts b/core/renderers/zelos/info.ts index 623f0a3b085..dd3702fe5d1 100644 --- a/core/renderers/zelos/info.ts +++ b/core/renderers/zelos/info.ts @@ -7,24 +7,23 @@ // Former goog.module ID: Blockly.zelos.RenderInfo import type {BlockSvg} from '../../block_svg.js'; -import {DummyInput} from '../../inputs/dummy_input.js'; -import {EndRowInput} from '../../inputs/end_row_input.js'; import {FieldImage} from '../../field_image.js'; import {FieldLabel} from '../../field_label.js'; import {FieldTextInput} from '../../field_textinput.js'; -import {Input} from '../../inputs/input.js'; import {Align} from '../../inputs/align.js'; +import {DummyInput} from '../../inputs/dummy_input.js'; +import {EndRowInput} from '../../inputs/end_row_input.js'; +import {Input} from '../../inputs/input.js'; +import {StatementInput} from '../../inputs/statement_input.js'; +import {ValueInput} from '../../inputs/value_input.js'; import {RenderInfo as BaseRenderInfo} from '../common/info.js'; import type {Measurable} from '../measurables/base.js'; import {Field} from '../measurables/field.js'; import {InRowSpacer} from '../measurables/in_row_spacer.js'; import {InputConnection} from '../measurables/input_connection.js'; -import {StatementInput} from '../../inputs/statement_input.js'; import type {Row} from '../measurables/row.js'; import type {SpacerRow} from '../measurables/spacer_row.js'; import {Types} from '../measurables/types.js'; -import {ValueInput} from '../../inputs/value_input.js'; - import type {ConstantProvider, InsideCorners} from './constants.js'; import {BottomRow} from './measurables/bottom_row.js'; import {StatementInput as StatementInputMeasurable} from './measurables/inputs.js'; diff --git a/core/renderers/zelos/marker_svg.ts b/core/renderers/zelos/marker_svg.ts index 4805e264b6c..395ece0b0be 100644 --- a/core/renderers/zelos/marker_svg.ts +++ b/core/renderers/zelos/marker_svg.ts @@ -15,7 +15,6 @@ import {Svg} from '../../utils/svg.js'; import type {WorkspaceSvg} from '../../workspace_svg.js'; import type {ConstantProvider as BaseConstantProvider} from '../common/constants.js'; import {MarkerSvg as BaseMarkerSvg} from '../common/marker_svg.js'; - import type {ConstantProvider as ZelosConstantProvider} from './constants.js'; /** diff --git a/core/renderers/zelos/measurables/inputs.ts b/core/renderers/zelos/measurables/inputs.ts index d405574e0b7..98dd9f33e5d 100644 --- a/core/renderers/zelos/measurables/inputs.ts +++ b/core/renderers/zelos/measurables/inputs.ts @@ -6,7 +6,6 @@ // Former goog.module ID: Blockly.zelos.StatementInput -/* eslint-disable-next-line no-unused-vars */ import type {Input} from '../../../inputs/input.js'; import type {ConstantProvider} from '../../../renderers/common/constants.js'; import {StatementInput as BaseStatementInput} from '../../../renderers/measurables/statement_input.js'; diff --git a/core/renderers/zelos/path_object.ts b/core/renderers/zelos/path_object.ts index fdc6ab8a626..060190ee1b0 100644 --- a/core/renderers/zelos/path_object.ts +++ b/core/renderers/zelos/path_object.ts @@ -12,7 +12,6 @@ import type {BlockStyle} from '../../theme.js'; import * as dom from '../../utils/dom.js'; import {Svg} from '../../utils/svg.js'; import {PathObject as BasePathObject} from '../common/path_object.js'; - import type {ConstantProvider} from './constants.js'; /** diff --git a/core/renderers/zelos/renderer.ts b/core/renderers/zelos/renderer.ts index 354a3f35adf..b48600a0b4d 100644 --- a/core/renderers/zelos/renderer.ts +++ b/core/renderers/zelos/renderer.ts @@ -12,17 +12,16 @@ import {InsertionMarkerManager} from '../../insertion_marker_manager.js'; import type {Marker} from '../../keyboard_nav/marker.js'; import type {RenderedConnection} from '../../rendered_connection.js'; import type {BlockStyle} from '../../theme.js'; +import * as deprecation from '../../utils/deprecation.js'; import type {WorkspaceSvg} from '../../workspace_svg.js'; import * as blockRendering from '../common/block_rendering.js'; import type {RenderInfo as BaseRenderInfo} from '../common/info.js'; import {Renderer as BaseRenderer} from '../common/renderer.js'; - import {ConstantProvider} from './constants.js'; import {Drawer} from './drawer.js'; import {RenderInfo} from './info.js'; import {MarkerSvg} from './marker_svg.js'; import {PathObject} from './path_object.js'; -import * as deprecation from '../../utils/deprecation.js'; /** * The zelos renderer. This renderer emulates Scratch-style and MakeCode-style diff --git a/core/scrollbar_pair.ts b/core/scrollbar_pair.ts index 231fe56f871..79ecff83417 100644 --- a/core/scrollbar_pair.ts +++ b/core/scrollbar_pair.ts @@ -27,7 +27,7 @@ export class ScrollbarPair { corner_: SVGRectElement | null = null; /** Previously recorded metrics from the workspace. */ - private oldHostMetrics_: Metrics | null = null; + private oldHostMetrics: Metrics | null = null; /** * @param workspace Workspace to bind the scrollbars to. @@ -84,7 +84,7 @@ export class ScrollbarPair { dispose() { dom.removeNode(this.corner_); this.corner_ = null; - this.oldHostMetrics_ = null; + this.oldHostMetrics = null; if (this.hScroll) { this.hScroll.dispose(); this.hScroll = null; @@ -111,11 +111,11 @@ export class ScrollbarPair { let resizeH = false; let resizeV = false; if ( - !this.oldHostMetrics_ || - this.oldHostMetrics_.viewWidth !== hostMetrics.viewWidth || - this.oldHostMetrics_.viewHeight !== hostMetrics.viewHeight || - this.oldHostMetrics_.absoluteTop !== hostMetrics.absoluteTop || - this.oldHostMetrics_.absoluteLeft !== hostMetrics.absoluteLeft + !this.oldHostMetrics || + this.oldHostMetrics.viewWidth !== hostMetrics.viewWidth || + this.oldHostMetrics.viewHeight !== hostMetrics.viewHeight || + this.oldHostMetrics.absoluteTop !== hostMetrics.absoluteTop || + this.oldHostMetrics.absoluteLeft !== hostMetrics.absoluteLeft ) { // The window has been resized or repositioned. resizeH = true; @@ -123,18 +123,18 @@ export class ScrollbarPair { } else { // Has the content been resized or moved? if ( - !this.oldHostMetrics_ || - this.oldHostMetrics_.scrollWidth !== hostMetrics.scrollWidth || - this.oldHostMetrics_.viewLeft !== hostMetrics.viewLeft || - this.oldHostMetrics_.scrollLeft !== hostMetrics.scrollLeft + !this.oldHostMetrics || + this.oldHostMetrics.scrollWidth !== hostMetrics.scrollWidth || + this.oldHostMetrics.viewLeft !== hostMetrics.viewLeft || + this.oldHostMetrics.scrollLeft !== hostMetrics.scrollLeft ) { resizeH = true; } if ( - !this.oldHostMetrics_ || - this.oldHostMetrics_.scrollHeight !== hostMetrics.scrollHeight || - this.oldHostMetrics_.viewTop !== hostMetrics.viewTop || - this.oldHostMetrics_.scrollTop !== hostMetrics.scrollTop + !this.oldHostMetrics || + this.oldHostMetrics.scrollHeight !== hostMetrics.scrollHeight || + this.oldHostMetrics.viewTop !== hostMetrics.viewTop || + this.oldHostMetrics.scrollTop !== hostMetrics.scrollTop ) { resizeV = true; } @@ -158,23 +158,23 @@ export class ScrollbarPair { if (this.hScroll && this.vScroll) { // Reposition the corner square. if ( - !this.oldHostMetrics_ || - this.oldHostMetrics_.viewWidth !== hostMetrics.viewWidth || - this.oldHostMetrics_.absoluteLeft !== hostMetrics.absoluteLeft + !this.oldHostMetrics || + this.oldHostMetrics.viewWidth !== hostMetrics.viewWidth || + this.oldHostMetrics.absoluteLeft !== hostMetrics.absoluteLeft ) { this.corner_?.setAttribute('x', String(this.vScroll.position.x)); } if ( - !this.oldHostMetrics_ || - this.oldHostMetrics_.viewHeight !== hostMetrics.viewHeight || - this.oldHostMetrics_.absoluteTop !== hostMetrics.absoluteTop + !this.oldHostMetrics || + this.oldHostMetrics.viewHeight !== hostMetrics.viewHeight || + this.oldHostMetrics.absoluteTop !== hostMetrics.absoluteTop ) { this.corner_?.setAttribute('y', String(this.hScroll.position.y)); } } // Cache the current metrics to potentially short-cut the next resize event. - this.oldHostMetrics_ = hostMetrics; + this.oldHostMetrics = hostMetrics; } /** diff --git a/core/serialization.ts b/core/serialization.ts index 8e159bb2b0b..3eb232a5479 100644 --- a/core/serialization.ts +++ b/core/serialization.ts @@ -9,24 +9,24 @@ */ // Former goog.module ID: Blockly.serialization +import {ISerializer} from './interfaces/i_serializer.js'; import * as blocks from './serialization/blocks.js'; import * as exceptions from './serialization/exceptions.js'; import * as priorities from './serialization/priorities.js'; import * as procedures from './serialization/procedures.js'; import * as registry from './serialization/registry.js'; import * as variables from './serialization/variables.js'; -import * as workspaces from './serialization/workspaces.js'; import * as workspaceComments from './serialization/workspace_comments.js'; -import {ISerializer} from './interfaces/i_serializer.js'; +import * as workspaces from './serialization/workspaces.js'; export { blocks, exceptions, + ISerializer, priorities, procedures, registry, variables, - workspaces, workspaceComments, - ISerializer, + workspaces, }; diff --git a/core/serialization/blocks.ts b/core/serialization/blocks.ts index dbb58cffb2a..b9026224063 100644 --- a/core/serialization/blocks.ts +++ b/core/serialization/blocks.ts @@ -10,16 +10,18 @@ import type {Block} from '../block.js'; import type {BlockSvg} from '../block_svg.js'; import type {Connection} from '../connection.js'; import {MANUALLY_DISABLED} from '../constants.js'; +import {EventType} from '../events/type.js'; import * as eventUtils from '../events/utils.js'; import {inputTypes} from '../inputs/input_types.js'; import {isSerializable} from '../interfaces/i_serializable.js'; import type {ISerializer} from '../interfaces/i_serializer.js'; import * as registry from '../registry.js'; +import * as renderManagement from '../render_management.js'; import * as utilsXml from '../utils/xml.js'; +import {VariableModel} from '../variable_model.js'; +import * as Variables from '../variables.js'; import type {Workspace} from '../workspace.js'; import * as Xml from '../xml.js'; -import * as renderManagement from '../render_management.js'; - import { BadConnectionCheck, MissingBlockType, @@ -29,11 +31,6 @@ import { } from './exceptions.js'; import * as priorities from './priorities.js'; import * as serializationRegistry from './registry.js'; -import * as Variables from '../variables.js'; -import {VariableModel} from '../variable_model.js'; - -// TODO(#5160): Remove this once lint is fixed. -/* eslint-disable no-use-before-define */ /** * Represents the state of a connection. @@ -433,7 +430,7 @@ export function appendInternal( if (eventUtils.isEnabled()) { // Block events come after var events, in case they refer to newly created // variables. - eventUtils.fire(new (eventUtils.get(eventUtils.BLOCK_CREATE))(block)); + eventUtils.fire(new (eventUtils.get(EventType.BLOCK_CREATE))(block)); } eventUtils.setGroup(existingGroup); eventUtils.setRecordUndo(prevRecordUndo); @@ -513,9 +510,7 @@ function checkNewVariables( // Fire a VarCreate event for each (if any) new variable created. for (let i = 0; i < newVariables.length; i++) { const thisVariable = newVariables[i]; - eventUtils.fire( - new (eventUtils.get(eventUtils.VAR_CREATE))(thisVariable), - ); + eventUtils.fire(new (eventUtils.get(EventType.VAR_CREATE))(thisVariable)); } } } @@ -797,7 +792,6 @@ const saveBlock = save; export class BlockSerializer implements ISerializer { priority: number; - /* eslint-disable-next-line require-jsdoc */ constructor() { /** The priority for deserializing blocks. */ this.priority = priorities.BLOCKS; diff --git a/core/serialization/procedures.ts b/core/serialization/procedures.ts index 55d72060417..5e2dd0d2858 100644 --- a/core/serialization/procedures.ts +++ b/core/serialization/procedures.ts @@ -7,8 +7,8 @@ import {IParameterModel} from '../interfaces/i_parameter_model.js'; import {IProcedureModel} from '../interfaces/i_procedure_model.js'; import type {ISerializer} from '../interfaces/i_serializer.js'; -import * as priorities from './priorities.js'; import type {Workspace} from '../workspace.js'; +import * as priorities from './priorities.js'; /** Represents the state of a procedure model. */ export interface State { @@ -44,7 +44,7 @@ interface ProcedureModelConstructor { * @param workspace The workspace to load the procedure model into. * @returns The constructed procedure model. */ - loadState(state: Object, workspace: Workspace): ProcedureModel; + loadState(state: object, workspace: Workspace): ProcedureModel; } /** @@ -64,7 +64,7 @@ interface ParameterModelConstructor { * @param workspace The workspace to load the parameter model into. * @returns The constructed parameter model. */ - loadState(state: Object, workspace: Workspace): ParameterModel; + loadState(state: object, workspace: Workspace): ParameterModel; } /** diff --git a/core/serialization/variables.ts b/core/serialization/variables.ts index 69c6cda8c1b..e4fc7fbaab8 100644 --- a/core/serialization/variables.ts +++ b/core/serialization/variables.ts @@ -8,7 +8,6 @@ import type {ISerializer} from '../interfaces/i_serializer.js'; import type {Workspace} from '../workspace.js'; - import * as priorities from './priorities.js'; import * as serializationRegistry from './registry.js'; @@ -27,7 +26,6 @@ export interface State { export class VariableSerializer implements ISerializer { priority: number; - /* eslint-disable-next-line require-jsdoc */ constructor() { /** The priority for deserializing variables. */ this.priority = priorities.VARIABLES; diff --git a/core/serialization/workspace_comments.ts b/core/serialization/workspace_comments.ts index 525274e58e4..61d1127b39c 100644 --- a/core/serialization/workspace_comments.ts +++ b/core/serialization/workspace_comments.ts @@ -4,14 +4,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {ISerializer} from '../interfaces/i_serializer.js'; -import {Workspace} from '../workspace.js'; -import * as priorities from './priorities.js'; import type {WorkspaceComment} from '../comments/workspace_comment.js'; import * as eventUtils from '../events/utils.js'; +import {ISerializer} from '../interfaces/i_serializer.js'; import {Coordinate} from '../utils/coordinate.js'; -import * as serializationRegistry from './registry.js'; import {Size} from '../utils/size.js'; +import {Workspace} from '../workspace.js'; +import * as priorities from './priorities.js'; +import * as serializationRegistry from './registry.js'; export interface State { id?: string; diff --git a/core/serialization/workspaces.ts b/core/serialization/workspaces.ts index 871060196c7..f201de19ea6 100644 --- a/core/serialization/workspaces.ts +++ b/core/serialization/workspaces.ts @@ -6,11 +6,11 @@ // Former goog.module ID: Blockly.serialization.workspaces +import {EventType} from '../events/type.js'; import * as eventUtils from '../events/utils.js'; import type {ISerializer} from '../interfaces/i_serializer.js'; import * as registry from '../registry.js'; import * as dom from '../utils/dom.js'; -// eslint-disable-next-line no-unused-vars import type {Workspace} from '../workspace.js'; import {WorkspaceSvg} from '../workspace_svg.js'; @@ -87,7 +87,7 @@ export function load( } dom.stopTextWidthCache(); - eventUtils.fire(new (eventUtils.get(eventUtils.FINISHED_LOADING))(workspace)); + eventUtils.fire(new (eventUtils.get(EventType.FINISHED_LOADING))(workspace)); eventUtils.setGroup(existingGroup); eventUtils.setRecordUndo(prevRecordUndo); diff --git a/core/shortcut_items.ts b/core/shortcut_items.ts index 6a7e29d26b2..3a32b687fe8 100644 --- a/core/shortcut_items.ts +++ b/core/shortcut_items.ts @@ -9,16 +9,16 @@ import {BlockSvg} from './block_svg.js'; import * as clipboard from './clipboard.js'; import * as common from './common.js'; +import * as eventUtils from './events/utils.js'; import {Gesture} from './gesture.js'; import {ICopyData, isCopyable} from './interfaces/i_copyable.js'; import {isDeletable} from './interfaces/i_deletable.js'; -import {KeyboardShortcut, ShortcutRegistry} from './shortcut_registry.js'; -import {KeyCodes} from './utils/keycodes.js'; -import type {WorkspaceSvg} from './workspace_svg.js'; import {isDraggable} from './interfaces/i_draggable.js'; -import * as eventUtils from './events/utils.js'; +import {KeyboardShortcut, ShortcutRegistry} from './shortcut_registry.js'; import {Coordinate} from './utils/coordinate.js'; +import {KeyCodes} from './utils/keycodes.js'; import {Rect} from './utils/rect.js'; +import type {WorkspaceSvg} from './workspace_svg.js'; /** * Object holding the names of the default shortcut items. diff --git a/core/shortcut_registry.ts b/core/shortcut_registry.ts index 161a2ed1495..09bd867e769 100644 --- a/core/shortcut_registry.ts +++ b/core/shortcut_registry.ts @@ -45,31 +45,27 @@ export class ShortcutRegistry { * Registers a keyboard shortcut. * * @param shortcut The shortcut for this key code. - * @param opt_allowOverrides True to prevent a warning when overriding an + * @param allowOverrides True to prevent a warning when overriding an * already registered item. * @throws {Error} if a shortcut with the same name already exists. */ - register(shortcut: KeyboardShortcut, opt_allowOverrides?: boolean) { + register(shortcut: KeyboardShortcut, allowOverrides?: boolean) { const registeredShortcut = this.shortcuts.get(shortcut.name); - if (registeredShortcut && !opt_allowOverrides) { + if (registeredShortcut && !allowOverrides) { throw new Error(`Shortcut named "${shortcut.name}" already exists.`); } this.shortcuts.set(shortcut.name, shortcut); const keyCodes = shortcut.keyCodes; - if (keyCodes && keyCodes.length > 0) { - for (let i = 0; i < keyCodes.length; i++) { - this.addKeyMapping( - keyCodes[i], - shortcut.name, - !!shortcut.allowCollision, - ); + if (keyCodes?.length) { + for (const keyCode of keyCodes) { + this.addKeyMapping(keyCode, shortcut.name, !!shortcut.allowCollision); } } } /** - * Unregisters a keyboard shortcut registered with the given key code. This + * Unregisters a keyboard shortcut registered with the given name. This * will also remove any key mappings that reference this shortcut. * * @param shortcutName The name of the shortcut to unregister. @@ -92,27 +88,34 @@ export class ShortcutRegistry { /** * Adds a mapping between a keycode and a keyboard shortcut. * + * Normally only one shortcut can be mapped to any given keycode, + * but setting allowCollisions to true allows a keyboard to be + * mapped to multiple shortcuts. In that case, when onKeyDown is + * called with the given keystroke, it will process the mapped + * shortcuts in reverse order, from the most- to least-recently + * mapped). + * * @param keyCode The key code for the keyboard shortcut. If registering a key * code with a modifier (ex: ctrl+c) use * ShortcutRegistry.registry.createSerializedKey; * @param shortcutName The name of the shortcut to execute when the given * keycode is pressed. - * @param opt_allowCollision True to prevent an error when adding a shortcut + * @param allowCollision True to prevent an error when adding a shortcut * to a key that is already mapped to a shortcut. * @throws {Error} if the given key code is already mapped to a shortcut. */ addKeyMapping( keyCode: string | number | KeyCodes, shortcutName: string, - opt_allowCollision?: boolean, + allowCollision?: boolean, ) { keyCode = `${keyCode}`; const shortcutNames = this.keyMap.get(keyCode); - if (shortcutNames && !opt_allowCollision) { + if (shortcutNames && !allowCollision) { throw new Error( `Shortcut named "${shortcutName}" collides with shortcuts "${shortcutNames}"`, ); - } else if (shortcutNames && opt_allowCollision) { + } else if (shortcutNames && allowCollision) { shortcutNames.unshift(shortcutName); } else { this.keyMap.set(keyCode, [shortcutName]); @@ -127,19 +130,19 @@ export class ShortcutRegistry { * ShortcutRegistry.registry.createSerializedKey; * @param shortcutName The name of the shortcut to execute when the given * keycode is pressed. - * @param opt_quiet True to not console warn when there is no shortcut to + * @param quiet True to not console warn when there is no shortcut to * remove. * @returns True if a key mapping was removed, false otherwise. */ removeKeyMapping( keyCode: string, shortcutName: string, - opt_quiet?: boolean, + quiet?: boolean, ): boolean { const shortcutNames = this.keyMap.get(keyCode); if (!shortcutNames) { - if (!opt_quiet) { + if (!quiet) { console.warn( `No keyboard shortcut named "${shortcutName}" registered with key code "${keyCode}"`, ); @@ -155,7 +158,7 @@ export class ShortcutRegistry { } return true; } - if (!opt_quiet) { + if (!quiet) { console.warn( `No keyboard shortcut named "${shortcutName}" registered with key code "${keyCode}"`, ); @@ -172,7 +175,7 @@ export class ShortcutRegistry { */ removeAllKeyMappings(shortcutName: string) { for (const keyCode of this.keyMap.keys()) { - this.removeKeyMapping(keyCode, shortcutName, true); + this.removeKeyMapping(keyCode, shortcutName, /* quiet= */ true); } } @@ -219,24 +222,39 @@ export class ShortcutRegistry { /** * Handles key down events. * + * - Any `KeyboardShortcut`(s) mapped to the keycodes that cause + * event `e` to be fired will be processed, in order from least- + * to most-recently registered. + * - If the shortcut's `preconditionFn` exists it will be called. + * If `preconditionFn` returns false the shortcut's `callback` + * function will be skipped. Processing will continue with the + * next shortcut, if any. + * - The shortcut's `callback` function will then be called. If it + * returns true, processing will terminate and `onKeyDown` will + * return true. If it returns false, processing will continue + * with with the next shortcut, if any. + * - If all registered shortcuts for the given keycode have been + * processed without any having returned true, `onKeyDown` will + * return false. + * * @param workspace The main workspace where the event was captured. * @param e The key down event. * @returns True if the event was handled, false otherwise. */ onKeyDown(workspace: WorkspaceSvg, e: KeyboardEvent): boolean { - const key = this.serializeKeyEvent_(e); + const key = this.serializeKeyEvent(e); const shortcutNames = this.getShortcutNamesByKeyCode(key); - if (!shortcutNames) { - return false; - } - for (let i = 0, shortcutName; (shortcutName = shortcutNames[i]); i++) { + if (!shortcutNames) return false; + for (const shortcutName of shortcutNames) { const shortcut = this.shortcuts.get(shortcutName); - if (!shortcut?.preconditionFn || shortcut?.preconditionFn(workspace)) { - // If the key has been handled, stop processing shortcuts. - if (shortcut?.callback && shortcut?.callback(workspace, e, shortcut)) { - return true; - } + if ( + !shortcut || + (shortcut.preconditionFn && !shortcut.preconditionFn(workspace)) + ) { + continue; } + // If the key has been handled, stop processing shortcuts. + if (shortcut.callback?.(workspace, e, shortcut)) return true; } return false; } @@ -276,7 +294,7 @@ export class ShortcutRegistry { * @param e A key down event. * @returns The serialized key code for the given event. */ - private serializeKeyEvent_(e: KeyboardEvent): string { + private serializeKeyEvent(e: KeyboardEvent): string { let serializedKey = ''; for (const modifier in ShortcutRegistry.modifierKeys) { if (e.getModifierState(modifier)) { @@ -300,8 +318,8 @@ export class ShortcutRegistry { * @param modifiers List of modifiers to be used with the key. * @throws {Error} if the modifier is not in the valid modifiers list. */ - private checkModifiers_(modifiers: KeyCodes[]) { - for (let i = 0, modifier; (modifier = modifiers[i]); i++) { + private checkModifiers(modifiers: KeyCodes[]) { + for (const modifier of modifiers) { if (!(modifier in ShortcutRegistry.modifierKeys)) { throw new Error(modifier + ' is not a valid modifier key.'); } @@ -313,14 +331,14 @@ export class ShortcutRegistry { * * @param keyCode Number code representing the key. * @param modifiers List of modifier key codes to be used with the key. All - * valid modifiers can be found in the ShortcutRegistry.modifierKeys. + * valid modifiers can be found in the `ShortcutRegistry.modifierKeys`. * @returns The serialized key code for the given modifiers and key. */ createSerializedKey(keyCode: number, modifiers: KeyCodes[] | null): string { let serializedKey = ''; if (modifiers) { - this.checkModifiers_(modifiers); + this.checkModifiers(modifiers); for (const modifier in ShortcutRegistry.modifierKeys) { const modifierKeyCode = ( ShortcutRegistry.modifierKeys as AnyDuringMigration @@ -344,12 +362,59 @@ export class ShortcutRegistry { } export namespace ShortcutRegistry { + /** Interface defining a keyboard shortcut. */ export interface KeyboardShortcut { - callback?: (p1: WorkspaceSvg, p2: Event, p3: KeyboardShortcut) => boolean; + /** + * The function to be called when the shorctut is invoked. + * + * @param workspace The `WorkspaceSvg` when the shortcut was + * invoked. + * @param e The event that caused the shortcut to be activated. + * @param shortcut The `KeyboardShortcut` that was activated + * (i.e., the one this callback is attached to). + * @returns Returning true ends processing of the invoked keycode. + * Returning false causes processing to continue with the + * next-most-recently registered shortcut for the invoked + * keycode. + */ + callback?: ( + workspace: WorkspaceSvg, + e: Event, + shortcut: KeyboardShortcut, + ) => boolean; + + /** The name of the shortcut. Should be unique. */ name: string; - preconditionFn?: (p1: WorkspaceSvg) => boolean; + + /** + * A function to be called when the shortcut is invoked, before + * calling `callback`, to decide if this shortcut is applicable in + * the current situation. + * + * @param workspace The `WorkspaceSvg` where the shortcut was + * invoked. + * @returns True iff `callback` function should be called. + */ + preconditionFn?: (workspace: WorkspaceSvg) => boolean; + + /** Optional arbitray extra data attached to the shortcut. */ metadata?: object; + + /** + * Optional list of key codes to be bound (via + * ShortcutRegistry.prototype.addKeyMapping) to this shortcut. + */ keyCodes?: (number | string)[]; + + /** + * Value of `allowCollision` to pass to `addKeyMapping` when + * binding this shortcut's `.keyCodes` (if any). + * + * N.B.: this is only used for binding keycodes at the time this + * shortcut is initially registered, not for any subsequent + * `addKeyMapping` calls that happen to reference this shortcut's + * name. + */ allowCollision?: boolean; } diff --git a/core/theme_manager.ts b/core/theme_manager.ts index 8d2ad72db59..966ca3fd298 100644 --- a/core/theme_manager.ts +++ b/core/theme_manager.ts @@ -23,7 +23,7 @@ import type {WorkspaceSvg} from './workspace_svg.js'; */ export class ThemeManager { /** A list of workspaces that are subscribed to this theme. */ - private subscribedWorkspaces_: Workspace[] = []; + private subscribedWorkspaces: Workspace[] = []; private componentDB = new Map(); /** @@ -73,7 +73,7 @@ export class ThemeManager { // Refresh all subscribed workspaces. for ( let i = 0, workspace; - (workspace = this.subscribedWorkspaces_[i]); + (workspace = this.subscribedWorkspaces[i]); i++ ) { (workspace as WorkspaceSvg).refreshTheme(); @@ -89,7 +89,7 @@ export class ThemeManager { } } - for (const workspace of this.subscribedWorkspaces_) { + for (const workspace of this.subscribedWorkspaces) { (workspace as WorkspaceSvg).hideChaff(); } } @@ -102,7 +102,7 @@ export class ThemeManager { * @internal */ subscribeWorkspace(workspace: Workspace) { - this.subscribedWorkspaces_.push(workspace); + this.subscribedWorkspaces.push(workspace); } /** @@ -112,7 +112,7 @@ export class ThemeManager { * @internal */ unsubscribeWorkspace(workspace: Workspace) { - if (!arrayUtils.removeElem(this.subscribedWorkspaces_, workspace)) { + if (!arrayUtils.removeElem(this.subscribedWorkspaces, workspace)) { throw Error( "Cannot unsubscribe a workspace that hasn't been subscribed.", ); @@ -176,7 +176,7 @@ export class ThemeManager { * @internal */ dispose() { - this.subscribedWorkspaces_.length = 0; + this.subscribedWorkspaces.length = 0; this.componentDB.clear(); } } diff --git a/core/toolbox/category.ts b/core/toolbox/category.ts index 6ff159b0b02..1394f72187e 100644 --- a/core/toolbox/category.ts +++ b/core/toolbox/category.ts @@ -16,6 +16,11 @@ import type {ICollapsibleToolboxItem} from '../interfaces/i_collapsible_toolbox_ import type {ISelectableToolboxItem} from '../interfaces/i_selectable_toolbox_item.js'; import type {IToolbox} from '../interfaces/i_toolbox.js'; import type {IToolboxItem} from '../interfaces/i_toolbox_item.js'; +import * as registry from '../registry.js'; +import * as aria from '../utils/aria.js'; +import * as colourUtils from '../utils/colour.js'; +import * as dom from '../utils/dom.js'; +import * as parsing from '../utils/parsing.js'; import type { CategoryInfo, DynamicCategoryInfo, @@ -24,13 +29,7 @@ import type { FlyoutItemInfoArray, StaticCategoryInfo, } from '../utils/toolbox.js'; -import * as registry from '../registry.js'; -import * as aria from '../utils/aria.js'; -import * as colourUtils from '../utils/colour.js'; -import * as dom from '../utils/dom.js'; -import * as parsing from '../utils/parsing.js'; import * as toolbox from '../utils/toolbox.js'; - import {ToolboxItem} from './toolbox_item.js'; /** @@ -248,9 +247,11 @@ export class ToolboxCategory const nestedPadding = `${ ToolboxCategory.nestedPadding * this.getLevel() }px`; - this.workspace_.RTL - ? (rowDiv.style.paddingRight = nestedPadding) - : (rowDiv.style.paddingLeft = nestedPadding); + if (this.workspace_.RTL) { + rowDiv.style.paddingRight = nestedPadding; + } else { + rowDiv.style.paddingLeft = nestedPadding; + } return rowDiv; } @@ -346,9 +347,9 @@ export class ToolboxCategory '" must not have both a style and a colour', ); } else if (styleName) { - return this.getColourfromStyle_(styleName); + return this.getColourfromStyle(styleName); } else if (colour) { - return this.parseColour_(colour); + return this.parseColour(colour); } return ''; } @@ -360,12 +361,12 @@ export class ToolboxCategory * @param styleName Name of the style. * @returns The hex colour for the category. */ - private getColourfromStyle_(styleName: string): string { + private getColourfromStyle(styleName: string): string { const theme = this.workspace_.getTheme(); if (styleName && theme) { const style = theme.categoryStyles[styleName]; if (style && style.colour) { - return this.parseColour_(style.colour); + return this.parseColour(style.colour); } else { console.warn( 'Style "' + styleName + '" must exist and contain a colour value', @@ -394,7 +395,7 @@ export class ToolboxCategory * reference string pointing to one of those two values. * @returns The hex colour for the category. */ - private parseColour_(colourValue: number | string): string { + private parseColour(colourValue: number | string): string { // Decode the colour for any potential message references // (eg. `%{BKY_MATH_HUE}`). const colour = parsing.replaceMessageReferences(colourValue); @@ -540,7 +541,7 @@ export class ToolboxCategory } const className = this.cssConfig_['selected']; if (isSelected) { - const defaultColour = this.parseColour_( + const defaultColour = this.parseColour( ToolboxCategory.defaultBackgroundColour, ); this.rowDiv_.style.backgroundColor = this.colour_ || defaultColour; @@ -564,9 +565,11 @@ export class ToolboxCategory setDisabled(isDisabled: boolean) { this.isDisabled_ = isDisabled; this.getDiv()!.setAttribute('disabled', `${isDisabled}`); - isDisabled - ? this.getDiv()!.setAttribute('disabled', 'true') - : this.getDiv()!.removeAttribute('disabled'); + if (isDisabled) { + this.getDiv()!.setAttribute('disabled', 'true'); + } else { + this.getDiv()!.removeAttribute('disabled'); + } } /** diff --git a/core/toolbox/collapsible_category.ts b/core/toolbox/collapsible_category.ts index faea8edcb80..59143642502 100644 --- a/core/toolbox/collapsible_category.ts +++ b/core/toolbox/collapsible_category.ts @@ -18,7 +18,6 @@ import * as registry from '../registry.js'; import * as aria from '../utils/aria.js'; import * as dom from '../utils/dom.js'; import * as toolbox from '../utils/toolbox.js'; - import {ToolboxCategory} from './category.js'; import {ToolboxSeparator} from './separator.js'; @@ -84,7 +83,7 @@ export class CollapsibleToolboxCategory this.flyoutItems_.push(flyoutItem); prevIsFlyoutItem = true; } else { - this.createToolboxItem_(itemDef); + this.createToolboxItem(itemDef); prevIsFlyoutItem = false; } } @@ -96,7 +95,7 @@ export class CollapsibleToolboxCategory * * @param itemDef The information needed to create a toolbox item. */ - private createToolboxItem_(itemDef: toolbox.ToolboxItemInfo) { + private createToolboxItem(itemDef: toolbox.ToolboxItemInfo) { let registryName = itemDef['kind']; const categoryDef = itemDef as toolbox.CategoryInfo; // Categories that are collapsible are created using a class registered diff --git a/core/toolbox/separator.ts b/core/toolbox/separator.ts index ec003daf686..23874e42e79 100644 --- a/core/toolbox/separator.ts +++ b/core/toolbox/separator.ts @@ -16,7 +16,6 @@ import type {IToolbox} from '../interfaces/i_toolbox.js'; import * as registry from '../registry.js'; import * as dom from '../utils/dom.js'; import type * as toolbox from '../utils/toolbox.js'; - import {ToolboxItem} from './toolbox_item.js'; /** @@ -30,7 +29,7 @@ export class ToolboxSeparator extends ToolboxItem { /** All the CSS class names that are used to create a separator. */ protected cssConfig_: CssConfig = {'container': 'blocklyTreeSeparator'}; - private htmlDiv_: HTMLDivElement | null = null; + private htmlDiv: HTMLDivElement | null = null; /** * @param separatorDef The information needed to create a separator. @@ -59,16 +58,16 @@ export class ToolboxSeparator extends ToolboxItem { if (className) { dom.addClass(container, className); } - this.htmlDiv_ = container; + this.htmlDiv = container; return container; } override getDiv() { - return this.htmlDiv_ as HTMLDivElement; + return this.htmlDiv as HTMLDivElement; } override dispose() { - dom.removeNode(this.htmlDiv_ as HTMLDivElement); + dom.removeNode(this.htmlDiv as HTMLDivElement); } } diff --git a/core/toolbox/toolbox.ts b/core/toolbox/toolbox.ts index e0fb62e23da..12037839399 100644 --- a/core/toolbox/toolbox.ts +++ b/core/toolbox/toolbox.ts @@ -12,8 +12,6 @@ // Former goog.module ID: Blockly.Toolbox // Unused import preserved for side-effects. Remove if unneeded. -import '../events/events_toolbox_item_select.js'; - import {BlockSvg} from '../block_svg.js'; import type {BlocklyOptions} from '../blockly_options.js'; import * as browserEvents from '../browser_events.js'; @@ -21,9 +19,12 @@ import * as common from '../common.js'; import {ComponentManager} from '../component_manager.js'; import * as Css from '../css.js'; import {DeleteArea} from '../delete_area.js'; +import '../events/events_toolbox_item_select.js'; +import {EventType} from '../events/type.js'; import * as eventUtils from '../events/utils.js'; import type {IAutoHideable} from '../interfaces/i_autohideable.js'; import type {ICollapsibleToolboxItem} from '../interfaces/i_collapsible_toolbox_item.js'; +import {isDeletable} from '../interfaces/i_deletable.js'; import type {IDraggable} from '../interfaces/i_draggable.js'; import type {IFlyout} from '../interfaces/i_flyout.js'; import type {IKeyboardAccessible} from '../interfaces/i_keyboard_accessible.js'; @@ -43,7 +44,6 @@ import * as toolbox from '../utils/toolbox.js'; import type {WorkspaceSvg} from '../workspace_svg.js'; import type {ToolboxCategory} from './category.js'; import {CollapsibleToolboxCategory} from './collapsible_category.js'; -import {isDeletable} from '../interfaces/i_deletable.js'; /** * Class for a Toolbox. @@ -59,7 +59,7 @@ export class Toolbox */ override id = 'toolbox'; protected toolboxDef_: toolbox.ToolboxInfo; - private readonly horizontalLayout_: boolean; + private readonly horizontalLayout: boolean; /** The HTML container for the toolbox. */ HtmlDiv: HTMLDivElement | null = null; @@ -81,7 +81,7 @@ export class Toolbox RTL: boolean; /** The flyout for the toolbox. */ - private flyout_: IFlyout | null = null; + private flyout: IFlyout | null = null; protected contentMap_: {[key: string]: IToolboxItem}; toolboxPosition: toolbox.Position; @@ -113,7 +113,7 @@ export class Toolbox }; /** Whether the toolbox should be laid out horizontally. */ - this.horizontalLayout_ = workspace.options.horizontalLayout; + this.horizontalLayout = workspace.options.horizontalLayout; /** Is RTL vs LTR. */ this.RTL = workspace.options.RTL; @@ -140,12 +140,12 @@ export class Toolbox const workspace = this.workspace_; const svg = workspace.getParentSvg(); - this.flyout_ = this.createFlyout_(); + this.flyout = this.createFlyout_(); this.HtmlDiv = this.createDom_(this.workspace_); - dom.insertAfter(this.flyout_.createDom('svg'), svg); + dom.insertAfter(this.flyout.createDom('svg'), svg); this.setVisible(true); - this.flyout_.init(workspace); + this.flyout.init(workspace); this.render(this.toolboxDef_); const themeManager = workspace.getThemeManager(); @@ -157,7 +157,7 @@ export class Toolbox themeManager.subscribe(this.HtmlDiv, 'toolboxForegroundColour', 'color'); this.workspace_.getComponentManager().addComponent({ component: this, - weight: 1, + weight: ComponentManager.ComponentWeight.TOOLBOX_WEIGHT, capabilities: [ ComponentManager.Capability.AUTOHIDEABLE, ComponentManager.Capability.DELETE_AREA, @@ -197,7 +197,6 @@ export class Toolbox const toolboxContainer = document.createElement('div'); toolboxContainer.setAttribute('layout', this.isHorizontal() ? 'h' : 'v'); dom.addClass(toolboxContainer, 'blocklyToolboxDiv'); - dom.addClass(toolboxContainer, 'blocklyNonSelectable'); toolboxContainer.setAttribute('dir', this.RTL ? 'RTL' : 'LTR'); return toolboxContainer; } @@ -281,16 +280,16 @@ export class Toolbox let handled = false; switch (e.key) { case 'ArrowDown': - handled = this.selectNext_(); + handled = this.selectNext(); break; case 'ArrowUp': - handled = this.selectPrevious_(); + handled = this.selectPrevious(); break; case 'ArrowLeft': - handled = this.selectParent_(); + handled = this.selectParent(); break; case 'ArrowRight': - handled = this.selectChild_(); + handled = this.selectChild(); break; case 'Enter': case ' ': @@ -391,7 +390,7 @@ export class Toolbox const fragment = document.createDocumentFragment(); for (let i = 0; i < toolboxDef.length; i++) { const toolboxItemDef = toolboxDef[i]; - this.createToolboxItem_(toolboxItemDef, fragment); + this.createToolboxItem(toolboxItemDef, fragment); } this.contentsDiv_!.appendChild(fragment); } @@ -403,7 +402,7 @@ export class Toolbox * the toolbox. * @param fragment The document fragment to add the child toolbox elements to. */ - private createToolboxItem_( + private createToolboxItem( toolboxItemDef: toolbox.ToolboxItemInfo, fragment: DocumentFragment, ) { @@ -644,7 +643,7 @@ export class Toolbox * @returns The toolbox flyout. */ getFlyout(): IFlyout | null { - return this.flyout_; + return this.flyout; } /** @@ -682,7 +681,7 @@ export class Toolbox * vertical. */ isHorizontal(): boolean { - return this.horizontalLayout_; + return this.horizontalLayout; } /** @@ -697,7 +696,7 @@ export class Toolbox return; } - if (this.horizontalLayout_) { + if (this.horizontalLayout) { toolboxDiv.style.left = '0'; toolboxDiv.style.height = 'auto'; toolboxDiv.style.width = '100%'; @@ -720,7 +719,7 @@ export class Toolbox this.width_ = toolboxDiv.offsetWidth; this.height_ = workspaceMetrics.viewHeight; } - this.flyout_!.position(); + this.flyout!.position(); } /** @@ -780,7 +779,7 @@ export class Toolbox this.selectedItem_.isSelectable() && this.selectedItem_.getContents().length ) { - this.flyout_!.show(this.selectedItem_.getContents()); + this.flyout!.show(this.selectedItem_.getContents()); } } @@ -808,7 +807,7 @@ export class Toolbox * Flyouts should not be closed if this is true. */ autoHide(onlyClosePopups: boolean) { - if (!onlyClosePopups && this.flyout_ && this.flyout_.autoClose) { + if (!onlyClosePopups && this.flyout && this.flyout.autoClose) { this.clearSelection(); } } @@ -838,7 +837,7 @@ export class Toolbox } this.updateFlyout_(oldItem, newItem); - this.fireSelectEvent_(oldItem, newItem); + this.fireSelectEvent(oldItem, newItem); } /** @@ -940,10 +939,10 @@ export class Toolbox (oldItem === newItem && !newItem.isCollapsible()) || !newItem.getContents().length ) { - this.flyout_!.hide(); + this.flyout!.hide(); } else { - this.flyout_!.show(newItem.getContents()); - this.flyout_!.scrollToStart(); + this.flyout!.show(newItem.getContents()); + this.flyout!.scrollToStart(); } } @@ -953,7 +952,7 @@ export class Toolbox * @param oldItem The previously selected toolbox item. * @param newItem The newly selected toolbox item. */ - private fireSelectEvent_( + private fireSelectEvent( oldItem: ISelectableToolboxItem | null, newItem: ISelectableToolboxItem | null, ) { @@ -963,7 +962,7 @@ export class Toolbox if (oldItem === newItem) { newElement = null; } - const event = new (eventUtils.get(eventUtils.TOOLBOX_ITEM_SELECT))( + const event = new (eventUtils.get(EventType.TOOLBOX_ITEM_SELECT))( oldElement, newElement, this.workspace_.id, @@ -976,7 +975,7 @@ export class Toolbox * * @returns True if a parent category was selected, false otherwise. */ - private selectParent_(): boolean { + private selectParent(): boolean { if (!this.selectedItem_) { return false; } @@ -1004,7 +1003,7 @@ export class Toolbox * * @returns True if a child category was selected, false otherwise. */ - private selectChild_(): boolean { + private selectChild(): boolean { if (!this.selectedItem_ || !this.selectedItem_.isCollapsible()) { return false; } @@ -1013,7 +1012,7 @@ export class Toolbox collapsibleItem.toggleExpanded(); return true; } else { - this.selectNext_(); + this.selectNext(); return true; } } @@ -1023,7 +1022,7 @@ export class Toolbox * * @returns True if a next category was selected, false otherwise. */ - private selectNext_(): boolean { + private selectNext(): boolean { if (!this.selectedItem_) { return false; } @@ -1047,7 +1046,7 @@ export class Toolbox * * @returns True if a previous category was selected, false otherwise. */ - private selectPrevious_(): boolean { + private selectPrevious(): boolean { if (!this.selectedItem_) { return false; } @@ -1069,7 +1068,7 @@ export class Toolbox /** Disposes of this toolbox. */ dispose() { this.workspace_.getComponentManager().removeComponent('toolbox'); - this.flyout_!.dispose(); + this.flyout!.dispose(); for (let i = 0; i < this.contents_.length; i++) { const toolboxItem = this.contents_[i]; toolboxItem.dispose(); diff --git a/core/tooltip.ts b/core/tooltip.ts index 0478b91fd55..bf379f29141 100644 --- a/core/tooltip.ts +++ b/core/tooltip.ts @@ -19,7 +19,7 @@ import * as blocklyString from './utils/string.js'; export type TipInfo = | string | {tooltip: AnyDuringMigration} - | (() => TipInfo | string | Function); + | (() => TipInfo | string); /** * A function that renders custom tooltip UI. diff --git a/core/trashcan.ts b/core/trashcan.ts index 050f506a48f..d30c4a4e22b 100644 --- a/core/trashcan.ts +++ b/core/trashcan.ts @@ -12,14 +12,14 @@ // Former goog.module ID: Blockly.Trashcan // Unused import preserved for side-effects. Remove if unneeded. -import './events/events_trashcan_open.js'; - import type {BlocklyOptions} from './blockly_options.js'; import * as browserEvents from './browser_events.js'; import {ComponentManager} from './component_manager.js'; import {DeleteArea} from './delete_area.js'; import type {Abstract} from './events/events_abstract.js'; -import type {BlockDelete} from './events/events_block_delete.js'; +import './events/events_trashcan_open.js'; +import {isBlockDelete} from './events/predicates.js'; +import {EventType} from './events/type.js'; import * as eventUtils from './events/utils.js'; import type {IAutoHideable} from './interfaces/i_autohideable.js'; import type {IDraggable} from './interfaces/i_draggable.js'; @@ -35,8 +35,8 @@ import * as dom from './utils/dom.js'; import {Rect} from './utils/rect.js'; import {Size} from './utils/size.js'; import {Svg} from './utils/svg.js'; -import {BlockInfo} from './utils/toolbox.js'; import * as toolbox from './utils/toolbox.js'; +import {BlockInfo} from './utils/toolbox.js'; import type {WorkspaceSvg} from './workspace_svg.js'; /** @@ -247,7 +247,7 @@ export class Trashcan } this.workspace.getComponentManager().addComponent({ component: this, - weight: 1, + weight: ComponentManager.ComponentWeight.TRASHCAN_WEIGHT, capabilities: [ ComponentManager.Capability.AUTOHIDEABLE, ComponentManager.Capability.DELETE_AREA, @@ -557,7 +557,7 @@ export class Trashcan * @param trashcanOpen Whether the flyout is opening. */ private fireUiEvent(trashcanOpen: boolean) { - const uiEvent = new (eventUtils.get(eventUtils.TRASHCAN_OPEN))( + const uiEvent = new (eventUtils.get(EventType.TRASHCAN_OPEN))( trashcanOpen, this.workspace.id, ); @@ -604,30 +604,22 @@ export class Trashcan private onDelete(event: Abstract) { if ( this.workspace.options.maxTrashcanContents <= 0 || - event.type !== eventUtils.BLOCK_DELETE + !isBlockDelete(event) || + event.wasShadow ) { return; } - const deleteEvent = event as BlockDelete; - if (event.type === eventUtils.BLOCK_DELETE && !deleteEvent.wasShadow) { - if (!deleteEvent.oldJson) { - throw new Error('Encountered a delete event without proper oldJson'); - } - const cleanedJson = JSON.stringify( - this.cleanBlockJson(deleteEvent.oldJson), - ); - if (this.contents.includes(cleanedJson)) { - return; - } - this.contents.unshift(cleanedJson); - while ( - this.contents.length > this.workspace.options.maxTrashcanContents - ) { - this.contents.pop(); - } - - this.setMinOpenness(HAS_BLOCKS_LID_ANGLE); + if (!event.oldJson) { + throw new Error('Encountered a delete event without proper oldJson'); + } + const cleanedJson = JSON.stringify(this.cleanBlockJson(event.oldJson)); + if (this.contents.includes(cleanedJson)) return; + this.contents.unshift(cleanedJson); + while (this.contents.length > this.workspace.options.maxTrashcanContents) { + this.contents.pop(); } + + this.setMinOpenness(HAS_BLOCKS_LID_ANGLE); } /** diff --git a/core/utils/dom.ts b/core/utils/dom.ts index e318e7e915e..309cd3fae3b 100644 --- a/core/utils/dom.ts +++ b/core/utils/dom.ts @@ -211,7 +211,7 @@ export function getTextWidth(textElement: SVGTextElement): number { // Attempt to compute fetch the width of the SVG text element. try { width = textElement.getComputedTextLength(); - } catch (e) { + } catch { // In other cases where we fail to get the computed text. Instead, use an // approximation and do not cache the result. At some later point in time // when the block is inserted into the visible DOM, this method will be diff --git a/core/utils/drag.ts b/core/utils/drag.ts new file mode 100644 index 00000000000..a6322933bf9 --- /dev/null +++ b/core/utils/drag.ts @@ -0,0 +1,74 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import * as browserEvents from '../browser_events.js'; +import type {WorkspaceSvg} from '../workspace_svg.js'; +import {Coordinate} from './coordinate.js'; + +const workspaceToDragDelta: WeakMap = new WeakMap(); + +/** + * Convert from mouse coordinates to workspace coordinates. + * + * @param workspace The workspace where the pointer event is occurring. + * @param e The pointer event with the source coordinates. + */ +function mouseToWorkspacePoint( + workspace: WorkspaceSvg, + e: PointerEvent, +): SVGPoint { + const point = browserEvents.mouseToSvg( + e, + workspace.getParentSvg(), + workspace.getInverseScreenCTM(), + ); + // Fix scale of mouse event. + point.x /= workspace.scale; + point.y /= workspace.scale; + return point; +} + +/** + * Start tracking a drag of an object on this workspace by recording the offset + * between the pointer's current location and the object's starting location. + * + * Used for resizing block comments and workspace comments. + * + * @param workspace The workspace where the drag is occurring. + * @param e Pointer down event. + * @param xy Starting location of object. + */ +export function start( + workspace: WorkspaceSvg, + e: PointerEvent, + xy: Coordinate, +) { + const point = mouseToWorkspacePoint(workspace, e); + // Record the starting offset between the bubble's location and the mouse. + workspaceToDragDelta.set(workspace, Coordinate.difference(xy, point)); +} + +/** + * Compute the new position of a dragged object in this workspace based on the + * current pointer position and the offset between the pointer's starting + * location and the object's starting location. + * + * The start function should have be called previously, when the drag started. + * + * Used for resizing block comments and workspace comments. + * + * @param workspace The workspace where the drag is occurring. + * @param e Pointer move event. + * @returns New location of object. + */ +export function move(workspace: WorkspaceSvg, e: PointerEvent): Coordinate { + const point = mouseToWorkspacePoint(workspace, e); + const dragDelta = workspaceToDragDelta.get(workspace); + if (!dragDelta) { + throw new Error('Drag not initialized'); + } + return Coordinate.sum(dragDelta, point); +} diff --git a/core/utils/parsing.ts b/core/utils/parsing.ts index 9950b80e642..3f70f5693f9 100644 --- a/core/utils/parsing.ts +++ b/core/utils/parsing.ts @@ -7,7 +7,6 @@ // Former goog.module ID: Blockly.utils.parsing import {Msg} from '../msg.js'; - import * as colourUtils from './colour.js'; /** diff --git a/core/utils/rect.ts b/core/utils/rect.ts index 817462b699d..c7da2a6860b 100644 --- a/core/utils/rect.ts +++ b/core/utils/rect.ts @@ -13,6 +13,8 @@ */ // Former goog.module ID: Blockly.utils.Rect +import {Coordinate} from './coordinate.js'; + /** * Class for representing rectangular regions. */ @@ -30,10 +32,21 @@ export class Rect { public right: number, ) {} + /** + * Creates a new copy of this rectangle. + * + * @returns A copy of this Rect. + */ + clone(): Rect { + return new Rect(this.top, this.bottom, this.left, this.right); + } + + /** Returns the height of this rectangle. */ getHeight(): number { return this.bottom - this.top; } + /** Returns the width of this rectangle. */ getWidth(): number { return this.right - this.left; } @@ -59,11 +72,56 @@ export class Rect { * @returns Whether this rectangle intersects the provided rectangle. */ intersects(other: Rect): boolean { - return !( - this.left > other.right || - this.right < other.left || - this.top > other.bottom || - this.bottom < other.top + // The following logic can be derived and then simplified from a longer form symmetrical check + // of verifying each rectangle's borders with the other rectangle by checking if either end of + // the border's line segment is contained within the other rectangle. The simplified version + // used here can be logically interpreted as ensuring that each line segment of 'this' rectangle + // is not outside the bounds of the 'other' rectangle (proving there's an intersection). + return ( + this.left <= other.right && + this.right >= other.left && + this.bottom >= other.top && + this.top <= other.bottom ); } + + /** + * Compares bounding rectangles for equality. + * + * @param a A Rect. + * @param b A Rect. + * @returns True iff the bounding rectangles are equal, or if both are null. + */ + static equals(a?: Rect | null, b?: Rect | null): boolean { + if (a === b) { + return true; + } + if (!a || !b) { + return false; + } + return ( + a.top === b.top && + a.bottom === b.bottom && + a.left === b.left && + a.right === b.right + ); + } + + /** + * Creates a new Rect using a position and supplied dimensions. + * + * @param position The upper left coordinate of the new rectangle. + * @param width The width of the rectangle, in pixels. + * @param height The height of the rectangle, in pixels. + * @returns A newly created Rect using the provided Coordinate and dimensions. + */ + static createFromPoint( + position: Coordinate, + width: number, + height: number, + ): Rect { + const left = position.x; + const top = position.y; + return new Rect(top, top + height, left, left + width); + } } diff --git a/core/utils/size.ts b/core/utils/size.ts index 705dc2c2897..4b5eede751b 100644 --- a/core/utils/size.ts +++ b/core/utils/size.ts @@ -34,7 +34,7 @@ export class Size { * @returns True iff the sizes have equal widths and equal heights, or if both * are null. */ - static equals(a: Size | null, b: Size | null): boolean { + static equals(a?: Size | null, b?: Size | null): boolean { if (a === b) { return true; } diff --git a/core/utils/svg_math.ts b/core/utils/svg_math.ts index 0444787add7..c29d6ae6999 100644 --- a/core/utils/svg_math.ts +++ b/core/utils/svg_math.ts @@ -7,7 +7,6 @@ // Former goog.module ID: Blockly.utils.svgMath import type {WorkspaceSvg} from '../workspace_svg.js'; - import {Coordinate} from './coordinate.js'; import {Rect} from './rect.js'; import * as style from './style.js'; diff --git a/core/utils/toolbox.ts b/core/utils/toolbox.ts index fbf031ac612..296bb6dcc94 100644 --- a/core/utils/toolbox.ts +++ b/core/utils/toolbox.ts @@ -285,9 +285,9 @@ function hasCategoriesInternal(toolboxJson: ToolboxInfo | null): boolean { return toolboxKind === CATEGORY_TOOLBOX_KIND; } - const categories = toolboxJson['contents'].filter(function (item) { - return item['kind'].toUpperCase() === 'CATEGORY'; - }); + const categories = toolboxJson['contents'].filter( + (item) => item['kind'].toUpperCase() === 'CATEGORY', + ); return !!categories.length; } diff --git a/core/variable_map.ts b/core/variable_map.ts index bc19b07a59a..b28e8a3550e 100644 --- a/core/variable_map.ts +++ b/core/variable_map.ts @@ -18,6 +18,7 @@ import './events/events_var_rename.js'; import type {Block} from './block.js'; import * as dialog from './dialog.js'; +import {EventType} from './events/type.js'; import * as eventUtils from './events/utils.js'; import {Msg} from './msg.js'; import {Names} from './names.js'; @@ -75,14 +76,9 @@ export class VariableMap { // The IDs may match if the rename is a simple case change (name1 -> // Name1). if (!conflictVar || conflictVar.getId() === variable.getId()) { - this.renameVariableAndUses_(variable, newName, blocks); + this.renameVariableAndUses(variable, newName, blocks); } else { - this.renameVariableWithConflict_( - variable, - newName, - conflictVar, - blocks, - ); + this.renameVariableWithConflict(variable, newName, conflictVar, blocks); } } finally { eventUtils.setGroup(existingGroup); @@ -113,13 +109,13 @@ export class VariableMap { * @param newName New variable name. * @param blocks The list of all blocks in the workspace. */ - private renameVariableAndUses_( + private renameVariableAndUses( variable: VariableModel, newName: string, blocks: Block[], ) { eventUtils.fire( - new (eventUtils.get(eventUtils.VAR_RENAME))(variable, newName), + new (eventUtils.get(EventType.VAR_RENAME))(variable, newName), ); variable.name = newName; for (let i = 0; i < blocks.length; i++) { @@ -138,7 +134,7 @@ export class VariableMap { * @param conflictVar The variable that was already using newName. * @param blocks The list of all blocks in the workspace. */ - private renameVariableWithConflict_( + private renameVariableWithConflict( variable: VariableModel, newName: string, conflictVar: VariableModel, @@ -149,7 +145,7 @@ export class VariableMap { if (newName !== oldCase) { // Simple rename to change the case and update references. - this.renameVariableAndUses_(conflictVar, newName, blocks); + this.renameVariableAndUses(conflictVar, newName, blocks); } // These blocks now refer to a different variable. @@ -158,7 +154,7 @@ export class VariableMap { blocks[i].renameVarById(variable.getId(), conflictVar.getId()); } // Finally delete the original variable, which is now unreferenced. - eventUtils.fire(new (eventUtils.get(eventUtils.VAR_DELETE))(variable)); + eventUtils.fire(new (eventUtils.get(EventType.VAR_DELETE))(variable)); // And remove it from the list. arrayUtils.removeElem(this.variableMap.get(type)!, variable); } @@ -213,7 +209,7 @@ export class VariableMap { this.variableMap.delete(type); this.variableMap.set(type, variables); - eventUtils.fire(new (eventUtils.get(eventUtils.VAR_CREATE))(variable)); + eventUtils.fire(new (eventUtils.get(EventType.VAR_CREATE))(variable)); return variable; } @@ -232,9 +228,7 @@ export class VariableMap { const tempVar = variableList[i]; if (tempVar.getId() === variableId) { variableList.splice(i, 1); - eventUtils.fire( - new (eventUtils.get(eventUtils.VAR_DELETE))(variable), - ); + eventUtils.fire(new (eventUtils.get(EventType.VAR_DELETE))(variable)); if (variableList.length === 0) { this.variableMap.delete(variable.type); } diff --git a/core/variable_model.ts b/core/variable_model.ts index 0728a3d564d..58e48f36268 100644 --- a/core/variable_model.ts +++ b/core/variable_model.ts @@ -25,7 +25,7 @@ import type {Workspace} from './workspace.js'; */ export class VariableModel { type: string; - private readonly id_: string; + private readonly id: string; /** * @param workspace The variable's workspace. @@ -56,12 +56,12 @@ export class VariableModel { * not change, even if the name changes. In most cases this should be a * UUID. */ - this.id_ = opt_id || idGenerator.genUid(); + this.id = opt_id || idGenerator.genUid(); } /** @returns The ID for the variable. */ getId(): string { - return this.id_; + return this.id; } /** diff --git a/core/variables.ts b/core/variables.ts index dee53a72bc8..491b4c1b758 100644 --- a/core/variables.ts +++ b/core/variables.ts @@ -8,9 +8,9 @@ import {Blocks} from './blocks.js'; import * as dialog from './dialog.js'; +import {isLegacyProcedureDefBlock} from './interfaces/i_legacy_procedure_blocks.js'; import {isVariableBackedParameterModel} from './interfaces/i_variable_backed_parameter_model.js'; import {Msg} from './msg.js'; -import {isLegacyProcedureDefBlock} from './interfaces/i_legacy_procedure_blocks.js'; import * as utilsXml from './utils/xml.js'; import {VariableModel} from './variable_model.js'; import type {Workspace} from './workspace.js'; @@ -202,7 +202,6 @@ export function generateUniqueNameFromOptions( let letterIndex = letters.indexOf(startChar); let potName = startChar; - // eslint-disable-next-line no-constant-condition while (true) { let inUse = false; for (let i = 0; i < usedNames.length; i++) { diff --git a/core/variables_dynamic.ts b/core/variables_dynamic.ts index 6c44575490f..9788962c7b2 100644 --- a/core/variables_dynamic.ts +++ b/core/variables_dynamic.ts @@ -7,13 +7,13 @@ // Former goog.module ID: Blockly.VariablesDynamic import {Blocks} from './blocks.js'; +import type {FlyoutButton} from './flyout_button.js'; import {Msg} from './msg.js'; import * as xml from './utils/xml.js'; import {VariableModel} from './variable_model.js'; import * as Variables from './variables.js'; import type {Workspace} from './workspace.js'; import type {WorkspaceSvg} from './workspace_svg.js'; -import type {FlyoutButton} from './flyout_button.js'; /** * String for use in the "custom" attribute of a category in toolbox XML. diff --git a/core/widgetdiv.ts b/core/widgetdiv.ts index 9f58bb1c544..897698611e0 100644 --- a/core/widgetdiv.ts +++ b/core/widgetdiv.ts @@ -7,8 +7,8 @@ // Former goog.module ID: Blockly.WidgetDiv import * as common from './common.js'; -import * as dom from './utils/dom.js'; import {Field} from './field.js'; +import * as dom from './utils/dom.js'; import type {Rect} from './utils/rect.js'; import type {Size} from './utils/size.js'; import type {WorkspaceSvg} from './workspace_svg.js'; @@ -126,7 +126,7 @@ export function hide() { div.style.display = 'none'; div.style.left = ''; div.style.top = ''; - dispose && dispose(); + if (dispose) dispose(); dispose = null; div.textContent = ''; diff --git a/core/workspace.ts b/core/workspace.ts index 2e9b2b0a1e9..89c79723726 100644 --- a/core/workspace.ts +++ b/core/workspace.ts @@ -16,12 +16,15 @@ import './connection_checker.js'; import type {Block} from './block.js'; import type {BlocklyOptions} from './blockly_options.js'; +import {WorkspaceComment} from './comments/workspace_comment.js'; +import * as common from './common.js'; import type {ConnectionDB} from './connection_db.js'; import type {Abstract} from './events/events_abstract.js'; -import * as common from './common.js'; import * as eventUtils from './events/utils.js'; import type {IASTNodeLocation} from './interfaces/i_ast_node_location.js'; import type {IConnectionChecker} from './interfaces/i_connection_checker.js'; +import {IProcedureMap} from './interfaces/i_procedure_map.js'; +import {ObservableProcedureMap} from './observable_procedure_map.js'; import {Options} from './options.js'; import * as registry from './registry.js'; import * as arrayUtils from './utils/array.js'; @@ -30,9 +33,6 @@ import * as math from './utils/math.js'; import type * as toolbox from './utils/toolbox.js'; import {VariableMap} from './variable_map.js'; import type {VariableModel} from './variable_model.js'; -import {WorkspaceComment} from './comments/workspace_comment.js'; -import {IProcedureMap} from './interfaces/i_procedure_map.js'; -import {ObservableProcedureMap} from './observable_procedure_map.js'; /** * Class for a workspace. This is a data structure that contains blocks. @@ -102,7 +102,7 @@ export class Workspace implements IASTNodeLocation { private readonly topBlocks: Block[] = []; private readonly topComments: WorkspaceComment[] = []; private readonly commentDB = new Map(); - private readonly listeners: Function[] = []; + private readonly listeners: ((e: Abstract) => void)[] = []; protected undoStack_: Abstract[] = []; protected redoStack_: Abstract[] = []; private readonly blockDB = new Map(); @@ -167,7 +167,7 @@ export class Workspace implements IASTNodeLocation { * @returns The comparison value. This tells Array.sort() how to change object * a's index. */ - private sortObjects_( + private sortObjects( a: Block | WorkspaceComment, b: Block | WorkspaceComment, ): number { @@ -209,7 +209,7 @@ export class Workspace implements IASTNodeLocation { // Copy the topBlocks list. const blocks = new Array().concat(this.topBlocks); if (ordered && blocks.length > 1) { - blocks.sort(this.sortObjects_.bind(this)); + blocks.sort(this.sortObjects.bind(this)); } return blocks; } @@ -252,12 +252,10 @@ export class Workspace implements IASTNodeLocation { } const blocks = this.typedBlocksDB.get(type)!.slice(0); if (ordered && blocks && blocks.length > 1) { - blocks.sort(this.sortObjects_.bind(this)); + blocks.sort(this.sortObjects.bind(this)); } - return blocks.filter(function (block: Block) { - return !block.isInsertionMarker(); - }); + return blocks.filter((block) => !block.isInsertionMarker()); } /** @@ -310,7 +308,7 @@ export class Workspace implements IASTNodeLocation { // Copy the topComments list. const comments = new Array().concat(this.topComments); if (ordered && comments.length > 1) { - comments.sort(this.sortObjects_.bind(this)); + comments.sort(this.sortObjects.bind(this)); } return comments; } @@ -341,11 +339,7 @@ export class Workspace implements IASTNodeLocation { // Insertion markers exist on the workspace for rendering reasons, but // aren't "real" blocks from a developer perspective. - const filtered = blocks.filter(function (block) { - return !block.isInsertionMarker(); - }); - - return filtered; + return blocks.filter((block) => !block.isInsertionMarker()); } /** Dispose of all blocks and comments in workspace. */ @@ -634,7 +628,7 @@ export class Workspace implements IASTNodeLocation { if (!inputEvent) { return; } - let events = [inputEvent]; + const events = [inputEvent]; // Do another undo/redo if the next one is of the same group. while ( inputStack.length && @@ -650,7 +644,6 @@ export class Workspace implements IASTNodeLocation { const event = events[i]; outputStack.push(event); } - events = eventUtils.filter(events, redo); eventUtils.setRecordUndo(false); try { for (let i = 0; i < events.length; i++) { @@ -679,7 +672,7 @@ export class Workspace implements IASTNodeLocation { * @param func Function to call. * @returns Obsolete return value, ignore. */ - addChangeListener(func: (e: Abstract) => void): Function { + addChangeListener(func: (e: Abstract) => void): (e: Abstract) => void { this.listeners.push(func); return func; } @@ -689,7 +682,7 @@ export class Workspace implements IASTNodeLocation { * * @param func Function to stop calling. */ - removeChangeListener(func: Function) { + removeChangeListener(func: (e: Abstract) => void) { arrayUtils.removeElem(this.listeners, func); } @@ -748,7 +741,6 @@ export class Workspace implements IASTNodeLocation { * * @param id ID of comment to find. * @returns The sought after comment, or null if not found. - * @internal */ getCommentById(id: string): WorkspaceComment | null { return this.commentDB.get(id) ?? null; diff --git a/core/workspace_audio.ts b/core/workspace_audio.ts index c2ab9322212..1759b30edbb 100644 --- a/core/workspace_audio.ts +++ b/core/workspace_audio.ts @@ -29,7 +29,7 @@ export class WorkspaceAudio { private sounds = new Map(); /** Time that the last sound was played. */ - private lastSound_: Date | null = null; + private lastSound: Date | null = null; /** Whether the audio is muted or not. */ private muted: boolean = false; @@ -64,7 +64,7 @@ export class WorkspaceAudio { let audioTest; try { audioTest = new globalThis['Audio'](); - } catch (e) { + } catch { // No browser support for Audio. // IE can throw an error even if the Audio object exists. return; @@ -132,12 +132,12 @@ export class WorkspaceAudio { // Don't play one sound on top of another. const now = new Date(); if ( - this.lastSound_ !== null && - now.getTime() - this.lastSound_.getTime() < SOUND_LIMIT + this.lastSound !== null && + now.getTime() - this.lastSound.getTime() < SOUND_LIMIT ) { return; } - this.lastSound_ = now; + this.lastSound = now; let mySound; if (userAgent.IPAD || userAgent.ANDROID) { // Creating a new audio node causes lag in Android and iPad. Android diff --git a/core/workspace_dragger.ts b/core/workspace_dragger.ts index b9318b6d579..7ad5651f791 100644 --- a/core/workspace_dragger.ts +++ b/core/workspace_dragger.ts @@ -21,17 +21,17 @@ import type {WorkspaceSvg} from './workspace_svg.js'; * */ export class WorkspaceDragger { - private readonly horizontalScrollEnabled_: boolean; - private readonly verticalScrollEnabled_: boolean; + private readonly horizontalScrollEnabled: boolean; + private readonly verticalScrollEnabled: boolean; protected startScrollXY_: Coordinate; /** @param workspace The workspace to drag. */ constructor(private workspace: WorkspaceSvg) { /** Whether horizontal scroll is enabled. */ - this.horizontalScrollEnabled_ = this.workspace.isMovableHorizontally(); + this.horizontalScrollEnabled = this.workspace.isMovableHorizontally(); /** Whether vertical scroll is enabled. */ - this.verticalScrollEnabled_ = this.workspace.isMovableVertically(); + this.verticalScrollEnabled = this.workspace.isMovableVertically(); /** * The scroll position of the workspace at the beginning of the drag. @@ -84,11 +84,11 @@ export class WorkspaceDragger { drag(currentDragDeltaXY: Coordinate) { const newXY = Coordinate.sum(this.startScrollXY_, currentDragDeltaXY); - if (this.horizontalScrollEnabled_ && this.verticalScrollEnabled_) { + if (this.horizontalScrollEnabled && this.verticalScrollEnabled) { this.workspace.scroll(newXY.x, newXY.y); - } else if (this.horizontalScrollEnabled_) { + } else if (this.horizontalScrollEnabled) { this.workspace.scroll(newXY.x, this.workspace.scrollY); - } else if (this.verticalScrollEnabled_) { + } else if (this.verticalScrollEnabled) { this.workspace.scroll(this.workspace.scrollX, newXY.y); } else { throw new TypeError('Invalid state.'); diff --git a/core/workspace_svg.ts b/core/workspace_svg.ts index aad748105f0..6acd31c9c7f 100644 --- a/core/workspace_svg.ts +++ b/core/workspace_svg.ts @@ -22,12 +22,18 @@ import type {Block} from './block.js'; import type {BlockSvg} from './block_svg.js'; import type {BlocklyOptions} from './blockly_options.js'; import * as browserEvents from './browser_events.js'; +import {RenderedWorkspaceComment} from './comments/rendered_workspace_comment.js'; +import {WorkspaceComment} from './comments/workspace_comment.js'; import * as common from './common.js'; import {ComponentManager} from './component_manager.js'; import {ConnectionDB} from './connection_db.js'; import * as ContextMenu from './contextmenu.js'; -import {ContextMenuRegistry} from './contextmenu_registry.js'; +import { + ContextMenuOption, + ContextMenuRegistry, +} from './contextmenu_registry.js'; import * as dropDownDiv from './dropdowndiv.js'; +import {EventType} from './events/type.js'; import * as eventUtils from './events/utils.js'; import type {FlyoutButton} from './flyout_button.js'; import {Gesture} from './gesture.js'; @@ -40,10 +46,12 @@ import type {IMetricsManager} from './interfaces/i_metrics_manager.js'; import type {IToolbox} from './interfaces/i_toolbox.js'; import type {Cursor} from './keyboard_nav/cursor.js'; import type {Marker} from './keyboard_nav/marker.js'; +import {LayerManager} from './layer_manager.js'; import {MarkerManager} from './marker_manager.js'; import {Options} from './options.js'; import * as Procedures from './procedures.js'; import * as registry from './registry.js'; +import * as renderManagement from './render_management.js'; import * as blockRendering from './renderers/common/block_rendering.js'; import type {Renderer} from './renderers/common/renderer.js'; import type {ScrollbarPair} from './scrollbar_pair.js'; @@ -55,6 +63,7 @@ import type {Trashcan} from './trashcan.js'; import * as arrayUtils from './utils/array.js'; import {Coordinate} from './utils/coordinate.js'; import * as dom from './utils/dom.js'; +import * as drag from './utils/drag.js'; import type {Metrics} from './utils/metrics.js'; import {Rect} from './utils/rect.js'; import {Size} from './utils/size.js'; @@ -68,12 +77,7 @@ import * as VariablesDynamic from './variables_dynamic.js'; import * as WidgetDiv from './widgetdiv.js'; import {Workspace} from './workspace.js'; import {WorkspaceAudio} from './workspace_audio.js'; -import {WorkspaceComment} from './comments/workspace_comment.js'; import {ZoomControls} from './zoom_controls.js'; -import {ContextMenuOption} from './contextmenu_registry.js'; -import * as renderManagement from './render_management.js'; -import {LayerManager} from './layer_manager.js'; -import {RenderedWorkspaceComment} from './comments/rendered_workspace_comment.js'; /** Margin around the top/bottom/left/right after a zoomToFit call. */ const ZOOM_TO_FIT_MARGIN = 20; @@ -100,7 +104,7 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { * Whether the workspace is visible. False if the workspace has been hidden * by calling `setVisible(false)`. */ - private isVisible_ = true; + private visible = true; /** * Whether this workspace has resizes enabled. @@ -178,9 +182,6 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { /** Vertical scroll value when scrolling started in pixel units. */ startScrollY = 0; - /** Distance from mouse to object being dragged. */ - private dragDeltaXY: Coordinate | null = null; - /** Current scale. */ scale = 1; @@ -208,7 +209,7 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { * Category-based toolbox providing blocks which may be dragged into this * workspace. */ - private toolbox_: IToolbox | null = null; + private toolbox: IToolbox | null = null; /** * The current gesture in progress on this workspace, if any. @@ -339,7 +340,7 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { /** Translates the workspace. */ this.setMetrics = - options.setMetrics || WorkspaceSvg.setTopLevelWorkspaceMetrics_; + options.setMetrics || WorkspaceSvg.setTopLevelWorkspaceMetrics; this.componentManager = new ComponentManager(); @@ -539,16 +540,14 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { } // Update all blocks in workspace that have a style name. - this.updateBlockStyles_( - this.getAllBlocks(false).filter(function (block) { - return !!block.getStyleName(); - }), + this.updateBlockStyles( + this.getAllBlocks(false).filter((block) => !!block.getStyleName()), ); // Update current toolbox selection. this.refreshToolboxSelection(); - if (this.toolbox_) { - this.toolbox_.refreshTheme(); + if (this.toolbox) { + this.toolbox.refreshTheme(); } // Re-render if workspace is visible @@ -556,7 +555,7 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { this.setVisible(true); } - const event = new (eventUtils.get(eventUtils.THEME_CHANGE))( + const event = new (eventUtils.get(EventType.THEME_CHANGE))( this.getTheme().name, this.id, ); @@ -568,7 +567,7 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { * * @param blocks List of blocks to update the style on. */ - private updateBlockStyles_(blocks: Block[]) { + private updateBlockStyles(blocks: Block[]) { for (let i = 0, block; (block = blocks[i]); i++) { const blockStyleName = block.getStyleName(); if (blockStyleName) { @@ -609,7 +608,7 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { * False if the workspace has been hidden by calling `setVisible(false)`. */ isVisible(): boolean { - return this.isVisible_; + return this.visible; } /** @@ -782,7 +781,7 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { this.svgGroup_, 'pointerdown', this, - this.onMouseDown_, + this.onMouseDown, false, ); // This no-op works around https://bugs.webkit.org/show_bug.cgi?id=226683, @@ -794,7 +793,7 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { this.svgGroup_, 'wheel', this, - this.onMouseWheel_, + this.onMouseWheel, ); } @@ -806,7 +805,7 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { this.options, true, ); - this.toolbox_ = new ToolboxClass!(this); + this.toolbox = new ToolboxClass!(this); } if (this.grid) { this.grid.update(this.scale); @@ -817,7 +816,7 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { this.options, ); - CursorClass && this.markerManager.setCursor(new CursorClass()); + if (CursorClass) this.markerManager.setCursor(new CursorClass()); this.renderer.createDom(this.svgGroup_, this.getTheme()); return this.svgGroup_; @@ -836,9 +835,9 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { if (this.svgGroup_) { dom.removeNode(this.svgGroup_); } - if (this.toolbox_) { - this.toolbox_.dispose(); - this.toolbox_ = null; + if (this.toolbox) { + this.toolbox.dispose(); + this.toolbox = null; } if (this.flyout) { this.flyout.dispose(); @@ -995,8 +994,8 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { if (this.flyout || opt_own) { return this.flyout; } - if (this.toolbox_) { - return this.toolbox_.getFlyout(); + if (this.toolbox) { + return this.toolbox.getFlyout(); } return null; } @@ -1007,14 +1006,14 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { * @returns The toolbox on this workspace. */ getToolbox(): IToolbox | null { - return this.toolbox_; + return this.toolbox; } /** * Update items that use screen coordinate calculations * because something has changed (e.g. scroll position, window size). */ - private updateScreenCalculations_() { + private updateScreenCalculations() { this.updateInverseScreenCTM(); this.recordDragTargets(); } @@ -1044,8 +1043,8 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { * trash, zoom, toolbox, etc. (e.g. window resize). */ resize() { - if (this.toolbox_) { - this.toolbox_.position(); + if (this.toolbox) { + this.toolbox.position(); } if (this.flyout) { this.flyout.position(); @@ -1068,7 +1067,7 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { if (this.scrollbar) { this.scrollbar.resize(); } - this.updateScreenCalculations_(); + this.updateScreenCalculations(); } /** @@ -1078,14 +1077,12 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { * @internal */ updateScreenCalculationsIfScrolled() { - /* eslint-disable indent */ const currScroll = svgMath.getDocumentScroll(); if (!Coordinate.equals(this.lastRecordedPageScroll, currScroll)) { this.lastRecordedPageScroll = currScroll; - this.updateScreenCalculations_(); + this.updateScreenCalculations(); } } - /* eslint-enable indent */ /** * @returns The layer manager for this workspace. @@ -1179,7 +1176,7 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { // of negligible changes in viewport top/left. return; } - const event = new (eventUtils.get(eventUtils.VIEWPORT_CHANGE))( + const event = new (eventUtils.get(EventType.VIEWPORT_CHANGE))( top, left, scale, @@ -1224,7 +1221,7 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { * @param isVisible True if workspace should be visible. */ setVisible(isVisible: boolean) { - this.isVisible_ = isVisible; + this.visible = isVisible; if (!this.svgGroup_) { return; } @@ -1242,9 +1239,9 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { } this.getParentSvg().style.display = isVisible ? 'block' : 'none'; - if (this.toolbox_) { + if (this.toolbox) { // Currently does not support toolboxes in mutators. - this.toolbox_.setVisible(isVisible); + this.toolbox.setVisible(isVisible); } if (!isVisible) { this.hideChaff(true); @@ -1311,8 +1308,8 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { */ refreshToolboxSelection() { const ws = this.isFlyout ? this.targetWorkspace : this; - if (ws && !ws.currentGesture_ && ws.toolbox_ && ws.toolbox_.getFlyout()) { - ws.toolbox_.refreshSelection(); + if (ws && !ws.currentGesture_ && ws.toolbox && ws.toolbox.getFlyout()) { + ws.toolbox.refreshSelection(); } } @@ -1432,7 +1429,7 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { * * @param e Pointer down event. */ - private onMouseDown_(e: PointerEvent) { + private onMouseDown(e: PointerEvent) { const gesture = this.getGesture(e); if (gesture) { gesture.handleWsStart(e, this); @@ -1446,16 +1443,7 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { * @param xy Starting location of object. */ startDrag(e: PointerEvent, xy: Coordinate) { - // Record the starting offset between the bubble's location and the mouse. - const point = browserEvents.mouseToSvg( - e, - this.getParentSvg(), - this.getInverseScreenCTM(), - ); - // Fix scale of mouse event. - point.x /= this.scale; - point.y /= this.scale; - this.dragDeltaXY = Coordinate.difference(xy, point); + drag.start(this, e, xy); } /** @@ -1465,15 +1453,7 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { * @returns New location of object. */ moveDrag(e: PointerEvent): Coordinate { - const point = browserEvents.mouseToSvg( - e, - this.getParentSvg(), - this.getInverseScreenCTM(), - ); - // Fix scale of mouse event. - point.x /= this.scale; - point.y /= this.scale; - return Coordinate.sum(this.dragDeltaXY!, point); + return drag.move(this, e); } /** @@ -1548,7 +1528,7 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { * * @param e Mouse wheel event. */ - private onMouseWheel_(e: WheelEvent) { + private onMouseWheel(e: WheelEvent) { // Don't scroll or zoom anything if drag is in progress. if (Gesture.inProgress()) { e.preventDefault(); @@ -1644,23 +1624,56 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { return boundary; } - /** Clean up the workspace by ordering all the blocks in a column. */ + /** Clean up the workspace by ordering all the blocks in a column such that none overlap. */ cleanUp() { this.setResizesEnabled(false); eventUtils.setGroup(true); + const topBlocks = this.getTopBlocks(true); - let cursorY = 0; - for (let i = 0, block; (block = topBlocks[i]); i++) { - if (!block.isMovable()) { - continue; + const movableBlocks = topBlocks.filter((block) => block.isMovable()); + const immovableBlocks = topBlocks.filter((block) => !block.isMovable()); + + const immovableBlockBounds = immovableBlocks.map((block) => + block.getBoundingRectangle(), + ); + + const getNextIntersectingImmovableBlock = function ( + rect: Rect, + ): Rect | null { + for (const immovableRect of immovableBlockBounds) { + if (rect.intersects(immovableRect)) { + return immovableRect; + } } - const xy = block.getRelativeToSurfaceXY(); - block.moveBy(-xy.x, cursorY - xy.y, ['cleanup']); + return null; + }; + + let cursorY = 0; + const minBlockHeight = this.renderer.getConstants().MIN_BLOCK_HEIGHT; + for (const block of movableBlocks) { + // Make the initial movement of shifting the block to its best possible position. + let boundingRect = block.getBoundingRectangle(); + block.moveBy(-boundingRect.left, cursorY - boundingRect.top, ['cleanup']); block.snapToGrid(); + + boundingRect = block.getBoundingRectangle(); + let conflictingRect = getNextIntersectingImmovableBlock(boundingRect); + while (conflictingRect != null) { + // If the block intersects with an immovable block, move it down past that immovable block. + cursorY = + conflictingRect.top + conflictingRect.getHeight() + minBlockHeight; + block.moveBy(0, cursorY - boundingRect.top, ['cleanup']); + block.snapToGrid(); + boundingRect = block.getBoundingRectangle(); + conflictingRect = getNextIntersectingImmovableBlock(boundingRect); + } + + // Ensure all next blocks start past the most recent (which will also put them past all + // previously intersecting immovable blocks). cursorY = block.getRelativeToSurfaceXY().y + block.getHeightWidth().height + - this.renderer.getConstants().MIN_BLOCK_HEIGHT; + minBlockHeight; } eventUtils.setGroup(false); this.setResizesEnabled(true); @@ -1709,11 +1722,11 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { } if (toolbox.hasCategories(parsedToolboxDef)) { - if (!this.toolbox_) { + if (!this.toolbox) { throw Error("Existing toolbox has no categories. Can't change mode."); } this.options.languageTree = parsedToolboxDef; - this.toolbox_.render(parsedToolboxDef); + this.toolbox.render(parsedToolboxDef); } else { if (!this.flyout) { throw Error("Existing toolbox has categories. Can't change mode."); @@ -2404,7 +2417,7 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { * @param xyRatio Contains an x and/or y property which is a float between 0 * and 1 specifying the degree of scrolling. */ - private static setTopLevelWorkspaceMetrics_( + private static setTopLevelWorkspaceMetrics( this: WorkspaceSvg, xyRatio: {x?: number; y?: number}, ) { diff --git a/core/xml.ts b/core/xml.ts index bad381c5d85..cecc4dce20e 100644 --- a/core/xml.ts +++ b/core/xml.ts @@ -8,12 +8,17 @@ import type {Block} from './block.js'; import type {BlockSvg} from './block_svg.js'; +import {RenderedWorkspaceComment} from './comments/rendered_workspace_comment.js'; +import {WorkspaceComment} from './comments/workspace_comment.js'; import type {Connection} from './connection.js'; import {MANUALLY_DISABLED} from './constants.js'; +import {EventType} from './events/type.js'; import * as eventUtils from './events/utils.js'; import type {Field} from './field.js'; import {IconType} from './icons/icon_types.js'; import {inputTypes} from './inputs/input_types.js'; +import * as renderManagement from './render_management.js'; +import {Coordinate} from './utils/coordinate.js'; import * as dom from './utils/dom.js'; import {Size} from './utils/size.js'; import * as utilsXml from './utils/xml.js'; @@ -21,10 +26,6 @@ import type {VariableModel} from './variable_model.js'; import * as Variables from './variables.js'; import type {Workspace} from './workspace.js'; import {WorkspaceSvg} from './workspace_svg.js'; -import * as renderManagement from './render_management.js'; -import {WorkspaceComment} from './comments/workspace_comment.js'; -import {RenderedWorkspaceComment} from './comments/rendered_workspace_comment.js'; -import {Coordinate} from './utils/coordinate.js'; /** * Encode a block tree as XML. @@ -497,7 +498,7 @@ export function domToWorkspace(xml: Element, workspace: Workspace): string[] { dom.stopTextWidthCache(); } // Re-enable workspace resizing. - eventUtils.fire(new (eventUtils.get(eventUtils.FINISHED_LOADING))(workspace)); + eventUtils.fire(new (eventUtils.get(EventType.FINISHED_LOADING))(workspace)); return newBlockIds; } @@ -666,13 +667,11 @@ export function domToBlockInternal( // Fire a VarCreate event for each (if any) new variable created. for (let i = 0; i < newVariables.length; i++) { const thisVariable = newVariables[i]; - eventUtils.fire( - new (eventUtils.get(eventUtils.VAR_CREATE))(thisVariable), - ); + eventUtils.fire(new (eventUtils.get(EventType.VAR_CREATE))(thisVariable)); } // Block events come after var events, in case they refer to newly created // variables. - eventUtils.fire(new (eventUtils.get(eventUtils.CREATE))(topBlock)); + eventUtils.fire(new (eventUtils.get(EventType.BLOCK_CREATE))(topBlock)); } return topBlock; } diff --git a/core/zoom_controls.ts b/core/zoom_controls.ts index 6534c732271..4f14b73bed6 100644 --- a/core/zoom_controls.ts +++ b/core/zoom_controls.ts @@ -17,6 +17,7 @@ import './events/events_click.js'; import * as browserEvents from './browser_events.js'; import {ComponentManager} from './component_manager.js'; import * as Css from './css.js'; +import {EventType} from './events/type.js'; import * as eventUtils from './events/utils.js'; import type {IPositionable} from './interfaces/i_positionable.js'; import type {UiMetrics} from './metrics_manager.js'; @@ -116,7 +117,7 @@ export class ZoomControls implements IPositionable { init() { this.workspace.getComponentManager().addComponent({ component: this, - weight: 2, + weight: ComponentManager.ComponentWeight.ZOOM_CONTROLS_WEIGHT, capabilities: [ComponentManager.Capability.POSITIONABLE], }); this.initialized = true; @@ -467,7 +468,7 @@ export class ZoomControls implements IPositionable { /** Fires a zoom control UI event. */ private fireZoomEvent() { - const uiEvent = new (eventUtils.get(eventUtils.CLICK))( + const uiEvent = new (eventUtils.get(EventType.CLICK))( null, this.workspace.id, 'zoom_controls', diff --git a/demos/blockfactory/app_controller.js b/demos/blockfactory/app_controller.js index fcfa2296dcf..3626eccf641 100644 --- a/demos/blockfactory/app_controller.js +++ b/demos/blockfactory/app_controller.js @@ -507,7 +507,7 @@ AppController.prototype.assignBlockFactoryClickHandlers = function() { document.getElementById('helpButton').addEventListener('click', function() { - open('https://developers.google.com/blockly/custom-blocks/block-factory', + open('https://developers.google.com/blockly/guides/create-custom-blocks/legacy-blockly-developer-tools', 'BlockFactoryHelp'); }); diff --git a/demos/blockfactory/block_library_controller.js b/demos/blockfactory/block_library_controller.js index 7bb34e8d623..8eed54db02c 100644 --- a/demos/blockfactory/block_library_controller.js +++ b/demos/blockfactory/block_library_controller.js @@ -109,9 +109,9 @@ BlockLibraryController.prototype.clearBlockLibrary = function() { BlockLibraryController.prototype.saveToBlockLibrary = function() { var blockType = this.getCurrentBlockType(); // If user has not changed the name of the starter block. - if (blockType === 'block_type') { + if (reservedBlockFactoryBlocks.has(blockType) || blockType === 'block_type') { // Do not save block if it has the default type, 'block_type'. - var msg = 'You cannot save a block under the name "block_type". Try ' + + var msg = `You cannot save a block under the name "${blockType}". Try ` + 'changing the name before saving. Then, click on the "Block Library"' + ' button to view your saved blocks.'; alert(msg); diff --git a/demos/blockfactory/block_library_view.js b/demos/blockfactory/block_library_view.js index a479804080b..2c91ce3782e 100644 --- a/demos/blockfactory/block_library_view.js +++ b/demos/blockfactory/block_library_view.js @@ -104,36 +104,36 @@ BlockLibraryView.prototype.updateButtons = // User is editing a block. if (!isInLibrary) { - // Block type has not been saved to library yet. Disable the delete button - // and allow user to save. + // Block type has not been saved to the library yet. + // Disable the delete button. this.saveButton.textContent = 'Save "' + blockType + '"'; - this.saveButton.disabled = false; this.deleteButton.disabled = true; } else { - // Block type has already been saved. Disable the save button unless the - // there are unsaved changes (checked below). + // A version of the block type has already been saved. + // Enable the delete button. this.saveButton.textContent = 'Update "' + blockType + '"'; - this.saveButton.disabled = true; this.deleteButton.disabled = false; } this.deleteButton.textContent = 'Delete "' + blockType + '"'; - // If changes to block have been made and are not saved, make button - // green to encourage user to save the block. + this.saveButton.classList.remove('button_alert', 'button_warn'); if (!savedChanges) { - var buttonFormatClass = 'button_warn'; + var buttonFormatClass; - // If block type is the default, 'block_type', make button red to alert - // user. - if (blockType === 'block_type') { + var isReserved = reservedBlockFactoryBlocks.has(blockType); + if (isReserved || blockType === 'block_type') { + // Make button red to alert user that the block type can't be saved. buttonFormatClass = 'button_alert'; + } else { + // Block type has not been saved to library yet or has unsaved changes. + // Make the button green to encourage the user to save the block. + buttonFormatClass = 'button_warn'; } this.saveButton.classList.add(buttonFormatClass); this.saveButton.disabled = false; } else { // No changes to save. - this.saveButton.classList.remove('button_alert', 'button_warn'); this.saveButton.disabled = true; } diff --git a/demos/blockfactory/blocks.js b/demos/blockfactory/blocks.js index 15c8ac864d6..9a983460f5f 100644 --- a/demos/blockfactory/blocks.js +++ b/demos/blockfactory/blocks.js @@ -85,8 +85,8 @@ Blockly.Blocks['factory_base'] = { var type = this.workspace.newBlock('type_null'); type.setShadow(true); type.outputConnection.connect(this.getInput(outputType).connection); - type.initSvg(); if (this.rendered) { + type.initSvg(); type.render(); } }, @@ -914,3 +914,7 @@ function inputNameCheck(referenceBlock) { 'There are ' + count + ' input blocks\n with this name.' : null; referenceBlock.setWarningText(msg); } + +// Make a set of all of block types that are required for the block factory. +var reservedBlockFactoryBlocks = + new Set(Object.getOwnPropertyNames(Blockly.Blocks)); diff --git a/demos/blockfactory/factory.css b/demos/blockfactory/factory.css index 73a1c1e3ceb..ded1f6cda50 100644 --- a/demos/blockfactory/factory.css +++ b/demos/blockfactory/factory.css @@ -127,6 +127,13 @@ button, .buttonStyle { float: right; } +#legacyBanner { + border: #ccc 1px solid; + background-color: #FFCDD2; + margin: 4px; + padding: 4px; +} + #blockFactoryContent { height: 85%; width: 100%; diff --git a/demos/blockfactory/factory.js b/demos/blockfactory/factory.js index 07ee889de7f..2e6ebc924e1 100644 --- a/demos/blockfactory/factory.js +++ b/demos/blockfactory/factory.js @@ -187,8 +187,9 @@ BlockFactory.updatePreview = function() { // Don't let the user create a block type that already exists, // because it doesn't work. var warnExistingBlock = function(blockType) { - if (blockType in Blockly.Blocks) { - var text = `You can't make a block called ${blockType} in this tool because that name already exists.`; + if (reservedBlockFactoryBlocks.has(blockType)) { + var text = `You can't make a block called ${blockType} in this tool ` + + `because that name is reserved.`; FactoryUtils.getRootBlock(BlockFactory.mainWorkspace).setWarningText(text); console.error(text); return true; diff --git a/demos/blockfactory/index.html b/demos/blockfactory/index.html index 77687bce14a..3e532bc49a6 100644 --- a/demos/blockfactory/index.html +++ b/demos/blockfactory/index.html @@ -53,6 +53,9 @@

Blockly >

+
+ This version of Developer Tools is only compatible with Blockly version 10 and earlier. Try the new Block Factory and learn how to migrate your blocks. +
Block Factory
Block Exporter
diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 00000000000..68f25133fa5 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,308 @@ +import eslint from '@eslint/js'; +import googleStyle from 'eslint-config-google'; +import jsdoc from 'eslint-plugin-jsdoc'; +import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'; +import globals from 'globals'; +import tseslint from 'typescript-eslint'; + +// These rules are no longer supported, but the Google style package we depend +// on hasn't been updated in years to remove them, even though they have been +// removed from the repo. Manually delete them here to avoid breaking linting. +delete googleStyle.rules['valid-jsdoc']; +delete googleStyle.rules['require-jsdoc']; + +const rules = { + 'spaced-comment': [ + 'error', + 'always', + { + 'block': { + 'balanced': true, + }, + 'exceptions': ['*'], + }, + ], + // Blockly uses prefixes for optional arguments and test-only functions. + 'camelcase': [ + 'error', + { + 'properties': 'never', + 'allow': ['^opt_', '^_opt_', '^testOnly_'], + }, + ], + // Blockly uses capital letters for some non-constructor namespaces. + // Keep them for legacy reasons. + 'new-cap': ['off'], + // Blockly uses objects as maps, but uses Object.create(null) to + // instantiate them. + 'guard-for-in': ['off'], +}; + +/** + * Build shared settings for TS linting and add in the config differences. + * @param {object} root0 A configuration options struct. + * @param {!Array} root0.files List of file globs to apply rules to. + * @param {string} root0.tsconfig Path to the tsconfig.json file to use. + * @returns {object} The override TS linting for given files and a given + * tsconfig. + */ +function buildTSOverride({files, tsconfig}) { + return { + files: files, + plugins: { + '@typescript-eslint': tseslint.plugin, + jsdoc, + }, + languageOptions: { + parser: tseslint.parser, + 'ecmaVersion': 2020, + 'sourceType': 'module', + parserOptions: { + 'project': tsconfig, + 'tsconfigRootDir': '.', + }, + globals: { + ...globals.browser, + }, + }, + extends: [ + ...tseslint.configs.recommended, + jsdoc.configs['flat/recommended-typescript'], + eslintPluginPrettierRecommended, + ], + rules: { + // TS rules + // Blockly uses namespaces to do declaration merging in some cases. + '@typescript-eslint/no-namespace': ['off'], + // Use the updated TypeScript-specific rule. + 'no-invalid-this': ['off'], + '@typescript-eslint/no-invalid-this': ['error'], + '@typescript-eslint/no-unused-vars': [ + 'error', + { + 'argsIgnorePattern': '^_', + 'varsIgnorePattern': '^_', + }, + ], + // Temporarily disable. 23 problems. + '@typescript-eslint/no-explicit-any': ['off'], + // We use this pattern extensively for block (e.g. controls_if) interfaces. + '@typescript-eslint/no-empty-object-type': ['off'], + + // params and returns docs are optional. + 'jsdoc/require-param-description': ['off'], + 'jsdoc/require-returns': ['off'], + // Disable for now (breaks on `this` which is not really a param). + 'jsdoc/require-param': ['off'], + // Don't auto-add missing jsdoc. Only required on exported items. + 'jsdoc/require-jsdoc': [ + 'warn', + { + 'enableFixer': false, + 'publicOnly': true, + }, + ], + 'jsdoc/check-tag-names': [ + 'error', + { + 'definedTags': [ + 'sealed', + 'typeParam', + 'remarks', + 'define', + 'nocollapse', + ], + }, + ], + // Disabled due to not handling `this`. If re-enabled, + // checkDestructured option + // should be left as false. + 'jsdoc/check-param-names': ['off', {'checkDestructured': false}], + // Allow any text in the license tag. Other checks are not relevant. + 'jsdoc/check-values': ['off'], + // Ensure there is a blank line between the body and any @tags, + // as required by the tsdoc spec (see #6353). + 'jsdoc/tag-lines': ['error', 'any', {'startLines': 1}], + }, + }; +} + +export default [ + { + // Note: there should be no other properties in this object + ignores: [ + // Build artifacts + 'msg/*', + 'build/*', + 'dist/*', + 'typings/*', + 'docs/*', + // Tests other than mocha unit tests + 'tests/blocks/*', + 'tests/themes/*', + 'tests/compile/*', + 'tests/jsunit/*', + 'tests/generators/*', + 'tests/mocha/webdriver.js', + 'tests/screenshot/*', + 'tests/test_runner.js', + 'tests/workspace_svg/*', + // Demos, scripts, misc + 'node_modules/*', + 'generators/*', + 'demos/*', + 'appengine/*', + 'externs/*', + 'closure/*', + 'scripts/gulpfiles/*', + 'CHANGELOG.md', + 'PULL_REQUEST_TEMPLATE.md', + ], + }, + eslint.configs.recommended, + jsdoc.configs['flat/recommended'], + googleStyle, + { + languageOptions: { + ecmaVersion: 2020, + sourceType: 'module', + }, + settings: { + // Allowlist some JSDoc tag aliases we use. + 'jsdoc': { + 'tagNamePreference': { + 'return': 'return', + 'fileoverview': 'fileoverview', + 'extends': 'extends', + 'constructor': 'constructor', + }, + }, + }, + rules, + }, + { + files: [ + 'eslint.config.mjs', + '.prettierrc.js', + 'gulpfile.js', + 'scripts/helpers.js', + 'tests/mocha/.mocharc.js', + 'tests/migration/validate-renamings.mjs', + ], + languageOptions: { + globals: { + ...globals.node, + }, + }, + rules: { + 'jsdoc/check-values': ['off'], + }, + }, + { + files: ['tests/**'], + languageOptions: { + globals: { + 'Blockly': true, + 'dartGenerator': true, + 'javascriptGenerator': true, + 'luaGenerator': true, + 'phpGenerator': true, + 'pythonGenerator': true, + }, + }, + rules: { + 'jsdoc/check-values': ['off'], + 'jsdoc/require-returns': ['off'], + 'jsdoc/no-undefined-types': ['off'], + 'jsdoc/valid-types': ['off'], + 'jsdoc/check-types': ['off'], + 'jsdoc/check-tag-names': ['warn', {'definedTags': ['record']}], + 'jsdoc/tag-lines': ['off'], + 'jsdoc/no-defaults': ['off'], + }, + }, + { + files: ['tests/browser/**'], + languageOptions: { + sourceType: 'module', + globals: { + 'chai': false, + 'sinon': false, + ...globals.mocha, + ...globals.browser, + ...globals.node, + }, + }, + rules: { + // Allow uncommented helper functions in tests. + 'jsdoc/require-jsdoc': ['off'], + 'jsdoc/require-returns-type': ['off'], + 'jsdoc/require-param-type': ['off'], + 'no-invalid-this': ['off'], + }, + }, + { + files: ['tests/mocha/**'], + languageOptions: { + sourceType: 'module', + globals: { + 'chai': false, + 'sinon': false, + ...globals.mocha, + ...globals.browser, + }, + }, + rules: { + 'no-unused-vars': ['off'], + // Allow uncommented helper functions in tests. + 'jsdoc/require-jsdoc': ['off'], + 'prefer-rest-params': ['off'], + 'no-invalid-this': ['off'], + }, + }, + { + files: ['tests/node/**'], + languageOptions: { + globals: { + 'console': true, + 'require': true, + ...globals.mocha, + ...globals.node, + }, + }, + }, + { + files: ['tests/playgrounds/**', 'tests/scripts/**'], + languageOptions: { + globals: { + ...globals.browser, + }, + }, + }, + { + files: ['scripts/**'], + languageOptions: { + globals: { + ...globals.browser, + }, + }, + rules: { + 'jsdoc/check-values': ['off'], + 'jsdoc/require-returns': ['off'], + 'jsdoc/tag-lines': ['off'], + }, + }, + ...tseslint.config( + buildTSOverride({ + files: ['**/*.ts', '**/*.tsx'], + tsconfig: './tsconfig.json', + }), + buildTSOverride({ + files: ['tests/typescript/**/*.ts', 'tests/typescript/**/*.tsx'], + tsconfig: './tests/typescript/tsconfig.json', + }), + ), + // Per the docs, this should be at the end because it disables rules that + // conflict with Prettier. + eslintPluginPrettierRecommended, +]; diff --git a/generators/dart/dart_generator.ts b/generators/dart/dart_generator.ts index 222bbd41d7c..20feeda6f41 100644 --- a/generators/dart/dart_generator.ts +++ b/generators/dart/dart_generator.ts @@ -11,13 +11,13 @@ // Former goog.module ID: Blockly.Dart -import * as Variables from '../../core/variables.js'; -import * as stringUtils from '../../core/utils/string.js'; import type {Block} from '../../core/block.js'; import {CodeGenerator} from '../../core/generator.js'; +import {inputTypes} from '../../core/inputs/input_types.js'; import {Names, NameType} from '../../core/names.js'; +import * as stringUtils from '../../core/utils/string.js'; +import * as Variables from '../../core/variables.js'; import type {Workspace} from '../../core/workspace.js'; -import {inputTypes} from '../../core/inputs/input_types.js'; /** * Order of operation ENUMs. diff --git a/generators/dart/lists.ts b/generators/dart/lists.ts index 4aaf3990592..176b88dc438 100644 --- a/generators/dart/lists.ts +++ b/generators/dart/lists.ts @@ -10,10 +10,10 @@ // Former goog.module ID: Blockly.Dart.lists -import type {Block} from '../../core/block.js'; import type {CreateWithBlock} from '../../blocks/lists.js'; -import type {DartGenerator} from './dart_generator.js'; +import type {Block} from '../../core/block.js'; import {NameType} from '../../core/names.js'; +import type {DartGenerator} from './dart_generator.js'; import {Order} from './dart_generator.js'; // RESERVED WORDS: 'Math' diff --git a/generators/dart/loops.ts b/generators/dart/loops.ts index a6b6bb18048..f2e6efab026 100644 --- a/generators/dart/loops.ts +++ b/generators/dart/loops.ts @@ -10,11 +10,11 @@ // Former goog.module ID: Blockly.Dart.loops -import * as stringUtils from '../../core/utils/string.js'; -import type {Block} from '../../core/block.js'; import type {ControlFlowInLoopBlock} from '../../blocks/loops.js'; -import type {DartGenerator} from './dart_generator.js'; +import type {Block} from '../../core/block.js'; import {NameType} from '../../core/names.js'; +import * as stringUtils from '../../core/utils/string.js'; +import type {DartGenerator} from './dart_generator.js'; import {Order} from './dart_generator.js'; export function controls_repeat_ext(block: Block, generator: DartGenerator) { diff --git a/generators/dart/procedures.ts b/generators/dart/procedures.ts index 0ecf6d21008..8890e713c90 100644 --- a/generators/dart/procedures.ts +++ b/generators/dart/procedures.ts @@ -10,8 +10,8 @@ // Former goog.module ID: Blockly.Dart.procedures -import type {Block} from '../../core/block.js'; import type {IfReturnBlock} from '../../blocks/procedures.js'; +import type {Block} from '../../core/block.js'; import type {DartGenerator} from './dart_generator.js'; import {Order} from './dart_generator.js'; diff --git a/generators/dart/text.ts b/generators/dart/text.ts index c141eaad0fa..c189c32cf5a 100644 --- a/generators/dart/text.ts +++ b/generators/dart/text.ts @@ -10,9 +10,9 @@ // Former goog.module ID: Blockly.Dart.texts +import type {JoinMutatorBlock} from '../../blocks/text.js'; import type {Block} from '../../core/block.js'; import type {DartGenerator} from './dart_generator.js'; -import type {JoinMutatorBlock} from '../../blocks/text.js'; import {Order} from './dart_generator.js'; // RESERVED WORDS: 'Html,Math' diff --git a/generators/javascript/javascript_generator.ts b/generators/javascript/javascript_generator.ts index 592563f919d..a247ed5dd74 100644 --- a/generators/javascript/javascript_generator.ts +++ b/generators/javascript/javascript_generator.ts @@ -11,13 +11,13 @@ // Former goog.module ID: Blockly.JavaScript -import * as Variables from '../../core/variables.js'; -import * as stringUtils from '../../core/utils/string.js'; import type {Block} from '../../core/block.js'; import {CodeGenerator} from '../../core/generator.js'; +import {inputTypes} from '../../core/inputs/input_types.js'; import {Names, NameType} from '../../core/names.js'; +import * as stringUtils from '../../core/utils/string.js'; +import * as Variables from '../../core/variables.js'; import type {Workspace} from '../../core/workspace.js'; -import {inputTypes} from '../../core/inputs/input_types.js'; /** * Order of operation ENUMs. diff --git a/generators/javascript/lists.ts b/generators/javascript/lists.ts index bbed5231b56..7fd1887fb2e 100644 --- a/generators/javascript/lists.ts +++ b/generators/javascript/lists.ts @@ -10,10 +10,10 @@ // Former goog.module ID: Blockly.JavaScript.lists -import type {Block} from '../../core/block.js'; import type {CreateWithBlock} from '../../blocks/lists.js'; -import type {JavascriptGenerator} from './javascript_generator.js'; +import type {Block} from '../../core/block.js'; import {NameType} from '../../core/names.js'; +import type {JavascriptGenerator} from './javascript_generator.js'; import {Order} from './javascript_generator.js'; export function lists_create_empty( diff --git a/generators/javascript/loops.ts b/generators/javascript/loops.ts index 555e43ff1a9..2bc56158259 100644 --- a/generators/javascript/loops.ts +++ b/generators/javascript/loops.ts @@ -10,11 +10,11 @@ // Former goog.module ID: Blockly.JavaScript.loops -import * as stringUtils from '../../core/utils/string.js'; -import type {Block} from '../../core/block.js'; import type {ControlFlowInLoopBlock} from '../../blocks/loops.js'; -import type {JavascriptGenerator} from './javascript_generator.js'; +import type {Block} from '../../core/block.js'; import {NameType} from '../../core/names.js'; +import * as stringUtils from '../../core/utils/string.js'; +import type {JavascriptGenerator} from './javascript_generator.js'; import {Order} from './javascript_generator.js'; export function controls_repeat_ext( diff --git a/generators/javascript/procedures.ts b/generators/javascript/procedures.ts index e0a055217cf..d4a2e203451 100644 --- a/generators/javascript/procedures.ts +++ b/generators/javascript/procedures.ts @@ -10,8 +10,8 @@ // Former goog.module ID: Blockly.JavaScript.procedures -import type {Block} from '../../core/block.js'; import type {IfReturnBlock} from '../../blocks/procedures.js'; +import type {Block} from '../../core/block.js'; import type {JavascriptGenerator} from './javascript_generator.js'; import {Order} from './javascript_generator.js'; diff --git a/generators/javascript/text.ts b/generators/javascript/text.ts index d31bdcf4b95..f991bb28a65 100644 --- a/generators/javascript/text.ts +++ b/generators/javascript/text.ts @@ -10,9 +10,9 @@ // Former goog.module ID: Blockly.JavaScript.texts +import type {JoinMutatorBlock} from '../../blocks/text.js'; import type {Block} from '../../core/block.js'; import type {JavascriptGenerator} from './javascript_generator.js'; -import type {JoinMutatorBlock} from '../../blocks/text.js'; import {Order} from './javascript_generator.js'; /** diff --git a/generators/lua.ts b/generators/lua.ts index 0cf81fb961f..35ac570af14 100644 --- a/generators/lua.ts +++ b/generators/lua.ts @@ -11,10 +11,10 @@ // Former goog.module ID: Blockly.Lua.all -import {LuaGenerator} from './lua/lua_generator.js'; import * as lists from './lua/lists.js'; import * as logic from './lua/logic.js'; import * as loops from './lua/loops.js'; +import {LuaGenerator} from './lua/lua_generator.js'; import * as math from './lua/math.js'; import * as procedures from './lua/procedures.js'; import * as text from './lua/text.js'; diff --git a/generators/lua/lists.ts b/generators/lua/lists.ts index 901ed88a671..f1f90cc4aed 100644 --- a/generators/lua/lists.ts +++ b/generators/lua/lists.ts @@ -10,10 +10,10 @@ // Former goog.module ID: Blockly.Lua.lists -import type {Block} from '../../core/block.js'; import type {CreateWithBlock} from '../../blocks/lists.js'; -import type {LuaGenerator} from './lua_generator.js'; +import type {Block} from '../../core/block.js'; import {NameType} from '../../core/names.js'; +import type {LuaGenerator} from './lua_generator.js'; import {Order} from './lua_generator.js'; export function lists_create_empty( diff --git a/generators/lua/loops.ts b/generators/lua/loops.ts index 01474cd81c5..2c09f6279f6 100644 --- a/generators/lua/loops.ts +++ b/generators/lua/loops.ts @@ -10,11 +10,11 @@ // Former goog.module ID: Blockly.Lua.loops -import * as stringUtils from '../../core/utils/string.js'; -import type {Block} from '../../core/block.js'; import type {ControlFlowInLoopBlock} from '../../blocks/loops.js'; -import type {LuaGenerator} from './lua_generator.js'; +import type {Block} from '../../core/block.js'; import {NameType} from '../../core/names.js'; +import * as stringUtils from '../../core/utils/string.js'; +import type {LuaGenerator} from './lua_generator.js'; import {Order} from './lua_generator.js'; /** diff --git a/generators/lua/lua_generator.ts b/generators/lua/lua_generator.ts index 76517c77d38..b753ff2c6d2 100644 --- a/generators/lua/lua_generator.ts +++ b/generators/lua/lua_generator.ts @@ -13,12 +13,12 @@ // Former goog.module ID: Blockly.Lua -import * as stringUtils from '../../core/utils/string.js'; import type {Block} from '../../core/block.js'; import {CodeGenerator} from '../../core/generator.js'; +import {inputTypes} from '../../core/inputs/input_types.js'; import {Names} from '../../core/names.js'; +import * as stringUtils from '../../core/utils/string.js'; import type {Workspace} from '../../core/workspace.js'; -import {inputTypes} from '../../core/inputs/input_types.js'; /** * Order of operation ENUMs. diff --git a/generators/lua/procedures.ts b/generators/lua/procedures.ts index 79dc58aa252..bd78ef7a619 100644 --- a/generators/lua/procedures.ts +++ b/generators/lua/procedures.ts @@ -10,8 +10,8 @@ // Former goog.module ID: Blockly.Lua.procedures -import type {Block} from '../../core/block.js'; import type {IfReturnBlock} from '../../blocks/procedures.js'; +import type {Block} from '../../core/block.js'; import type {LuaGenerator} from './lua_generator.js'; import {Order} from './lua_generator.js'; diff --git a/generators/lua/text.ts b/generators/lua/text.ts index 1c4a79a8e96..47d9a2033e4 100644 --- a/generators/lua/text.ts +++ b/generators/lua/text.ts @@ -10,8 +10,8 @@ // Former goog.module ID: Blockly.Lua.texts -import type {Block} from '../../core/block.js'; import type {JoinMutatorBlock} from '../../blocks/text.js'; +import type {Block} from '../../core/block.js'; import type {LuaGenerator} from './lua_generator.js'; import {Order} from './lua_generator.js'; diff --git a/generators/php.ts b/generators/php.ts index 30a08086670..69f6cda74de 100644 --- a/generators/php.ts +++ b/generators/php.ts @@ -12,11 +12,11 @@ // Former goog.module ID: Blockly.PHP.all -import {PhpGenerator} from './php/php_generator.js'; import * as lists from './php/lists.js'; import * as logic from './php/logic.js'; import * as loops from './php/loops.js'; import * as math from './php/math.js'; +import {PhpGenerator} from './php/php_generator.js'; import * as procedures from './php/procedures.js'; import * as text from './php/text.js'; import * as variables from './php/variables.js'; diff --git a/generators/php/lists.ts b/generators/php/lists.ts index 7ca2639b7f2..009d7ccc807 100644 --- a/generators/php/lists.ts +++ b/generators/php/lists.ts @@ -21,12 +21,12 @@ // Former goog.module ID: Blockly.generator.lists -import * as stringUtils from '../../core/utils/string.js'; -import type {Block} from '../../core/block.js'; import type {CreateWithBlock} from '../../blocks/lists.js'; +import type {Block} from '../../core/block.js'; import {NameType} from '../../core/names.js'; -import {Order} from './php_generator.js'; +import * as stringUtils from '../../core/utils/string.js'; import type {PhpGenerator} from './php_generator.js'; +import {Order} from './php_generator.js'; export function lists_create_empty( block: Block, diff --git a/generators/php/logic.ts b/generators/php/logic.ts index 8aaa5c89213..731fe570867 100644 --- a/generators/php/logic.ts +++ b/generators/php/logic.ts @@ -11,8 +11,8 @@ // Former goog.module ID: Blockly.PHP.logic import type {Block} from '../../core/block.js'; -import {Order} from './php_generator.js'; import type {PhpGenerator} from './php_generator.js'; +import {Order} from './php_generator.js'; export function controls_if(block: Block, generator: PhpGenerator) { // If/elseif/else condition. diff --git a/generators/php/loops.ts b/generators/php/loops.ts index ae87dbb294b..991cbaf4e9b 100644 --- a/generators/php/loops.ts +++ b/generators/php/loops.ts @@ -10,12 +10,12 @@ // Former goog.module ID: Blockly.PHP.loops -import * as stringUtils from '../../core/utils/string.js'; -import type {Block} from '../../core/block.js'; import type {ControlFlowInLoopBlock} from '../../blocks/loops.js'; +import type {Block} from '../../core/block.js'; import {NameType} from '../../core/names.js'; -import {Order} from './php_generator.js'; +import * as stringUtils from '../../core/utils/string.js'; import type {PhpGenerator} from './php_generator.js'; +import {Order} from './php_generator.js'; export function controls_repeat_ext(block: Block, generator: PhpGenerator) { // Repeat n times. diff --git a/generators/php/math.ts b/generators/php/math.ts index 6218bf4d114..2026af0641e 100644 --- a/generators/php/math.ts +++ b/generators/php/math.ts @@ -11,8 +11,8 @@ // Former goog.module ID: Blockly.PHP.math import type {Block} from '../../core/block.js'; -import {Order} from './php_generator.js'; import type {PhpGenerator} from './php_generator.js'; +import {Order} from './php_generator.js'; export function math_number( block: Block, diff --git a/generators/php/php_generator.ts b/generators/php/php_generator.ts index ecdfb76fd01..8ac23c057bd 100644 --- a/generators/php/php_generator.ts +++ b/generators/php/php_generator.ts @@ -11,12 +11,12 @@ // Former goog.module ID: Blockly.PHP -import * as stringUtils from '../../core/utils/string.js'; import type {Block} from '../../core/block.js'; import {CodeGenerator} from '../../core/generator.js'; +import {inputTypes} from '../../core/inputs/input_types.js'; import {Names} from '../../core/names.js'; +import * as stringUtils from '../../core/utils/string.js'; import type {Workspace} from '../../core/workspace.js'; -import {inputTypes} from '../../core/inputs/input_types.js'; /** * Order of operation ENUMs. diff --git a/generators/php/procedures.ts b/generators/php/procedures.ts index acf84aea658..bad6c1443aa 100644 --- a/generators/php/procedures.ts +++ b/generators/php/procedures.ts @@ -10,12 +10,12 @@ // Former goog.module ID: Blockly.PHP.procedures -import * as Variables from '../../core/variables.js'; -import type {Block} from '../../core/block.js'; import type {IfReturnBlock} from '../../blocks/procedures.js'; +import type {Block} from '../../core/block.js'; import {NameType} from '../../core/names.js'; -import {Order} from './php_generator.js'; +import * as Variables from '../../core/variables.js'; import type {PhpGenerator} from './php_generator.js'; +import {Order} from './php_generator.js'; export function procedures_defreturn(block: Block, generator: PhpGenerator) { // Define a procedure with a return value. diff --git a/generators/php/text.ts b/generators/php/text.ts index 811e0251fb3..f50c7694602 100644 --- a/generators/php/text.ts +++ b/generators/php/text.ts @@ -10,10 +10,10 @@ // Former goog.module ID: Blockly.PHP.texts -import type {Block} from '../../core/block.js'; import type {JoinMutatorBlock} from '../../blocks/text.js'; -import {Order} from './php_generator.js'; +import type {Block} from '../../core/block.js'; import type {PhpGenerator} from './php_generator.js'; +import {Order} from './php_generator.js'; export function text(block: Block, generator: PhpGenerator): [string, Order] { // Text value. diff --git a/generators/php/variables.ts b/generators/php/variables.ts index 4aacc293b6d..2275719da81 100644 --- a/generators/php/variables.ts +++ b/generators/php/variables.ts @@ -11,8 +11,8 @@ // Former goog.module ID: Blockly.PHP.variables import type {Block} from '../../core/block.js'; -import {Order} from './php_generator.js'; import type {PhpGenerator} from './php_generator.js'; +import {Order} from './php_generator.js'; export function variables_get( block: Block, diff --git a/generators/python.ts b/generators/python.ts index d7b505763d7..6d57229e39d 100644 --- a/generators/python.ts +++ b/generators/python.ts @@ -12,12 +12,12 @@ // Former goog.module ID: Blockly.Python.all -import {PythonGenerator} from './python/python_generator.js'; import * as lists from './python/lists.js'; import * as logic from './python/logic.js'; import * as loops from './python/loops.js'; import * as math from './python/math.js'; import * as procedures from './python/procedures.js'; +import {PythonGenerator} from './python/python_generator.js'; import * as text from './python/text.js'; import * as variables from './python/variables.js'; import * as variablesDynamic from './python/variables_dynamic.js'; diff --git a/generators/python/lists.ts b/generators/python/lists.ts index 6e412c23fa3..79cfe9dd863 100644 --- a/generators/python/lists.ts +++ b/generators/python/lists.ts @@ -10,12 +10,12 @@ // Former goog.module ID: Blockly.Python.lists -import * as stringUtils from '../../core/utils/string.js'; -import type {Block} from '../../core/block.js'; import type {CreateWithBlock} from '../../blocks/lists.js'; +import type {Block} from '../../core/block.js'; import {NameType} from '../../core/names.js'; -import {Order} from './python_generator.js'; +import * as stringUtils from '../../core/utils/string.js'; import type {PythonGenerator} from './python_generator.js'; +import {Order} from './python_generator.js'; export function lists_create_empty( block: Block, diff --git a/generators/python/loops.ts b/generators/python/loops.ts index 7ca7a5582e5..84aa613c638 100644 --- a/generators/python/loops.ts +++ b/generators/python/loops.ts @@ -10,11 +10,11 @@ // Former goog.module ID: Blockly.Python.loops -import * as stringUtils from '../../core/utils/string.js'; -import type {Block} from '../../core/block.js'; import type {ControlFlowInLoopBlock} from '../../blocks/loops.js'; -import type {PythonGenerator} from './python_generator.js'; +import type {Block} from '../../core/block.js'; import {NameType} from '../../core/names.js'; +import * as stringUtils from '../../core/utils/string.js'; +import type {PythonGenerator} from './python_generator.js'; import {Order} from './python_generator.js'; export function controls_repeat_ext(block: Block, generator: PythonGenerator) { diff --git a/generators/python/procedures.ts b/generators/python/procedures.ts index 51d2ee9a31b..32eae97b9e0 100644 --- a/generators/python/procedures.ts +++ b/generators/python/procedures.ts @@ -10,12 +10,12 @@ // Former goog.module ID: Blockly.Python.procedures -import * as Variables from '../../core/variables.js'; -import type {Block} from '../../core/block.js'; import type {IfReturnBlock} from '../../blocks/procedures.js'; +import type {Block} from '../../core/block.js'; import {NameType} from '../../core/names.js'; -import {Order} from './python_generator.js'; +import * as Variables from '../../core/variables.js'; import type {PythonGenerator} from './python_generator.js'; +import {Order} from './python_generator.js'; export function procedures_defreturn(block: Block, generator: PythonGenerator) { // Define a procedure with a return value. diff --git a/generators/python/python_generator.ts b/generators/python/python_generator.ts index bf7b87496ee..f96312e6dac 100644 --- a/generators/python/python_generator.ts +++ b/generators/python/python_generator.ts @@ -11,13 +11,13 @@ // Former goog.module ID: Blockly.Python -import * as stringUtils from '../../core/utils/string.js'; -import * as Variables from '../../core/variables.js'; import type {Block} from '../../core/block.js'; import {CodeGenerator} from '../../core/generator.js'; +import {inputTypes} from '../../core/inputs/input_types.js'; import {Names} from '../../core/names.js'; +import * as stringUtils from '../../core/utils/string.js'; +import * as Variables from '../../core/variables.js'; import type {Workspace} from '../../core/workspace.js'; -import {inputTypes} from '../../core/inputs/input_types.js'; /** * Order of operation ENUMs. diff --git a/generators/python/text.ts b/generators/python/text.ts index e9154da83fe..1ccf6b200a3 100644 --- a/generators/python/text.ts +++ b/generators/python/text.ts @@ -10,12 +10,12 @@ // Former goog.module ID: Blockly.Python.texts -import * as stringUtils from '../../core/utils/string.js'; -import type {Block} from '../../core/block.js'; import type {JoinMutatorBlock} from '../../blocks/text.js'; +import type {Block} from '../../core/block.js'; import {NameType} from '../../core/names.js'; -import {Order} from './python_generator.js'; +import * as stringUtils from '../../core/utils/string.js'; import type {PythonGenerator} from './python_generator.js'; +import {Order} from './python_generator.js'; export function text( block: Block, diff --git a/package-lock.json b/package-lock.json index c6d9871b7b8..9b070fb54f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,35 +1,37 @@ { "name": "blockly", - "version": "11.1.1", + "version": "11.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "blockly", - "version": "11.1.1", + "version": "11.2.0", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "jsdom": "23.0.0" + "jsdom": "25.0.1" }, "devDependencies": { - "@blockly/block-test": "^5.0.0", - "@blockly/dev-tools": "^7.0.2", - "@blockly/theme-modern": "^5.0.0", + "@blockly/block-test": "^6.0.4", + "@blockly/dev-tools": "^8.0.6", + "@blockly/theme-modern": "^6.0.3", + "@hyperjump/browser": "^1.1.4", "@hyperjump/json-schema": "^1.5.0", "@microsoft/api-documenter": "^7.22.4", "@microsoft/api-extractor": "^7.29.5", - "@typescript-eslint/eslint-plugin": "^7.3.1", "async-done": "^2.0.0", - "chai": "^4.2.0", - "concurrently": "^8.0.1", - "eslint": "^8.4.1", + "chai": "^5.1.1", + "concurrently": "^9.0.1", + "eslint": "^9.15.0", "eslint-config-google": "^0.14.0", - "eslint-config-prettier": "^9.0.0", - "eslint-plugin-jsdoc": "^48.0.2", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-jsdoc": "^50.5.0", + "eslint-plugin-prettier": "^5.2.1", "glob": "^10.3.4", - "google-closure-compiler": "^20230802.0.0", - "gulp": "^4.0.2", + "globals": "^15.12.0", + "google-closure-compiler": "^20240317.0.0", + "gulp": "^5.0.0", "gulp-concat": "^2.6.1", "gulp-gzip": "^1.4.2", "gulp-header": "^2.0.9", @@ -45,11 +47,13 @@ "markdown-tables-to-json": "^0.1.7", "mocha": "^10.0.0", "patch-package": "^8.0.0", - "prettier": "3.2.5", + "prettier": "^3.3.3", + "prettier-plugin-organize-imports": "^4.0.0", "readline-sync": "^1.4.10", "rimraf": "^5.0.0", "typescript": "^5.3.3", - "webdriverio": "^8.32.2", + "typescript-eslint": "^8.16.0", + "webdriverio": "^9.0.7", "yargs": "^17.2.1" }, "engines": { @@ -65,41 +69,29 @@ "node": ">=0.10.0" } }, - "node_modules/@babel/runtime": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz", - "integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.13.11" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@blockly/block-test": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@blockly/block-test/-/block-test-5.1.0.tgz", - "integrity": "sha512-beqBTJbrrDGECohJo6uczeLAvRxKgMFn9Ew1po6d8PBka/aNwSkT33jHRUAeasHnraBdFBx8pwYh7By2gVZURQ==", + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/@blockly/block-test/-/block-test-6.0.8.tgz", + "integrity": "sha512-uJg7d79gqqZGuF8tWriT1SJHaELFWQgv4Hf8/j7EDn5qnCRkDtoDqDQrVWNsios3tJHXviFNL3aetWkbBNOrVA==", "dev": true, "engines": { "node": ">=8.17.0" }, "peerDependencies": { - "blockly": "^10.0.0" + "blockly": "^11.0.0" } }, "node_modules/@blockly/dev-tools": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/@blockly/dev-tools/-/dev-tools-7.1.7.tgz", - "integrity": "sha512-ar/6A7JyTSzhJ6ojEOzoCxnm4jRTQJeYn87g+iTEJrM9K8tk/Ccn4sZY34T+ULhy8A2MbFkbtmERCLx6HNrAkA==", + "version": "8.0.9", + "resolved": "https://registry.npmjs.org/@blockly/dev-tools/-/dev-tools-8.0.9.tgz", + "integrity": "sha512-ta8tzBOJRZdjKynDFTtzK8xWuEzsBlKIc84zX15OhBShUZqvrsS1abRNDcnVe8/ZH93K2yezCgVfAf3AcOFvbQ==", "dev": true, "dependencies": { - "@blockly/block-test": "^5.1.0", - "@blockly/theme-dark": "^6.0.5", - "@blockly/theme-deuteranopia": "^5.0.6", - "@blockly/theme-highcontrast": "^5.0.5", - "@blockly/theme-tritanopia": "^5.0.5", + "@blockly/block-test": "^6.0.8", + "@blockly/theme-dark": "^7.0.7", + "@blockly/theme-deuteranopia": "^6.0.7", + "@blockly/theme-highcontrast": "^6.0.7", + "@blockly/theme-tritanopia": "^6.0.7", "chai": "^4.2.0", "dat.gui": "^0.7.7", "lodash.assign": "^4.2.0", @@ -111,78 +103,147 @@ "node": ">=8.0.0" }, "peerDependencies": { - "blockly": "^10.0.0" + "blockly": "^11.0.0" + } + }, + "node_modules/@blockly/dev-tools/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/@blockly/dev-tools/node_modules/chai": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", + "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@blockly/dev-tools/node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@blockly/dev-tools/node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@blockly/dev-tools/node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/@blockly/dev-tools/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/@blockly/theme-dark": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/@blockly/theme-dark/-/theme-dark-6.0.5.tgz", - "integrity": "sha512-6vftqOY4ZfwqiAUh2lR12TL16t+7UcmiGVYOBSs4dj1emP89UEO7EMaj0RQ+m0BsV9IHsf2fN6iKZu1gWkmnnA==", + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@blockly/theme-dark/-/theme-dark-7.0.7.tgz", + "integrity": "sha512-p6urK/fLyzLhrHcSo1DhEvRkasyJjBYDpBPgPipAqGNJRlLR1pbNoBRcrpv3RzTgKIKbA0TeawsWHrHOXG0S/w==", "dev": true, "engines": { "node": ">=8.17.0" }, "peerDependencies": { - "blockly": "^10.0.0" + "blockly": "^11.0.0" } }, "node_modules/@blockly/theme-deuteranopia": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@blockly/theme-deuteranopia/-/theme-deuteranopia-5.0.6.tgz", - "integrity": "sha512-bYQz2TrkbwPxYjZXlQGf6pMEnSBD/If4FtBqAavt/lutwib0awM0NbPWu8RP89z4aRcAlsByYYSzFQMNqYBaiA==", + "version": "6.0.7", + "resolved": "https://registry.npmjs.org/@blockly/theme-deuteranopia/-/theme-deuteranopia-6.0.7.tgz", + "integrity": "sha512-br1pto4qKhHQYYZZdzWz+gooBmH0MAIpnu038BIzEiRzpcXtKNvsPexwVLAqYII+w37rZTvE4vgl/9yjH/AzJA==", "dev": true, "engines": { "node": ">=8.17.0" }, "peerDependencies": { - "blockly": "^10.0.0" + "blockly": "^11.0.0" } }, "node_modules/@blockly/theme-highcontrast": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@blockly/theme-highcontrast/-/theme-highcontrast-5.0.5.tgz", - "integrity": "sha512-5pi7urLW7UNZhAoDbsb7C0vqFGHEeWi7pp1+OyFSmB+xMNkcVv1Es4X35QQCuUmM6FXfCFeqoDH+N/DYNDHHjg==", + "version": "6.0.7", + "resolved": "https://registry.npmjs.org/@blockly/theme-highcontrast/-/theme-highcontrast-6.0.7.tgz", + "integrity": "sha512-zZry3A1UBbuDclo3+yhJ45te5dQypwMCbao4djR28PVQEousM1t6h7AiQHy8zCop+nxqVSTESsgjEt96OQTb/g==", "dev": true, "engines": { "node": ">=8.17.0" }, "peerDependencies": { - "blockly": "^10.0.0" + "blockly": "^11.0.0" } }, "node_modules/@blockly/theme-modern": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@blockly/theme-modern/-/theme-modern-5.0.5.tgz", - "integrity": "sha512-rbVOGxKHAatzHI6Yhy9lJbIRPzAW2Xgf+N1U1KSkyVmUziLKKaNKwwYvnOSx4MmoDD49SrZMdUgT8G+VBLFhYw==", + "version": "6.0.7", + "resolved": "https://registry.npmjs.org/@blockly/theme-modern/-/theme-modern-6.0.7.tgz", + "integrity": "sha512-RUEmunGe1L6So0sTpBd1yUz3foUAzjTj1x0y3P4iyuGu0HzfLIacqUpdU4wQNteGPbKSBp7qDFRXaH/V2eJ6QA==", "dev": true, "engines": { "node": ">=8.17.0" }, "peerDependencies": { - "blockly": "^10.0.0" + "blockly": "^11.0.0" } }, "node_modules/@blockly/theme-tritanopia": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@blockly/theme-tritanopia/-/theme-tritanopia-5.0.5.tgz", - "integrity": "sha512-vVFMwvdreQoPDR8y6/5ymOoVYK/kE7zcH3Ra0NCEG4w/CBOlEYMYpNnCkpmM8HTjQj4fvDSTwh2HybiHMlfLrQ==", + "version": "6.0.7", + "resolved": "https://registry.npmjs.org/@blockly/theme-tritanopia/-/theme-tritanopia-6.0.7.tgz", + "integrity": "sha512-AF0iyzFYxY41pOVvZiCy1kAa4LeIHL9007B2xfRbVN/bTEA4rnd4W2k3XaEGv9xO026iBfvfRL9DJ9xASF9LFw==", "dev": true, "engines": { "node": ">=8.17.0" }, "peerDependencies": { - "blockly": "^10.0.0" + "blockly": "^11.0.0" } }, "node_modules/@es-joy/jsdoccomment": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.41.0.tgz", - "integrity": "sha512-aKUhyn1QI5Ksbqcr3fFJj16p99QdjUxXAEuFst1Z47DRyoiMwivIH9MV/ARcJOCXVjPfjITciej8ZD2O/6qUmw==", + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.49.0.tgz", + "integrity": "sha512-xjZTSFgECpb9Ohuk5yMX5RhUEbfeQcuOp8IF60e+wyzWEF0M5xeSgqsfLtvPEX8BIyOX9saZqzuGPmZ8oWc+5Q==", "dev": true, "dependencies": { "comment-parser": "1.4.1", - "esquery": "^1.5.0", - "jsdoc-type-pratt-parser": "~4.0.0" + "esquery": "^1.6.0", + "jsdoc-type-pratt-parser": "~4.1.0" }, "engines": { "node": ">=16" @@ -204,24 +265,47 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.0.tgz", - "integrity": "sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.0.tgz", + "integrity": "sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.0.tgz", + "integrity": "sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -229,28 +313,52 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "9.16.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.16.0.tgz", + "integrity": "sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@fastify/busboy": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz", - "integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==", + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", "dev": true, "engines": { - "node": ">=14" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", + "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", + "dev": true, + "dependencies": { + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@gulp-sourcemaps/identity-map": { @@ -350,18 +458,60 @@ "xtend": "~4.0.1" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "node_modules/@gulpjs/messages": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@gulpjs/messages/-/messages-1.1.0.tgz", + "integrity": "sha512-Ys9sazDatyTgZVb4xPlDufLweJ/Os2uHWOv+Caxvy2O85JcnT4M3vc73bi8pdLWlv3fdWQz3pdI9tVwo8rQQSg==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@gulpjs/to-absolute-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@gulpjs/to-absolute-glob/-/to-absolute-glob-4.0.0.tgz", + "integrity": "sha512-kjotm7XJrJ6v+7knhPaRgaT6q8F8K2jiafwYdNHLzmV0uGLuZY43FK6smNSHUPrhq5kX2slCUy+RGG/xGqmIKA==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "is-negated-glob": "^1.0.0" }, "engines": { - "node": ">=10.10.0" + "node": ">=10.13.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, "node_modules/@humanwhocodes/module-importer": { @@ -377,46 +527,68 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", - "dev": true + "node_modules/@humanwhocodes/retry": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, - "node_modules/@hyperjump/json-pointer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@hyperjump/json-pointer/-/json-pointer-1.0.1.tgz", - "integrity": "sha512-vV2pSc7JCwbKEMzh8kr/ICZdO+UZbA3aZ7N8t7leDi9cduWKa9yoP5LS04LnsbErlPbUNHvWBFlbTaR/o/uf7A==", + "node_modules/@hyperjump/browser": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@hyperjump/browser/-/browser-1.1.6.tgz", + "integrity": "sha512-i27uPV7SxK1GOn7TLTRxTorxchYa5ur9JHgtl6TxZ1MHuyb9ROAnXxEeu4q4H1836Xb7lL2PGPsaa5Jl3p+R6g==", "dev": true, "dependencies": { + "@hyperjump/json-pointer": "^1.1.0", + "@hyperjump/uri": "^1.2.0", + "content-type": "^1.0.5", "just-curry-it": "^5.3.0" }, + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jdesrosiers" + } + }, + "node_modules/@hyperjump/json-pointer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@hyperjump/json-pointer/-/json-pointer-1.1.0.tgz", + "integrity": "sha512-tFCKxMKDKK3VEdtUA3EBOS9GmSOS4mbrTjh9v3RnK10BphDMOb6+bxTh++/ae1AyfHyWb6R54O/iaoAtPMZPCg==", + "dev": true, "funding": { "type": "github", "url": "https://github.com/sponsors/jdesrosiers" } }, "node_modules/@hyperjump/json-schema": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/@hyperjump/json-schema/-/json-schema-1.6.7.tgz", - "integrity": "sha512-6ufO5Iov85FBXQ1a//7sQDwzZRoyEMR1MD7Te6k00DvApvj1/x3k/S1RcPmmPCCuj7BDxHVixu4qBTM6sBsmBA==", + "version": "1.9.8", + "resolved": "https://registry.npmjs.org/@hyperjump/json-schema/-/json-schema-1.9.8.tgz", + "integrity": "sha512-qmdMpYn8CpYR7z3fxkL6fgkDvMaAEFKtmYu3XDi6hWW2BT+rLl7T4Y4QpafEIR4wkcmCxcJf9me9FmxKpv3i9g==", "dev": true, "dependencies": { - "@hyperjump/json-pointer": "^1.0.0", + "@hyperjump/json-pointer": "^1.1.0", "@hyperjump/pact": "^1.2.0", "@hyperjump/uri": "^1.2.0", "content-type": "^1.0.4", - "fastest-stable-stringify": "^2.0.2", + "json-stringify-deterministic": "^1.0.12", "just-curry-it": "^5.3.0", - "undici": "^5.19.1", "uuid": "^9.0.0" }, - "engines": { - "node": ">=18.0.0" - }, "funding": { "type": "github", "url": "https://github.com/sponsors/jdesrosiers" + }, + "peerDependencies": { + "@hyperjump/browser": "^1.1.0" } }, "node_modules/@hyperjump/pact": { @@ -459,18 +631,6 @@ "node": ">=12" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, "node_modules/@isaacs/cliui/node_modules/ansi-styles": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", @@ -539,16 +699,16 @@ } }, "node_modules/@microsoft/api-documenter": { - "version": "7.23.14", - "resolved": "https://registry.npmjs.org/@microsoft/api-documenter/-/api-documenter-7.23.14.tgz", - "integrity": "sha512-D9cX3sS/6xN8SFbrR6I1ZTKvGl5UIPFZKYqTLg8YBUKJtFbUSDLrzRLWOcjxwxjnu+gCHAHyaNpG4G//CQivLw==", + "version": "7.25.14", + "resolved": "https://registry.npmjs.org/@microsoft/api-documenter/-/api-documenter-7.25.14.tgz", + "integrity": "sha512-nysAB+j4l5Al3XvCdee6tw0rw4fXpnlIq9En2opcc3DgITeoehiaYYoZZqoqOQSKlSUDWF7Z55GGsvntVrcBkg==", "dev": true, "dependencies": { - "@microsoft/api-extractor-model": "7.28.3", - "@microsoft/tsdoc": "0.14.2", - "@rushstack/node-core-library": "3.62.0", - "@rushstack/ts-command-line": "4.17.1", - "colors": "~1.2.1", + "@microsoft/api-extractor-model": "7.29.8", + "@microsoft/tsdoc": "~0.15.0", + "@rushstack/node-core-library": "5.9.0", + "@rushstack/terminal": "0.14.2", + "@rushstack/ts-command-line": "4.22.8", "js-yaml": "~3.13.1", "resolve": "~1.22.1" }, @@ -579,18 +739,18 @@ } }, "node_modules/@microsoft/api-extractor": { - "version": "7.43.0", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.43.0.tgz", - "integrity": "sha512-GFhTcJpB+MI6FhvXEI9b2K0snulNLWHqC/BbcJtyNYcKUiw7l3Lgis5ApsYncJ0leALX7/of4XfmXk+maT111w==", - "dev": true, - "dependencies": { - "@microsoft/api-extractor-model": "7.28.13", - "@microsoft/tsdoc": "0.14.2", - "@microsoft/tsdoc-config": "~0.16.1", - "@rushstack/node-core-library": "4.0.2", - "@rushstack/rig-package": "0.5.2", - "@rushstack/terminal": "0.10.0", - "@rushstack/ts-command-line": "4.19.1", + "version": "7.47.11", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.47.11.tgz", + "integrity": "sha512-lrudfbPub5wzBhymfFtgZKuBvXxoSIAdrvS2UbHjoMT2TjIEddq6Z13pcve7A03BAouw0x8sW8G4txdgfiSwpQ==", + "dev": true, + "dependencies": { + "@microsoft/api-extractor-model": "7.29.8", + "@microsoft/tsdoc": "~0.15.0", + "@microsoft/tsdoc-config": "~0.17.0", + "@rushstack/node-core-library": "5.9.0", + "@rushstack/rig-package": "0.5.3", + "@rushstack/terminal": "0.14.2", + "@rushstack/ts-command-line": "4.23.0", "lodash": "~4.17.15", "minimatch": "~3.0.3", "resolve": "~1.22.1", @@ -603,56 +763,23 @@ } }, "node_modules/@microsoft/api-extractor-model": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.28.3.tgz", - "integrity": "sha512-wT/kB2oDbdZXITyDh2SQLzaWwTOFbV326fP0pUwNW00WeliARs0qjmXBWmGWardEzp2U3/axkO3Lboqun6vrig==", - "dev": true, - "dependencies": { - "@microsoft/tsdoc": "0.14.2", - "@microsoft/tsdoc-config": "~0.16.1", - "@rushstack/node-core-library": "3.62.0" - } - }, - "node_modules/@microsoft/api-extractor/node_modules/@microsoft/api-extractor-model": { - "version": "7.28.13", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.28.13.tgz", - "integrity": "sha512-39v/JyldX4MS9uzHcdfmjjfS6cYGAoXV+io8B5a338pkHiSt+gy2eXQ0Q7cGFJ7quSa1VqqlMdlPrB6sLR/cAw==", - "dev": true, - "dependencies": { - "@microsoft/tsdoc": "0.14.2", - "@microsoft/tsdoc-config": "~0.16.1", - "@rushstack/node-core-library": "4.0.2" - } - }, - "node_modules/@microsoft/api-extractor/node_modules/@rushstack/node-core-library": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-4.0.2.tgz", - "integrity": "sha512-hyES82QVpkfQMeBMteQUnrhASL/KHPhd7iJ8euduwNJG4mu2GSOKybf0rOEjOm1Wz7CwJEUm9y0yD7jg2C1bfg==", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.29.8.tgz", + "integrity": "sha512-t3Z/xcO6TRbMcnKGVMs4uMzv/gd5j0NhMiJIGjD4cJMeFJ1Hf8wnLSx37vxlRlL0GWlGJhnFgxvnaL6JlS+73g==", "dev": true, "dependencies": { - "fs-extra": "~7.0.1", - "import-lazy": "~4.0.0", - "jju": "~1.4.0", - "resolve": "~1.22.1", - "semver": "~7.5.4", - "z-schema": "~5.0.2" - }, - "peerDependencies": { - "@types/node": "*" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "@microsoft/tsdoc": "~0.15.0", + "@microsoft/tsdoc-config": "~0.17.0", + "@rushstack/node-core-library": "5.9.0" } }, "node_modules/@microsoft/api-extractor/node_modules/@rushstack/ts-command-line": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.19.1.tgz", - "integrity": "sha512-J7H768dgcpG60d7skZ5uSSwyCZs/S2HrWP1Ds8d1qYAyaaeJmpmmLr9BVw97RjFzmQPOYnoXcKA4GkqDCkduQg==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.23.0.tgz", + "integrity": "sha512-jYREBtsxduPV6ptNq8jOKp9+yx0ld1Tb/Tkdnlj8gTjazl1sF3DwX2VbluyYrNd0meWIL0bNeer7WDf5tKFjaQ==", "dev": true, "dependencies": { - "@rushstack/terminal": "0.10.0", + "@rushstack/terminal": "0.14.2", "@types/argparse": "1.0.38", "argparse": "~1.0.9", "string-argv": "~0.3.1" @@ -702,36 +829,45 @@ } }, "node_modules/@microsoft/tsdoc": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", - "integrity": "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.0.tgz", + "integrity": "sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==", "dev": true }, "node_modules/@microsoft/tsdoc-config": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz", - "integrity": "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.17.0.tgz", + "integrity": "sha512-v/EYRXnCAIHxOHW+Plb6OWuUoMotxTN0GLatnpOb1xq0KuTNw/WI3pamJx/UbsoJP5k9MCw1QxvvhPcF9pH3Zg==", "dev": true, "dependencies": { - "@microsoft/tsdoc": "0.14.2", - "ajv": "~6.12.6", + "@microsoft/tsdoc": "0.15.0", + "ajv": "~8.12.0", "jju": "~1.4.0", - "resolve": "~1.19.0" + "resolve": "~1.22.2" } }, - "node_modules/@microsoft/tsdoc-config/node_modules/resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "node_modules/@microsoft/tsdoc-config/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, "dependencies": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/@microsoft/tsdoc-config/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -777,80 +913,85 @@ "node": ">=14" } }, - "node_modules/@puppeteer/browsers": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.4.6.tgz", - "integrity": "sha512-x4BEjr2SjOPowNeiguzjozQbsc6h437ovD/wu+JpaenxVLm3jkgzHY2xOslMTp50HoTvQreMjiexiGQw1sqZlQ==", + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", "dev": true, - "dependencies": { - "debug": "4.3.4", - "extract-zip": "2.0.1", - "progress": "2.0.3", - "proxy-agent": "6.3.0", - "tar-fs": "3.0.4", - "unbzip2-stream": "1.4.3", - "yargs": "17.7.1" - }, - "bin": { - "browsers": "lib/cjs/main-cli.js" - }, "engines": { - "node": ">=16.3.0" - }, - "peerDependencies": { - "typescript": ">= 4.7.4" + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "funding": { + "url": "https://opencollective.com/unts" } }, - "node_modules/@puppeteer/browsers/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "node_modules/@promptbook/utils": { + "version": "0.70.0-1", + "resolved": "https://registry.npmjs.org/@promptbook/utils/-/utils-0.70.0-1.tgz", + "integrity": "sha512-qd2lLRRN+sE6UuNMi2tEeUUeb4zmXnxY5EMdfHVXNE+bqBDpUC7/aEfXgA3jnUXEr+xFjQ8PTFQgWvBMaKvw0g==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://buymeacoffee.com/hejny" + }, + { + "type": "github", + "url": "https://github.com/webgptorg/promptbook/blob/main/README.md#%EF%B8%8F-contributing" + } + ], "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "spacetrim": "0.11.39" + } + }, + "node_modules/@puppeteer/browsers": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.4.0.tgz", + "integrity": "sha512-x8J1csfIygOwf6D6qUAZ0ASk3z63zPb7wkNeHRerCMh82qWKUrOgkuP005AJC8lDL6/evtXETGEJVcwykKT4/g==", + "dev": true, + "dependencies": { + "debug": "^4.3.6", + "extract-zip": "^2.0.1", + "progress": "^2.0.3", + "proxy-agent": "^6.4.0", + "semver": "^7.6.3", + "tar-fs": "^3.0.6", + "unbzip2-stream": "^1.4.3", + "yargs": "^17.7.2" + }, + "bin": { + "browsers": "lib/cjs/main-cli.js" }, "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@puppeteer/browsers/node_modules/yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "node_modules/@puppeteer/browsers/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=12" + "node": ">=10" } }, "node_modules/@rushstack/node-core-library": { - "version": "3.62.0", - "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.62.0.tgz", - "integrity": "sha512-88aJn2h8UpSvdwuDXBv1/v1heM6GnBf3RjEy6ZPP7UnzHNCqOHA2Ut+ScYUbXcqIdfew9JlTAe3g+cnX9xQ/Aw==", + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.9.0.tgz", + "integrity": "sha512-MMsshEWkTbXqxqFxD4gcIUWQOCeBChlGczdZbHfqmNZQFLHB3yWxDFSMHFUdu2/OB9NUk7Awn5qRL+rws4HQNg==", "dev": true, "dependencies": { - "colors": "~1.2.1", + "ajv": "~8.13.0", + "ajv-draft-04": "~1.0.0", + "ajv-formats": "~3.0.1", "fs-extra": "~7.0.1", "import-lazy": "~4.0.0", "jju": "~1.4.0", "resolve": "~1.22.1", - "semver": "~7.5.4", - "z-schema": "~5.0.2" + "semver": "~7.5.4" }, "peerDependencies": { "@types/node": "*" @@ -861,46 +1002,46 @@ } } }, - "node_modules/@rushstack/rig-package": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.5.2.tgz", - "integrity": "sha512-mUDecIJeH3yYGZs2a48k+pbhM6JYwWlgjs2Ca5f2n1G2/kgdgP9D/07oglEGf6mRyXEnazhEENeYTSNDRCwdqA==", + "node_modules/@rushstack/node-core-library/node_modules/ajv": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz", + "integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==", "dev": true, "dependencies": { - "resolve": "~1.22.1", - "strip-json-comments": "~3.1.1" + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@rushstack/terminal": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.10.0.tgz", - "integrity": "sha512-UbELbXnUdc7EKwfH2sb8ChqNgapUOdqcCIdQP4NGxBpTZV2sQyeekuK3zmfQSa/MN+/7b4kBogl2wq0vpkpYGw==", + "node_modules/@rushstack/node-core-library/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/@rushstack/rig-package": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.5.3.tgz", + "integrity": "sha512-olzSSjYrvCNxUFZowevC3uz8gvKr3WTpHQ7BkpjtRpA3wK+T0ybep/SRUMfr195gBzJm5gaXw0ZMgjIyHqJUow==", "dev": true, "dependencies": { - "@rushstack/node-core-library": "4.0.2", - "supports-color": "~8.1.1" - }, - "peerDependencies": { - "@types/node": "*" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "resolve": "~1.22.1", + "strip-json-comments": "~3.1.1" } }, - "node_modules/@rushstack/terminal/node_modules/@rushstack/node-core-library": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-4.0.2.tgz", - "integrity": "sha512-hyES82QVpkfQMeBMteQUnrhASL/KHPhd7iJ8euduwNJG4mu2GSOKybf0rOEjOm1Wz7CwJEUm9y0yD7jg2C1bfg==", + "node_modules/@rushstack/terminal": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.14.2.tgz", + "integrity": "sha512-2fC1wqu1VCExKC0/L+0noVcFQEXEnoBOtCIex1TOjBzEDWcw8KzJjjj7aTP6mLxepG0XIyn9OufeFb6SFsa+sg==", "dev": true, "dependencies": { - "fs-extra": "~7.0.1", - "import-lazy": "~4.0.0", - "jju": "~1.4.0", - "resolve": "~1.22.1", - "semver": "~7.5.4", - "z-schema": "~5.0.2" + "@rushstack/node-core-library": "5.9.0", + "supports-color": "~8.1.1" }, "peerDependencies": { "@types/node": "*" @@ -927,14 +1068,14 @@ } }, "node_modules/@rushstack/ts-command-line": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.17.1.tgz", - "integrity": "sha512-2jweO1O57BYP5qdBGl6apJLB+aRIn5ccIRTPDyULh0KMwVzFqWtw6IZWt1qtUoZD/pD2RNkIOosH6Cq45rIYeg==", + "version": "4.22.8", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.22.8.tgz", + "integrity": "sha512-XbFjOoV7qZHJnSuFUHv0pKaFA4ixyCuki+xMjsMfDwfvQjs5MYG0IK5COal3tRnG7KCDe2l/G+9LrzYE/RJhgg==", "dev": true, "dependencies": { + "@rushstack/terminal": "0.14.2", "@types/argparse": "1.0.38", "argparse": "~1.0.9", - "colors": "~1.2.1", "string-argv": "~0.3.1" } }, @@ -947,18 +1088,6 @@ "sprintf-js": "~1.0.2" } }, - "node_modules/@sindresorhus/is": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", - "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, "node_modules/@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", @@ -994,28 +1123,6 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, - "node_modules/@szmarczak/http-timer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", - "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", - "dev": true, - "dependencies": { - "defer-to-connect": "^2.0.1" - }, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 10" - } - }, "node_modules/@tootallnate/quickjs-emscripten": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", @@ -1043,18 +1150,18 @@ "integrity": "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==", "dev": true }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true + }, "node_modules/@types/expect": { "version": "1.20.4", "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", "dev": true }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", - "dev": true - }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -1062,21 +1169,24 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.0.tgz", - "integrity": "sha512-cumHmIAf6On83X7yP+LrsEyUOf/YlociZelmpRYaGFydoaPdxdt80MAbu6vWerQT2COCp2nPvHdsbD7tHn/YlQ==", - "dev": true + "version": "20.16.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.3.tgz", + "integrity": "sha512-/wdGiWRkMOm53gAsSyFMXFZHbVg7C6CbkrzHNpaHoYfsUWPg7m6ZRKtvQjgvQ9i8WT540a3ydRlRQbxjY30XxQ==", + "dev": true, + "dependencies": { + "undici-types": "~6.19.2" + } }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", + "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", "dev": true }, "node_modules/@types/vinyl": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.6.tgz", - "integrity": "sha512-ayJ0iOCDNHnKpKTgBG6Q6JOnHTj9zFta+3j2b8Ejza0e4cvRyMn0ZoLEmbPrTHe5YYRlDYPvPWVdV4cTaRyH7g==", + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.12.tgz", + "integrity": "sha512-Sr2fYMBUVGYq8kj3UthXFAu5UN6ZW+rYr4NACjZQJvHvj+c8lYv0CahmZ2P/r7iUkN44gGUBwqxZkrKXYPb7cw==", "dev": true, "dependencies": { "@types/expect": "^1.20.4", @@ -1090,18 +1200,18 @@ "dev": true }, "node_modules/@types/ws": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", - "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "version": "8.5.12", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", + "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", "dev": true, "optional": true, "dependencies": { @@ -1109,33 +1219,31 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.3.1.tgz", - "integrity": "sha512-STEDMVQGww5lhCuNXVSQfbfuNII5E08QWkvAw5Qwf+bj2WT+JkG1uc+5/vXA3AOYMDHVOSpL+9rcbEUiHIm2dw==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.16.0.tgz", + "integrity": "sha512-5YTHKV8MYlyMI6BaEG7crQ9BhSc8RxzshOReKwZwRWN0+XvvTOm+L/UYLCYxFpfwYuAAqhxiq4yae0CMFwbL7Q==", "dev": true, "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.3.1", - "@typescript-eslint/type-utils": "7.3.1", - "@typescript-eslint/utils": "7.3.1", - "@typescript-eslint/visitor-keys": "7.3.1", - "debug": "^4.3.4", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.16.0", + "@typescript-eslint/type-utils": "8.16.0", + "@typescript-eslint/utils": "8.16.0", + "@typescript-eslint/visitor-keys": "8.16.0", "graphemer": "^1.4.0", - "ignore": "^5.2.4", + "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -1144,27 +1252,26 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.3.1.tgz", - "integrity": "sha512-Rq49+pq7viTRCH48XAbTA+wdLRrB/3sRq4Lpk0oGDm0VmnjBrAOVXH/Laalmwsv2VpekiEfVFwJYVk6/e8uvQw==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.16.0.tgz", + "integrity": "sha512-D7DbgGFtsqIPIFMPJwCad9Gfi/hC0PWErRRHFnaCWoEDYi5tQUDiJCTmGUbBiLzjqAck4KcXt9Ayj0CNlIrF+w==", "dev": true, - "peer": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.3.1", - "@typescript-eslint/types": "7.3.1", - "@typescript-eslint/typescript-estree": "7.3.1", - "@typescript-eslint/visitor-keys": "7.3.1", + "@typescript-eslint/scope-manager": "8.16.0", + "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/typescript-estree": "8.16.0", + "@typescript-eslint/visitor-keys": "8.16.0", "debug": "^4.3.4" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -1173,16 +1280,16 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.3.1.tgz", - "integrity": "sha512-fVS6fPxldsKY2nFvyT7IP78UO1/I2huG+AYu5AMjCT9wtl6JFiDnsv4uad4jQ0GTFzcUV5HShVeN96/17bTBag==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.16.0.tgz", + "integrity": "sha512-mwsZWubQvBki2t5565uxF0EYvG+FwdFb8bMtDuGQLdCCnGPrDEDvm1gtfynuKlnpzeBRqdFCkMf9jg1fnAK8sg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.3.1", - "@typescript-eslint/visitor-keys": "7.3.1" + "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/visitor-keys": "8.16.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -1190,25 +1297,25 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.3.1.tgz", - "integrity": "sha512-iFhaysxFsMDQlzJn+vr3OrxN8NmdQkHks4WaqD4QBnt5hsq234wcYdyQ9uquzJJIDAj5W4wQne3yEsYA6OmXGw==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.16.0.tgz", + "integrity": "sha512-IqZHGG+g1XCWX9NyqnI/0CX5LL8/18awQqmkZSl2ynn8F76j579dByc0jhfVSnSnhf7zv76mKBQv9HQFKvDCgg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.3.1", - "@typescript-eslint/utils": "7.3.1", + "@typescript-eslint/typescript-estree": "8.16.0", + "@typescript-eslint/utils": "8.16.0", "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -1217,12 +1324,12 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.3.1.tgz", - "integrity": "sha512-2tUf3uWggBDl4S4183nivWQ2HqceOZh1U4hhu4p1tPiIJoRRXrab7Y+Y0p+dozYwZVvLPRI6r5wKe9kToF9FIw==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.16.0.tgz", + "integrity": "sha512-NzrHj6thBAOSE4d9bsuRNMvk+BvaQvmY4dDglgkgGC0EW/tB3Kelnp3tAKH87GEwzoxgeQn9fNGRyFJM/xd+GQ==", "dev": true, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -1230,22 +1337,22 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.3.1.tgz", - "integrity": "sha512-tLpuqM46LVkduWP7JO7yVoWshpJuJzxDOPYIVWUUZbW+4dBpgGeUdl/fQkhuV0A8eGnphYw3pp8d2EnvPOfxmQ==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.16.0.tgz", + "integrity": "sha512-E2+9IzzXMc1iaBy9zmo+UYvluE3TW7bCGWSF41hVWUE01o8nzr1rvOQYSxelxr6StUvRcTMe633eY8mXASMaNw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.3.1", - "@typescript-eslint/visitor-keys": "7.3.1", + "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/visitor-keys": "8.16.0", "debug": "^4.3.4", - "globby": "^11.1.0", + "fast-glob": "^3.3.2", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -1267,9 +1374,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -1281,88 +1388,96 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@typescript-eslint/utils": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.3.1.tgz", - "integrity": "sha512-jIERm/6bYQ9HkynYlNZvXpzmXWZGhMbrOvq3jJzOSOlKXsVjrrolzWBjDW6/TvT5Q3WqaN4EkmcfdQwi9tDjBQ==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.16.0.tgz", + "integrity": "sha512-C1zRy/mOL8Pj157GiX4kaw7iyRLKfJXBR3L82hk5kS/GyHcOFmy4YUq/zfZti72I9wnuQtA/+xzft4wCC8PJdA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.3.1", - "@typescript-eslint/types": "7.3.1", - "@typescript-eslint/typescript-estree": "7.3.1", - "semver": "^7.5.4" + "@typescript-eslint/scope-manager": "8.16.0", + "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/typescript-estree": "8.16.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.3.1.tgz", - "integrity": "sha512-9RMXwQF8knsZvfv9tdi+4D/j7dMG28X/wMJ8Jj6eOHyHWwDW4ngQJcqEczSsqIKKjFiLFr40Mnr7a5ulDD3vmw==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.16.0.tgz", + "integrity": "sha512-pq19gbaMOmFE3CbL0ZB8J8BFCo2ckfHBfaIsaOZgBIF4EoISJIdLX5xRhd0FGB0LlHReNRuzoJoMGpTjq8F2CQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.3.1", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "8.16.0", + "eslint-visitor-keys": "^4.2.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } }, "node_modules/@wdio/config": { - "version": "8.32.2", - "resolved": "https://registry.npmjs.org/@wdio/config/-/config-8.32.2.tgz", - "integrity": "sha512-ubqe4X+TgcERzXKIpMfisquNxPZNtRU5uPeV7hvas++mD75QyNpmWHCtea2+TjoXKxlZd1MVrtZAwtmqMmyhPw==", + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@wdio/config/-/config-9.0.8.tgz", + "integrity": "sha512-37L+hd+A1Nyehd/pgfTrLC6w+Ngbu0CIoFh9Vv6v8Cgu5Hih0TLofvlg+J1BNbcTd5eQ2tFKZBDeFMhQaIiTpg==", "dev": true, "dependencies": { - "@wdio/logger": "8.28.0", - "@wdio/types": "8.32.2", - "@wdio/utils": "8.32.2", + "@wdio/logger": "9.0.8", + "@wdio/types": "9.0.8", + "@wdio/utils": "9.0.8", "decamelize": "^6.0.0", - "deepmerge-ts": "^5.0.0", + "deepmerge-ts": "^7.0.3", "glob": "^10.2.2", "import-meta-resolve": "^4.0.0" }, "engines": { - "node": "^16.13 || >=18" - } - }, - "node_modules/@wdio/config/node_modules/decamelize": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", - "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18.20.0" } }, "node_modules/@wdio/logger": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-8.28.0.tgz", - "integrity": "sha512-/s6zNCqwy1hoc+K4SJypis0Ud0dlJ+urOelJFO1x0G0rwDRWyFiUP6ijTaCcFxAm29jYEcEPWijl2xkVIHwOyA==", + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-9.0.8.tgz", + "integrity": "sha512-uIyYIDBwLczmsp9JE5hN3ME8Xg+9WNBfSNXD69ICHrY9WPTzFf94UeTuavK7kwSKF3ro2eJbmNZItYOfnoovnw==", "dev": true, "dependencies": { "chalk": "^5.1.2", @@ -1371,19 +1486,7 @@ "strip-ansi": "^7.1.0" }, "engines": { - "node": "^16.13 || >=18" - } - }, - "node_modules/@wdio/logger/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">=18.20.0" } }, "node_modules/@wdio/logger/node_modules/chalk": { @@ -1414,164 +1517,92 @@ } }, "node_modules/@wdio/protocols": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-8.32.0.tgz", - "integrity": "sha512-inLJRrtIGdTz/YPbcsvpSvPlYQFTVtF3OYBwAXhG2FiP1ZwE1CQNLP/xgRGye1ymdGCypGkexRqIx3KBGm801Q==", + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-9.0.8.tgz", + "integrity": "sha512-xRH54byFf623/w/KW62xkf/C2mGyigSfMm+UT3tNEAd5ZA9X2VAWQWQBPzdcrsck7Fxk4zlQX8Kb34RSs7Cy4Q==", "dev": true }, "node_modules/@wdio/repl": { - "version": "8.24.12", - "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-8.24.12.tgz", - "integrity": "sha512-321F3sWafnlw93uRTSjEBVuvWCxTkWNDs7ektQS15drrroL3TMeFOynu4rDrIz0jXD9Vas0HCD2Tq/P0uxFLdw==", + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-9.0.8.tgz", + "integrity": "sha512-3iubjl4JX5zD21aFxZwQghqC3lgu+mSs8c3NaiYYNCC+IT5cI/8QuKlgh9s59bu+N3gG988jqMJeCYlKuUv/iw==", "dev": true, "dependencies": { "@types/node": "^20.1.0" }, "engines": { - "node": "^16.13 || >=18" + "node": ">=18.20.0" } }, "node_modules/@wdio/types": { - "version": "8.32.2", - "resolved": "https://registry.npmjs.org/@wdio/types/-/types-8.32.2.tgz", - "integrity": "sha512-jq8LcBBQpBP9ZF5kECKEpXv8hN7irCGCjLFAN0Bd5ScRR6qu6MGWvwkDkau2sFPr0b++sKDCEaMzQlwrGFjZXg==", + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-9.0.8.tgz", + "integrity": "sha512-pmz2iRWddTanrv8JC7v3wUGm17KRv2WyyJhQfklMSANn9V1ep6pw1RJG2WJnKq4NojMvH1nVv1sMZxXrYPhpYw==", "dev": true, "dependencies": { "@types/node": "^20.1.0" }, "engines": { - "node": "^16.13 || >=18" + "node": ">=18.20.0" } }, "node_modules/@wdio/utils": { - "version": "8.32.2", - "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.32.2.tgz", - "integrity": "sha512-PJcP4d1Fr8Zp+YIfGN93G0fjDj/6J0I6Gf6p0IpJk8qKQpdFDm4gB+lc202iv2YkyC+oT6b4Ik2W9LzvpSKNoQ==", + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-9.0.8.tgz", + "integrity": "sha512-p3EgOdkhCvMxJFd3WTtSChqYFQu2mz69/5tOsljDaL+4QYwnRR7O8M9wFsL3/9XMVcHdnC4Ija2VRxQ/lb+hHQ==", "dev": true, "dependencies": { - "@puppeteer/browsers": "^1.6.0", - "@wdio/logger": "8.28.0", - "@wdio/types": "8.32.2", + "@puppeteer/browsers": "^2.2.0", + "@wdio/logger": "9.0.8", + "@wdio/types": "9.0.8", "decamelize": "^6.0.0", - "deepmerge-ts": "^5.1.0", - "edgedriver": "^5.3.5", - "geckodriver": "^4.3.1", + "deepmerge-ts": "^7.0.3", + "edgedriver": "^5.6.1", + "geckodriver": "^4.3.3", "get-port": "^7.0.0", "import-meta-resolve": "^4.0.0", - "locate-app": "^2.1.0", - "safaridriver": "^0.1.0", + "locate-app": "^2.2.24", + "safaridriver": "^0.1.2", "split2": "^4.2.0", - "wait-port": "^1.0.4" - }, - "engines": { - "node": "^16.13 || >=18" - } - }, - "node_modules/@wdio/utils/node_modules/@puppeteer/browsers": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.9.1.tgz", - "integrity": "sha512-PuvK6xZzGhKPvlx3fpfdM2kYY3P/hB1URtK8wA7XUJ6prn6pp22zvJHu48th0SGcHL9SutbPHrFuQgfXTFobWA==", - "dev": true, - "dependencies": { - "debug": "4.3.4", - "extract-zip": "2.0.1", - "progress": "2.0.3", - "proxy-agent": "6.3.1", - "tar-fs": "3.0.4", - "unbzip2-stream": "1.4.3", - "yargs": "17.7.2" - }, - "bin": { - "browsers": "lib/cjs/main-cli.js" - }, - "engines": { - "node": ">=16.3.0" - } - }, - "node_modules/@wdio/utils/node_modules/decamelize": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", - "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@wdio/utils/node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" + "wait-port": "^1.1.0" }, "engines": { - "node": ">= 14" + "node": ">=18.20.0" } }, - "node_modules/@wdio/utils/node_modules/https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", - "dev": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true }, - "node_modules/@wdio/utils/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "node_modules/@zip.js/zip.js": { + "version": "2.7.52", + "resolved": "https://registry.npmjs.org/@zip.js/zip.js/-/zip.js-2.7.52.tgz", + "integrity": "sha512-+5g7FQswvrCHwYKNMd/KFxZSObctLSsQOgqBSi0LzwHo3li9Eh1w5cF5ndjQw9Zbr3ajVnd2+XyiX85gAetx1Q==", "dev": true, "engines": { - "node": ">=12" + "bun": ">=0.7.0", + "deno": ">=1.0.0", + "node": ">=16.5.0" } }, - "node_modules/@wdio/utils/node_modules/proxy-agent": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", - "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", "dev": true, "dependencies": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.0.1", - "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.2" + "event-target-shim": "^5.0.0" }, "engines": { - "node": ">= 14" + "node": ">=6.5" } }, - "node_modules/@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "dev": true - }, - "node_modules/abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "deprecated": "Use your platform's native atob() and btoa() methods instead", - "dev": true, - "peer": true - }, "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -1590,9 +1621,9 @@ } }, "node_modules/agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dependencies": { "debug": "^4.3.4" }, @@ -1616,10 +1647,63 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "dev": true, + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.14.0.tgz", + "integrity": "sha512-oYs1UUtO97ZO2lJ4bwnWeQW8/zvOIQLGKcvPTsWmvc2SYgBb+upuNS5NxoLaMU4h8Ju3Nbj6Cq8mD2LQoqVKFA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "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" @@ -1638,12 +1722,15 @@ } }, "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/ansi-styles": { @@ -1677,9 +1764,9 @@ "dev": true }, "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "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", @@ -1689,98 +1776,188 @@ "node": ">= 8" } }, - "node_modules/append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "dependencies": { - "buffer-equal": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/archiver": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-6.0.1.tgz", - "integrity": "sha512-CXGy4poOLBKptiZH//VlWdFuUC1RESbdZjGjILwBuZ73P7WkAUN0htfSfBq/7k6FRFlpu7bg4JOkj1vU9G6jcQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", + "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==", "dev": true, "dependencies": { - "archiver-utils": "^4.0.1", + "archiver-utils": "^5.0.2", "async": "^3.2.4", - "buffer-crc32": "^0.2.1", - "readable-stream": "^3.6.0", + "buffer-crc32": "^1.0.0", + "readable-stream": "^4.0.0", "readdir-glob": "^1.1.2", "tar-stream": "^3.0.0", - "zip-stream": "^5.0.1" + "zip-stream": "^6.0.1" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 14" } }, "node_modules/archiver-utils": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-4.0.1.tgz", - "integrity": "sha512-Q4Q99idbvzmgCTEAAhi32BkOyq8iVI5EwdO0PmBDSGIzzjYNdcFn7Q7k3OzbLy4kLUPXfJtG6fO2RjftXbobBg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz", + "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==", "dev": true, "dependencies": { - "glob": "^8.0.0", + "glob": "^10.0.0", "graceful-fs": "^4.2.0", + "is-stream": "^2.0.1", "lazystream": "^1.0.0", "lodash": "^4.17.15", "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" + "readable-stream": "^4.0.0" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 14" } }, - "node_modules/archiver-utils/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==", + "node_modules/archiver-utils/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } }, - "node_modules/archiver-utils/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "node_modules/archiver-utils/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/archiver-utils/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "node_modules/archiver-utils/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/archiver-utils/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "safe-buffer": "~5.2.0" + } + }, + "node_modules/archiver/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "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" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/archiver/node_modules/buffer-crc32": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", + "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/archiver/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dev": true, + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true + "node_modules/archiver/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/archiver/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } }, "node_modules/are-docs-informative": { "version": "0.0.2", @@ -1798,12 +1975,12 @@ "dev": true }, "node_modules/aria-query": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.0.tgz", - "integrity": "sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", "dev": true, - "engines": { - "node": ">=6.0" + "dependencies": { + "dequal": "^2.0.3" } }, "node_modules/arr-diff": { @@ -1815,39 +1992,6 @@ "node": ">=0.10.0" } }, - "node_modules/arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true, - "dependencies": { - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true, - "dependencies": { - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", @@ -1860,50 +2004,7 @@ "node_modules/array-each": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", - "dev": true, - "dependencies": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-initial/node_modules/is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "dev": true, - "dependencies": { - "is-number": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-last/node_modules/is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "integrity": "sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -1918,45 +2019,13 @@ "node": ">=0.10.0" } }, - "node_modules/array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "dev": true, - "dependencies": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "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==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "engines": { - "node": "*" + "node": ">=12" } }, "node_modules/assign-symbols": { @@ -1981,15 +2050,15 @@ } }, "node_modules/ast-types/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", "dev": true }, "node_modules/async-done": { @@ -2006,37 +2075,16 @@ "node": ">= 10.13.0" } }, - "node_modules/async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, "node_modules/async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true, - "dependencies": { - "async-done": "^1.2.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/async-settle/node_modules/async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-2.0.0.tgz", + "integrity": "sha512-Obu/KE8FurfQRN6ODdHN9LuXqwC+JFIM9NRyZqJJ4ZfLJmIYN9Rg0/kb+wF70VV5+fJusTMQlJ1t5rF7J/ETdg==", "dev": true, "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" + "async-done": "^2.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">= 10.13.0" } }, "node_modules/asynckit": { @@ -2066,44 +2114,23 @@ } }, "node_modules/b4a": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", - "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==", + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", + "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==", "dev": true }, "node_modules/bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true, - "dependencies": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/bach/node_modules/async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bach/-/bach-2.0.1.tgz", + "integrity": "sha512-A7bvGMGiTOxGMpNupYl9HQTf0FFDNF4VCmks4PJpFyN1AX2pdKuxuwdvUz2Hu388wcgp+OvGFNsumBfFNkR7eg==", "dev": true, "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" + "async-done": "^2.0.0", + "async-settle": "^2.0.0", + "now-and-later": "^3.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=10.13.0" } }, "node_modules/balanced-match": { @@ -2112,34 +2139,51 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "node_modules/base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "node_modules/bare-events": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.3.1.tgz", + "integrity": "sha512-sJnSOTVESURZ61XgEleqmP255T6zTYwHPwE4r6SssIh0U9/uDvfpdoJYpVUerJJZH2fueO+CdT8ZT+OC/7aZDA==", + "dev": true, + "optional": true + }, + "node_modules/bare-fs": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.3.5.tgz", + "integrity": "sha512-SlE9eTxifPDJrT6YgemQ1WGFleevzwY+XAP1Xqgl56HtcrisC2CHCZ2tq6dBpcH2TnNxwUEUGhweo+lrQtYuiw==", "dev": true, + "optional": true, "dependencies": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" + "bare-events": "^2.0.0", + "bare-path": "^2.0.0", + "bare-stream": "^2.0.0" } }, - "node_modules/base/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "node_modules/bare-os": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.4.4.tgz", + "integrity": "sha512-z3UiI2yi1mK0sXeRdc4O1Kk8aOa/e+FNWZcTiPB/dfTWyLypuE99LibgRaQki914Jq//yAWylcAt+mknKdixRQ==", + "dev": true, + "optional": true + }, + "node_modules/bare-path": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.3.tgz", + "integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==", "dev": true, + "optional": true, "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" + "bare-os": "^2.1.0" + } + }, + "node_modules/bare-stream": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.3.0.tgz", + "integrity": "sha512-pVRWciewGUeCyKEuRxwv06M079r+fRjAQjBEK2P6OYGrO43O+Z0LrPZZEjlc4mB6C2RpZ9AxJ1s7NLEtOHO6eA==", + "dev": true, + "optional": true, + "dependencies": { + "b4a": "^1.6.6", + "streamx": "^2.20.0" } }, "node_modules/base64-js": { @@ -2175,49 +2219,27 @@ } }, "node_modules/basic-ftp": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.3.tgz", - "integrity": "sha512-QHX8HLlncOLpy54mh+k/sWIFd0ThmRqwe9ZjELybGZK+tZ8rUb9VO0saKJUROTbE+KhzDUT7xziGpGrW8Kmd+g==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", + "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", "dev": true, "engines": { "node": ">=10.0.0" } }, - "node_modules/big-integer": { - "version": "1.6.52", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", - "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, "engines": { - "node": ">=0.6" + "node": ">=8" } }, - "node_modules/binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", - "dev": true, - "dependencies": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/binaryextensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.3.0.tgz", - "integrity": "sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg==", + "node_modules/binaryextensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.3.0.tgz", + "integrity": "sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg==", "dev": true, "engines": { "node": ">=0.8" @@ -2226,180 +2248,45 @@ "url": "https://bevry.me/fund" } }, - "node_modules/blockly": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/blockly/-/blockly-10.0.2.tgz", - "integrity": "sha512-d4o8x/cyJt6KkeStcQxbihvOVFADIrYQaHt85+TOTgUZKPHSTDPKqjKzrUQRJ3ouwYGF9KXC6y2V+oordnDLKA==", - "dev": true, - "peer": true, - "dependencies": { - "jsdom": "22.1.0" - } - }, - "node_modules/blockly/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, - "peer": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/blockly/node_modules/data-urls": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-4.0.0.tgz", - "integrity": "sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==", - "dev": true, - "peer": true, - "dependencies": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^12.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/blockly/node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "peer": true, - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/blockly/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==", + "node_modules/bl": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", + "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", "dev": true, - "peer": true, "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" } }, - "node_modules/blockly/node_modules/jsdom": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-22.1.0.tgz", - "integrity": "sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw==", + "node_modules/bl/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "dev": true, - "peer": true, - "dependencies": { - "abab": "^2.0.6", - "cssstyle": "^3.0.0", - "data-urls": "^4.0.0", - "decimal.js": "^10.4.3", - "domexception": "^4.0.0", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.4", - "parse5": "^7.1.2", - "rrweb-cssom": "^0.6.0", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.2", - "w3c-xmlserializer": "^4.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^2.0.0", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^12.0.1", - "ws": "^8.13.0", - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": 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/blockly/node_modules/tr46": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", - "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", - "dev": true, - "peer": true, - "dependencies": { - "punycode": "^2.3.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/blockly/node_modules/w3c-xmlserializer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", - "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", - "dev": true, - "peer": true, - "dependencies": { - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/blockly/node_modules/whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "dev": true, - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/blockly/node_modules/whatwg-url": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-12.0.1.tgz", - "integrity": "sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==", - "dev": true, - "peer": true, + ], "dependencies": { - "tr46": "^4.1.1", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/blockly/node_modules/xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "dev": true, - "peer": true, - "engines": { - "node": ">=12" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "node_modules/bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "dev": true }, "node_modules/brace-expansion": { @@ -2413,12 +2300,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "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.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -2457,57 +2344,18 @@ "node_modules/buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "dev": true, "engines": { "node": "*" } }, - "node_modules/buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "node_modules/buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", - "dev": true, - "engines": { - "node": ">=0.2.0" - } - }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -2517,78 +2365,6 @@ "node": ">= 0.8" } }, - "node_modules/cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "dependencies": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cacheable-lookup": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", - "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", - "dev": true, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/cacheable-request": { - "version": "10.2.14", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", - "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", - "dev": true, - "dependencies": { - "@types/http-cache-semantics": "^4.0.2", - "get-stream": "^6.0.1", - "http-cache-semantics": "^4.1.1", - "keyv": "^4.5.3", - "mimic-response": "^4.0.0", - "normalize-url": "^8.0.0", - "responselike": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/cacheable-request/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -2599,33 +2375,19 @@ } }, "node_modules/chai": { - "version": "4.3.10", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", - "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", - "dev": true, - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.0.8" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz", + "integrity": "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==", "dev": true, "dependencies": { - "traverse": ">=0.3.0 <0.4" + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" }, "engines": { - "node": "*" + "node": ">=12" } }, "node_modules/chalk": { @@ -2645,15 +2407,54 @@ } }, "node_modules/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "dev": true, + "engines": { + "node": ">= 16" + } + }, + "node_modules/cheerio": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz", + "integrity": "sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==", "dev": true, "dependencies": { - "get-func-name": "^2.0.2" + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.1.0", + "encoding-sniffer": "^0.2.0", + "htmlparser2": "^9.1.0", + "parse5": "^7.1.2", + "parse5-htmlparser2-tree-adapter": "^7.0.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^6.19.5", + "whatwg-mimetype": "^4.0.0" }, "engines": { - "node": "*" + "node": ">=18.17" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" } }, "node_modules/chokidar": { @@ -2683,18 +2484,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/chromium-bidi": { - "version": "0.4.16", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.16.tgz", - "integrity": "sha512-7ZbXdWERxRxSwo3txsBjjmc/NLxqb1Bk30mRb0BMS4YIaiV6zvKZqL/UAH+DdqcDYayDWk2n/y8klkBDODrPvA==", - "dev": true, - "dependencies": { - "mitt": "3.0.0" - }, - "peerDependencies": { - "devtools-protocol": "*" - } - }, "node_modules/ci-info": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", @@ -2710,110 +2499,21 @@ "node": ">=8" } }, - "node_modules/class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "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": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, - "node_modules/class-utils/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", "dev": true, "engines": { "node": ">=0.8" @@ -2860,42 +2560,6 @@ "util-deprecate": "~1.0.1" } }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, - "dependencies": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "dependencies": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2923,15 +2587,6 @@ "color-support": "bin.js" } }, - "node_modules/colors": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.5.tgz", - "integrity": "sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==", - "dev": true, - "engines": { - "node": ">=0.1.90" - } - }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -2961,25 +2616,89 @@ "node": ">= 12.0.0" } }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, "node_modules/compress-commons": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-5.0.1.tgz", - "integrity": "sha512-MPh//1cERdLtqwO3pOFLeXtpuai0Y2WCd5AhtKxznqM7WtaMYaOEMSgn45d9D10sIHSfIKE603HlOp8OPGrvag==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", + "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==", "dev": true, "dependencies": { "crc-32": "^1.2.0", - "crc32-stream": "^5.0.0", + "crc32-stream": "^6.0.0", + "is-stream": "^2.0.1", "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" + "readable-stream": "^4.0.0" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 14" + } + }, + "node_modules/compress-commons/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "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" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/compress-commons/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dev": true, + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/compress-commons/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/compress-commons/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" } }, "node_modules/concat-map": { @@ -3037,17 +2756,15 @@ } }, "node_modules/concurrently": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz", - "integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.0.1.tgz", + "integrity": "sha512-wYKvCd/f54sTXJMSfV6Ln/B8UrfLBKOYa+lzc6CHay3Qek+LorVSBdMVfyewFhRbH0Rbabsk4D+3PL/VjQ5gzg==", "dev": true, "dependencies": { "chalk": "^4.1.2", - "date-fns": "^2.30.0", "lodash": "^4.17.21", "rxjs": "^7.8.1", "shell-quote": "^1.8.1", - "spawn-command": "0.0.2", "supports-color": "^8.1.1", "tree-kill": "^1.2.2", "yargs": "^17.7.2" @@ -3057,7 +2774,7 @@ "concurrently": "dist/bin/concurrently.js" }, "engines": { - "node": "^14.13.0 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" @@ -3096,23 +2813,17 @@ "safe-buffer": "~5.1.1" } }, - "node_modules/copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/copy-props": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", - "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-4.0.0.tgz", + "integrity": "sha512-bVWtw1wQLzzKiYROtvNlbJgxgBYt2bMJpkCbKmXM3xyijvcjjWXEk5nyrrT3bgJ7ODb19ZohE2T0Y3FgNPyoTw==", "dev": true, "dependencies": { - "each-props": "^1.3.2", + "each-props": "^3.0.0", "is-plain-object": "^5.0.0" + }, + "engines": { + "node": ">= 10.13.0" } }, "node_modules/core-util-is": { @@ -3143,31 +2854,91 @@ } }, "node_modules/crc32-stream": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-5.0.0.tgz", - "integrity": "sha512-B0EPa1UK+qnpBZpG+7FgPCu0J2ETLpXq09o9BkLkEAhdB6Z61Qo4pJ3JYu0c+Qi+/SAL7QThqnzS06pmSSyZaw==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz", + "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==", "dev": true, "dependencies": { "crc-32": "^1.2.0", - "readable-stream": "^3.4.0" + "readable-stream": "^4.0.0" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 14" } }, - "node_modules/cross-fetch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", - "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", + "node_modules/crc32-stream/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "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" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/crc32-stream/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dev": true, + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/crc32-stream/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/crc32-stream/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, "dependencies": { - "node-fetch": "^2.6.12" + "safe-buffer": "~5.2.0" } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "dependencies": { "path-key": "^3.1.0", @@ -3189,6 +2960,22 @@ "source-map-resolve": "^0.6.0" } }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/css-shorthand-properties": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/css-shorthand-properties/-/css-shorthand-properties-1.1.1.tgz", @@ -3201,6 +2988,18 @@ "integrity": "sha1-Xv1sLupeof1rasV+wEJ7GEUkJOo=", "dev": true }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/css/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -3211,14 +3010,14 @@ } }, "node_modules/cssstyle": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-3.0.0.tgz", - "integrity": "sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", + "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", "dependencies": { - "rrweb-cssom": "^0.6.0" + "rrweb-cssom": "^0.7.1" }, "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/d": { @@ -3238,12 +3037,12 @@ "dev": true }, "node_modules/data-uri-to-buffer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-5.0.1.tgz", - "integrity": "sha512-a9l6T1qqDogvvnw0nKlfZzqsyikEBZBClF39V3TFoKhDtGBqHu2HkuomJc02j5zft8zrUaXEuoicLeW54RkzPg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", "dev": true, "engines": { - "node": ">= 14" + "node": ">= 12" } }, "node_modules/data-urls": { @@ -3281,26 +3080,10 @@ "node": ">=18" } }, - "node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.21.0" - }, - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dependencies": { "ms": "2.1.2" }, @@ -3334,12 +3117,15 @@ } }, "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", + "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/decimal.js": { @@ -3356,43 +3142,13 @@ "node": ">=0.10" } }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, - "dependencies": { - "mimic-response": "^3.1.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-eql": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", - "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", - "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=6" + "node": ">=6" } }, "node_modules/deep-is": { @@ -3402,69 +3158,14 @@ "dev": true }, "node_modules/deepmerge-ts": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-5.1.0.tgz", - "integrity": "sha512-eS8dRJOckyo9maw9Tu5O5RUi/4inFLrnoLkBe3cPfDMx3WZioXtmOew4TXQaxq7Rhl4xjDtR7c6x8nNTxOvbFw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.0.tgz", + "integrity": "sha512-q6bNsfNBtgr8ZOQqmZbl94MmYWm+QcDNIkqCxVWiw1vKvf+y/N2dZQKdnDXn4c5Ygt/y63tDof6OCN+2YwWVEg==", "dev": true, "engines": { "node": ">=16.0.0" } }, - "node_modules/default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "dev": true, - "dependencies": { - "kind-of": "^5.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/degenerator": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", @@ -3487,10 +3188,19 @@ "node": ">=0.4.0" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/detect-file": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", "dev": true, "engines": { "node": ">=0.10.0" @@ -3505,130 +3215,81 @@ "node": ">=0.10.0" } }, - "node_modules/devtools-protocol": { - "version": "0.0.1261483", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1261483.tgz", - "integrity": "sha512-7vJvejpzA5DTfZVkr7a8sGpEAzEiAqcgmRTB0LSUrWeOicwL09lMQTzxHtFNVhJ1OOJkgYdH6Txvy9E5j3VOUQ==", - "dev": true - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dir-glob/node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, "engines": { - "node": ">=6.0.0" + "node": ">=0.3.1" } }, - "node_modules/domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "deprecated": "Use your platform's native DOMException instead", + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "dev": true, - "peer": true, "dependencies": { - "webidl-conversions": "^7.0.0" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" }, - "engines": { - "node": ">=12" - } - }, - "node_modules/duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.2" + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/duplexer2/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] }, - "node_modules/duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "dev": true, "dependencies": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/duplexify/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", "dev": true, "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" } }, "node_modules/each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-3.0.0.tgz", + "integrity": "sha512-IYf1hpuWrdzse/s/YJOrFmU15lyhSzxelNVAHTEG3DtP4QsLTWZUzcUL3HMXmKQxXpa4EIrBPpwRgj0aehdvAw==", "dev": true, "dependencies": { - "is-plain-object": "^2.0.1", + "is-plain-object": "^5.0.0", "object.defaults": "^1.1.0" - } - }, - "node_modules/each-props/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 10.13.0" } }, "node_modules/eastasianwidth": { @@ -3654,42 +3315,49 @@ } }, "node_modules/edgedriver": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/edgedriver/-/edgedriver-5.3.10.tgz", - "integrity": "sha512-RFSHYMNtcF1PjaGZCA2rdQQ8hSTLPZgcYgeY1V6dC+tR4NhZXwFAku+8hCbRYh7ZlwKKrTbVu9FwknjFddIuuw==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/edgedriver/-/edgedriver-5.6.1.tgz", + "integrity": "sha512-3Ve9cd5ziLByUdigw6zovVeWJjVs8QHVmqOB0sJ0WNeVPcwf4p18GnxMmVvlFmYRloUwf5suNuorea4QzwBIOA==", "dev": true, "hasInstallScript": true, "dependencies": { - "@wdio/logger": "^8.28.0", + "@wdio/logger": "^8.38.0", + "@zip.js/zip.js": "^2.7.48", "decamelize": "^6.0.0", "edge-paths": "^3.0.5", + "fast-xml-parser": "^4.4.1", "node-fetch": "^3.3.2", - "unzipper": "^0.10.14", "which": "^4.0.0" }, "bin": { "edgedriver": "bin/edgedriver.js" } }, - "node_modules/edgedriver/node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "node_modules/edgedriver/node_modules/@wdio/logger": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-8.38.0.tgz", + "integrity": "sha512-kcHL86RmNbcQP+Gq/vQUGlArfU6IIcbbnNp32rRIraitomZow+iEoc519rdQmSVusDozMS5DZthkgDdxK+vz6Q==", "dev": true, + "dependencies": { + "chalk": "^5.1.2", + "loglevel": "^1.6.0", + "loglevel-plugin-prefix": "^0.8.4", + "strip-ansi": "^7.1.0" + }, "engines": { - "node": ">= 12" + "node": "^16.13 || >=18" } }, - "node_modules/edgedriver/node_modules/decamelize": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", - "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", + "node_modules/edgedriver/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/edgedriver/node_modules/isexe": { @@ -3701,22 +3369,19 @@ "node": ">=16" } }, - "node_modules/edgedriver/node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "node_modules/edgedriver/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" + "ansi-regex": "^6.0.1" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/edgedriver/node_modules/which": { @@ -3740,6 +3405,31 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "node_modules/encoding-sniffer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.0.tgz", + "integrity": "sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==", + "dev": true, + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + } + }, + "node_modules/encoding-sniffer/node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dev": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -3750,9 +3440,9 @@ } }, "node_modules/entities": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "engines": { "node": ">=0.12" }, @@ -3760,14 +3450,11 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true }, "node_modules/es5-ext": { "version": "0.10.53", @@ -3866,58 +3553,62 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.16.0.tgz", + "integrity": "sha512-whp8mSQI4C8VXd+fLgSM0lh3UlmcFtVwUQjyKCFfsp+2ItAIYhlq/hqGahGqHE6cv9unM41VlqKk2VtKYR2TaA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.9.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.16.0", + "@eslint/plugin-kit": "^0.2.3", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", + "@humanwhocodes/retry": "^0.4.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.5", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-config-google": { @@ -3945,20 +3636,22 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "48.0.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.0.2.tgz", - "integrity": "sha512-CBFl5Jc7+jlV36RwDm+PQ8Uw5r28pn2/uW/OaB+Gw5bFwn4Py/1eYMZ3hGf9S4meUFZ/sRvS+hVif2mRAp6WqQ==", + "version": "50.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.5.0.tgz", + "integrity": "sha512-xTkshfZrUbiSHXBwZ/9d5ulZ2OcHXxSvm/NPo494H/hadLRJwOq5PMV0EUpMqsb9V+kQo+9BAgi6Z7aJtdBp2A==", "dev": true, "dependencies": { - "@es-joy/jsdoccomment": "~0.41.0", + "@es-joy/jsdoccomment": "~0.49.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", - "debug": "^4.3.4", + "debug": "^4.3.6", "escape-string-regexp": "^4.0.0", - "esquery": "^1.5.0", - "is-builtin-module": "^3.2.1", - "semver": "^7.5.4", - "spdx-expression-parse": "^4.0.0" + "espree": "^10.1.0", + "esquery": "^1.6.0", + "parse-imports": "^2.1.1", + "semver": "^7.6.3", + "spdx-expression-parse": "^4.0.0", + "synckit": "^0.9.1" }, "engines": { "node": ">=18" @@ -3967,6 +3660,18 @@ "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, + "node_modules/eslint-plugin-jsdoc/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/eslint-plugin-jsdoc/node_modules/spdx-expression-parse": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", @@ -3977,17 +3682,47 @@ "spdx-license-ids": "^3.0.0" } }, + "node_modules/eslint-plugin-prettier": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", + "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.9.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -4005,6 +3740,18 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -4018,17 +3765,29 @@ } }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -4048,9 +3807,9 @@ } }, "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -4099,144 +3858,34 @@ "es5-ext": "~0.10.14" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "dev": true }, - "node_modules/expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/expand-brackets/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=0.8.x" } }, - "node_modules/expand-brackets/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, "node_modules/expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", "dev": true, "dependencies": { "homedir-polyfill": "^1.0.1" @@ -4279,58 +3928,6 @@ "node": ">=0.10.0" } }, - "node_modules/extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "dependencies": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", @@ -4372,6 +3969,12 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, "node_modules/fast-fifo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", @@ -4394,19 +3997,6 @@ "node": ">=8.6.0" } }, - "node_modules/fast-glob/node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -4419,11 +4009,36 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, - "node_modules/fastest-stable-stringify": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz", - "integrity": "sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==", - "dev": true + "node_modules/fast-xml-parser": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.0.tgz", + "integrity": "sha512-/PlTQCI96+fZMAOLMZK4CWG1ItCbfZ/0jx7UIJFChPNrx7tcEgerUgWbeieCM9MfHInUDyK8DWYZ+YrywDJuTg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } }, "node_modules/fastq": { "version": "1.13.0", @@ -4437,7 +4052,7 @@ "node_modules/fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", "dev": true, "dependencies": { "pend": "~1.2.0" @@ -4467,21 +4082,21 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "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" @@ -4515,69 +4130,44 @@ "micromatch": "^4.0.2" } }, - "node_modules/find-yarn-workspace-root/node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, "node_modules/findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-5.0.0.tgz", + "integrity": "sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==", "dev": true, "dependencies": { "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", + "is-glob": "^4.0.3", + "micromatch": "^4.0.4", "resolve-dir": "^1.0.1" }, "engines": { - "node": ">= 0.10" + "node": ">= 10.13.0" } }, "node_modules/fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-2.0.0.tgz", + "integrity": "sha512-OFRzsL6ZMHz5s0JrsEr+TpdGNCtrVtnuG3x1yzGNiQHT0yaDnXAj8V/lWcpJVrnoDpcwXcASxAZYbuXda2Y82A==", "dev": true, "dependencies": { "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", + "is-plain-object": "^5.0.0", "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fined/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" + "object.pick": "^1.3.0", + "parse-filepath": "^1.0.2" }, "engines": { - "node": ">=0.10.0" + "node": ">= 10.13.0" } }, "node_modules/flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-2.0.0.tgz", + "integrity": "sha512-Gq/a6YCi8zexmGHMuJwahTGzXlAZAOsbCVKduWXC6TlLCjjFRlExMJc4GC2NYPYZ0r/brw9P7CpRgQmlPVeOoA==", "dev": true, "engines": { - "node": ">= 0.10" + "node": ">= 10.13.0" } }, "node_modules/flat": { @@ -4590,88 +4180,28 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flat-cache/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=16" } }, "node_modules/flatted": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz", - "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", "dev": true }, - "node_modules/flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "node_modules/flush-write-stream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, "node_modules/follow-redirects": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", - "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "dev": true, "funding": [ { @@ -4691,7 +4221,7 @@ "node_modules/for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", "dev": true, "engines": { "node": ">=0.10.0" @@ -4700,7 +4230,7 @@ "node_modules/for-own": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==", "dev": true, "dependencies": { "for-in": "^1.0.1" @@ -4738,15 +4268,6 @@ "node": ">= 6" } }, - "node_modules/form-data-encoder": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", - "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", - "dev": true, - "engines": { - "node": ">= 14.17" - } - }, "node_modules/formdata-polyfill": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", @@ -4759,18 +4280,6 @@ "node": ">=12.20.0" } }, - "node_modules/fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "dependencies": { - "map-cache": "^0.2.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", @@ -4804,41 +4313,16 @@ } }, "node_modules/fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-2.0.1.tgz", + "integrity": "sha512-UTOY+59K6IA94tec8Wjqm0FSh5OVudGNB0NL/P6fB3HiE3bYOY3VYBGijsnOHNkQSwC1FKkU77pmq7xp9CskLw==", "dev": true, "dependencies": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" + "graceful-fs": "^4.2.8", + "streamx": "^2.12.0" }, "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fs-mkdirp-stream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/fs-mkdirp-stream/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "node": ">=10.13.0" } }, "node_modules/fs.realpath": { @@ -4847,73 +4331,29 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, - "node_modules/fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/fstream/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/fstream/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, "node_modules/geckodriver": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/geckodriver/-/geckodriver-4.3.2.tgz", - "integrity": "sha512-TNOoy+ULXJWI5XOq7CXD3PAD9TJa4NjMe7nKUXjlIsf+vezuaRsFgPwcgYdEem1K7106wabYsqr7Kqn51g0sJg==", + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/geckodriver/-/geckodriver-4.4.4.tgz", + "integrity": "sha512-0zaw19tcmWeluqx7+Y559JGBtidu1D0Lb8ElYKiNEQu8r3sCfrLUf5V10xypl8u29ZLbgRV7WflxCJVTCkCMFA==", "dev": true, "hasInstallScript": true, "dependencies": { - "@wdio/logger": "^8.28.0", + "@wdio/logger": "^9.0.0", + "@zip.js/zip.js": "^2.7.48", "decamelize": "^6.0.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", "node-fetch": "^3.3.2", - "tar-fs": "^3.0.4", - "unzipper": "^0.10.14", + "tar-fs": "^3.0.6", "which": "^4.0.0" }, "bin": { @@ -4923,53 +4363,6 @@ "node": "^16.13 || >=18 || >=20" } }, - "node_modules/geckodriver/node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/geckodriver/node_modules/decamelize": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", - "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/geckodriver/node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/geckodriver/node_modules/https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", - "dev": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/geckodriver/node_modules/isexe": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", @@ -4979,24 +4372,6 @@ "node": ">=16" } }, - "node_modules/geckodriver/node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "dev": true, - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, "node_modules/geckodriver/node_modules/which": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", @@ -5030,24 +4405,10 @@ "node": "*" } }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/get-port": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-7.0.0.tgz", - "integrity": "sha512-mDHFgApoQd+azgMdwylJrv2DX47ywGq1i5VFJE7fZ0dttNq3iQMfsU4IvEgBHojA3KqEudyu7Vq+oN8kNaNkWw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-7.1.0.tgz", + "integrity": "sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==", "dev": true, "engines": { "node": ">=16" @@ -5072,78 +4433,60 @@ } }, "node_modules/get-uri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.1.tgz", - "integrity": "sha512-7ZqONUVqaabogsYNWlYj0t3YZaL6dhuEueZXGF+/YVmf6dHmaFg8/6psJKqhx9QykIDKzpGcy2cn4oV4YC7V/Q==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz", + "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==", "dev": true, "dependencies": { "basic-ftp": "^5.0.2", - "data-uri-to-buffer": "^5.0.1", + "data-uri-to-buffer": "^6.0.2", "debug": "^4.3.4", - "fs-extra": "^8.1.0" + "fs-extra": "^11.2.0" }, "engines": { "node": ">= 14" } }, - "node_modules/get-uri/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/get-uri/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/get-uri/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "node_modules/get-uri/node_modules/data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", "dev": true, "engines": { - "node": ">= 4.0.0" + "node": ">= 14" } }, - "node_modules/get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "node_modules/get-uri/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=14.14" } }, "node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", + "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -5162,336 +4505,82 @@ } }, "node_modules/glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-8.0.2.tgz", + "integrity": "sha512-R8z6eTB55t3QeZMmU1C+Gv+t5UnNRkA55c5yo67fAVfxODxieTwsjNG7utxS/73NdP1NbDgCrhVEg2h00y4fFw==", "dev": true, "dependencies": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", + "@gulpjs/to-absolute-glob": "^4.0.0", + "anymatch": "^3.1.3", + "fastq": "^1.13.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" + "normalize-path": "^3.0.0", + "streamx": "^2.12.5" }, "engines": { - "node": ">= 0.10" + "node": ">=10.13.0" } }, - "node_modules/glob-stream/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/glob-stream/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "is-glob": "^4.0.3" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-stream/node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" + "node": ">=10.13.0" } }, - "node_modules/glob-stream/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "node_modules/glob-watcher": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-6.0.0.tgz", + "integrity": "sha512-wGM28Ehmcnk2NqRORXFOTOR064L4imSw3EeOqU5bIwUf62eXGwg89WivH6VMahL8zlQHeodzvHpXplrqzrz3Nw==", "dev": true, "dependencies": { - "is-extglob": "^2.1.0" + "async-done": "^2.0.0", + "chokidar": "^3.5.3" }, "engines": { - "node": ">=0.10.0" + "node": ">= 10.13.0" } }, - "node_modules/glob-stream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "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": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "balanced-match": "^1.0.0" } }, - "node_modules/glob-watcher": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", - "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, "dependencies": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">= 0.10" - } - }, - "node_modules/glob-watcher/node_modules/anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "dependencies": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/glob-watcher/node_modules/anymatch/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "node_modules/global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", "dev": true, "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-watcher/node_modules/async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/glob-watcher/node_modules/binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-watcher/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-watcher/node_modules/chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "deprecated": "Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.", - "dev": true, - "dependencies": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "optionalDependencies": { - "fsevents": "^1.2.7" - } - }, - "node_modules/glob-watcher/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-watcher/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-watcher/node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "node_modules/glob-watcher/node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-watcher/node_modules/is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "dependencies": { - "binary-extensions": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-watcher/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-watcher/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/glob-watcher/node_modules/readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/glob-watcher/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "dependencies": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" }, "engines": { "node": ">=0.10.0" @@ -5500,7 +4589,7 @@ "node_modules/global-prefix": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", "dev": true, "dependencies": { "expand-tilde": "^2.0.2", @@ -5526,72 +4615,37 @@ } }, "node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globals/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "version": "15.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.12.0.tgz", + "integrity": "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==", "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-2.2.0.tgz", + "integrity": "sha512-eWv1ds/zAlz+M1ioHsyKJomfY7jbDDPpwSkv14KQj89bycx1nvK5/2Cj/T9g7kzJcX5Bc7Yv22FjfBZS/jl94A==", "dev": true, "dependencies": { - "sparkles": "^1.0.0" + "sparkles": "^2.1.0" }, "engines": { - "node": ">= 0.10" + "node": ">= 10.13.0" } }, "node_modules/google-closure-compiler": { - "version": "20230802.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20230802.0.0.tgz", - "integrity": "sha512-o2fYoc8lqOBdhm95Ick0vWrtwH2Icd5yLZhbTcQ0T7NfGiBepYvx1BB63hR8ebgzEZemz9Fh+O6Kg/3Mjm28ww==", + "version": "20240317.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20240317.0.0.tgz", + "integrity": "sha512-PlC5aU2vwsypKbxyFNXOW4psDZfhDoOr2dCwuo8VcgQji+HVIgRi2lviO66x2SfTi0ilm3kI6rq/RSdOMFczcQ==", "dev": true, "dependencies": { "chalk": "4.x", - "google-closure-compiler-java": "^20230802.0.0", + "google-closure-compiler-java": "^20240317.0.0", "minimist": "1.x", "vinyl": "2.x", "vinyl-sourcemaps-apply": "^0.2.0" @@ -5603,21 +4657,21 @@ "node": ">=10" }, "optionalDependencies": { - "google-closure-compiler-linux": "^20230802.0.0", - "google-closure-compiler-osx": "^20230802.0.0", - "google-closure-compiler-windows": "^20230802.0.0" + "google-closure-compiler-linux": "^20240317.0.0", + "google-closure-compiler-osx": "^20240317.0.0", + "google-closure-compiler-windows": "^20240317.0.0" } }, "node_modules/google-closure-compiler-java": { - "version": "20230802.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-java/-/google-closure-compiler-java-20230802.0.0.tgz", - "integrity": "sha512-PWKLMLwj7pR/U0yYbiy649LLqAscu+F1gyY4Y/jK6CmSLb8cIJbL8BTJd00828TzTNfWnYwxbkcQw0y9C2YsGw==", + "version": "20240317.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-java/-/google-closure-compiler-java-20240317.0.0.tgz", + "integrity": "sha512-oWURPChjcCrVfiQOuVtpSoUJVvtOYo41JGEQ2qtArsTGmk/DpWh40vS6hitwKRM/0YzJX/jYUuyt9ibuXXJKmg==", "dev": true }, "node_modules/google-closure-compiler-linux": { - "version": "20230802.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20230802.0.0.tgz", - "integrity": "sha512-F13U4iSXiWeGtHOFS25LVem1s6zI+pJvXVPVR7zSib5ppoUJ0JXnABJQezUR3FnpxmnkALG4oIGW0syH9zPLZA==", + "version": "20240317.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20240317.0.0.tgz", + "integrity": "sha512-dYLtcbbJdbbBS0lTy9SzySdVv/aGkpyTekQiW4ADhT/i1p1b4r0wQTKj6kpVVmFvbZ6t9tW/jbXc9EXXNUahZw==", "cpu": [ "x32", "x64" @@ -5629,9 +4683,9 @@ ] }, "node_modules/google-closure-compiler-osx": { - "version": "20230802.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-osx/-/google-closure-compiler-osx-20230802.0.0.tgz", - "integrity": "sha512-ANAi/ux92Tt+Na7vFDLeK2hRzotjC5j+nxoPtE0OcuNcbjji5dREKoJxkq7r0YwRTCzAFZszK5ip/NPdTOdCEg==", + "version": "20240317.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-osx/-/google-closure-compiler-osx-20240317.0.0.tgz", + "integrity": "sha512-0mABwjD4HP11rikFd8JRIb9OgPqn9h3o3wS0otufMfmbwS7zRpnnoJkunifhORl3VoR1gFm6vcTC9YziTEFdOw==", "cpu": [ "x32", "x64", @@ -5644,9 +4698,9 @@ ] }, "node_modules/google-closure-compiler-windows": { - "version": "20230802.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-windows/-/google-closure-compiler-windows-20230802.0.0.tgz", - "integrity": "sha512-ZQPujoNiiUyTGl8zEGR/0yAygWnbMtX/NQ/S/EHVgq5nmYkvDEVuiVbgpPAmO9lzBTq0hvUTRRATZbTU2ISxgA==", + "version": "20240317.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-windows/-/google-closure-compiler-windows-20240317.0.0.tgz", + "integrity": "sha512-fTueVFzNOWURFlXZmrFkAB7yA+jzpA2TeDOYeBEFwVlVGHwi8PV3Q9vCIWlbkE8wLpukKEg5wfRHYrLwVPINCA==", "cpu": [ "x32", "x64" @@ -5657,47 +4711,10 @@ "win32" ] }, - "node_modules/got": { - "version": "12.6.1", - "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", - "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^5.2.0", - "@szmarczak/http-timer": "^5.0.1", - "cacheable-lookup": "^7.0.0", - "cacheable-request": "^10.2.8", - "decompress-response": "^6.0.0", - "form-data-encoder": "^2.1.2", - "get-stream": "^6.0.1", - "http2-wrapper": "^2.1.10", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^3.0.0", - "responselike": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/got/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, "node_modules/grapheme-splitter": { @@ -5713,287 +4730,103 @@ "dev": true }, "node_modules/gulp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-5.0.0.tgz", + "integrity": "sha512-S8Z8066SSileaYw1S2N1I64IUc/myI2bqe2ihOBzO6+nKpvNSg7ZcWJt/AwF8LC/NVN+/QZ560Cb/5OPsyhkhg==", "dev": true, "dependencies": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" + "glob-watcher": "^6.0.0", + "gulp-cli": "^3.0.0", + "undertaker": "^2.0.0", + "vinyl-fs": "^4.0.0" }, "bin": { "gulp": "bin/gulp.js" }, "engines": { - "node": ">= 0.10" + "node": ">=10.13.0" } }, "node_modules/gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-3.0.0.tgz", + "integrity": "sha512-RtMIitkT8DEMZZygHK2vEuLPqLPAFB4sntSxg4NoDta7ciwGZ18l7JuhCTiS5deOJi2IoK0btE+hs6R4sfj7AA==", "dev": true, "dependencies": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" + "@gulpjs/messages": "^1.1.0", + "chalk": "^4.1.2", + "copy-props": "^4.0.0", + "gulplog": "^2.2.0", + "interpret": "^3.1.1", + "liftoff": "^5.0.0", + "mute-stdout": "^2.0.0", + "replace-homedir": "^2.0.0", + "semver-greatest-satisfied-range": "^2.0.0", + "string-width": "^4.2.3", + "v8flags": "^4.0.0", + "yargs": "^16.2.0" }, "bin": { "gulp": "bin/gulp.js" }, "engines": { - "node": ">= 0.10" + "node": ">=10.13.0" } }, - "node_modules/gulp-cli/node_modules/ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "node_modules/gulp-cli/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": { - "ansi-wrap": "^0.1.0" + "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": ">=0.10.0" + "node": ">=10" } }, - "node_modules/gulp-cli/node_modules/camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "node_modules/gulp-cli/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": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" + "node": ">=10" } }, - "node_modules/gulp-cli/node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "node_modules/gulp-concat": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", + "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", "dev": true, "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "concat-with-sourcemaps": "^1.0.0", + "through2": "^2.0.0", + "vinyl": "^2.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.10" } }, - "node_modules/gulp-cli/node_modules/get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "node_modules/gulp-cli/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/gulp-cli/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "node_modules/gulp-concat/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/gulp-cli/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "dependencies": { - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "dependencies": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "dependencies": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/gulp-cli/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-cli/node_modules/y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true - }, - "node_modules/gulp-cli/node_modules/yargs": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", - "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", - "dev": true, - "dependencies": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.1" - } - }, - "node_modules/gulp-cli/node_modules/yargs-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", - "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", - "dev": true, - "dependencies": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } - }, - "node_modules/gulp-concat": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", - "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", - "dev": true, - "dependencies": { - "concat-with-sourcemaps": "^1.0.0", - "through2": "^2.0.0", - "vinyl": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-concat/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, "node_modules/gulp-concat/node_modules/through2": { @@ -6307,27 +5140,15 @@ } }, "node_modules/gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "dependencies": { - "glogg": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-2.2.0.tgz", + "integrity": "sha512-V2FaKiOhpR3DRXZuYdRLn/qiY0yI5XmqbTKrYbdemJ+xOh2d2MOweI/XFgMzd/9+1twdvMwllnZbWZNJ+BOm4A==", "dev": true, "dependencies": { - "function-bind": "^1.1.1" + "glogg": "^2.2.0" }, "engines": { - "node": ">= 0.4.0" + "node": ">= 10.13.0" } }, "node_modules/has-flag": { @@ -6339,55 +5160,16 @@ "node": ">=8" } }, - "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "dependencies": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, "dependencies": { - "is-buffer": "^1.1.5" + "function-bind": "^1.1.2" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, "node_modules/he": { @@ -6423,12 +5205,31 @@ "node": ">=12" } }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "node_modules/htmlfy": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/htmlfy/-/htmlfy-0.2.1.tgz", + "integrity": "sha512-HoomFHQ3av1uhq+7FxJTq4Ns0clAD+tGbQNrSd0WFY3UAjjUk6G3LaWEqdgmIXYkY4pexZiyZ3ykZJhQlM0J5A==", "dev": true }, + "node_modules/htmlparser2": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", + "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.1.0", + "entities": "^4.5.0" + } + }, "node_modules/http-proxy": { "version": "1.18.1", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", @@ -6444,9 +5245,9 @@ } }, "node_modules/http-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", - "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -6482,23 +5283,10 @@ "node": ">=12" } }, - "node_modules/http2-wrapper": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", - "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", - "dev": true, - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.2.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, "node_modules/https-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", - "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "dependencies": { "agent-base": "^7.0.2", "debug": "4" @@ -6539,14 +5327,20 @@ ] }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { "node": ">= 4" } }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -6573,9 +5367,9 @@ } }, "node_modules/import-meta-resolve": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz", - "integrity": "sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", + "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", "dev": true, "funding": { "type": "github", @@ -6614,27 +5408,31 @@ "dev": true }, "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", "dev": true, "engines": { - "node": ">= 0.10" + "node": ">=10.13.0" } }, - "node_modules/invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", "dev": true, + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 12" } }, - "node_modules/ip": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz", - "integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==", + "node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "dev": true }, "node_modules/is-absolute": { @@ -6650,33 +5448,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "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", @@ -6689,83 +5460,18 @@ "node": ">=8" } }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", - "dev": true, - "dependencies": { - "builtin-modules": "^3.3.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-descriptor/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -6838,49 +5544,25 @@ "node_modules/is-negated-glob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", + "integrity": "sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, "engines": { - "node": ">=0.10.0" + "node": ">=0.12.0" } }, - "node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true, "engines": { "node": ">=0.10.0" @@ -6909,6 +5591,18 @@ "node": ">=0.10.0" } }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", @@ -6933,16 +5627,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, "node_modules/is-valid-glob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", + "integrity": "sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -7007,9 +5695,9 @@ } }, "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz", + "integrity": "sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==", "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" @@ -7042,47 +5730,53 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "dev": true + }, "node_modules/jsdoc-type-pratt-parser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", - "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.1.0.tgz", + "integrity": "sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==", "dev": true, "engines": { "node": ">=12.0.0" } }, "node_modules/jsdom": { - "version": "23.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-23.0.0.tgz", - "integrity": "sha512-cbL/UCtohJguhFC7c2/hgW6BeZCNvP7URQGnx9tSJRYKCdnfbfWOrtuLTMfiB2VxKsx5wPHVsh/J0aBy9lIIhQ==", + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", + "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", "dependencies": { - "cssstyle": "^3.0.0", + "cssstyle": "^4.1.0", "data-urls": "^5.0.0", "decimal.js": "^10.4.3", "form-data": "^4.0.0", "html-encoding-sniffer": "^4.0.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.7", + "nwsapi": "^2.2.12", "parse5": "^7.1.2", - "rrweb-cssom": "^0.6.0", + "rrweb-cssom": "^0.7.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.3", + "tough-cookie": "^5.0.0", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0", - "ws": "^8.14.2", + "ws": "^8.18.0", "xml-name-validator": "^5.0.0" }, "engines": { "node": ">=18" }, "peerDependencies": { - "canvas": "^3.0.0" + "canvas": "^2.11.2" }, "peerDependenciesMeta": { "canvas": { @@ -7135,26 +5829,6 @@ "node": ">=18" } }, - "node_modules/jsdom/node_modules/ws": { - "version": "8.14.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", - "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -7185,6 +5859,15 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "node_modules/json-stringify-deterministic": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/json-stringify-deterministic/-/json-stringify-deterministic-1.0.12.tgz", + "integrity": "sha512-q3PN0lbUdv0pmurkBNdJH3pfFvOTL/Zp0lquqpvcjfKzt6Y0j49EPHAmVHCAS4Ceq/Y+PejWTzyiVpoY71+D6g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -7218,18 +5901,39 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dev": true, + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/jszip/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, "node_modules/just-curry-it": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/just-curry-it/-/just-curry-it-5.3.0.tgz", "integrity": "sha512-silMIRiFjUWlfaDhkgSzpuAyQ6EX/o09Eu8ZBfmFwQMbax7+LQzeIU2CBrICT6Ne4l86ITCGvUCBpCubWYy0Yw==", "dev": true }, - "node_modules/just-debounce": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.1.0.tgz", - "integrity": "sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ==", - "dev": true - }, "node_modules/just-extend": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", @@ -7245,15 +5949,6 @@ "json-buffer": "3.0.1" } }, - "node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/klaw-sync": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", @@ -7263,29 +5958,13 @@ "graceful-fs": "^4.1.11" } }, - "node_modules/ky": { - "version": "0.33.3", - "resolved": "https://registry.npmjs.org/ky/-/ky-0.33.3.tgz", - "integrity": "sha512-CasD9OCEQSFIam2U8efFK81Yeg8vNMTBUqtMOHlrcWQHqUX3HeCl9Dr31u4toV7emlH8Mymk5+9p0lL6mKb/Xw==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/ky?sponsor=1" - } - }, "node_modules/last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-2.0.0.tgz", + "integrity": "sha512-j+y6WhTLN4Itnf9j5ZQos1BGPCS8DAwmgMroR3OzfxAsBxam0hMw7J8M3KqZl0pLQJ1jNnwIexg5DYpC/ctwEQ==", "dev": true, - "dependencies": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - }, "engines": { - "node": ">= 0.10" + "node": ">= 10.13.0" } }, "node_modules/lazystream": { @@ -7315,28 +5994,13 @@ "util-deprecate": "~1.0.1" } }, - "node_modules/lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "dependencies": { - "invert-kv": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-4.0.0.tgz", + "integrity": "sha512-DpMa59o5uGUWWjruMp71e6knmwKU3jRBBn1kjuLWN9EeIOxNeSAwvHf03WIl8g/ZMR2oSQC9ej3yeLBwdDc/pg==", "dev": true, - "dependencies": { - "flush-write-stream": "^1.0.2" - }, "engines": { - "node": ">= 0.10" + "node": ">=10.13.0" } }, "node_modules/levn": { @@ -7352,78 +6016,50 @@ "node": ">= 0.8.0" } }, - "node_modules/liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true, - "dependencies": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/liftoff/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", - "dev": true - }, - "node_modules/load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", "dev": true, "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" + "immediate": "~3.0.5" } }, - "node_modules/load-json-file/node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "node_modules/liftoff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-5.0.0.tgz", + "integrity": "sha512-a5BQjbCHnB+cy+gsro8lXJ4kZluzOijzJ1UVVfyJYZC+IP2pLv1h4+aysQeKuTmyO8NAqfyQAk4HWaP/HjcKTg==", "dev": true, "dependencies": { - "error-ex": "^1.2.0" + "extend": "^3.0.2", + "findup-sync": "^5.0.0", + "fined": "^2.0.0", + "flagged-respawn": "^2.0.0", + "is-plain-object": "^5.0.0", + "rechoir": "^0.8.0", + "resolve": "^1.20.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10.13.0" } }, "node_modules/locate-app": { - "version": "2.2.19", - "resolved": "https://registry.npmjs.org/locate-app/-/locate-app-2.2.19.tgz", - "integrity": "sha512-mjhvrYRHnLAVwreShl8NTwq9EUyfRoCqB0UsOlMKXo2KBmtb4dhlHbZH4mcfDsoNoLkHZ1Rq4TsWP/59Ix62Ww==", + "version": "2.4.43", + "resolved": "https://registry.npmjs.org/locate-app/-/locate-app-2.4.43.tgz", + "integrity": "sha512-BX6NEdECUGcDQw8aqqg02qLyF9rF8V+dAfyAnBzL2AofIlIvf4Q6EGXnzVWpWot9uBE+x/o8CjXHo7Zlegu91Q==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://buymeacoffee.com/hejny" + }, + { + "type": "github", + "url": "https://github.com/hejny/locate-app/blob/main/README.md#%EF%B8%8F-contributing" + } + ], "dependencies": { - "n12": "1.8.22", + "@promptbook/utils": "0.70.0-1", "type-fest": "2.13.0", "userhome": "1.0.0" } @@ -7473,12 +6109,6 @@ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "dev": true - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -7527,9 +6157,9 @@ } }, "node_modules/loglevel": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.1.tgz", - "integrity": "sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.2.tgz", + "integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==", "dev": true, "engines": { "node": ">= 0.6.0" @@ -7546,26 +6176,14 @@ "dev": true }, "node_modules/loupe": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", - "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.1.tgz", + "integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==", "dev": true, "dependencies": { "get-func-name": "^2.0.1" } }, - "node_modules/lowercase-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", - "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -7587,31 +6205,10 @@ "es5-ext": "~0.10.2" } }, - "node_modules/make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/make-iterator/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", "dev": true, "engines": { "node": ">=0.10.0" @@ -7623,18 +6220,6 @@ "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", "dev": true }, - "node_modules/map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "dependencies": { - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/markdown-tables-to-json": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/markdown-tables-to-json/-/markdown-tables-to-json-0.1.7.tgz", @@ -7644,48 +6229,6 @@ "@ts-stack/markdown": "^1.3.0" } }, - "node_modules/matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "dev": true, - "dependencies": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/matchdep/node_modules/findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/matchdep/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/memoizee": { "version": "0.4.15", "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", @@ -7718,173 +6261,59 @@ } }, "node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", "dev": true, "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8.6" } }, - "node_modules/micromatch/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "bin": { + "mime": "cli.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/micromatch/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/micromatch/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" + "mime-db": "1.52.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/micromatch/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "is-extendable": "^0.1.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/micromatch/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-response": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", - "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "node": "*" } }, "node_modules/minimist": { @@ -7894,31 +6323,12 @@ "dev": true }, "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mitt": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz", - "integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==", - "dev": true - }, - "node_modules/mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, - "dependencies": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, "engines": { - "node": ">=0.10.0" + "node": ">=16 || 14 >=14.17" } }, "node_modules/mkdirp": { @@ -7933,39 +6343,32 @@ "mkdirp": "bin/cmd.js" } }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true - }, "node_modules/mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.3.tgz", + "integrity": "sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A==", + "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", @@ -7973,10 +6376,6 @@ }, "engines": { "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" } }, "node_modules/mocha/node_modules/brace-expansion": { @@ -7988,61 +6387,30 @@ "balanced-match": "^1.0.0" } }, - "node_modules/mocha/node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/mocha/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "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": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { - "node": "*" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mocha/node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/mocha/node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "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" @@ -8091,9 +6459,9 @@ } }, "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "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" @@ -8111,61 +6479,12 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/n12": { - "version": "1.8.22", - "resolved": "https://registry.npmjs.org/n12/-/n12-1.8.22.tgz", - "integrity": "sha512-nzPCOuLOIoUuninAMRXfrbkB7O9XkWS7iv7fzDW1pRUaQhMpatj8iX55evwcNRWnm0UF29uuoHpwubYbsV7OGw==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanomatch/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-2.0.0.tgz", + "integrity": "sha512-32GSKM3Wyc8dg/p39lWPKYu8zci9mJFzV1Np9Of0ZEpe6Fhssn/FbI7ywAMd40uX+p3ZKh3T5EeCFv81qS3HmQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 10.13.0" } }, "node_modules/natural-compare": { @@ -8222,23 +6541,21 @@ } }, "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", "dev": true, "dependencies": { - "whatwg-url": "^5.0.0" + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" }, "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" } }, "node_modules/normalize-path": { @@ -8250,43 +6567,34 @@ "node": ">=0.10.0" } }, - "node_modules/normalize-url": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.0.tgz", - "integrity": "sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-3.0.0.tgz", + "integrity": "sha512-pGO4pzSdaxhWTGkfSfHx3hVzJVslFPwBp2Myq9MYN/ChfJZF87ochMAXnvz6/58RJSf5ik2q9tXprBBrk2cpcg==", "dev": true, "dependencies": { - "once": "^1.3.2" + "once": "^1.4.0" }, "engines": { - "node": ">= 0.10" + "node": ">= 10.13.0" } }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" } }, "node_modules/nwsapi": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", - "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==" + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", + "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==" }, "node_modules/object-assign": { "version": "4.1.1", @@ -8297,215 +6605,65 @@ "node": ">=0.10.0" } }, - "node_modules/object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "node_modules/object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==", "dev": true, "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/object-copy/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", "dev": true, "dependencies": { - "is-descriptor": "^0.1.0" + "isobject": "^3.0.1" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/object-copy/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" + "wrappy": "1" } }, - "node_modules/object-copy/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", "dev": true, "dependencies": { - "kind-of": "^3.0.2" + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "node": ">=8" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "dependencies": { - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "dependencies": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "dev": true, - "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/open": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0", - "is-wsl": "^2.1.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/opener": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "dev": true, - "bin": { - "opener": "bin/opener-bin.js" + "bin": { + "opener": "bin/opener-bin.js" } }, "node_modules/optionator": { @@ -8525,42 +6683,6 @@ "node": ">= 0.8.0" } }, - "node_modules/ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.1" - } - }, - "node_modules/ordered-read-streams/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "dependencies": { - "lcid": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -8570,15 +6692,6 @@ "node": ">=0.10.0" } }, - "node_modules/p-cancelable": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", - "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", - "dev": true, - "engines": { - "node": ">=12.20" - } - }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -8610,9 +6723,9 @@ } }, "node_modules/pac-proxy-agent": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", - "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz", + "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==", "dev": true, "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", @@ -8620,28 +6733,33 @@ "debug": "^4.3.4", "get-uri": "^6.0.1", "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", - "pac-resolver": "^7.0.0", - "socks-proxy-agent": "^8.0.2" + "https-proxy-agent": "^7.0.5", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.4" }, "engines": { "node": ">= 14" } }, "node_modules/pac-resolver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.0.tgz", - "integrity": "sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", "dev": true, "dependencies": { "degenerator": "^5.0.0", - "ip": "^1.1.8", "netmask": "^2.0.2" }, "engines": { "node": ">= 14" } }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -8657,7 +6775,7 @@ "node_modules/parse-filepath": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", "dev": true, "dependencies": { "is-absolute": "^1.0.0", @@ -8668,6 +6786,19 @@ "node": ">=0.8" } }, + "node_modules/parse-imports": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.2.1.tgz", + "integrity": "sha512-OL/zLggRp8mFhKL0rNORUTR4yBYujK/uU+xZL+/0Rgm2QE4nLO9v8PzEweSJEbMGKmDRjJE4R3IMJlL2di4JeQ==", + "dev": true, + "dependencies": { + "es-module-lexer": "^1.5.3", + "slashes": "^3.0.12" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/parse-node-version": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", @@ -8680,7 +6811,7 @@ "node_modules/parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", "dev": true, "engines": { "node": ">=0.10.0" @@ -8697,13 +6828,29 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", + "dev": true, + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, "node_modules/patch-package": { @@ -8792,12 +6939,6 @@ "node": ">=6" } }, - "node_modules/path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -8834,7 +6975,7 @@ "node_modules/path-root": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", "dev": true, "dependencies": { "path-root-regex": "^0.1.0" @@ -8846,32 +6987,32 @@ "node_modules/path-root-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.0.tgz", - "integrity": "sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw==", + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", "dev": true, "engines": { "node": "14 || >=16.14" @@ -8892,33 +7033,19 @@ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, - "node_modules/path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", "dev": true, "engines": { - "node": "*" + "node": ">= 14.16" } }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true }, "node_modules/picocolors": { @@ -8939,36 +7066,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/plugin-error": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", @@ -9028,15 +7125,6 @@ "ms": "^2.1.1" } }, - "node_modules/posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/postcss": { "version": "7.0.39", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", @@ -9073,10 +7161,11 @@ } }, "node_modules/prettier": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", - "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, @@ -9087,13 +7176,46 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, "engines": { - "node": ">= 0.8" + "node": ">=6.0.0" + } + }, + "node_modules/prettier-plugin-organize-imports": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-4.0.0.tgz", + "integrity": "sha512-vnKSdgv9aOlqKeEFGhf9SCBsTyzDSyScy1k7E0R1Uo4L0cTcOV7c1XQaT7jfXIOc/p08WLBfN2QUQA9zDSZMxA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@vue/language-plugin-pug": "^2.0.24", + "prettier": ">=2.0", + "typescript": ">=2.9", + "vue-tsc": "^2.0.24" + }, + "peerDependenciesMeta": { + "@vue/language-plugin-pug": { + "optional": true + }, + "vue-tsc": { + "optional": true + } + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "engines": { + "node": ">= 0.6.0" } }, "node_modules/process-nextick-args": { @@ -9112,19 +7234,19 @@ } }, "node_modules/proxy-agent": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.0.tgz", - "integrity": "sha512-0LdR757eTj/JfuU7TL2YCuAZnxWXu3tkJbg4Oq3geW/qFNT/32T0sp2HnZ9O0lMR4q3vwAt0+xCA8SR0WAD0og==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", + "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", "dev": true, "dependencies": { "agent-base": "^7.0.2", "debug": "^4.3.4", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.0", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.3", "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.0.0", + "pac-proxy-agent": "^7.0.1", "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.1" + "socks-proxy-agent": "^8.0.2" }, "engines": { "node": ">= 14" @@ -9145,81 +7267,24 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" - }, "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, - "node_modules/pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "dependencies": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" } }, - "node_modules/pumpify/node_modules/pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/puppeteer-core": { - "version": "20.9.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-20.9.0.tgz", - "integrity": "sha512-H9fYZQzMTRrkboEfPmf7m3CLDN6JvbxXA3qTtS+dFt27tR+CsFHzPsT6pzp6lYL6bJbAPaR0HaPO6uSi+F94Pg==", - "dev": true, - "dependencies": { - "@puppeteer/browsers": "1.4.6", - "chromium-bidi": "0.4.16", - "cross-fetch": "4.0.0", - "debug": "4.3.4", - "devtools-protocol": "0.0.1147663", - "ws": "8.13.0" - }, - "engines": { - "node": ">=16.3.0" - }, - "peerDependencies": { - "typescript": ">= 4.7.4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/puppeteer-core/node_modules/devtools-protocol": { - "version": "0.0.1147663", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1147663.tgz", - "integrity": "sha512-hyWmRrexdhbZ1tcJUGpO95ivbRhWXz++F4Ko+n21AY5PNln2ovoJw+8ZMNDTtip+CNFQfrtLVh/w4009dXO/eQ==", - "dev": true - }, "node_modules/qs": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", @@ -9235,11 +7300,6 @@ "integrity": "sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw==", "dev": true }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -9266,18 +7326,6 @@ "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", "dev": true }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -9353,86 +7401,15 @@ } }, "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "dev": true - }, - "node_modules/regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", "dev": true, "dependencies": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" + "resolve": "^1.20.0" }, "engines": { - "node": ">= 0.10" - } - }, - "node_modules/remove-bom-stream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/remove-bom-stream/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "node": ">= 10.13.0" } }, "node_modules/remove-trailing-separator": { @@ -9441,36 +7418,22 @@ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", "dev": true }, - "node_modules/repeat-element": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "node_modules/replace-ext": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", + "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", "dev": true, "engines": { - "node": ">=0.10" + "node": ">= 10" } }, "node_modules/replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-2.0.0.tgz", + "integrity": "sha512-bgEuQQ/BHW0XkkJtawzrfzHFSN70f/3cNOiHa2QsYxqrjaC30X1k74FJ6xswVBP0sr0SpGIdVFuPwfrYziVeyw==", "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - }, "engines": { - "node": ">= 0.10" + "node": ">= 10.13.0" } }, "node_modules/replacestream": { @@ -9517,24 +7480,28 @@ "node": ">=0.10.0" } }, - "node_modules/require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "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": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true }, "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "dependencies": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -9545,16 +7512,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true - }, "node_modules/resolve-dir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", "dev": true, "dependencies": { "expand-tilde": "^2.0.0", @@ -9574,43 +7535,21 @@ } }, "node_modules/resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "dependencies": { - "value-or-function": "^3.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "deprecated": "https://github.com/lydell/resolve-url#deprecated", - "dev": true - }, - "node_modules/responselike": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", - "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-2.0.0.tgz", + "integrity": "sha512-/FopbmmFOQCfsCx77BRFdKOniglTiHumLgwvd6IDPihy1GKkadZbgQJBcTb2lMzSR1pndzd96b1nZrreZ7+9/A==", "dev": true, "dependencies": { - "lowercase-keys": "^3.0.0" + "value-or-function": "^4.0.0" }, "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 10.13.0" } }, "node_modules/resq": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/resq/-/resq-1.10.1.tgz", - "integrity": "sha512-zhp1iyUH02MLciv3bIM2bNtTFx/fqRsK4Jk73jcPqp00d/sMTTjOtjdTMAcgjrQKGx5DvQ/HSpeqaMW0atGRJA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/resq/-/resq-1.11.0.tgz", + "integrity": "sha512-G10EBz+zAAy3zUd/CDoBbXRL6ia9kOo3xRHrMDsHljI0GDkhYlyjwoCx5+3eCC4swi1uCoZQhskuJkj7Gp57Bw==", "dev": true, "dependencies": { "fast-deep-equal": "^2.0.1" @@ -9619,18 +7558,9 @@ "node_modules/resq/node_modules/fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==", "dev": true }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true, - "engines": { - "node": ">=0.12" - } - }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -9648,9 +7578,9 @@ "dev": true }, "node_modules/rimraf": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", - "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", "dev": true, "dependencies": { "glob": "^10.3.7" @@ -9658,17 +7588,14 @@ "bin": { "rimraf": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=14" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/rrweb-cssom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", - "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==" + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==" }, "node_modules/run-parallel": { "version": "1.2.0", @@ -9720,15 +7647,6 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "dependencies": { - "ret": "~0.1.10" - } - }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -9767,21 +7685,21 @@ } }, "node_modules/semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-2.0.0.tgz", + "integrity": "sha512-lH3f6kMbwyANB7HuOWRMlLCa2itaCrZJ+SAqqkSZrZKO/cAsk2EOyaKHUtNkVLFyFW9pct22SFesFp3Z7zpA0g==", "dev": true, "dependencies": { - "sver-compat": "^1.5.0" + "sver": "^1.8.3" }, "engines": { - "node": ">= 0.10" + "node": ">= 10.13.0" } }, "node_modules/serialize-error": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-11.0.2.tgz", - "integrity": "sha512-o43i0jLcA0LXA5Uu+gI1Vj+lF66KR9IAcy0ThbGq1bAMPN+k5IgSHsulfnqf/ddKAz6dWf+k8PD5hAr9oCSHEQ==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-11.0.3.tgz", + "integrity": "sha512-2G2y++21dhj2R7iHAdd0FIzjGwuKZld+7Pl/bTU6YIkrC2ZMbVUjm+luj6A6V34Rv9XfKJDKpTWu9W4Gse1D9g==", "dev": true, "dependencies": { "type-fest": "^2.12.2" @@ -9794,68 +7712,14 @@ } }, "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "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/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -9931,14 +7795,11 @@ "node": ">=0.3.1" } }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } + "node_modules/slashes": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/slashes/-/slashes-3.0.12.tgz", + "integrity": "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==", + "dev": true }, "node_modules/smart-buffer": { "version": "4.2.0", @@ -9950,232 +7811,34 @@ "npm": ">= 3.0.0" } }, - "node_modules/snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "dependencies": { - "kind-of": "^3.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/snapdragon/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/snapdragon/node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", "dev": true, "dependencies": { - "ip": "^2.0.0", + "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" }, "engines": { - "node": ">= 10.13.0", + "node": ">= 10.0.0", "npm": ">= 3.0.0" } }, "node_modules/socks-proxy-agent": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", - "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", "dev": true, "dependencies": { - "agent-base": "^7.0.2", + "agent-base": "^7.1.1", "debug": "^4.3.4", - "socks": "^2.7.1" + "socks": "^2.8.3" }, "engines": { "node": ">= 14" } }, - "node_modules/socks/node_modules/ip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", - "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", - "dev": true - }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -10195,180 +7858,65 @@ "decode-uri-component": "^0.2.0" } }, - "node_modules/source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", - "dev": true - }, - "node_modules/sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/spawn-command": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz", - "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==", - "dev": true - }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", - "dev": true - }, - "node_modules/split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "dev": true, - "engines": { - "node": ">= 10.x" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "node_modules/spacetrim": { + "version": "0.11.39", + "resolved": "https://registry.npmjs.org/spacetrim/-/spacetrim-0.11.39.tgz", + "integrity": "sha512-S/baW29azJ7py5ausQRE2S6uEDQnlxgMHOEEq4V770ooBDD1/9kZnxRcco/tjZYuDuqYXblCk/r3N13ZmvHZ2g==", "dev": true, - "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } + "funding": [ + { + "type": "individual", + "url": "https://buymeacoffee.com/hejny" + }, + { + "type": "github", + "url": "https://github.com/hejny/spacetrim/blob/main/README.md#%EF%B8%8F-contributing" + } + ] }, - "node_modules/static-extend/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "node_modules/sparkles": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-2.1.0.tgz", + "integrity": "sha512-r7iW1bDw8R/cFifrD3JnQJX0K1jqT0kprL48BiBpLZLJPmAm34zsVBsK5lc7HirZYZqMW65dOXZgbAGt/I6frg==", "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, "engines": { - "node": ">=0.10.0" + "node": ">= 10.13.0" } }, - "node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-license-ids": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", + "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", + "dev": true + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, "engines": { - "node": ">=0.10.0" + "node": ">= 10.x" } }, - "node_modules/static-extend/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/stream-composer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-composer/-/stream-composer-1.0.2.tgz", + "integrity": "sha512-bnBselmwfX5K10AH6L4c8+S5lgZMWI7ZYrz2rvYjCPB2DIMC4Ig8OpxGpNJSxRZ58oti7y1IcNvjBAz9vW5m4w==", "dev": true, "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" + "streamx": "^2.13.2" } }, "node_modules/stream-exhaust": { @@ -10377,12 +7925,6 @@ "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", "dev": true }, - "node_modules/stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, "node_modules/stream-to-array": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/stream-to-array/-/stream-to-array-2.3.0.tgz", @@ -10429,13 +7971,17 @@ "dev": true }, "node_modules/streamx": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.1.tgz", - "integrity": "sha512-fQMzy2O/Q47rgwErk/eGeLu/roaFWV0jVsogDmrszM9uIw8L5OA+t+V93MgYlufNptfjmYR1tOMWhei/Eh7TQA==", + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.20.1.tgz", + "integrity": "sha512-uTa0mU6WUC65iUvzKH4X9hEdvSW7rbPxPtwfWiLMSj3qTdQbAiUboZTxauKfpFuGIGa1C2BYijZ7wgdUXICJhA==", "dev": true, "dependencies": { - "fast-fifo": "^1.1.0", - "queue-tick": "^1.0.1" + "fast-fifo": "^1.3.2", + "queue-tick": "^1.0.1", + "text-decoder": "^1.1.0" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" } }, "node_modules/string_decoder": { @@ -10528,18 +8074,6 @@ "node": ">=8" } }, - "node_modules/strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "dependencies": { - "is-utf8": "^0.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/strip-bom-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", @@ -10561,6 +8095,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "dev": true + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -10585,14 +8125,23 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "node_modules/sver": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/sver/-/sver-1.8.4.tgz", + "integrity": "sha512-71o1zfzyawLfIWBOmw8brleKyvnbn73oVHNCsu51uPMz/HWiKkkXsI31JjHW5zqXEqnPYkIiHd8ZmL7FCimLEA==", "dev": true, - "dependencies": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" + "optionalDependencies": { + "semver": "^6.3.0" + } + }, + "node_modules/sver/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "optional": true, + "bin": { + "semver": "bin/semver.js" } }, "node_modules/symbol-tree": { @@ -10600,15 +8149,40 @@ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, + "node_modules/synckit": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", + "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/synckit/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true + }, "node_modules/tar-fs": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", - "integrity": "sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz", + "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", "dev": true, "dependencies": { - "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^2.1.1", + "bare-path": "^2.1.0" } }, "node_modules/tar-stream": { @@ -10622,11 +8196,23 @@ "streamx": "^2.15.0" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true + "node_modules/teex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", + "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", + "dev": true, + "dependencies": { + "streamx": "^2.12.5" + } + }, + "node_modules/text-decoder": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.0.tgz", + "integrity": "sha512-TmLJNj6UgX8xcUZo4UDStGQtDiTzF7BzWlzn9g7UWrjkpHr5uJTK1ld16wZ3LXb2vb6jH8qU89dW5whuMdXYdw==", + "dev": true, + "dependencies": { + "b4a": "^1.6.4" + } }, "node_modules/textextensions": { "version": "3.3.0", @@ -10646,41 +8232,6 @@ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, - "node_modules/through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "dependencies": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "node_modules/through2-filter/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/through2-filter/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, "node_modules/time-stamp": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", @@ -10700,6 +8251,22 @@ "next-tick": "1" } }, + "node_modules/tldts": { + "version": "6.1.48", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.48.tgz", + "integrity": "sha512-SPbnh1zaSzi/OsmHb1vrPNnYuwJbdWjwo5TbBYYMlTtH3/1DSb41t8bcSxkwDmmbG2q6VLPVvQc7Yf23T+1EEw==", + "dependencies": { + "tldts-core": "^6.1.48" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.48", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.48.tgz", + "integrity": "sha512-3gD9iKn/n2UuFH1uilBviK9gvTNT6iYwdqrj1Vr5mh8FuelvpRNaYVH4pNYqUgOGU4aAdL9X35eLuuj0gRsx+A==" + }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -10712,58 +8279,6 @@ "node": ">=0.6.0" } }, - "node_modules/to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "dev": true, - "dependencies": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -10776,87 +8291,27 @@ "node": ">=8.0" } }, - "node_modules/to-regex-range/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/to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-3.0.0.tgz", + "integrity": "sha512-y8MN937s/HVhEoBU1SxfHC+wxCHkV1a9gW8eAdTadYh/bGyesZIVcbjI+mSpFbSVwQici/XjBjuUyri1dnXwBw==", "dev": true, "dependencies": { - "through2": "^2.0.3" + "streamx": "^2.12.5" }, "engines": { - "node": ">= 0.10" - } - }, - "node_modules/to-through/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/to-through/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "node": ">=10.13.0" } }, "node_modules/tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", + "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" + "tldts": "^6.1.32" }, "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==", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, - "node_modules/traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", - "dev": true, - "engines": { - "node": "*" + "node": ">=16" } }, "node_modules/tree-kill": { @@ -10932,229 +8387,130 @@ "dev": true }, "node_modules/typescript": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", - "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=14.17" - } - }, - "node_modules/unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "dev": true, - "dependencies": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, - "node_modules/unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/undertaker": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", - "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "fast-levenshtein": "^1.0.0", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/undertaker/node_modules/fast-levenshtein": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", - "integrity": "sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk=", - "dev": true - }, - "node_modules/undici": { - "version": "5.28.3", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz", - "integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==", - "dev": true, - "dependencies": { - "@fastify/busboy": "^2.0.0" - }, - "engines": { - "node": ">=14.0" - } - }, - "node_modules/union": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", - "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", - "dev": true, - "dependencies": { - "qs": "^6.4.0" - }, - "engines": { - "node": ">= 0.8.0" + "node": ">=14.17" } }, - "node_modules/union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "node_modules/typescript-eslint": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.16.0.tgz", + "integrity": "sha512-wDkVmlY6O2do4V+lZd0GtRfbtXbeD0q9WygwXXSJnC1xorE8eqyC2L1tJimqpSeFrOzRlYtWnUp/uzgHQOgfBQ==", "dev": true, "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" + "@typescript-eslint/eslint-plugin": "8.16.0", + "@typescript-eslint/parser": "8.16.0", + "@typescript-eslint/utils": "8.16.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/union-value/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", "dev": true, "dependencies": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" + "buffer": "^5.2.1", + "through": "^2.3.8" } }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "node_modules/unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", "dev": true, "engines": { - "node": ">= 10.0.0" + "node": ">=0.10.0" } }, - "node_modules/unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "node_modules/undertaker": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-2.0.0.tgz", + "integrity": "sha512-tO/bf30wBbTsJ7go80j0RzA2rcwX6o7XPBpeFcb+jzoeb4pfMM2zUeSDIkY1AWqeZabWxaQZ/h8N9t35QKDLPQ==", "dev": true, "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" + "bach": "^2.0.1", + "fast-levenshtein": "^3.0.0", + "last-run": "^2.0.0", + "undertaker-registry": "^2.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10.13.0" } }, - "node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "node_modules/undertaker-registry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-2.0.0.tgz", + "integrity": "sha512-+hhVICbnp+rlzZMgxXenpvTxpuvA67Bfgtt+O9WOE5jo7w/dyiF1VmoZVIHvP2EkUjsyKyTwYKlLhA+j47m1Ew==", "dev": true, - "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">= 10.13.0" } }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "node_modules/undertaker/node_modules/fast-levenshtein": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-3.0.0.tgz", + "integrity": "sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ==", "dev": true, "dependencies": { - "isarray": "1.0.0" - }, - "engines": { - "node": ">=0.10.0" + "fastest-levenshtein": "^1.0.7" } }, - "node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "node_modules/undici": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.19.8.tgz", + "integrity": "sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=18.17" } }, - "node_modules/unzipper": { - "version": "0.10.14", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.14.tgz", - "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==", - "dev": true, - "dependencies": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - } + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true }, - "node_modules/unzipper/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "node_modules/union": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", + "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", "dev": true, "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "qs": "^6.4.0" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "dev": true, "engines": { - "node": ">=4", - "yarn": "*" + "node": ">= 10.0.0" } }, "node_modules/uri-js": { @@ -11166,36 +8522,17 @@ "punycode": "^2.1.0" } }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "deprecated": "Please see https://github.com/lydell/urix#deprecated", - "dev": true - }, "node_modules/url-join": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", "dev": true }, - "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==", - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "node_modules/use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/urlpattern-polyfill": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", + "dev": true }, "node_modules/userhome": { "version": "1.0.0", @@ -11222,43 +8559,21 @@ } }, "node_modules/v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/validator": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", - "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-4.0.1.tgz", + "integrity": "sha512-fcRLaS4H/hrZk9hYwbdRM35D0U8IYMfEClhXxCivOojl+yTRAZH3Zy2sSy6qVCiGbV9YAtPssP6jaChqC9vPCg==", "dev": true, "engines": { - "node": ">= 0.10" + "node": ">= 10.13.0" } }, "node_modules/value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-4.0.0.tgz", + "integrity": "sha512-aeVK81SIuT6aMJfNo9Vte8Dw0/FZINGBV8BfCraGtqVxIeLAEhJyoWs8SmvRVmXfGss2PmmOwZCuBPbZR+IYWg==", "dev": true, "engines": { - "node": ">= 0.10" + "node": ">= 10.13.0" } }, "node_modules/vinyl": { @@ -11278,87 +8593,113 @@ "node": ">= 0.10" } }, - "node_modules/vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "node_modules/vinyl-contents": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vinyl-contents/-/vinyl-contents-2.0.0.tgz", + "integrity": "sha512-cHq6NnGyi2pZ7xwdHSW1v4Jfnho4TEGtxZHw01cmnc8+i7jgR6bRnED/LbrKan/Q7CvVLbnvA5OepnhbpjBZ5Q==", "dev": true, "dependencies": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" + "bl": "^5.0.0", + "vinyl": "^3.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=10.13.0" } }, - "node_modules/vinyl-fs/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "node_modules/vinyl-contents/node_modules/vinyl": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.0.tgz", + "integrity": "sha512-rC2VRfAVVCGEgjnxHUnpIVh3AGuk62rP3tqVrn+yab0YH7UULisC085+NYH+mnqf3Wx4SpSi1RQMwudL89N03g==", "dev": true, "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "clone": "^2.1.2", + "clone-stats": "^1.0.0", + "remove-trailing-separator": "^1.1.0", + "replace-ext": "^2.0.0", + "teex": "^1.0.1" + }, + "engines": { + "node": ">=10.13.0" } }, - "node_modules/vinyl-fs/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "node_modules/vinyl-fs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-4.0.0.tgz", + "integrity": "sha512-7GbgBnYfaquMk3Qu9g22x000vbYkOex32930rBnc3qByw6HfMEAoELjCjoJv4HuEQxHAurT+nvMHm6MnJllFLw==", "dev": true, "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "fs-mkdirp-stream": "^2.0.1", + "glob-stream": "^8.0.0", + "graceful-fs": "^4.2.11", + "iconv-lite": "^0.6.3", + "is-valid-glob": "^1.0.0", + "lead": "^4.0.0", + "normalize-path": "3.0.0", + "resolve-options": "^2.0.0", + "stream-composer": "^1.0.2", + "streamx": "^2.14.0", + "to-through": "^3.0.0", + "value-or-function": "^4.0.0", + "vinyl": "^3.0.0", + "vinyl-sourcemap": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/vinyl-fs/node_modules/vinyl": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.0.tgz", + "integrity": "sha512-rC2VRfAVVCGEgjnxHUnpIVh3AGuk62rP3tqVrn+yab0YH7UULisC085+NYH+mnqf3Wx4SpSi1RQMwudL89N03g==", + "dev": true, + "dependencies": { + "clone": "^2.1.2", + "clone-stats": "^1.0.0", + "remove-trailing-separator": "^1.1.0", + "replace-ext": "^2.0.0", + "teex": "^1.0.1" + }, + "engines": { + "node": ">=10.13.0" } }, "node_modules/vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-2.0.0.tgz", + "integrity": "sha512-BAEvWxbBUXvlNoFQVFVHpybBbjW1r03WhohJzJDSfgrrK5xVYIDTan6xN14DlyImShgDRv2gl9qhM6irVMsV0Q==", "dev": true, "dependencies": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" + "convert-source-map": "^2.0.0", + "graceful-fs": "^4.2.10", + "now-and-later": "^3.0.0", + "streamx": "^2.12.5", + "vinyl": "^3.0.0", + "vinyl-contents": "^2.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=10.13.0" } }, - "node_modules/vinyl-sourcemap/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "node_modules/vinyl-sourcemap/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/vinyl-sourcemap/node_modules/vinyl": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.0.tgz", + "integrity": "sha512-rC2VRfAVVCGEgjnxHUnpIVh3AGuk62rP3tqVrn+yab0YH7UULisC085+NYH+mnqf3Wx4SpSi1RQMwudL89N03g==", "dev": true, "dependencies": { - "remove-trailing-separator": "^1.0.1" + "clone": "^2.1.2", + "clone-stats": "^1.0.0", + "remove-trailing-separator": "^1.1.0", + "replace-ext": "^2.0.0", + "teex": "^1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=10.13.0" } }, "node_modules/vinyl-sourcemaps-apply": { @@ -11417,66 +8758,67 @@ } }, "node_modules/webdriver": { - "version": "8.32.2", - "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-8.32.2.tgz", - "integrity": "sha512-uyCT2QzCqoz+EsMLTApG5/+RvHJR9MVbdEnjMoxpJDt+IeZCG2Vy/Gq9oNgNQfpxrvZme/EY+PtBsltZi7BAyg==", + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-9.0.8.tgz", + "integrity": "sha512-UnV0ANriSTUgypGk0pz8lApeQuHt+72WEDQG5hFwkkSvggtKLyWdT7+PQkNoXvDajTmiLIqUOq8XPI/Pm71rtw==", "dev": true, "dependencies": { "@types/node": "^20.1.0", "@types/ws": "^8.5.3", - "@wdio/config": "8.32.2", - "@wdio/logger": "8.28.0", - "@wdio/protocols": "8.32.0", - "@wdio/types": "8.32.2", - "@wdio/utils": "8.32.2", - "deepmerge-ts": "^5.1.0", - "got": "^12.6.1", - "ky": "^0.33.0", + "@wdio/config": "9.0.8", + "@wdio/logger": "9.0.8", + "@wdio/protocols": "9.0.8", + "@wdio/types": "9.0.8", + "@wdio/utils": "9.0.8", + "deepmerge-ts": "^7.0.3", "ws": "^8.8.0" }, "engines": { - "node": "^16.13 || >=18" + "node": ">=18.20.0" } }, "node_modules/webdriverio": { - "version": "8.32.2", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-8.32.2.tgz", - "integrity": "sha512-Z0Wc/dHFfWGWJZpaQ8u910/LG0E9EIVTO7J5yjqWx2XtXz2LzQMxYwNRnvNLhY/1tI4y/cZxI6kFMWr8wD2TtA==", - "dev": true, - "dependencies": { - "@types/node": "^20.1.0", - "@wdio/config": "8.32.2", - "@wdio/logger": "8.28.0", - "@wdio/protocols": "8.32.0", - "@wdio/repl": "8.24.12", - "@wdio/types": "8.32.2", - "@wdio/utils": "8.32.2", - "archiver": "^6.0.0", - "aria-query": "^5.0.0", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-9.0.9.tgz", + "integrity": "sha512-IwvKzhcJ9NjOL55xwj27uTTKkfxsg77dmAfqoKFSP5dQ70JzU+NgxiALEjjWQDybtt1yGIkHk7wjjxjboMU1uw==", + "dev": true, + "dependencies": { + "@types/node": "^20.11.30", + "@types/sinonjs__fake-timers": "^8.1.5", + "@wdio/config": "9.0.8", + "@wdio/logger": "9.0.8", + "@wdio/protocols": "9.0.8", + "@wdio/repl": "9.0.8", + "@wdio/types": "9.0.8", + "@wdio/utils": "9.0.8", + "archiver": "^7.0.1", + "aria-query": "^5.3.0", + "cheerio": "^1.0.0-rc.12", "css-shorthand-properties": "^1.1.1", "css-value": "^0.0.1", - "devtools-protocol": "^0.0.1261483", - "grapheme-splitter": "^1.0.2", + "grapheme-splitter": "^1.0.4", + "htmlfy": "^0.2.1", "import-meta-resolve": "^4.0.0", "is-plain-obj": "^4.1.0", + "jszip": "^3.10.1", "lodash.clonedeep": "^4.5.0", "lodash.zip": "^4.2.0", - "minimatch": "^9.0.0", - "puppeteer-core": "^20.9.0", - "query-selector-shadow-dom": "^1.0.0", - "resq": "^1.9.1", + "minimatch": "^9.0.3", + "query-selector-shadow-dom": "^1.0.1", + "resq": "^1.11.0", "rgb2hex": "0.2.5", - "serialize-error": "^11.0.1", - "webdriver": "8.32.2" + "serialize-error": "^11.0.3", + "urlpattern-polyfill": "^10.0.0", + "webdriver": "9.0.8" }, "engines": { - "node": "^16.13 || >=18" + "node": ">=18.20.0" }, "peerDependencies": { - "devtools": "^8.14.0" + "puppeteer-core": "^22.3.0" }, "peerDependenciesMeta": { - "devtools": { + "puppeteer-core": { "optional": true } } @@ -11545,22 +8887,6 @@ "node": ">=18" } }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/whatwg-url/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -11576,16 +8902,10 @@ "node": ">= 8" } }, - "node_modules/which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "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": { @@ -11630,10 +8950,9 @@ "dev": true }, "node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "dev": true, + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "engines": { "node": ">=10.0.0" }, @@ -11788,7 +9107,7 @@ "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", "dev": true, "dependencies": { "buffer-crc32": "~0.2.3", @@ -11807,45 +9126,87 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/z-schema": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.4.tgz", - "integrity": "sha512-gm/lx3hDzJNcLwseIeQVm1UcwhWIKpSB4NqH89pTBtFns4k/HDHudsICtvG05Bvw/Mv3jMyk700y5dadueLHdA==", + "node_modules/zip-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", + "integrity": "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==", "dev": true, "dependencies": { - "lodash.get": "^4.4.2", - "lodash.isequal": "^4.5.0", - "validator": "^13.7.0" - }, - "bin": { - "z-schema": "bin/z-schema" + "archiver-utils": "^5.0.0", + "compress-commons": "^6.0.2", + "readable-stream": "^4.0.0" }, "engines": { - "node": ">=8.0.0" - }, - "optionalDependencies": { - "commander": "^2.20.3" + "node": ">= 14" } }, - "node_modules/z-schema/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "node_modules/zip-stream/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "dev": true, - "optional": 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" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } }, - "node_modules/zip-stream": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-5.0.1.tgz", - "integrity": "sha512-UfZ0oa0C8LI58wJ+moL46BDIMgCQbnsb+2PoiJYtonhBsMh2bq1eRBVkvjfVsqbEHd9/EgKPUuL9saSSsec8OA==", + "node_modules/zip-stream/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", "dev": true, "dependencies": { - "archiver-utils": "^4.0.1", - "compress-commons": "^5.0.1", - "readable-stream": "^3.6.0" + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, "engines": { - "node": ">= 12.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/zip-stream/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/zip-stream/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" } } } diff --git a/package.json b/package.json index 06c4703b269..ca6de2f073c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "blockly", - "version": "11.1.1", + "version": "11.2.0", "description": "Blockly is a library for building visual programming editors.", "keywords": [ "blockly" @@ -22,17 +22,12 @@ "build-debug-log": "npm run build:debug > build-debug.log 2>&1 && tail -3 build-debug.log", "build-strict": "gulp build --verbose --strict", "build-strict-log": "npm run build:strict > build-debug.log 2>&1 && tail -3 build-debug.log", - "build:compiled": "exit 1 # Deprecated; use \"npm run minify\" instead.", - "build:compressed": "exit 1 # Deprecated; use \"npm run minify\" instead.", - "build:js": "exit 1 # Deprecated; use \"npm run tsc\" instead.", - "build:langfiles": "exit 1 # Deprecated; use \"npm run langfiles\" instead.", "clean": "gulp clean", "deployDemos": "npm ci && gulp deployDemos", "deployDemos:beta": "npm ci && gulp deployDemosBeta", "docs": "gulp docs", "format": "prettier --write .", "format:check": "prettier --check .", - "generate:langfiles": "exit 1 # Deprecated; use \"npm run messages\" instead.", "messages": "gulp messages", "lint": "eslint .", "lint:fix": "eslint . --fix", @@ -105,23 +100,25 @@ }, "license": "Apache-2.0", "devDependencies": { - "@blockly/block-test": "^5.0.0", - "@blockly/dev-tools": "^7.0.2", - "@blockly/theme-modern": "^5.0.0", + "@blockly/block-test": "^6.0.4", + "@blockly/dev-tools": "^8.0.6", + "@blockly/theme-modern": "^6.0.3", + "@hyperjump/browser": "^1.1.4", "@hyperjump/json-schema": "^1.5.0", "@microsoft/api-documenter": "^7.22.4", "@microsoft/api-extractor": "^7.29.5", - "@typescript-eslint/eslint-plugin": "^7.3.1", "async-done": "^2.0.0", - "chai": "^4.2.0", - "concurrently": "^8.0.1", - "eslint": "^8.4.1", + "chai": "^5.1.1", + "concurrently": "^9.0.1", + "eslint": "^9.15.0", "eslint-config-google": "^0.14.0", - "eslint-config-prettier": "^9.0.0", - "eslint-plugin-jsdoc": "^48.0.2", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-jsdoc": "^50.5.0", + "eslint-plugin-prettier": "^5.2.1", "glob": "^10.3.4", - "google-closure-compiler": "^20230802.0.0", - "gulp": "^4.0.2", + "globals": "^15.12.0", + "google-closure-compiler": "^20240317.0.0", + "gulp": "^5.0.0", "gulp-concat": "^2.6.1", "gulp-gzip": "^1.4.2", "gulp-header": "^2.0.9", @@ -137,15 +134,17 @@ "markdown-tables-to-json": "^0.1.7", "mocha": "^10.0.0", "patch-package": "^8.0.0", - "prettier": "3.2.5", + "prettier": "^3.3.3", + "prettier-plugin-organize-imports": "^4.0.0", "readline-sync": "^1.4.10", "rimraf": "^5.0.0", "typescript": "^5.3.3", - "webdriverio": "^8.32.2", + "typescript-eslint": "^8.16.0", + "webdriverio": "^9.0.7", "yargs": "^17.2.1" }, "dependencies": { - "jsdom": "23.0.0" + "jsdom": "25.0.1" }, "engines": { "node": ">=18" diff --git a/scripts/gulpfiles/build_tasks.js b/scripts/gulpfiles/build_tasks.js index 27a02cf30cd..a00c1b17dc3 100644 --- a/scripts/gulpfiles/build_tasks.js +++ b/scripts/gulpfiles/build_tasks.js @@ -699,7 +699,7 @@ function buildAdvancedCompilationTest() { // a later browser-based test won't check it should the compile fail. try { fs.unlinkSync('./tests/compile/main_compressed.js'); - } catch (_e) { + } catch { // Probably it didn't exist. } diff --git a/scripts/helpers.js b/scripts/helpers.js index 8150593ddfb..08a147d3e58 100644 --- a/scripts/helpers.js +++ b/scripts/helpers.js @@ -35,7 +35,7 @@ function posixPath(target) { * @return {string} The value s as a eval-able string literal. */ function quote(str) { - /* eslint-disable no-control-regex, no-multi-spaces */ + /* eslint-disable no-control-regex */ /** Regexp for characters to be escaped in a single-quoted string. */ const singleRE = /[\x00-\x1f\\\u2028\u2029']/g; @@ -63,7 +63,7 @@ function quote(str) { '\u2028': '\\u2028', '\u2029': '\\u2029', }; - /* eslint-enable no-control-regex, no-multi-spaces */ + /* eslint-enable no-control-regex */ return "'" + str.replace(singleRE, (c) => replacements[c]) + "'"; } diff --git a/scripts/migration/cjs2esm b/scripts/migration/cjs2esm new file mode 100755 index 00000000000..99a0e222322 --- /dev/null +++ b/scripts/migration/cjs2esm @@ -0,0 +1,162 @@ +#!/usr/bin/env node + +const fs = require('fs'); +const path = require('path'); + +const filenames = process.argv.slice(2); // Trim off node and script name. + +/** Absolute path of repository root. */ +const repoPath = path.resolve(__dirname, '..', '..'); + +////////////////////////////////////////////////////////////////////// +// Process files mentioned on the command line. +////////////////////////////////////////////////////////////////////// + +/** RegExp matching require statements. */ +const requireRE = + /(?:const\s+(?:([$\w]+)|(\{[^}]*\}))\s*=\s*)?require\('([^']+)'\);/g; + +/** RegExp matching key: value pairs in destructuring assignments. */ +const keyValueRE = /([$\w]+)\s*:\s*([$\w]+)\s*(?=,|})/g; + +/** Prefix for RegExp matching a top-level declaration. */ +const declPrefix = '(?:const|let|var|(?:async\\s+)?function(?:\\s*\\*)?|class)'; + +for (const filename of filenames) { + let contents = null; + try { + contents = String(fs.readFileSync(filename)); + } catch (e) { + console.error(`error while reading ${filename}: ${e.message}`); + continue; + } + console.log(`Converting ${filename} from CJS to ESM...`); + + // Remove "use strict". + contents = contents.replace(/^\s*["']use strict["']\s*; *\n/m, ''); + + // Migrate from require to import. + contents = contents.replace( + requireRE, + function ( + orig, // Whole statement to be replaced. + name, // Name of named import of whole module (if applicable). + names, // {}-enclosed list of destructured imports. + moduleName, // Imported module name or path. + ) { + if (moduleName[0] === '.') { + // Relative path. Could check and add '.mjs' suffix if desired. + } + if (name) { + return `import * as ${name} from '${moduleName}';`; + } else if (names) { + names = names.replace(keyValueRE, '$1 as $2'); + return `import ${names} from '${moduleName}';`; + } else { + // Side-effect only require. + return `import '${moduleName}';`; + } + }, + ); + + // Find and update or remove old-style single-export assignments + // like: + // + // exports.bar = foo; // becomes export {foo as bar}; + // exports.foo = foo; // remove the export and export at declaration + // // instead, if possible. + /** @type {!Array<{name: string, re: RegExp>}>} */ + const easyExports = []; + contents = contents.replace( + /^\s*exports\.([$\w]+)\s*=\s*([$\w]+)\s*;\n/gm, + function ( + orig, // Whole statement to be replaced. + exportName, // Name to export item as. + declName, // Already-declared name for item being exported. + ) { + // Renamed exports have to be translated as-is. + if (exportName !== declName) { + return `export {${declName} as ${exportName}};\n`; + } + // OK, we're doing "export.foo = foo;". Can we update the + // declaration? We can't actualy modify it yet as we're in + // the middle of a search-and-replace on contents already, but + // we can delete the old export and later update the + // declaration into an export. + const declRE = new RegExp( + `^(\\s*)(${declPrefix}\\s+${declName})\\b`, + 'gm', + ); + if (contents.match(declRE)) { + easyExports.push({exportName, declRE}); + return ''; // Delete existing export assignment. + } else { + return `export ${exportName};\n`; // Safe fallback. + } + }, + ); + + // Find and update or remove old-style module.exports assignment + // like: + // + // module.exports = {foo, bar: baz, quux}; + // + // which becomes export {baz as bar}, with foo and quux exported at + // declaration instead, if possible. + contents = contents.replace( + /^module\.exports\s*=\s*\{([^\}]+)\};?(\n?)/m, + function ( + orig, // Whole statement to be replaced. + items, // List of items to be exported. + ) { + items = items.replace( + /( *)([$\w]+)\s*(?::\s*([$\w]+)\s*)?,?(\s*?\n?)/gm, + function ( + origItem, // Whole item being replaced. + indent, // Optional leading whitespace. + exportName, // Name to export item as. + declName, // Already-declared name being exported, if different. + newline, // Optional trailing whitespace. + ) { + if (!declName) declName = exportName; + + // Renamed exports have to be translated as-is. + if (exportName !== declName) { + return `${indent}${declName} as ${exportName},${newline}`; + } + // OK, this item has no rename. Can we update the + // declaration? We can't actualy modify it yet as we're in + // the middle of a search-and-replace on contents already, + // but we can delete the item and later update the + // declaration into an export. + const declRE = new RegExp( + `^(\\s*)(${declPrefix}\\s+${declName})\\b`, + 'gm', + ); + if (contents.match(declRE)) { + easyExports.push({exportName, declRE}); + return ''; // Delete existing item. + } else { + return `${indent}${exportName},${newline}`; // Safe fallback. + } + }, + ); + if (/^\s*$/s.test(items)) { + // No items left? + return ''; // Delete entire module.export assignment. + } else { + return `export {${items}};\n`; + } + }, + ); + + // Add 'export' to existing declarations where appropriate. + for (const {exportName, declRE} of easyExports) { + contents = contents.replace(declRE, '$1export $2'); + } + + // Write converted file with new extension. + const newFilename = filename.replace(/.c?js$/, '.mjs'); + fs.writeFileSync(newFilename, contents); + console.log(`Wrote ${newFilename}.`); +} diff --git a/tests/.eslintrc.json b/tests/.eslintrc.json deleted file mode 100644 index 1d5e1fea295..00000000000 --- a/tests/.eslintrc.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "globals": { - "Blockly": true, - "dartGenerator": true, - "javascriptGenerator": true, - "luaGenerator": true, - "phpGenerator": true, - "pythonGenerator": true - } -} diff --git a/tests/browser/.eslintrc.json b/tests/browser/.eslintrc.json deleted file mode 100644 index 2fe4f6a6bb5..00000000000 --- a/tests/browser/.eslintrc.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "env": { - "browser": true, - "mocha": true, - "node": true - }, - "globals": { - "chai": false, - "sinon": false - }, - "rules": { - "no-unused-vars": ["off"], - // Allow uncommented helper functions in tests. - "require-jsdoc": ["off"], - "prefer-rest-params": ["off"], - "no-invalid-this": ["off"], - "valid-jsdoc": [ - "error", - { - "requireReturnType": false, - "requireParamType": false - } - ] - }, - "extends": "../../.eslintrc.js", - "parserOptions": { - "sourceType": "module" - } -} diff --git a/tests/browser/.mocharc.js b/tests/browser/.mocharc.js index b11a846fb5a..879bb462378 100644 --- a/tests/browser/.mocharc.js +++ b/tests/browser/.mocharc.js @@ -2,5 +2,5 @@ module.exports = { ui: 'tdd', - require: __dirname + '/test/hooks.js', + require: __dirname + '/test/hooks.mjs', }; diff --git a/tests/browser/test/basic_block_factory_test.js b/tests/browser/test/basic_block_factory_test.mjs similarity index 93% rename from tests/browser/test/basic_block_factory_test.js rename to tests/browser/test/basic_block_factory_test.mjs index 026f2565950..a9f3cc3f37d 100644 --- a/tests/browser/test/basic_block_factory_test.js +++ b/tests/browser/test/basic_block_factory_test.mjs @@ -8,8 +8,8 @@ * @fileoverview Node.js script to run Automated tests in Chrome, via webdriver. */ -const chai = require('chai'); -const {testSetup, testFileLocations} = require('./test_setup'); +import * as chai from 'chai'; +import {testFileLocations, testSetup} from './test_setup.mjs'; suite('Testing Connecting Blocks', function (done) { // Setting timeout to unlimited as the webdriver takes a longer time to run than most mocha test diff --git a/tests/browser/test/basic_block_test.js b/tests/browser/test/basic_block_test.mjs similarity index 89% rename from tests/browser/test/basic_block_test.js rename to tests/browser/test/basic_block_test.mjs index 7d594c50ede..326e20ecfd4 100644 --- a/tests/browser/test/basic_block_test.js +++ b/tests/browser/test/basic_block_test.mjs @@ -9,14 +9,13 @@ * webdriver, of basic Blockly block functionality. */ -const chai = require('chai'); -const { - testSetup, - testFileLocations, - getAllBlocks, +import * as chai from 'chai'; +import { dragNthBlockFromFlyout, -} = require('./test_setup'); -const {Key} = require('webdriverio'); + getAllBlocks, + testFileLocations, + testSetup, +} from './test_setup.mjs'; suite('Basic block tests', function (done) { // Setting timeout to unlimited as the webdriver takes a longer time diff --git a/tests/browser/test/basic_playground_test.js b/tests/browser/test/basic_playground_test.mjs similarity index 98% rename from tests/browser/test/basic_playground_test.js rename to tests/browser/test/basic_playground_test.mjs index 091f2f6b5ce..55ff58e4b05 100644 --- a/tests/browser/test/basic_playground_test.js +++ b/tests/browser/test/basic_playground_test.mjs @@ -8,16 +8,16 @@ * @fileoverview Node.js script to run Automated tests in Chrome, via webdriver. */ -const chai = require('chai'); -const { - testSetup, - testFileLocations, - dragNthBlockFromFlyout, - dragBlockTypeFromFlyout, +import * as chai from 'chai'; +import { connect, contextMenuSelect, + dragBlockTypeFromFlyout, + dragNthBlockFromFlyout, PAUSE_TIME, -} = require('./test_setup'); + testFileLocations, + testSetup, +} from './test_setup.mjs'; async function getIsCollapsed(browser, blockId) { return await browser.execute((blockId) => { diff --git a/tests/browser/test/block_undo_test.js b/tests/browser/test/block_undo_test.mjs similarity index 91% rename from tests/browser/test/block_undo_test.js rename to tests/browser/test/block_undo_test.mjs index 3dc5babc5ea..0d9f256c280 100644 --- a/tests/browser/test/block_undo_test.js +++ b/tests/browser/test/block_undo_test.mjs @@ -8,15 +8,15 @@ * @fileoverview Node.js script to run Automated tests in Chrome, via webdriver. */ -const chai = require('chai'); -const {Key} = require('webdriverio'); -const { - testSetup, - testFileLocations, +import * as chai from 'chai'; +import {Key} from 'webdriverio'; +import { dragBlockTypeFromFlyout, - screenDirection, getAllBlocks, -} = require('./test_setup'); + screenDirection, + testFileLocations, + testSetup, +} from './test_setup.mjs'; suite('Testing undo block movement', function (done) { // Setting timeout to unlimited as the webdriver takes a longer time to run than most mocha test diff --git a/tests/browser/test/delete_blocks_test.js b/tests/browser/test/delete_blocks_test.mjs similarity index 98% rename from tests/browser/test/delete_blocks_test.js rename to tests/browser/test/delete_blocks_test.mjs index b25c096a1ec..27e17054d56 100644 --- a/tests/browser/test/delete_blocks_test.js +++ b/tests/browser/test/delete_blocks_test.mjs @@ -4,17 +4,17 @@ * SPDX-License-Identifier: Apache-2.0 */ -const chai = require('chai'); -const { - testSetup, - testFileLocations, - getAllBlocks, - getBlockElementById, +import * as chai from 'chai'; +import {Key} from 'webdriverio'; +import { clickBlock, contextMenuSelect, + getAllBlocks, + getBlockElementById, PAUSE_TIME, -} = require('./test_setup'); -const {Key} = require('webdriverio'); + testFileLocations, + testSetup, +} from './test_setup.mjs'; const firstBlockId = 'root_block'; const startBlocks = { diff --git a/tests/browser/test/extensive_test.js b/tests/browser/test/extensive_test.mjs similarity index 98% rename from tests/browser/test/extensive_test.js rename to tests/browser/test/extensive_test.mjs index b16a06bbce2..786be0ade53 100644 --- a/tests/browser/test/extensive_test.js +++ b/tests/browser/test/extensive_test.mjs @@ -8,15 +8,15 @@ * @fileoverview Node.js script to run Automated tests in Chrome, via webdriver. */ -const chai = require('chai'); -const { - testSetup, - testFileLocations, - getBlockElementById, +import * as chai from 'chai'; +import {Key} from 'webdriverio'; +import { getAllBlocks, + getBlockElementById, PAUSE_TIME, -} = require('./test_setup'); -const {Key} = require('webdriverio'); + testFileLocations, + testSetup, +} from './test_setup.mjs'; suite('This tests loading Large Configuration and Deletion', function (done) { // Setting timeout to unlimited as the webdriver takes a longer time to run than most mocha test diff --git a/tests/browser/test/field_edits_test.js b/tests/browser/test/field_edits_test.mjs similarity index 93% rename from tests/browser/test/field_edits_test.js rename to tests/browser/test/field_edits_test.mjs index bad2e10eda0..bd4da0019ef 100644 --- a/tests/browser/test/field_edits_test.js +++ b/tests/browser/test/field_edits_test.mjs @@ -8,15 +8,15 @@ * @fileoverview Node.js script to run Automated tests in Chrome, via webdriver. */ -const chai = require('chai'); -const { - testSetup, - testFileLocations, +import * as chai from 'chai'; +import {Key} from 'webdriverio'; +import { + clickWorkspace, dragBlockTypeFromFlyout, screenDirection, - clickWorkspace, -} = require('./test_setup'); -const {Key} = require('webdriverio'); + testFileLocations, + testSetup, +} from './test_setup.mjs'; suite('Testing Field Edits', function (done) { // Setting timeout to unlimited as the webdriver takes a longer time to run than most mocha test diff --git a/tests/browser/test/hooks.js b/tests/browser/test/hooks.mjs similarity index 80% rename from tests/browser/test/hooks.js rename to tests/browser/test/hooks.mjs index a7f08ed564e..5b86150060d 100644 --- a/tests/browser/test/hooks.js +++ b/tests/browser/test/hooks.mjs @@ -9,9 +9,9 @@ * These create a shared chromedriver instance, so we don't have to fire up * a new one for every suite. */ -const {driverSetup, driverTeardown} = require('./test_setup'); +import {driverSetup, driverTeardown} from './test_setup.mjs'; -const mochaHooks = { +export const mochaHooks = { async beforeAll() { // Set a long timeout for startup. this.timeout(10000); @@ -21,5 +21,3 @@ const mochaHooks = { return await driverTeardown(); }, }; - -module.exports = {mochaHooks}; diff --git a/tests/browser/test/mutator_test.js b/tests/browser/test/mutator_test.mjs similarity index 97% rename from tests/browser/test/mutator_test.js rename to tests/browser/test/mutator_test.mjs index 93e698af635..6d077b9fd92 100644 --- a/tests/browser/test/mutator_test.js +++ b/tests/browser/test/mutator_test.mjs @@ -4,18 +4,18 @@ * SPDX-License-Identifier: Apache-2.0 */ -const chai = require('chai'); -const { - testSetup, - testFileLocations, +import * as chai from 'chai'; +import { + PAUSE_TIME, connect, + dragBlockFromMutatorFlyout, dragBlockTypeFromFlyout, - screenDirection, - PAUSE_TIME, getBlockElementById, - dragBlockFromMutatorFlyout, openMutatorForBlock, -} = require('./test_setup'); + screenDirection, + testFileLocations, + testSetup, +} from './test_setup.mjs'; suite('Mutating a block', function (done) { this.timeout(0); diff --git a/tests/browser/test/procedure_test.js b/tests/browser/test/procedure_test.mjs similarity index 97% rename from tests/browser/test/procedure_test.js rename to tests/browser/test/procedure_test.mjs index c36cb918592..34368c73241 100644 --- a/tests/browser/test/procedure_test.js +++ b/tests/browser/test/procedure_test.mjs @@ -8,16 +8,16 @@ * @fileoverview Node.js script to run Automated tests in Chrome, via webdriver. */ -const chai = require('chai'); -const { - testSetup, - testFileLocations, - getSelectedBlockElement, - getNthBlockOfCategory, - getBlockTypeFromCategory, +import * as chai from 'chai'; +import { connect, + getBlockTypeFromCategory, + getNthBlockOfCategory, + getSelectedBlockElement, PAUSE_TIME, -} = require('./test_setup'); + testFileLocations, + testSetup, +} from './test_setup.mjs'; suite('Testing Connecting Blocks', function (done) { // Setting timeout to unlimited as the webdriver takes a longer time to run than most mocha test diff --git a/tests/browser/test/test_setup.js b/tests/browser/test/test_setup.mjs similarity index 90% rename from tests/browser/test/test_setup.js rename to tests/browser/test/test_setup.mjs index a07b274e4d1..523a5d851fc 100644 --- a/tests/browser/test/test_setup.js +++ b/tests/browser/test/test_setup.mjs @@ -16,9 +16,10 @@ * identifiers that Selenium can use to find those elements. */ -const webdriverio = require('webdriverio'); -const path = require('path'); -const {posixPath} = require('../../../scripts/helpers'); +import * as path from 'path'; +import {fileURLToPath} from 'url'; +import * as webdriverio from 'webdriverio'; +import {posixPath} from '../../../scripts/helpers.js'; let driver = null; @@ -26,14 +27,14 @@ let driver = null; * The default amount of time to wait during a test. Increase this to make * tests easier to watch; decrease it to make tests run faster. */ -const PAUSE_TIME = 50; +export const PAUSE_TIME = 50; /** * Start up the test page. This should only be done once, to avoid * constantly popping browser windows open and closed. * @return A Promsie that resolves to a webdriverIO browser that tests can manipulate. */ -async function driverSetup() { +export async function driverSetup() { const options = { capabilities: { 'browserName': 'chrome', @@ -67,7 +68,7 @@ async function driverSetup() { * End the webdriverIO session. * @return A Promise that resolves after the actions have been completed. */ -async function driverTeardown() { +export async function driverTeardown() { await driver.deleteSession(); driver = null; return; @@ -79,7 +80,7 @@ async function driverTeardown() { * a Blockly playground with a workspace. * @return A Promsie that resolves to a webdriverIO browser that tests can manipulate. */ -async function testSetup(playgroundUrl) { +export async function testSetup(playgroundUrl) { if (!driver) { await driverSetup(); } @@ -91,7 +92,9 @@ async function testSetup(playgroundUrl) { return driver; } -const testFileLocations = { +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +export const testFileLocations = { BLOCK_FACTORY: 'file://' + posixPath(path.join(__dirname, '..', '..', '..', 'demos', 'blockfactory')) + @@ -116,7 +119,7 @@ const testFileLocations = { * @readonly * @enum {number} */ -const screenDirection = { +export const screenDirection = { RTL: -1, LTR: 1, }; @@ -125,7 +128,7 @@ const screenDirection = { * @param browser The active WebdriverIO Browser object. * @return A Promise that resolves to the ID of the currently selected block. */ -async function getSelectedBlockId(browser) { +export async function getSelectedBlockId(browser) { return await browser.execute(() => { // Note: selected is an ICopyable and I am assuming that it is a BlockSvg. return Blockly.common.getSelected()?.id; @@ -137,7 +140,7 @@ async function getSelectedBlockId(browser) { * @return A Promise that resolves to the selected block's root SVG element, * as an interactable browser element. */ -async function getSelectedBlockElement(browser) { +export async function getSelectedBlockElement(browser) { const id = await getSelectedBlockId(browser); return getBlockElementById(browser, id); } @@ -148,7 +151,7 @@ async function getSelectedBlockElement(browser) { * @return A Promise that resolves to the root SVG element of the block with * the given ID, as an interactable browser element. */ -async function getBlockElementById(browser, id) { +export async function getBlockElementById(browser, id) { const elem = await browser.$(`[data-id="${id}"]`); elem['id'] = id; return elem; @@ -165,7 +168,7 @@ async function getBlockElementById(browser, id) { * @param clickOptions The options to pass to webdriverio's element.click function. * @return A Promise that resolves when the actions are completed. */ -async function clickBlock(browser, block, clickOptions) { +export async function clickBlock(browser, block, clickOptions) { const findableId = 'clickTargetElement'; // In the browser context, find the element that we want and give it a findable ID. await browser.execute( @@ -203,7 +206,7 @@ async function clickBlock(browser, block, clickOptions) { * @param browser The active WebdriverIO Browser object. * @return A Promise that resolves when the actions are completed. */ -async function clickWorkspace(browser) { +export async function clickWorkspace(browser) { const workspace = await browser.$('#blocklyDiv > div > svg.blocklySvg > g'); await workspace.click(); await browser.pause(PAUSE_TIME); @@ -215,7 +218,7 @@ async function clickWorkspace(browser) { * @return A Promise that resolves when the actions are completed. * @throws If the mutator workspace cannot be found. */ -async function clickMutatorWorkspace(browser) { +export async function clickMutatorWorkspace(browser) { const hasMutator = await browser.$('.blocklyMutatorBackground'); if (!hasMutator) { throw new Error('No mutator workspace found'); @@ -234,7 +237,7 @@ async function clickMutatorWorkspace(browser) { * category with the given name, as an interactable browser element. * @throws If the category cannot be found. */ -async function getCategory(browser, categoryName) { +export async function getCategory(browser, categoryName) { const category = browser.$(`.blocklyToolboxCategory*=${categoryName}`); category.waitForExist(); @@ -248,7 +251,7 @@ async function getCategory(browser, categoryName) { * @return A Promise that resolves to the root element of the nth * block in the given category. */ -async function getNthBlockOfCategory(browser, categoryName, n) { +export async function getNthBlockOfCategory(browser, categoryName, n) { const category = await getCategory(browser, categoryName); await category.click(); const block = await browser.$( @@ -265,7 +268,11 @@ async function getNthBlockOfCategory(browser, categoryName, n) { * @return A Promise that resolves to the root element of the first * block with the given type in the given category. */ -async function getBlockTypeFromCategory(browser, categoryName, blockType) { +export async function getBlockTypeFromCategory( + browser, + categoryName, + blockType, +) { if (categoryName) { const category = await getCategory(browser, categoryName); await category.click(); @@ -287,7 +294,7 @@ async function getBlockTypeFromCategory(browser, categoryName, blockType) { * @return A Promise that resolves to the root element of the block with the * given position and type on the workspace. */ -async function getBlockTypeFromWorkspace(browser, blockType, position) { +export async function getBlockTypeFromWorkspace(browser, blockType, position) { const id = await browser.execute( (blockType, position) => { return Blockly.getMainWorkspace().getBlocksByType(blockType, true)[ @@ -372,7 +379,7 @@ async function getLocationOfBlockConnection( * @param dragBlockSelector The selector of the block to drag * @return A Promise that resolves when the actions are completed. */ -async function connect( +export async function connect( browser, draggedBlock, draggedConnection, @@ -411,7 +418,7 @@ async function connect( * @param browser The active WebdriverIO Browser object. * @return A Promise that resolves when the actions are completed. */ -async function switchRTL(browser) { +export async function switchRTL(browser) { const ltrForm = await browser.$('#options > select:nth-child(1)'); await ltrForm.selectByIndex(1); await browser.pause(PAUSE_TIME + 450); @@ -431,7 +438,7 @@ async function switchRTL(browser) { * @return A Promise that resolves to the root element of the newly * created block. */ -async function dragNthBlockFromFlyout(browser, categoryName, n, x, y) { +export async function dragNthBlockFromFlyout(browser, categoryName, n, x, y) { const flyoutBlock = await getNthBlockOfCategory(browser, categoryName, n); await flyoutBlock.dragAndDrop({x: x, y: y}); return await getSelectedBlockElement(browser); @@ -452,7 +459,13 @@ async function dragNthBlockFromFlyout(browser, categoryName, n, x, y) { * @return A Promise that resolves to the root element of the newly * created block. */ -async function dragBlockTypeFromFlyout(browser, categoryName, type, x, y) { +export async function dragBlockTypeFromFlyout( + browser, + categoryName, + type, + x, + y, +) { const flyoutBlock = await getBlockTypeFromCategory( browser, categoryName, @@ -477,7 +490,13 @@ async function dragBlockTypeFromFlyout(browser, categoryName, type, x, y) { * @return A Promise that resolves to the root element of the newly * created block. */ -async function dragBlockFromMutatorFlyout(browser, mutatorBlock, type, x, y) { +export async function dragBlockFromMutatorFlyout( + browser, + mutatorBlock, + type, + x, + y, +) { const id = await browser.execute( (mutatorBlockId, blockType) => { return Blockly.getMainWorkspace() @@ -505,7 +524,7 @@ async function dragBlockFromMutatorFlyout(browser, mutatorBlock, type, x, y) { * @param itemText The display text of the context menu item to click. * @return A Promise that resolves when the actions are completed. */ -async function contextMenuSelect(browser, block, itemText) { +export async function contextMenuSelect(browser, block, itemText) { await clickBlock(browser, block, {button: 2}); const item = await browser.$(`div=${itemText}`); @@ -522,7 +541,7 @@ async function contextMenuSelect(browser, block, itemText) { * @param block The block to click, as an interactable element. * @return A Promise that resolves when the actions are complete. */ -async function openMutatorForBlock(browser, block) { +export async function openMutatorForBlock(browser, block) { const icon = await browser.$(`[data-id="${block.id}"] > g.blocklyIconGroup`); await icon.click(); } @@ -535,7 +554,7 @@ async function openMutatorForBlock(browser, block) { * @param browser The active WebdriverIO Browser object. * @return A Promise that resolves to an array of blocks on the main workspace. */ -async function getAllBlocks(browser) { +export async function getAllBlocks(browser) { return browser.execute(() => { return Blockly.getMainWorkspace() .getAllBlocks(false) @@ -556,7 +575,7 @@ async function getAllBlocks(browser) { * @param yDelta How far to drag the flyout in the y direction. Positive is down. * @return A Promise that resolves when the actions are completed. */ -async function scrollFlyout(browser, xDelta, yDelta) { +export async function scrollFlyout(browser, xDelta, yDelta) { // There are two flyouts on the playground workspace: one for the trash can // and one for the toolbox. We want the second one. // This assumes there is only one scrollbar handle in the flyout, but it could @@ -568,31 +587,3 @@ async function scrollFlyout(browser, xDelta, yDelta) { await scrollbarHandle.dragAndDrop({x: xDelta, y: yDelta}); await browser.pause(PAUSE_TIME); } - -module.exports = { - testSetup, - testFileLocations, - driverSetup, - driverTeardown, - getSelectedBlockElement, - getSelectedBlockId, - getBlockElementById, - clickBlock, - clickWorkspace, - clickMutatorWorkspace, - getCategory, - getNthBlockOfCategory, - getBlockTypeFromCategory, - dragNthBlockFromFlyout, - dragBlockTypeFromFlyout, - dragBlockFromMutatorFlyout, - connect, - switchRTL, - contextMenuSelect, - openMutatorForBlock, - screenDirection, - getBlockTypeFromWorkspace, - getAllBlocks, - scrollFlyout, - PAUSE_TIME, -}; diff --git a/tests/browser/test/toolbox_drag_test.js b/tests/browser/test/toolbox_drag_test.mjs similarity index 98% rename from tests/browser/test/toolbox_drag_test.js rename to tests/browser/test/toolbox_drag_test.mjs index 14a9f0836db..742872d9339 100644 --- a/tests/browser/test/toolbox_drag_test.js +++ b/tests/browser/test/toolbox_drag_test.mjs @@ -8,15 +8,15 @@ * @fileoverview Tests for the dragging out of the toolbox and flyout. */ -const chai = require('chai'); -const { - testSetup, - testFileLocations, +import * as chai from 'chai'; +import { getCategory, - scrollFlyout, - screenDirection, PAUSE_TIME, -} = require('./test_setup'); + screenDirection, + scrollFlyout, + testFileLocations, + testSetup, +} from './test_setup.mjs'; // Categories in the basic toolbox. const basicCategories = [ @@ -25,7 +25,6 @@ const basicCategories = [ 'Math', 'Text', 'Lists', - 'Colour', 'Variables', 'Functions', ]; @@ -39,12 +38,13 @@ const testCategories = [ 'Row', 'Stack', 'Statement', - 'Drag', + // Disabled due to #8466 + // 'Drag', + // Skip fields because it's an accordion that is already open. // 'Fields', 'Defaults', 'Numbers', - 'Angles', 'Drop-downs', // Note: images has a block that has a bad image source, but still builds and renders // just fine. diff --git a/tests/browser/test/workspace_comment_test.js b/tests/browser/test/workspace_comment_test.mjs similarity index 97% rename from tests/browser/test/workspace_comment_test.js rename to tests/browser/test/workspace_comment_test.mjs index b6adfebcd20..5719948d0e9 100644 --- a/tests/browser/test/workspace_comment_test.js +++ b/tests/browser/test/workspace_comment_test.mjs @@ -4,10 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -const chai = require('chai'); -const sinon = require('sinon'); -const {Key} = require('webdriverio'); -const {testSetup, testFileLocations} = require('./test_setup'); +import * as chai from 'chai'; +import * as sinon from 'sinon'; +import {testFileLocations, testSetup} from './test_setup.mjs'; suite('Workspace comments', function () { // Setting timeout to unlimited as the webdriver takes a longer time diff --git a/tests/compile/main.js b/tests/compile/main.js index 9144c4d3bae..bbca3909f90 100644 --- a/tests/compile/main.js +++ b/tests/compile/main.js @@ -47,7 +47,7 @@ window['healthCheck'] = function() { const blockCount = getMainWorkspace().getFlyout().getWorkspace().getTopBlocks().length; return (blockCount > 5 && blockCount < 100); - } catch (_e) { + } catch { return false; } }; diff --git a/tests/migration/validate-renamings.mjs b/tests/migration/validate-renamings.mjs index b0f0e6f7fbf..e7f9f4a702e 100755 --- a/tests/migration/validate-renamings.mjs +++ b/tests/migration/validate-renamings.mjs @@ -11,11 +11,10 @@ * (renamings-schema.json). */ -import JSON5 from 'json5'; -import {readFile} from 'fs/promises'; -import {posixPath} from '../../scripts/helpers.js'; import {validate} from '@hyperjump/json-schema/draft-2020-12'; -import {DETAILED} from '@hyperjump/json-schema/experimental'; +import {BASIC} from '@hyperjump/json-schema/experimental'; +import {readFile} from 'fs/promises'; +import JSON5 from 'json5'; /** @type {URL} Renaming schema filename. */ const SCHEMA_URL = new URL('renamings.schema.json', import.meta.url); @@ -26,35 +25,39 @@ const RENAMINGS_URL = new URL( import.meta.url, ); -const renamingsJson5 = await readFile(RENAMINGS_URL); -const renamings = JSON5.parse(renamingsJson5); +readFile(RENAMINGS_URL).then((renamingsJson5) => { + const renamings = JSON5.parse(renamingsJson5); -const output = await validate(SCHEMA_URL, renamings, DETAILED); - -if (!output.valid) { - console.log('Renamings file is invalid.'); - console.log('Maybe this validator output will help you find the problem:'); - console.log(JSON5.stringify(output, undefined, ' ')); - process.exit(1); -} - -// File passed schema validation. Do some additional checks. -let ok = true; -Object.entries(renamings).forEach(([version, modules]) => { - // Scan through modules and check for duplicates. - const seen = new Set(); - for (const {oldName} of modules) { - if (seen.has(oldName)) { - console.log( - `Duplicate entry for module ${oldName} ` + `in version ${version}.`, + validate(SCHEMA_URL, renamings, BASIC).then((output) => { + if (!output.valid) { + console.error(`Renamings file is invalid. First error occurs at: + ${output.errors[0].instanceLocation}`); + console.info( + `Here is the full validator output, in case that helps:\n`, + output, ); - ok = false; + process.exit(1); + } + + // File passed schema validation. Do some additional checks. + let ok = true; + Object.entries(renamings).forEach(([version, modules]) => { + // Scan through modules and check for duplicates. + const seen = new Set(); + for (const {oldName} of modules) { + if (seen.has(oldName)) { + console.error( + `Duplicate entry for module ${oldName} ` + `in version ${version}.`, + ); + ok = false; + } + seen.add(oldName); + } + }); + if (!ok) { + console.error('Renamings file is invalid.'); + process.exit(1); } - seen.add(oldName); - } + // Default is a successful exit 0. + }); }); -if (!ok) { - console.log('Renamings file is invalid.'); - process.exit(1); -} -// Default is a successful exit 0. diff --git a/tests/mocha/.eslintrc.json b/tests/mocha/.eslintrc.json deleted file mode 100644 index 0de898aa6dd..00000000000 --- a/tests/mocha/.eslintrc.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "env": { - "browser": true, - "mocha": true - }, - "globals": { - "chai": false, - "sinon": false - }, - "rules": { - "no-unused-vars": ["off"], - // Allow uncommented helper functions in tests. - "require-jsdoc": ["off"], - "prefer-rest-params": ["off"], - "no-invalid-this": ["off"] - }, - "extends": "../../.eslintrc.js", - "parserOptions": { - "sourceType": "module" - } -} diff --git a/tests/mocha/astnode_test.js b/tests/mocha/astnode_test.js index a9f0de0d33c..7ffe8efb90a 100644 --- a/tests/mocha/astnode_test.js +++ b/tests/mocha/astnode_test.js @@ -5,6 +5,7 @@ */ import {ASTNode} from '../../build/src/core/keyboard_nav/ast_node.js'; +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -110,7 +111,7 @@ suite('ASTNode', function () { const connection = input.connection; const node = ASTNode.createConnectionNode(connection); const newASTNode = node.findNextForInput(input); - chai.assert.equal(newASTNode.getLocation(), input2.connection); + assert.equal(newASTNode.getLocation(), input2.connection); }); test('findPrevForInput', function () { @@ -119,7 +120,7 @@ suite('ASTNode', function () { const connection = input2.connection; const node = ASTNode.createConnectionNode(connection); const newASTNode = node.findPrevForInput(input2); - chai.assert.equal(newASTNode.getLocation(), input.connection); + assert.equal(newASTNode.getLocation(), input.connection); }); test('findNextForField', function () { @@ -127,7 +128,7 @@ suite('ASTNode', function () { const field2 = this.blocks.statementInput1.inputList[0].fieldRow[1]; const node = ASTNode.createFieldNode(field); const newASTNode = node.findNextForField(field); - chai.assert.equal(newASTNode.getLocation(), field2); + assert.equal(newASTNode.getLocation(), field2); }); test('findPrevForField', function () { @@ -135,7 +136,7 @@ suite('ASTNode', function () { const field2 = this.blocks.statementInput1.inputList[0].fieldRow[1]; const node = ASTNode.createFieldNode(field2); const newASTNode = node.findPrevForField(field2); - chai.assert.equal(newASTNode.getLocation(), field); + assert.equal(newASTNode.getLocation(), field); }); test('navigateBetweenStacks_Forward', function () { @@ -144,7 +145,7 @@ suite('ASTNode', function () { this.blocks.statementInput1.nextConnection, ); const newASTNode = node.navigateBetweenStacks(true); - chai.assert.equal(newASTNode.getLocation(), this.blocks.statementInput4); + assert.equal(newASTNode.getLocation(), this.blocks.statementInput4); }); test('navigateBetweenStacks_Backward', function () { @@ -153,7 +154,7 @@ suite('ASTNode', function () { this.blocks.statementInput4, ); const newASTNode = node.navigateBetweenStacks(false); - chai.assert.equal(newASTNode.getLocation(), this.blocks.statementInput1); + assert.equal(newASTNode.getLocation(), this.blocks.statementInput1); }); test('getOutAstNodeForBlock', function () { const node = new ASTNode( @@ -163,7 +164,7 @@ suite('ASTNode', function () { const newASTNode = node.getOutAstNodeForBlock( this.blocks.statementInput2, ); - chai.assert.equal(newASTNode.getLocation(), this.blocks.statementInput1); + assert.equal(newASTNode.getLocation(), this.blocks.statementInput1); }); test('getOutAstNodeForBlock_OneBlock', function () { const node = new ASTNode( @@ -173,7 +174,7 @@ suite('ASTNode', function () { const newASTNode = node.getOutAstNodeForBlock( this.blocks.statementInput4, ); - chai.assert.equal(newASTNode.getLocation(), this.blocks.statementInput4); + assert.equal(newASTNode.getLocation(), this.blocks.statementInput4); }); test('findFirstFieldOrInput_', function () { const node = new ASTNode( @@ -184,7 +185,7 @@ suite('ASTNode', function () { const newASTNode = node.findFirstFieldOrInput( this.blocks.statementInput4, ); - chai.assert.equal(newASTNode.getLocation(), field); + assert.equal(newASTNode.getLocation(), field); }); }); @@ -345,31 +346,31 @@ suite('ASTNode', function () { const prevConnection = this.blocks.statementInput1.previousConnection; const node = ASTNode.createConnectionNode(prevConnection); const nextNode = node.next(); - chai.assert.equal(nextNode.getLocation(), this.blocks.statementInput1); + assert.equal(nextNode.getLocation(), this.blocks.statementInput1); }); test('fromBlockToNext', function () { const nextConnection = this.blocks.statementInput1.nextConnection; const node = ASTNode.createBlockNode(this.blocks.statementInput1); const nextNode = node.next(); - chai.assert.equal(nextNode.getLocation(), nextConnection); + assert.equal(nextNode.getLocation(), nextConnection); }); test('fromBlockToNull', function () { const node = ASTNode.createBlockNode(this.blocks.noNextConnection); const nextNode = node.next(); - chai.assert.isNull(nextNode); + assert.isNull(nextNode); }); test('fromNextToPrevious', function () { const nextConnection = this.blocks.statementInput1.nextConnection; const prevConnection = this.blocks.statementInput2.previousConnection; const node = ASTNode.createConnectionNode(nextConnection); const nextNode = node.next(); - chai.assert.equal(nextNode.getLocation(), prevConnection); + assert.equal(nextNode.getLocation(), prevConnection); }); test('fromNextToNull', function () { const nextConnection = this.blocks.statementInput2.nextConnection; const node = ASTNode.createConnectionNode(nextConnection); const nextNode = node.next(); - chai.assert.isNull(nextNode); + assert.isNull(nextNode); }); test('fromInputToInput', function () { const input = this.blocks.statementInput1.inputList[0]; @@ -377,7 +378,7 @@ suite('ASTNode', function () { this.blocks.statementInput1.inputList[1].connection; const node = ASTNode.createInputNode(input); const nextNode = node.next(); - chai.assert.equal(nextNode.getLocation(), inputConnection); + assert.equal(nextNode.getLocation(), inputConnection); }); test('fromInputToStatementInput', function () { const input = this.blocks.fieldAndInputs2.inputList[1]; @@ -385,26 +386,26 @@ suite('ASTNode', function () { this.blocks.fieldAndInputs2.inputList[2].connection; const node = ASTNode.createInputNode(input); const nextNode = node.next(); - chai.assert.equal(nextNode.getLocation(), inputConnection); + assert.equal(nextNode.getLocation(), inputConnection); }); test('fromInputToField', function () { const input = this.blocks.fieldAndInputs2.inputList[0]; const field = this.blocks.fieldAndInputs2.inputList[1].fieldRow[0]; const node = ASTNode.createInputNode(input); const nextNode = node.next(); - chai.assert.equal(nextNode.getLocation(), field); + assert.equal(nextNode.getLocation(), field); }); test('fromInputToNull', function () { const input = this.blocks.fieldAndInputs2.inputList[2]; const node = ASTNode.createInputNode(input); const nextNode = node.next(); - chai.assert.isNull(nextNode); + assert.isNull(nextNode); }); test('fromOutputToBlock', function () { const output = this.blocks.fieldWithOutput.outputConnection; const node = ASTNode.createConnectionNode(output); const nextNode = node.next(); - chai.assert.equal(nextNode.getLocation(), this.blocks.fieldWithOutput); + assert.equal(nextNode.getLocation(), this.blocks.fieldWithOutput); }); test('fromFieldToInput', function () { const field = this.blocks.statementInput1.inputList[0].fieldRow[1]; @@ -412,31 +413,31 @@ suite('ASTNode', function () { this.blocks.statementInput1.inputList[0].connection; const node = ASTNode.createFieldNode(field); const nextNode = node.next(); - chai.assert.equal(nextNode.getLocation(), inputConnection); + assert.equal(nextNode.getLocation(), inputConnection); }); test('fromFieldToField', function () { const field = this.blocks.fieldAndInputs.inputList[0].fieldRow[0]; const node = ASTNode.createFieldNode(field); const field2 = this.blocks.fieldAndInputs.inputList[1].fieldRow[0]; const nextNode = node.next(); - chai.assert.equal(nextNode.getLocation(), field2); + assert.equal(nextNode.getLocation(), field2); }); test('fromFieldToNull', function () { const field = this.blocks.twoFields.inputList[0].fieldRow[0]; const node = ASTNode.createFieldNode(field); const nextNode = node.next(); - chai.assert.isNull(nextNode); + assert.isNull(nextNode); }); test('fromStackToStack', function () { const node = ASTNode.createStackNode(this.blocks.statementInput1); const nextNode = node.next(); - chai.assert.equal(nextNode.getLocation(), this.blocks.statementInput4); - chai.assert.equal(nextNode.getType(), ASTNode.types.STACK); + assert.equal(nextNode.getLocation(), this.blocks.statementInput4); + assert.equal(nextNode.getType(), ASTNode.types.STACK); }); test('fromStackToNull', function () { const node = ASTNode.createStackNode(this.blocks.singleBlock); const nextNode = node.next(); - chai.assert.isNull(nextNode); + assert.isNull(nextNode); }); }); @@ -445,55 +446,55 @@ suite('ASTNode', function () { const prevConnection = this.blocks.statementInput1.previousConnection; const node = ASTNode.createConnectionNode(prevConnection); const prevNode = node.prev(); - chai.assert.isNull(prevNode); + assert.isNull(prevNode); }); test('fromPreviousToNext', function () { const prevConnection = this.blocks.statementInput2.previousConnection; const node = ASTNode.createConnectionNode(prevConnection); const prevNode = node.prev(); const nextConnection = this.blocks.statementInput1.nextConnection; - chai.assert.equal(prevNode.getLocation(), nextConnection); + assert.equal(prevNode.getLocation(), nextConnection); }); test('fromPreviousToInput', function () { const prevConnection = this.blocks.statementInput3.previousConnection; const node = ASTNode.createConnectionNode(prevConnection); const prevNode = node.prev(); - chai.assert.isNull(prevNode); + assert.isNull(prevNode); }); test('fromBlockToPrevious', function () { const node = ASTNode.createBlockNode(this.blocks.statementInput1); const prevNode = node.prev(); const prevConnection = this.blocks.statementInput1.previousConnection; - chai.assert.equal(prevNode.getLocation(), prevConnection); + assert.equal(prevNode.getLocation(), prevConnection); }); test('fromBlockToNull', function () { const node = ASTNode.createBlockNode(this.blocks.noPrevConnection); const prevNode = node.prev(); - chai.assert.isNull(prevNode); + assert.isNull(prevNode); }); test('fromBlockToOutput', function () { const node = ASTNode.createBlockNode(this.blocks.fieldWithOutput); const prevNode = node.prev(); const outputConnection = this.blocks.fieldWithOutput.outputConnection; - chai.assert.equal(prevNode.getLocation(), outputConnection); + assert.equal(prevNode.getLocation(), outputConnection); }); test('fromNextToBlock', function () { const nextConnection = this.blocks.statementInput1.nextConnection; const node = ASTNode.createConnectionNode(nextConnection); const prevNode = node.prev(); - chai.assert.equal(prevNode.getLocation(), this.blocks.statementInput1); + assert.equal(prevNode.getLocation(), this.blocks.statementInput1); }); test('fromInputToField', function () { const input = this.blocks.statementInput1.inputList[0]; const node = ASTNode.createInputNode(input); const prevNode = node.prev(); - chai.assert.equal(prevNode.getLocation(), input.fieldRow[1]); + assert.equal(prevNode.getLocation(), input.fieldRow[1]); }); test('fromInputToNull', function () { const input = this.blocks.fieldAndInputs2.inputList[0]; const node = ASTNode.createInputNode(input); const prevNode = node.prev(); - chai.assert.isNull(prevNode); + assert.isNull(prevNode); }); test('fromInputToInput', function () { const input = this.blocks.fieldAndInputs2.inputList[2]; @@ -501,19 +502,19 @@ suite('ASTNode', function () { this.blocks.fieldAndInputs2.inputList[1].connection; const node = ASTNode.createInputNode(input); const prevNode = node.prev(); - chai.assert.equal(prevNode.getLocation(), inputConnection); + assert.equal(prevNode.getLocation(), inputConnection); }); test('fromOutputToNull', function () { const output = this.blocks.fieldWithOutput.outputConnection; const node = ASTNode.createConnectionNode(output); const prevNode = node.prev(); - chai.assert.isNull(prevNode); + assert.isNull(prevNode); }); test('fromFieldToNull', function () { const field = this.blocks.statementInput1.inputList[0].fieldRow[0]; const node = ASTNode.createFieldNode(field); const prevNode = node.prev(); - chai.assert.isNull(prevNode); + assert.isNull(prevNode); }); test('fromFieldToInput', function () { const field = this.blocks.fieldAndInputs2.inputList[1].fieldRow[0]; @@ -521,20 +522,20 @@ suite('ASTNode', function () { this.blocks.fieldAndInputs2.inputList[0].connection; const node = ASTNode.createFieldNode(field); const prevNode = node.prev(); - chai.assert.equal(prevNode.getLocation(), inputConnection); + assert.equal(prevNode.getLocation(), inputConnection); }); test('fromFieldToField', function () { const field = this.blocks.fieldAndInputs.inputList[1].fieldRow[0]; const field2 = this.blocks.fieldAndInputs.inputList[0].fieldRow[0]; const node = ASTNode.createFieldNode(field); const prevNode = node.prev(); - chai.assert.equal(prevNode.getLocation(), field2); + assert.equal(prevNode.getLocation(), field2); }); test('fromStackToStack', function () { const node = ASTNode.createStackNode(this.blocks.statementInput4); const prevNode = node.prev(); - chai.assert.equal(prevNode.getLocation(), this.blocks.statementInput1); - chai.assert.equal(prevNode.getType(), ASTNode.types.STACK); + assert.equal(prevNode.getLocation(), this.blocks.statementInput1); + assert.equal(prevNode.getType(), ASTNode.types.STACK); }); }); @@ -551,13 +552,13 @@ suite('ASTNode', function () { const node = ASTNode.createInputNode(input); const inNode = node.in(); const outputConnection = this.blocks.fieldWithOutput.outputConnection; - chai.assert.equal(inNode.getLocation(), outputConnection); + assert.equal(inNode.getLocation(), outputConnection); }); test('fromInputToNull', function () { const input = this.blocks.statementInput2.inputList[0]; const node = ASTNode.createInputNode(input); const inNode = node.in(); - chai.assert.isNull(inNode); + assert.isNull(inNode); }); test('fromInputToPrevious', function () { const input = this.blocks.statementInput2.inputList[1]; @@ -565,60 +566,57 @@ suite('ASTNode', function () { this.blocks.statementInput3.previousConnection; const node = ASTNode.createInputNode(input); const inNode = node.in(); - chai.assert.equal(inNode.getLocation(), previousConnection); + assert.equal(inNode.getLocation(), previousConnection); }); test('fromBlockToInput', function () { const input = this.blocks.valueInput.inputList[0]; const node = ASTNode.createBlockNode(this.blocks.valueInput); const inNode = node.in(); - chai.assert.equal(inNode.getLocation(), input.connection); + assert.equal(inNode.getLocation(), input.connection); }); test('fromBlockToField', function () { const node = ASTNode.createBlockNode(this.blocks.statementInput1); const inNode = node.in(); const field = this.blocks.statementInput1.inputList[0].fieldRow[0]; - chai.assert.equal(inNode.getLocation(), field); + assert.equal(inNode.getLocation(), field); }); test('fromBlockToPrevious', function () { const prevConnection = this.blocks.statementInput4.previousConnection; const node = ASTNode.createStackNode(this.blocks.statementInput4); const inNode = node.in(); - chai.assert.equal(inNode.getLocation(), prevConnection); - chai.assert.equal(inNode.getType(), ASTNode.types.PREVIOUS); + assert.equal(inNode.getLocation(), prevConnection); + assert.equal(inNode.getType(), ASTNode.types.PREVIOUS); }); test('fromBlockToNull_DummyInput', function () { const node = ASTNode.createBlockNode(this.blocks.dummyInput); const inNode = node.in(); - chai.assert.isNull(inNode); + assert.isNull(inNode); }); test('fromBlockToInput_DummyInputValue', function () { const node = ASTNode.createBlockNode(this.blocks.dummyInputValue); const inputConnection = this.blocks.dummyInputValue.inputList[1].connection; const inNode = node.in(); - chai.assert.equal(inNode.getLocation(), inputConnection); + assert.equal(inNode.getLocation(), inputConnection); }); test('fromOuputToNull', function () { const output = this.blocks.fieldWithOutput.outputConnection; const node = ASTNode.createConnectionNode(output); const inNode = node.in(); - chai.assert.isNull(inNode); + assert.isNull(inNode); }); test('fromFieldToNull', function () { const field = this.blocks.statementInput1.inputList[0].fieldRow[0]; const node = ASTNode.createFieldNode(field); const inNode = node.in(); - chai.assert.isNull(inNode); + assert.isNull(inNode); }); test('fromWorkspaceToStack', function () { const coordinate = new Blockly.utils.Coordinate(100, 100); const node = ASTNode.createWorkspaceNode(this.workspace, coordinate); const inNode = node.in(); - chai.assert.equal( - inNode.getLocation(), - this.workspace.getTopBlocks()[0], - ); - chai.assert.equal(inNode.getType(), ASTNode.types.STACK); + assert.equal(inNode.getLocation(), this.workspace.getTopBlocks()[0]); + assert.equal(inNode.getType(), ASTNode.types.STACK); }); test('fromWorkspaceToNull', function () { const coordinate = new Blockly.utils.Coordinate(100, 100); @@ -627,27 +625,27 @@ suite('ASTNode', function () { coordinate, ); const inNode = node.in(); - chai.assert.isNull(inNode); + assert.isNull(inNode); }); test('fromStackToPrevious', function () { const node = ASTNode.createStackNode(this.blocks.statementInput1); const previous = this.blocks.statementInput1.previousConnection; const inNode = node.in(); - chai.assert.equal(inNode.getLocation(), previous); - chai.assert.equal(inNode.getType(), ASTNode.types.PREVIOUS); + assert.equal(inNode.getLocation(), previous); + assert.equal(inNode.getType(), ASTNode.types.PREVIOUS); }); test('fromStackToOutput', function () { const node = ASTNode.createStackNode(this.blocks.fieldWithOutput2); const output = this.blocks.fieldWithOutput2.outputConnection; const inNode = node.in(); - chai.assert.equal(inNode.getLocation(), output); - chai.assert.equal(inNode.getType(), ASTNode.types.OUTPUT); + assert.equal(inNode.getLocation(), output); + assert.equal(inNode.getType(), ASTNode.types.OUTPUT); }); test('fromStackToBlock', function () { const node = ASTNode.createStackNode(this.blocks.dummyInput); const inNode = node.in(); - chai.assert.equal(inNode.getLocation(), this.blocks.dummyInput); - chai.assert.equal(inNode.getType(), ASTNode.types.BLOCK); + assert.equal(inNode.getLocation(), this.blocks.dummyInput); + assert.equal(inNode.getType(), ASTNode.types.BLOCK); }); }); @@ -667,15 +665,15 @@ suite('ASTNode', function () { const input = this.blocks.statementInput1.inputList[0]; const node = ASTNode.createInputNode(input); const outNode = node.out(); - chai.assert.equal(outNode.getType(), ASTNode.types.BLOCK); - chai.assert.equal(outNode.getLocation(), this.blocks.statementInput1); + assert.equal(outNode.getType(), ASTNode.types.BLOCK); + assert.equal(outNode.getLocation(), this.blocks.statementInput1); }); test('fromOutputToInput', function () { const output = this.blocks.fieldWithOutput.outputConnection; const node = ASTNode.createConnectionNode(output); const outNode = node.out(); - chai.assert.equal(outNode.getType(), ASTNode.types.INPUT); - chai.assert.equal( + assert.equal(outNode.getType(), ASTNode.types.INPUT); + assert.equal( outNode.getLocation(), this.blocks.statementInput1.inputList[0].connection, ); @@ -684,15 +682,15 @@ suite('ASTNode', function () { const output = this.blocks.fieldWithOutput2.outputConnection; const node = ASTNode.createConnectionNode(output); const outNode = node.out(); - chai.assert.equal(outNode.getType(), ASTNode.types.STACK); - chai.assert.equal(outNode.getLocation(), this.blocks.fieldWithOutput2); + assert.equal(outNode.getType(), ASTNode.types.STACK); + assert.equal(outNode.getLocation(), this.blocks.fieldWithOutput2); }); test('fromFieldToBlock', function () { const field = this.blocks.statementInput1.inputList[0].fieldRow[0]; const node = ASTNode.createFieldNode(field); const outNode = node.out(); - chai.assert.equal(outNode.getType(), ASTNode.types.BLOCK); - chai.assert.equal(outNode.getLocation(), this.blocks.statementInput1); + assert.equal(outNode.getType(), ASTNode.types.BLOCK); + assert.equal(outNode.getLocation(), this.blocks.statementInput1); }); test('fromStackToWorkspace', function () { const stub = sinon @@ -700,9 +698,9 @@ suite('ASTNode', function () { .returns({x: 10, y: 10}); const node = ASTNode.createStackNode(this.blocks.statementInput4); const outNode = node.out(); - chai.assert.equal(outNode.getType(), ASTNode.types.WORKSPACE); - chai.assert.equal(outNode.wsCoordinate.x, 10); - chai.assert.equal(outNode.wsCoordinate.y, -10); + assert.equal(outNode.getType(), ASTNode.types.WORKSPACE); + assert.equal(outNode.wsCoordinate.x, 10); + assert.equal(outNode.wsCoordinate.y, -10); stub.restore(); }); test('fromPreviousToInput', function () { @@ -711,15 +709,15 @@ suite('ASTNode', function () { this.blocks.statementInput2.inputList[1].connection; const node = ASTNode.createConnectionNode(previous); const outNode = node.out(); - chai.assert.equal(outNode.getType(), ASTNode.types.INPUT); - chai.assert.equal(outNode.getLocation(), inputConnection); + assert.equal(outNode.getType(), ASTNode.types.INPUT); + assert.equal(outNode.getLocation(), inputConnection); }); test('fromPreviousToStack', function () { const previous = this.blocks.statementInput2.previousConnection; const node = ASTNode.createConnectionNode(previous); const outNode = node.out(); - chai.assert.equal(outNode.getType(), ASTNode.types.STACK); - chai.assert.equal(outNode.getLocation(), this.blocks.statementInput1); + assert.equal(outNode.getType(), ASTNode.types.STACK); + assert.equal(outNode.getLocation(), this.blocks.statementInput1); }); test('fromNextToInput', function () { const next = this.blocks.statementInput3.nextConnection; @@ -727,22 +725,22 @@ suite('ASTNode', function () { this.blocks.statementInput2.inputList[1].connection; const node = ASTNode.createConnectionNode(next); const outNode = node.out(); - chai.assert.equal(outNode.getType(), ASTNode.types.INPUT); - chai.assert.equal(outNode.getLocation(), inputConnection); + assert.equal(outNode.getType(), ASTNode.types.INPUT); + assert.equal(outNode.getLocation(), inputConnection); }); test('fromNextToStack', function () { const next = this.blocks.statementInput2.nextConnection; const node = ASTNode.createConnectionNode(next); const outNode = node.out(); - chai.assert.equal(outNode.getType(), ASTNode.types.STACK); - chai.assert.equal(outNode.getLocation(), this.blocks.statementInput1); + assert.equal(outNode.getType(), ASTNode.types.STACK); + assert.equal(outNode.getLocation(), this.blocks.statementInput1); }); test('fromNextToStack_NoPreviousConnection', function () { const next = this.blocks.secondBlock.nextConnection; const node = ASTNode.createConnectionNode(next); const outNode = node.out(); - chai.assert.equal(outNode.getType(), ASTNode.types.STACK); - chai.assert.equal(outNode.getLocation(), this.blocks.noPrevConnection); + assert.equal(outNode.getType(), ASTNode.types.STACK); + assert.equal(outNode.getLocation(), this.blocks.noPrevConnection); }); /** * This is where there is a block with both an output connection and a @@ -752,8 +750,8 @@ suite('ASTNode', function () { const next = this.blocks.outputNextBlock.nextConnection; const node = ASTNode.createConnectionNode(next); const outNode = node.out(); - chai.assert.equal(outNode.getType(), ASTNode.types.INPUT); - chai.assert.equal( + assert.equal(outNode.getType(), ASTNode.types.INPUT); + assert.equal( outNode.getLocation(), this.blocks.secondBlock.inputList[0].connection, ); @@ -761,34 +759,34 @@ suite('ASTNode', function () { test('fromBlockToStack', function () { const node = ASTNode.createBlockNode(this.blocks.statementInput2); const outNode = node.out(); - chai.assert.equal(outNode.getType(), ASTNode.types.STACK); - chai.assert.equal(outNode.getLocation(), this.blocks.statementInput1); + assert.equal(outNode.getType(), ASTNode.types.STACK); + assert.equal(outNode.getLocation(), this.blocks.statementInput1); }); test('fromBlockToInput', function () { const input = this.blocks.statementInput2.inputList[1].connection; const node = ASTNode.createBlockNode(this.blocks.statementInput3); const outNode = node.out(); - chai.assert.equal(outNode.getType(), ASTNode.types.INPUT); - chai.assert.equal(outNode.getLocation(), input); + assert.equal(outNode.getType(), ASTNode.types.INPUT); + assert.equal(outNode.getLocation(), input); }); test('fromTopBlockToStack', function () { const node = ASTNode.createBlockNode(this.blocks.statementInput1); const outNode = node.out(); - chai.assert.equal(outNode.getType(), ASTNode.types.STACK); - chai.assert.equal(outNode.getLocation(), this.blocks.statementInput1); + assert.equal(outNode.getType(), ASTNode.types.STACK); + assert.equal(outNode.getLocation(), this.blocks.statementInput1); }); test('fromBlockToStack_OutputConnection', function () { const node = ASTNode.createBlockNode(this.blocks.fieldWithOutput2); const outNode = node.out(); - chai.assert.equal(outNode.getType(), ASTNode.types.STACK); - chai.assert.equal(outNode.getLocation(), this.blocks.fieldWithOutput2); + assert.equal(outNode.getType(), ASTNode.types.STACK); + assert.equal(outNode.getLocation(), this.blocks.fieldWithOutput2); }); test('fromBlockToInput_OutputConnection', function () { const node = ASTNode.createBlockNode(this.blocks.outputNextBlock); const inputConnection = this.blocks.secondBlock.inputList[0].connection; const outNode = node.out(); - chai.assert.equal(outNode.getType(), ASTNode.types.INPUT); - chai.assert.equal(outNode.getLocation(), inputConnection); + assert.equal(outNode.getType(), ASTNode.types.INPUT); + assert.equal(outNode.getLocation(), inputConnection); }); }); @@ -796,31 +794,31 @@ suite('ASTNode', function () { test('createFieldNode', function () { const field = this.blocks.statementInput1.inputList[0].fieldRow[0]; const node = ASTNode.createFieldNode(field); - chai.assert.equal(node.getLocation(), field); - chai.assert.equal(node.getType(), ASTNode.types.FIELD); - chai.assert.isFalse(node.isConnection()); + assert.equal(node.getLocation(), field); + assert.equal(node.getType(), ASTNode.types.FIELD); + assert.isFalse(node.isConnection()); }); test('createConnectionNode', function () { const prevConnection = this.blocks.statementInput4.previousConnection; const node = ASTNode.createConnectionNode(prevConnection); - chai.assert.equal(node.getLocation(), prevConnection); - chai.assert.equal(node.getType(), ASTNode.types.PREVIOUS); - chai.assert.isTrue(node.isConnection()); + assert.equal(node.getLocation(), prevConnection); + assert.equal(node.getType(), ASTNode.types.PREVIOUS); + assert.isTrue(node.isConnection()); }); test('createInputNode', function () { const input = this.blocks.statementInput1.inputList[0]; const node = ASTNode.createInputNode(input); - chai.assert.equal(node.getLocation(), input.connection); - chai.assert.equal(node.getType(), ASTNode.types.INPUT); - chai.assert.isTrue(node.isConnection()); + assert.equal(node.getLocation(), input.connection); + assert.equal(node.getType(), ASTNode.types.INPUT); + assert.isTrue(node.isConnection()); }); test('createWorkspaceNode', function () { const coordinate = new Blockly.utils.Coordinate(100, 100); const node = ASTNode.createWorkspaceNode(this.workspace, coordinate); - chai.assert.equal(node.getLocation(), this.workspace); - chai.assert.equal(node.getType(), ASTNode.types.WORKSPACE); - chai.assert.equal(node.getWsCoordinate(), coordinate); - chai.assert.isFalse(node.isConnection()); + assert.equal(node.getLocation(), this.workspace); + assert.equal(node.getType(), ASTNode.types.WORKSPACE); + assert.equal(node.getWsCoordinate(), coordinate); + assert.isFalse(node.isConnection()); }); test('createStatementConnectionNode', function () { const nextConnection = @@ -828,24 +826,24 @@ suite('ASTNode', function () { const inputConnection = this.blocks.statementInput1.inputList[1].connection; const node = ASTNode.createConnectionNode(nextConnection); - chai.assert.equal(node.getLocation(), inputConnection); - chai.assert.equal(node.getType(), ASTNode.types.INPUT); - chai.assert.isTrue(node.isConnection()); + assert.equal(node.getLocation(), inputConnection); + assert.equal(node.getType(), ASTNode.types.INPUT); + assert.isTrue(node.isConnection()); }); test('createTopNode-previous', function () { const block = this.blocks.statementInput1; const topNode = ASTNode.createTopNode(block); - chai.assert.equal(topNode.getLocation(), block.previousConnection); + assert.equal(topNode.getLocation(), block.previousConnection); }); test('createTopNode-block', function () { const block = this.blocks.noPrevConnection; const topNode = ASTNode.createTopNode(block); - chai.assert.equal(topNode.getLocation(), block); + assert.equal(topNode.getLocation(), block); }); test('createTopNode-output', function () { const block = this.blocks.outputNextBlock; const topNode = ASTNode.createTopNode(block); - chai.assert.equal(topNode.getLocation(), block.outputConnection); + assert.equal(topNode.getLocation(), block.outputConnection); }); }); }); diff --git a/tests/mocha/block_json_test.js b/tests/mocha/block_json_test.js index e89c68e7c1d..4baccef6b7b 100644 --- a/tests/mocha/block_json_test.js +++ b/tests/mocha/block_json_test.js @@ -5,6 +5,7 @@ */ import {Align} from '../../build/src/core/inputs/align.js'; +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -20,25 +21,25 @@ suite('Block JSON initialization', function () { sharedTestTeardown.call(this); }); - suite('validateTokens_', function () { + suite('validateTokens', function () { setup(function () { this.assertError = function (tokens, count, error) { const block = { type: 'test', - validateTokens_: Blockly.Block.prototype.validateTokens_, + validateTokens: Blockly.Block.prototype.validateTokens, }; - chai.assert.throws(function () { - block.validateTokens_(tokens, count); + assert.throws(function () { + block.validateTokens(tokens, count); }, error); }; this.assertNoError = function (tokens, count) { const block = { type: 'test', - validateTokens_: Blockly.Block.prototype.validateTokens_, + validateTokens: Blockly.Block.prototype.validateTokens, }; - chai.assert.doesNotThrow(function () { - block.validateTokens_(tokens, count); + assert.doesNotThrow(function () { + block.validateTokens(tokens, count); }); }; }); @@ -96,17 +97,17 @@ suite('Block JSON initialization', function () { }); }); - suite('interpolateArguments_', function () { + suite('interpolateArguments', function () { setup(function () { this.assertInterpolation = function (tokens, args, lastAlign, elements) { const block = { type: 'test', - interpolateArguments_: Blockly.Block.prototype.interpolateArguments_, - stringToFieldJson_: Blockly.Block.prototype.stringToFieldJson_, - isInputKeyword_: Blockly.Block.prototype.isInputKeyword_, + interpolateArguments: Blockly.Block.prototype.interpolateArguments, + stringToFieldJson: Blockly.Block.prototype.stringToFieldJson, + isInputKeyword: Blockly.Block.prototype.isInputKeyword, }; - chai.assert.deepEqual( - block.interpolateArguments_(tokens, args, lastAlign), + assert.deepEqual( + block.interpolateArguments(tokens, args, lastAlign), elements, ); }; @@ -380,7 +381,7 @@ suite('Block JSON initialization', function () { }); }); - suite('fieldFromJson_', function () { + suite('fieldFromJson', function () { setup(function () { this.stub = sinon .stub(Blockly.fieldRegistry.TEST_ONLY, 'fromJsonInternal') @@ -402,10 +403,10 @@ suite('Block JSON initialization', function () { this.assertField = function (json, expectedType) { const block = { type: 'test', - fieldFromJson_: Blockly.Block.prototype.fieldFromJson_, - stringToFieldJson_: Blockly.Block.prototype.stringToFieldJson_, + fieldFromJson: Blockly.Block.prototype.fieldFromJson, + stringToFieldJson: Blockly.Block.prototype.stringToFieldJson, }; - chai.assert.strictEqual(block.fieldFromJson_(json), expectedType); + assert.strictEqual(block.fieldFromJson(json), expectedType); }; }); @@ -562,7 +563,7 @@ suite('Block JSON initialization', function () { }); }); - suite('inputFromJson_', function () { + suite('inputFromJson', function () { setup(function () { this.assertInput = function (json, type, check, align) { const block = this.workspace.newBlock('test_basic_empty'); @@ -570,37 +571,37 @@ suite('Block JSON initialization', function () { sinon.spy(block, 'appendValueInput'); sinon.spy(block, 'appendStatementInput'); - const input = block.inputFromJson_(json); + const input = block.inputFromJson(json); switch (type) { case 'input_dummy': - chai.assert.isTrue( + assert.isTrue( block.appendDummyInput.calledOnce, 'Expected a dummy input to be created.', ); break; case 'input_value': - chai.assert.isTrue( + assert.isTrue( block.appendValueInput.calledOnce, 'Expected a value input to be created.', ); break; case 'input_statement': - chai.assert.isTrue( + assert.isTrue( block.appendStatementInput.calledOnce, 'Expected a statement input to be created.', ); break; default: - chai.assert.isNull(input, 'Expected input to be null'); - chai.assert.isTrue( + assert.isNull(input, 'Expected input to be null'); + assert.isTrue( block.appendDummyInput.notCalled, 'Expected no input to be created', ); - chai.assert.isTrue( + assert.isTrue( block.appendValueInput.notCalled, 'Expected no input to be created', ); - chai.assert.isTrue( + assert.isTrue( block.appendStatementInput.notCalled, 'Expected no input to be created', ); @@ -608,13 +609,13 @@ suite('Block JSON initialization', function () { } if (check) { if (Array.isArray(check)) { - chai.assert.deepEqual(check, input.connection.getCheck()); + assert.deepEqual(check, input.connection.getCheck()); } else { - chai.assert.deepEqual([check], input.connection.getCheck()); + assert.deepEqual([check], input.connection.getCheck()); } } if (align !== undefined) { - chai.assert.equal(align, input.align); + assert.equal(align, input.align); } }; }); @@ -666,8 +667,8 @@ suite('Block JSON initialization', function () { CustomInput, ); const block = this.workspace.newBlock('test_basic_empty'); - block.inputFromJson_({'type': 'custom'}); - chai.assert.instanceOf( + block.inputFromJson({'type': 'custom'}); + assert.instanceOf( block.inputList[0], CustomInput, 'Expected the registered input to be constructed', diff --git a/tests/mocha/block_test.js b/tests/mocha/block_test.js index e158391fc12..a489fb3e3c5 100644 --- a/tests/mocha/block_test.js +++ b/tests/mocha/block_test.js @@ -4,22 +4,23 @@ * SPDX-License-Identifier: Apache-2.0 */ +import * as common from '../../build/src/core/common.js'; import {ConnectionType} from '../../build/src/core/connection_type.js'; -import {createDeprecationWarningStub} from './test_helpers/warnings.js'; -import {createRenderedBlock} from './test_helpers/block_definitions.js'; +import {EventType} from '../../build/src/core/events/type.js'; import * as eventUtils from '../../build/src/core/events/utils.js'; import {EndRowInput} from '../../build/src/core/inputs/end_row_input.js'; +import {assert} from '../../node_modules/chai/chai.js'; +import {createRenderedBlock} from './test_helpers/block_definitions.js'; +import { + createChangeListenerSpy, + createMockEvent, +} from './test_helpers/events.js'; +import {MockBubbleIcon, MockIcon} from './test_helpers/icon_mocks.js'; import { sharedTestSetup, sharedTestTeardown, workspaceTeardown, } from './test_helpers/setup_teardown.js'; -import { - createChangeListenerSpy, - createMockEvent, -} from './test_helpers/events.js'; -import {MockIcon, MockBubbleIcon} from './test_helpers/icon_mocks.js'; -import {IconType} from '../../build/src/core/icons/icon_types.js'; suite('Blocks', function () { setup(function () { @@ -80,7 +81,7 @@ suite('Blocks', function () { blockB.nextConnection.connect(blockC.previousConnection); } - chai.assert.equal(blockC.getParent(), blockB); + assert.equal(blockC.getParent(), blockB); return { A: blockA /* Parent */, @@ -92,30 +93,30 @@ suite('Blocks', function () { suite('Unplug', function () { function assertUnpluggedNoheal(blocks) { // A has nothing connected to it. - chai.assert.equal(blocks.A.getChildren().length, 0); + assert.equal(blocks.A.getChildren().length, 0); // B and C are still connected. - chai.assert.equal(blocks.C.getParent(), blocks.B); + assert.equal(blocks.C.getParent(), blocks.B); // B is the top of its stack. - chai.assert.isNull(blocks.B.getParent()); + assert.isNull(blocks.B.getParent()); } function assertUnpluggedHealed(blocks) { // A and C are connected. - chai.assert.equal(blocks.A.getChildren().length, 1); - chai.assert.equal(blocks.C.getParent(), blocks.A); + assert.equal(blocks.A.getChildren().length, 1); + assert.equal(blocks.C.getParent(), blocks.A); // B has nothing connected to it. - chai.assert.equal(blocks.B.getChildren().length, 0); + assert.equal(blocks.B.getChildren().length, 0); // B is the top of its stack. - chai.assert.isNull(blocks.B.getParent()); + assert.isNull(blocks.B.getParent()); } function assertUnpluggedHealFailed(blocks) { // A has nothing connected to it. - chai.assert.equal(blocks.A.getChildren().length, 0); + assert.equal(blocks.A.getChildren().length, 0); // B has nothing connected to it. - chai.assert.equal(blocks.B.getChildren().length, 0); + assert.equal(blocks.B.getChildren().length, 0); // B is the top of its stack. - chai.assert.isNull(blocks.B.getParent()); + assert.isNull(blocks.B.getParent()); // C is the top of its stack. - chai.assert.isNull(blocks.C.getParent()); + assert.isNull(blocks.C.getParent()); } suite('Row', function () { @@ -232,7 +233,7 @@ suite('Blocks', function () { this.block.dispose(); - chai.assert.isTrue(spy.calledOnce, 'Expected destroy to be called.'); + assert.isTrue(spy.calledOnce, 'Expected destroy to be called.'); }); test('disposing is set before destroy', function () { @@ -243,7 +244,7 @@ suite('Blocks', function () { this.block.dispose(); - chai.assert.isTrue( + assert.isTrue( disposing, 'Expected disposing to be set to true before destroy is called.', ); @@ -257,7 +258,7 @@ suite('Blocks', function () { this.block.dispose(); - chai.assert.isFalse( + assert.isFalse( disposed, 'Expected disposed to be false when destroy is called', ); @@ -273,7 +274,7 @@ suite('Blocks', function () { this.block.dispose(); this.clock.runAll(); - chai.assert.isTrue( + assert.isTrue( spy.calledWith(mockEvent), 'Expected to be able to fire events from destroy', ); @@ -293,7 +294,7 @@ suite('Blocks', function () { this.block.dispose(); this.clock.runAll(); - chai.assert.isTrue( + assert.isTrue( spy.calledWith(mockEvent), 'Expected to be able to fire events from destroy', ); @@ -302,34 +303,34 @@ suite('Blocks', function () { suite('stack/row healing', function () { function assertDisposedNoheal(blocks) { - chai.assert.isFalse(blocks.A.disposed); + assert.isFalse(blocks.A.disposed); // A has nothing connected to it. - chai.assert.equal(blocks.A.getChildren().length, 0); + assert.equal(blocks.A.getChildren().length, 0); // B is disposed. - chai.assert.isTrue(blocks.B.disposed); + assert.isTrue(blocks.B.disposed); // And C is disposed. - chai.assert.isTrue(blocks.C.disposed); + assert.isTrue(blocks.C.disposed); } function assertDisposedHealed(blocks) { - chai.assert.isFalse(blocks.A.disposed); - chai.assert.isFalse(blocks.C.disposed); + assert.isFalse(blocks.A.disposed); + assert.isFalse(blocks.C.disposed); // A and C are connected. - chai.assert.equal(blocks.A.getChildren().length, 1); - chai.assert.equal(blocks.C.getParent(), blocks.A); + assert.equal(blocks.A.getChildren().length, 1); + assert.equal(blocks.C.getParent(), blocks.A); // B is disposed. - chai.assert.isTrue(blocks.B.disposed); + assert.isTrue(blocks.B.disposed); } function assertDisposedHealFailed(blocks) { - chai.assert.isFalse(blocks.A.disposed); - chai.assert.isFalse(blocks.C.disposed); + assert.isFalse(blocks.A.disposed); + assert.isFalse(blocks.C.disposed); // A has nothing connected to it. - chai.assert.equal(blocks.A.getChildren().length, 0); + assert.equal(blocks.A.getChildren().length, 0); // B is disposed. - chai.assert.isTrue(blocks.B.disposed); + assert.isTrue(blocks.B.disposed); // C is the top of its stack. - chai.assert.isNull(blocks.C.getParent()); + assert.isNull(blocks.C.getParent()); } suite('Row', function () { @@ -444,6 +445,39 @@ suite('Blocks', function () { }); }); }); + + suite('Disposing selected shadow block', function () { + setup(function () { + this.workspace = Blockly.inject('blocklyDiv'); + this.parentBlock = this.workspace.newBlock('row_block'); + this.parentBlock.initSvg(); + this.parentBlock.render(); + this.parentBlock.inputList[0].connection.setShadowState({ + 'type': 'row_block', + 'id': 'shadow_child', + }); + this.shadowChild = + this.parentBlock.inputList[0].connection.targetConnection.getSourceBlock(); + }); + + teardown(function () { + workspaceTeardown.call(this, this.workspace); + }); + + test('Disposing selected shadow unhighlights parent', function () { + const parentBlock = this.parentBlock; + common.setSelected(this.shadowChild); + assert.isTrue( + parentBlock.pathObject.svgRoot.classList.contains('blocklySelected'), + 'Expected parent to be highlighted after selecting shadow child', + ); + this.shadowChild.dispose(); + assert.isFalse( + parentBlock.pathObject.svgRoot.classList.contains('blocklySelected'), + 'Expected parent to be unhighlighted after deleting shadow child', + ); + }); + }); }); suite('Remove Input', function () { @@ -469,7 +503,7 @@ suite('Blocks', function () { test('No Connected', function () { this.blockA.removeInput('VALUE'); - chai.assert.isNull(this.blockA.getInput('VALUE')); + assert.isNull(this.blockA.getInput('VALUE')); }); test('Block Connected', function () { const blockB = this.workspace.newBlock('row_block'); @@ -478,8 +512,8 @@ suite('Blocks', function () { .connection.connect(blockB.outputConnection); this.blockA.removeInput('VALUE'); - chai.assert.isFalse(blockB.disposed); - chai.assert.equal(this.blockA.getChildren().length, 0); + assert.isFalse(blockB.disposed); + assert.equal(this.blockA.getChildren().length, 0); }); test('Shadow Connected', function () { const blockB = this.workspace.newBlock('row_block'); @@ -489,8 +523,8 @@ suite('Blocks', function () { .connection.connect(blockB.outputConnection); this.blockA.removeInput('VALUE'); - chai.assert.isTrue(blockB.disposed); - chai.assert.equal(this.blockA.getChildren().length, 0); + assert.isTrue(blockB.disposed); + assert.equal(this.blockA.getChildren().length, 0); }); }); suite('Statement', function () { @@ -500,7 +534,7 @@ suite('Blocks', function () { test('No Connected', function () { this.blockA.removeInput('STATEMENT'); - chai.assert.isNull(this.blockA.getInput('STATEMENT')); + assert.isNull(this.blockA.getInput('STATEMENT')); }); test('Block Connected', function () { const blockB = this.workspace.newBlock('stack_block'); @@ -509,8 +543,8 @@ suite('Blocks', function () { .connection.connect(blockB.previousConnection); this.blockA.removeInput('STATEMENT'); - chai.assert.isFalse(blockB.disposed); - chai.assert.equal(this.blockA.getChildren().length, 0); + assert.isFalse(blockB.disposed); + assert.equal(this.blockA.getChildren().length, 0); }); test('Shadow Connected', function () { const blockB = this.workspace.newBlock('stack_block'); @@ -520,8 +554,8 @@ suite('Blocks', function () { .connection.connect(blockB.previousConnection); this.blockA.removeInput('STATEMENT'); - chai.assert.isTrue(blockB.disposed); - chai.assert.equal(this.blockA.getChildren().length, 0); + assert.isTrue(blockB.disposed); + assert.equal(this.blockA.getChildren().length, 0); }); }); }); @@ -549,10 +583,10 @@ suite('Blocks', function () { }; this.assertConnectionsEmpty = function () { - chai.assert.isEmpty(this.getInputs()); - chai.assert.isEmpty(this.getOutputs()); - chai.assert.isEmpty(this.getNext()); - chai.assert.isEmpty(this.getPrevious()); + assert.isEmpty(this.getInputs()); + assert.isEmpty(this.getOutputs()); + assert.isEmpty(this.getNext()); + assert.isEmpty(this.getPrevious()); }; }); teardown(function () { @@ -572,8 +606,8 @@ suite('Blocks', function () { this.deserializationHelper( '' + ' ' + '', ); - chai.assert.equal(this.getPrevious().length, 1); - chai.assert.equal(this.getNext().length, 1); + assert.equal(this.getPrevious().length, 1); + assert.equal(this.getNext().length, 1); }); test('Multi-Stack', function () { this.deserializationHelper( @@ -589,15 +623,15 @@ suite('Blocks', function () { ' ' + '', ); - chai.assert.equal(this.getPrevious().length, 3); - chai.assert.equal(this.getNext().length, 3); + assert.equal(this.getPrevious().length, 3); + assert.equal(this.getNext().length, 3); }); test('Collapsed Stack', function () { this.deserializationHelper( '' + ' ' + '', ); - chai.assert.equal(this.getPrevious().length, 1); - chai.assert.equal(this.getNext().length, 1); + assert.equal(this.getPrevious().length, 1); + assert.equal(this.getNext().length, 1); }); test('Collapsed Multi-Stack', function () { this.deserializationHelper( @@ -613,15 +647,15 @@ suite('Blocks', function () { ' ' + '', ); - chai.assert.equal(this.getPrevious().length, 3); - chai.assert.equal(this.getNext().length, 3); + assert.equal(this.getPrevious().length, 3); + assert.equal(this.getNext().length, 3); }); test('Row', function () { this.deserializationHelper( '' + ' ' + '', ); - chai.assert.equal(this.getOutputs().length, 1); - chai.assert.equal(this.getInputs().length, 1); + assert.equal(this.getOutputs().length, 1); + assert.equal(this.getInputs().length, 1); }); test('Multi-Row', function () { this.deserializationHelper( @@ -637,15 +671,15 @@ suite('Blocks', function () { ' ' + '', ); - chai.assert.equal(this.getOutputs().length, 3); - chai.assert.equal(this.getInputs().length, 3); + assert.equal(this.getOutputs().length, 3); + assert.equal(this.getInputs().length, 3); }); test('Collapsed Row', function () { this.deserializationHelper( '' + ' ' + '', ); - chai.assert.equal(this.getOutputs().length, 1); - chai.assert.equal(this.getInputs().length, 0); + assert.equal(this.getOutputs().length, 1); + assert.equal(this.getInputs().length, 0); }); test('Collapsed Multi-Row', function () { this.deserializationHelper( @@ -661,8 +695,8 @@ suite('Blocks', function () { ' ' + '', ); - chai.assert.equal(this.getOutputs().length, 1); - chai.assert.equal(this.getInputs().length, 0); + assert.equal(this.getOutputs().length, 1); + assert.equal(this.getInputs().length, 0); }); test('Collapsed Multi-Row Middle', function () { Blockly.Xml.appendDomToWorkspace( @@ -683,15 +717,15 @@ suite('Blocks', function () { ); this.assertConnectionsEmpty(); this.clock.runAll(); - chai.assert.equal(this.getOutputs().length, 2); - chai.assert.equal(this.getInputs().length, 1); + assert.equal(this.getOutputs().length, 2); + assert.equal(this.getInputs().length, 1); }); test('Statement', function () { this.deserializationHelper( '' + ' ' + '', ); - chai.assert.equal(this.getPrevious().length, 1); - chai.assert.equal(this.getNext().length, 2); + assert.equal(this.getPrevious().length, 1); + assert.equal(this.getNext().length, 2); }); test('Multi-Statement', function () { this.deserializationHelper( @@ -707,8 +741,8 @@ suite('Blocks', function () { ' ' + '', ); - chai.assert.equal(this.getPrevious().length, 3); - chai.assert.equal(this.getNext().length, 6); + assert.equal(this.getPrevious().length, 3); + assert.equal(this.getNext().length, 6); }); test('Collapsed Statement', function () { this.deserializationHelper( @@ -716,8 +750,8 @@ suite('Blocks', function () { ' ' + '', ); - chai.assert.equal(this.getPrevious().length, 1); - chai.assert.equal(this.getNext().length, 1); + assert.equal(this.getPrevious().length, 1); + assert.equal(this.getNext().length, 1); }); test('Collapsed Multi-Statement', function () { this.deserializationHelper( @@ -733,8 +767,8 @@ suite('Blocks', function () { ' ' + '', ); - chai.assert.equal(this.getPrevious().length, 1); - chai.assert.equal(this.getNext().length, 1); + assert.equal(this.getPrevious().length, 1); + assert.equal(this.getNext().length, 1); }); test('Collapsed Multi-Statement Middle', function () { this.deserializationHelper( @@ -750,8 +784,8 @@ suite('Blocks', function () { ' ' + '', ); - chai.assert.equal(this.getPrevious().length, 2); - chai.assert.equal(this.getNext().length, 3); + assert.equal(this.getPrevious().length, 2); + assert.equal(this.getNext().length, 3); }); }); suite('Programmatic Block Creation', function () { @@ -761,8 +795,8 @@ suite('Blocks', function () { block.initSvg(); block.render(); - chai.assert.equal(this.getPrevious().length, 1); - chai.assert.equal(this.getNext().length, 1); + assert.equal(this.getPrevious().length, 1); + assert.equal(this.getNext().length, 1); }); test('Row', function () { const block = this.workspace.newBlock('row_block'); @@ -770,8 +804,8 @@ suite('Blocks', function () { block.initSvg(); block.render(); - chai.assert.equal(this.getOutputs().length, 1); - chai.assert.equal(this.getInputs().length, 1); + assert.equal(this.getOutputs().length, 1); + assert.equal(this.getInputs().length, 1); }); test('Statement', function () { const block = this.workspace.newBlock('statement_block'); @@ -779,8 +813,8 @@ suite('Blocks', function () { block.initSvg(); block.render(); - chai.assert.equal(this.getPrevious().length, 1); - chai.assert.equal(this.getNext().length, 2); + assert.equal(this.getPrevious().length, 1); + assert.equal(this.getNext().length, 2); }); }); suite('setCollapsed', function () { @@ -790,16 +824,16 @@ suite('Blocks', function () { this.workspace, ); this.clock.runAll(); - chai.assert.equal(this.getPrevious().length, 1); - chai.assert.equal(this.getNext().length, 1); + assert.equal(this.getPrevious().length, 1); + assert.equal(this.getNext().length, 1); block.setCollapsed(true); - chai.assert.equal(this.getPrevious().length, 1); - chai.assert.equal(this.getNext().length, 1); + assert.equal(this.getPrevious().length, 1); + assert.equal(this.getNext().length, 1); block.setCollapsed(false); - chai.assert.equal(this.getPrevious().length, 1); - chai.assert.equal(this.getNext().length, 1); + assert.equal(this.getPrevious().length, 1); + assert.equal(this.getNext().length, 1); }); test('Multi-Stack', function () { const block = Blockly.Xml.domToBlock( @@ -818,16 +852,16 @@ suite('Blocks', function () { ); this.assertConnectionsEmpty(); this.clock.runAll(); - chai.assert.equal(this.getPrevious().length, 3); - chai.assert.equal(this.getNext().length, 3); + assert.equal(this.getPrevious().length, 3); + assert.equal(this.getNext().length, 3); block.setCollapsed(true); - chai.assert.equal(this.getPrevious().length, 3); - chai.assert.equal(this.getNext().length, 3); + assert.equal(this.getPrevious().length, 3); + assert.equal(this.getNext().length, 3); block.setCollapsed(false); - chai.assert.equal(this.getPrevious().length, 3); - chai.assert.equal(this.getNext().length, 3); + assert.equal(this.getPrevious().length, 3); + assert.equal(this.getNext().length, 3); }); test('Row', function () { const block = Blockly.Xml.domToBlock( @@ -835,16 +869,16 @@ suite('Blocks', function () { this.workspace, ); this.clock.runAll(); - chai.assert.equal(this.getOutputs().length, 1); - chai.assert.equal(this.getInputs().length, 1); + assert.equal(this.getOutputs().length, 1); + assert.equal(this.getInputs().length, 1); block.setCollapsed(true); - chai.assert.equal(this.getOutputs().length, 1); - chai.assert.equal(this.getInputs().length, 0); + assert.equal(this.getOutputs().length, 1); + assert.equal(this.getInputs().length, 0); block.setCollapsed(false); - chai.assert.equal(this.getOutputs().length, 1); - chai.assert.equal(this.getInputs().length, 1); + assert.equal(this.getOutputs().length, 1); + assert.equal(this.getInputs().length, 1); }); test('Multi-Row', function () { const block = Blockly.Xml.domToBlock( @@ -862,16 +896,16 @@ suite('Blocks', function () { this.workspace, ); this.clock.runAll(); - chai.assert.equal(this.getOutputs().length, 3); - chai.assert.equal(this.getInputs().length, 3); + assert.equal(this.getOutputs().length, 3); + assert.equal(this.getInputs().length, 3); block.setCollapsed(true); - chai.assert.equal(this.getOutputs().length, 1); - chai.assert.equal(this.getInputs().length, 0); + assert.equal(this.getOutputs().length, 1); + assert.equal(this.getInputs().length, 0); block.setCollapsed(false); - chai.assert.equal(this.getOutputs().length, 3); - chai.assert.equal(this.getInputs().length, 3); + assert.equal(this.getOutputs().length, 3); + assert.equal(this.getInputs().length, 3); }); test('Multi-Row Middle', function () { let block = Blockly.Xml.domToBlock( @@ -889,17 +923,17 @@ suite('Blocks', function () { this.workspace, ); this.clock.runAll(); - chai.assert.equal(this.getOutputs().length, 3); - chai.assert.equal(this.getInputs().length, 3); + assert.equal(this.getOutputs().length, 3); + assert.equal(this.getInputs().length, 3); block = block.getInputTargetBlock('INPUT'); block.setCollapsed(true); - chai.assert.equal(this.getOutputs().length, 2); - chai.assert.equal(this.getInputs().length, 1); + assert.equal(this.getOutputs().length, 2); + assert.equal(this.getInputs().length, 1); block.setCollapsed(false); - chai.assert.equal(this.getOutputs().length, 3); - chai.assert.equal(this.getInputs().length, 3); + assert.equal(this.getOutputs().length, 3); + assert.equal(this.getInputs().length, 3); }); test('Multi-Row Double Collapse', function () { // Collapse middle -> Collapse top -> @@ -919,25 +953,25 @@ suite('Blocks', function () { this.workspace, ); this.clock.runAll(); - chai.assert.equal(this.getOutputs().length, 3); - chai.assert.equal(this.getInputs().length, 3); + assert.equal(this.getOutputs().length, 3); + assert.equal(this.getInputs().length, 3); const middleBlock = block.getInputTargetBlock('INPUT'); middleBlock.setCollapsed(true); - chai.assert.equal(this.getOutputs().length, 2); - chai.assert.equal(this.getInputs().length, 1); + assert.equal(this.getOutputs().length, 2); + assert.equal(this.getInputs().length, 1); block.setCollapsed(true); - chai.assert.equal(this.getOutputs().length, 1); - chai.assert.equal(this.getInputs().length, 0); + assert.equal(this.getOutputs().length, 1); + assert.equal(this.getInputs().length, 0); block.setCollapsed(false); - chai.assert.equal(this.getOutputs().length, 2); - chai.assert.equal(this.getInputs().length, 1); + assert.equal(this.getOutputs().length, 2); + assert.equal(this.getInputs().length, 1); middleBlock.setCollapsed(false); - chai.assert.equal(this.getOutputs().length, 3); - chai.assert.equal(this.getInputs().length, 3); + assert.equal(this.getOutputs().length, 3); + assert.equal(this.getInputs().length, 3); }); test('Statement', function () { const block = Blockly.Xml.domToBlock( @@ -945,16 +979,16 @@ suite('Blocks', function () { this.workspace, ); this.clock.runAll(); - chai.assert.equal(this.getPrevious().length, 1); - chai.assert.equal(this.getNext().length, 2); + assert.equal(this.getPrevious().length, 1); + assert.equal(this.getNext().length, 2); block.setCollapsed(true); - chai.assert.equal(this.getPrevious().length, 1); - chai.assert.equal(this.getNext().length, 1); + assert.equal(this.getPrevious().length, 1); + assert.equal(this.getNext().length, 1); block.setCollapsed(false); - chai.assert.equal(this.getPrevious().length, 1); - chai.assert.equal(this.getNext().length, 2); + assert.equal(this.getPrevious().length, 1); + assert.equal(this.getNext().length, 2); }); test('Multi-Statement', function () { const block = Blockly.Xml.domToBlock( @@ -973,16 +1007,16 @@ suite('Blocks', function () { ); this.assertConnectionsEmpty(); this.clock.runAll(); - chai.assert.equal(this.getPrevious().length, 3); - chai.assert.equal(this.getNext().length, 6); + assert.equal(this.getPrevious().length, 3); + assert.equal(this.getNext().length, 6); block.setCollapsed(true); - chai.assert.equal(this.getPrevious().length, 1); - chai.assert.equal(this.getNext().length, 1); + assert.equal(this.getPrevious().length, 1); + assert.equal(this.getNext().length, 1); block.setCollapsed(false); - chai.assert.equal(this.getPrevious().length, 3); - chai.assert.equal(this.getNext().length, 6); + assert.equal(this.getPrevious().length, 3); + assert.equal(this.getNext().length, 6); }); test('Multi-Statement Middle', function () { let block = Blockly.Xml.domToBlock( @@ -1001,17 +1035,17 @@ suite('Blocks', function () { ); this.assertConnectionsEmpty(); this.clock.runAll(); - chai.assert.equal(this.getPrevious().length, 3); - chai.assert.equal(this.getNext().length, 6); + assert.equal(this.getPrevious().length, 3); + assert.equal(this.getNext().length, 6); block = block.getInputTargetBlock('STATEMENT'); block.setCollapsed(true); - chai.assert.equal(this.getPrevious().length, 2); - chai.assert.equal(this.getNext().length, 3); + assert.equal(this.getPrevious().length, 2); + assert.equal(this.getNext().length, 3); block.setCollapsed(false); - chai.assert.equal(this.getPrevious().length, 3); - chai.assert.equal(this.getNext().length, 6); + assert.equal(this.getPrevious().length, 3); + assert.equal(this.getNext().length, 6); }); test('Multi-Statement Double Collapse', function () { const block = Blockly.Xml.domToBlock( @@ -1030,25 +1064,25 @@ suite('Blocks', function () { ); this.assertConnectionsEmpty(); this.clock.runAll(); - chai.assert.equal(this.getPrevious().length, 3); - chai.assert.equal(this.getNext().length, 6); + assert.equal(this.getPrevious().length, 3); + assert.equal(this.getNext().length, 6); const middleBlock = block.getInputTargetBlock('STATEMENT'); middleBlock.setCollapsed(true); - chai.assert.equal(this.getPrevious().length, 2); - chai.assert.equal(this.getNext().length, 3); + assert.equal(this.getPrevious().length, 2); + assert.equal(this.getNext().length, 3); block.setCollapsed(true); - chai.assert.equal(this.getPrevious().length, 1); - chai.assert.equal(this.getNext().length, 1); + assert.equal(this.getPrevious().length, 1); + assert.equal(this.getNext().length, 1); block.setCollapsed(false); - chai.assert.equal(this.getPrevious().length, 2); - chai.assert.equal(this.getNext().length, 3); + assert.equal(this.getPrevious().length, 2); + assert.equal(this.getNext().length, 3); middleBlock.setCollapsed(false); - chai.assert.equal(this.getPrevious().length, 3); - chai.assert.equal(this.getNext().length, 6); + assert.equal(this.getPrevious().length, 3); + assert.equal(this.getNext().length, 6); }); }); suite('Setting Parent Block', function () { @@ -1074,14 +1108,14 @@ suite('Blocks', function () { }); function assertBlockIsOnlyChild(parent, child, inputName) { - chai.assert.equal(parent.getChildren().length, 1); - chai.assert.equal(parent.getInputTargetBlock(inputName), child); - chai.assert.equal(child.getParent(), parent); + assert.equal(parent.getChildren().length, 1); + assert.equal(parent.getInputTargetBlock(inputName), child); + assert.equal(child.getParent(), parent); } function assertNonParentAndOrphan(nonParent, orphan, inputName) { - chai.assert.equal(nonParent.getChildren().length, 0); - chai.assert.isNull(nonParent.getInputTargetBlock('TEXT')); - chai.assert.isNull(orphan.getParent()); + assert.equal(nonParent.getChildren().length, 0); + assert.isNull(nonParent.getInputTargetBlock('TEXT')); + assert.isNull(orphan.getParent()); } function assertOriginalSetup() { assertBlockIsOnlyChild(this.printBlock, this.textJoinBlock, 'TEXT'); @@ -1089,7 +1123,7 @@ suite('Blocks', function () { } test('Setting to connected parent', function () { - chai.assert.doesNotThrow( + assert.doesNotThrow( this.textJoinBlock.setParent.bind( this.textJoinBlock, this.printBlock, @@ -1102,19 +1136,19 @@ suite('Blocks', function () { this.textBlock.outputConnection.connect( this.printBlock.getInput('TEXT').connection, ); - chai.assert.doesNotThrow( + assert.doesNotThrow( this.textBlock.setParent.bind(this.textBlock, this.printBlock), ); assertBlockIsOnlyChild(this.printBlock, this.textBlock, 'TEXT'); }); test('Setting to new parent while connected to other block', function () { // Setting to grandparent with no available input connection. - chai.assert.throws( + assert.throws( this.textBlock.setParent.bind(this.textBlock, this.printBlock), ); this.textJoinBlock.outputConnection.disconnect(); // Setting to block with available input connection. - chai.assert.throws( + assert.throws( this.textBlock.setParent.bind(this.textBlock, this.printBlock), ); assertNonParentAndOrphan(this.printBlock, this.textJoinBlock, 'TEXT'); @@ -1122,7 +1156,7 @@ suite('Blocks', function () { }); test('Setting to same parent after disconnecting from it', function () { this.textJoinBlock.outputConnection.disconnect(); - chai.assert.throws( + assert.throws( this.textJoinBlock.setParent.bind( this.textJoinBlock, this.printBlock, @@ -1133,12 +1167,12 @@ suite('Blocks', function () { test('Setting to new parent when orphan', function () { this.textBlock.outputConnection.disconnect(); // When new parent has no available input connection. - chai.assert.throws( + assert.throws( this.textBlock.setParent.bind(this.textBlock, this.printBlock), ); this.textJoinBlock.outputConnection.disconnect(); // When new parent has available input connection. - chai.assert.throws( + assert.throws( this.textBlock.setParent.bind(this.textBlock, this.printBlock), ); @@ -1148,13 +1182,13 @@ suite('Blocks', function () { }); test('Setting parent to null after disconnecting', function () { this.textBlock.outputConnection.disconnect(); - chai.assert.doesNotThrow( + assert.doesNotThrow( this.textBlock.setParent.bind(this.textBlock, null), ); assertNonParentAndOrphan(this.textJoinBlock, this.textBlock, 'ADD0'); }); test('Setting parent to null without disconnecting', function () { - chai.assert.throws(this.textBlock.setParent.bind(this.textBlock, null)); + assert.throws(this.textBlock.setParent.bind(this.textBlock, null)); assertOriginalSetup.call(this); }); }); @@ -1164,40 +1198,40 @@ suite('Blocks', function () { block.setOutput(false); - chai.assert.equal(this.getOutputs().length, 0); - chai.assert.equal(this.getInputs().length, 1); + assert.equal(this.getOutputs().length, 0); + assert.equal(this.getInputs().length, 1); }); test('Value', function () { const block = createRenderedBlock(this.workspace, 'row_block'); block.removeInput('INPUT'); - chai.assert.equal(this.getOutputs().length, 1); - chai.assert.equal(this.getInputs().length, 0); + assert.equal(this.getOutputs().length, 1); + assert.equal(this.getInputs().length, 0); }); test('Previous', function () { const block = createRenderedBlock(this.workspace, 'stack_block'); block.setPreviousStatement(false); - chai.assert.equal(this.getPrevious().length, 0); - chai.assert.equal(this.getNext().length, 1); + assert.equal(this.getPrevious().length, 0); + assert.equal(this.getNext().length, 1); }); test('Next', function () { const block = createRenderedBlock(this.workspace, 'stack_block'); block.setNextStatement(false); - chai.assert.equal(this.getPrevious().length, 1); - chai.assert.equal(this.getNext().length, 0); + assert.equal(this.getPrevious().length, 1); + assert.equal(this.getNext().length, 0); }); test('Statement', function () { const block = createRenderedBlock(this.workspace, 'statement_block'); block.removeInput('STATEMENT'); - chai.assert.equal(this.getPrevious().length, 1); - chai.assert.equal(this.getNext().length, 1); + assert.equal(this.getPrevious().length, 1); + assert.equal(this.getNext().length, 1); }); }); suite('Add Connections Programmatically', function () { @@ -1208,7 +1242,7 @@ suite('Blocks', function () { this.clock.runAll(); this.clock.runAll(); - chai.assert.equal(this.getOutputs().length, 1); + assert.equal(this.getOutputs().length, 1); }); test('Value', function () { const block = createRenderedBlock(this.workspace, 'empty_block'); @@ -1216,7 +1250,7 @@ suite('Blocks', function () { block.appendValueInput('INPUT'); this.clock.runAll(); - chai.assert.equal(this.getInputs().length, 1); + assert.equal(this.getInputs().length, 1); }); test('Previous', function () { const block = createRenderedBlock(this.workspace, 'empty_block'); @@ -1225,7 +1259,7 @@ suite('Blocks', function () { this.clock.runAll(); this.clock.runAll(); - chai.assert.equal(this.getPrevious().length, 1); + assert.equal(this.getPrevious().length, 1); }); test('Next', function () { const block = createRenderedBlock(this.workspace, 'empty_block'); @@ -1234,7 +1268,7 @@ suite('Blocks', function () { this.clock.runAll(); this.clock.runAll(); - chai.assert.equal(this.getNext().length, 1); + assert.equal(this.getNext().length, 1); }); test('Statement', function () { const block = createRenderedBlock(this.workspace, 'empty_block'); @@ -1242,7 +1276,7 @@ suite('Blocks', function () { block.appendStatementInput('STATEMENT'); this.clock.runAll(); - chai.assert.equal(this.getNext().length, 1); + assert.equal(this.getNext().length, 1); }); }); }); @@ -1252,18 +1286,18 @@ suite('Blocks', function () { function assertCommentEvent(eventSpy, oldValue, newValue) { const calls = eventSpy.getCalls(); const event = calls[calls.length - 1].args[0]; - chai.assert.equal(event.type, eventUtils.BLOCK_CHANGE); - chai.assert.equal( + assert.equal(event.type, EventType.BLOCK_CHANGE); + assert.equal( event.element, 'comment', 'Expected the element to be a comment', ); - chai.assert.equal( + assert.equal( event.oldValue, oldValue, 'Expected the old values to match', ); - chai.assert.equal( + assert.equal( event.newValue, newValue, 'Expected the new values to match', @@ -1272,7 +1306,7 @@ suite('Blocks', function () { function assertNoCommentEvent(eventSpy) { const calls = eventSpy.getCalls(); const event = calls[calls.length - 1].args[0]; - chai.assert.notEqual(event.type, eventUtils.BLOCK_CHANGE); + assert.notEqual(event.type, EventType.BLOCK_CHANGE); } setup(function () { this.eventsFireSpy = sinon.spy(eventUtils.TEST_ONLY, 'fireInternal'); @@ -1289,24 +1323,24 @@ suite('Blocks', function () { }); test('Text', function () { this.block.setCommentText('test text'); - chai.assert.equal(this.block.getCommentText(), 'test text'); + assert.equal(this.block.getCommentText(), 'test text'); assertCommentEvent(this.eventsFireSpy, null, 'test text'); }); test('Text Empty', function () { this.block.setCommentText(''); - chai.assert.equal(this.block.getCommentText(), ''); + assert.equal(this.block.getCommentText(), ''); assertCommentEvent(this.eventsFireSpy, null, ''); }); test('Text Null', function () { this.block.setCommentText(null); - chai.assert.isNull(this.block.getCommentText()); + assert.isNull(this.block.getCommentText()); assertNoCommentEvent(this.eventsFireSpy); }); test('Text -> Null', function () { this.block.setCommentText('first text'); this.block.setCommentText(null); - chai.assert.isNull(this.block.getCommentText()); + assert.isNull(this.block.getCommentText()); assertCommentEvent(this.eventsFireSpy, 'first text', null); }); }); @@ -1326,24 +1360,24 @@ suite('Blocks', function () { }); test('Text', function () { this.block.setCommentText('test text'); - chai.assert.equal(this.block.getCommentText(), 'test text'); + assert.equal(this.block.getCommentText(), 'test text'); assertCommentEvent(this.eventsFireSpy, null, 'test text'); }); test('Text Empty', function () { this.block.setCommentText(''); - chai.assert.equal(this.block.getCommentText(), ''); + assert.equal(this.block.getCommentText(), ''); assertCommentEvent(this.eventsFireSpy, null, ''); }); test('Text Null', function () { this.block.setCommentText(null); - chai.assert.isNull(this.block.getCommentText()); + assert.isNull(this.block.getCommentText()); assertNoCommentEvent(this.eventsFireSpy); }); test('Text -> Null', function () { this.block.setCommentText('first text'); this.block.setCommentText(null); - chai.assert.isNull(this.block.getCommentText()); + assert.isNull(this.block.getCommentText()); assertCommentEvent(this.eventsFireSpy, 'first text', null); }); test('Set While Visible - Editable', function () { @@ -1352,7 +1386,7 @@ suite('Blocks', function () { icon.setBubbleVisible(true); this.block.setCommentText('test2'); - chai.assert.equal(this.block.getCommentText(), 'test2'); + assert.equal(this.block.getCommentText(), 'test2'); assertCommentEvent(this.eventsFireSpy, 'test1', 'test2'); }); test('Set While Visible - NonEditable', function () { @@ -1363,7 +1397,7 @@ suite('Blocks', function () { icon.setBubbleVisible(true); this.block.setCommentText('test2'); - chai.assert.equal(this.block.getCommentText(), 'test2'); + assert.equal(this.block.getCommentText(), 'test2'); assertCommentEvent(this.eventsFireSpy, 'test1', 'test2'); }); }); @@ -1431,7 +1465,7 @@ suite('Blocks', function () { this.block.setCommentText('test text'); - chai.assert.instanceOf( + assert.instanceOf( this.block.getIcon(Blockly.icons.IconType.COMMENT), MockComment, ); @@ -1442,7 +1476,7 @@ suite('Blocks', function () { Blockly.icons.IconType.COMMENT.toString(), ); - chai.assert.throws(() => { + assert.throws(() => { this.block.setCommentText('test text'); }, 'No comment icon class is registered, so a comment cannot be set'); }); @@ -1456,7 +1490,7 @@ suite('Blocks', function () { MockIcon, ); - chai.assert.throws(() => { + assert.throws(() => { this.block.setCommentText('test text'); }, 'The class registered as a comment icon does not conform to the ICommentIcon interface'); }); @@ -1479,13 +1513,13 @@ suite('Blocks', function () { }); test('Getting Field', function () { - chai.assert.instanceOf(this.block.getField('TEXT'), Blockly.Field); + assert.instanceOf(this.block.getField('TEXT'), Blockly.Field); }); test('Getting Field without Name', function () { - chai.assert.throws(this.block.getField.bind(this.block), TypeError); + assert.throws(this.block.getField.bind(this.block), TypeError); }); test('Getting Value of Field without Name', function () { - chai.assert.throws(this.block.getFieldValue.bind(this.block), TypeError); + assert.throws(this.block.getFieldValue.bind(this.block), TypeError); }); test('Getting Field with Wrong Type', function () { const testFunction = function () { @@ -1499,7 +1533,7 @@ suite('Blocks', function () { ['TEXT'], ]; for (let i = 0; i < inputs.length; i++) { - chai.assert.throws( + assert.throws( this.block.getField.bind(this.block, inputs[i]), TypeError, ); @@ -1517,19 +1551,19 @@ suite('Blocks', function () { ['TEXT'], ]; for (let i = 0; i < inputs.length; i++) { - chai.assert.throws( + assert.throws( this.block.getFieldValue.bind(this.block, inputs[i]), TypeError, ); } }); test('Getting/Setting Field Value', function () { - chai.assert.equal(this.block.getFieldValue('TEXT'), 'test'); + assert.equal(this.block.getFieldValue('TEXT'), 'test'); this.block.setFieldValue('abc', 'TEXT'); - chai.assert.equal(this.block.getFieldValue('TEXT'), 'abc'); + assert.equal(this.block.getFieldValue('TEXT'), 'abc'); }); test('Setting Field without Name', function () { - chai.assert.throws(this.block.setFieldValue.bind(this.block, 'test')); + assert.throws(this.block.setFieldValue.bind(this.block, 'test')); }); test('Setting Field with Wrong Type', function () { const testFunction = function () { @@ -1543,7 +1577,7 @@ suite('Blocks', function () { ['TEXT'], ]; for (let i = 0; i < inputs.length; i++) { - chai.assert.throws( + assert.throws( this.block.setFieldValue.bind(this.block, 'test', inputs[i]), TypeError, ); @@ -1589,15 +1623,12 @@ suite('Blocks', function () { test('icons get added to the block', function () { this.block.addIcon(new MockIconA()); - chai.assert.isTrue( - this.block.hasIcon('A'), - 'Expected the icon to be added', - ); + assert.isTrue(this.block.hasIcon('A'), 'Expected the icon to be added'); }); test('adding two icons of the same type throws', function () { this.block.addIcon(new MockIconA()); - chai.assert.throws( + assert.throws( () => { this.block.addIcon(new MockIconA()); }, @@ -1610,7 +1641,7 @@ suite('Blocks', function () { test('adding an icon triggers a render', function () { this.renderSpy.resetHistory(); this.block.addIcon(new MockIconA()); - chai.assert.isTrue( + assert.isTrue( this.renderSpy.calledOnce, 'Expected adding an icon to trigger a render', ); @@ -1634,18 +1665,18 @@ suite('Blocks', function () { test('icons get removed from the block', function () { this.block.addIcon(new MockIconA()); - chai.assert.isTrue( + assert.isTrue( this.block.removeIcon(new Blockly.icons.IconType('A')), 'Expected removeIcon to return true', ); - chai.assert.isFalse( + assert.isFalse( this.block.hasIcon('A'), 'Expected the icon to be removed', ); }); test('removing an icon that does not exist returns false', function () { - chai.assert.isFalse( + assert.isFalse( this.block.removeIcon(new Blockly.icons.IconType('B')), 'Expected removeIcon to return false', ); @@ -1655,7 +1686,7 @@ suite('Blocks', function () { this.block.addIcon(new MockIconA()); this.renderSpy.resetHistory(); this.block.removeIcon(new Blockly.icons.IconType('A')); - chai.assert.isTrue( + assert.isTrue( this.renderSpy.calledOnce, 'Expected removing an icon to trigger a render', ); @@ -1672,7 +1703,7 @@ suite('Blocks', function () { const iconB = new MockIconB(); this.block.addIcon(iconB); this.block.addIcon(iconA); - chai.assert.sameOrderedMembers( + assert.sameOrderedMembers( this.block.getIcons(), [iconA, iconB], 'Expected getIcon to return both icons in order of weight', @@ -1680,7 +1711,7 @@ suite('Blocks', function () { }); test('if there are no icons, getIcons returns an empty array', function () { - chai.assert.isEmpty( + assert.isEmpty( this.block.getIcons(), 'Expected getIcons to return an empty array ' + 'for a block with no icons', @@ -1688,7 +1719,7 @@ suite('Blocks', function () { }); test('if there are no icons, getIcons returns an empty array', function () { - chai.assert.isEmpty( + assert.isEmpty( this.block.getIcons(), 'Expected getIcons to return an empty array ' + 'for a block with no icons', @@ -1700,7 +1731,7 @@ suite('Blocks', function () { const iconB = new MockIconB(); this.block.addIcon(iconA); this.block.addIcon(iconB); - chai.assert.equal( + assert.equal( this.block.getIcon('B'), iconB, 'Expected getIcon to return the icon with the given type', @@ -1709,7 +1740,7 @@ suite('Blocks', function () { test('if there is no matching icon, getIcon returns undefined', function () { this.block.addIcon(new MockIconA()); - chai.assert.isUndefined( + assert.isUndefined( this.block.getIcon('B'), 'Expected getIcon to return null if there is no ' + 'icon with a matching type', @@ -1733,7 +1764,7 @@ suite('Blocks', function () { test('Block with no warning text does not have warning icon', function () { const icon = this.block.getIcon(Blockly.icons.WarningIcon.TYPE); - chai.assert.isUndefined( + assert.isUndefined( icon, 'Block with no warning should not have warning icon', ); @@ -1745,7 +1776,7 @@ suite('Blocks', function () { this.block.setWarningText(text); const icon = this.block.getIcon(Blockly.icons.WarningIcon.TYPE); - chai.assert.equal( + assert.equal( icon.getText(), text, 'Expected warning icon text to be set', @@ -1760,7 +1791,7 @@ suite('Blocks', function () { this.block.setWarningText(text2, '2'); const icon = this.block.getIcon(Blockly.icons.WarningIcon.TYPE); - chai.assert.equal(icon.getText(), `${text1}\n${text2}`); + assert.equal(icon.getText(), `${text1}\n${text2}`); }); test('Clearing all warning text deletes the warning icon', function () { @@ -1770,7 +1801,7 @@ suite('Blocks', function () { this.block.setWarningText(null); const icon = this.block.getIcon(Blockly.icons.WarningIcon.TYPE); - chai.assert.isUndefined( + assert.isUndefined( icon, 'Expected warning icon to be undefined after deleting all warning text', ); @@ -1785,7 +1816,7 @@ suite('Blocks', function () { this.block.setWarningText(null, '1'); const icon = this.block.getIcon(Blockly.icons.WarningIcon.TYPE); - chai.assert.equal( + assert.equal( icon.getText(), text2, 'Expected first warning text to be deleted', @@ -1802,7 +1833,7 @@ suite('Blocks', function () { this.block.setWarningText(null, '2'); const icon = this.block.getIcon(Blockly.icons.WarningIcon.TYPE); - chai.assert.isUndefined( + assert.isUndefined( icon, 'Expected warning icon to be deleted after all warning text is cleared', ); @@ -1839,7 +1870,7 @@ suite('Blocks', function () { parentBlock.setCollapsed(true); - chai.assert.isFalse( + assert.isFalse( icon.bubbleIsVisible(), "Expected collapsing the parent block to hide the child block's " + "icon's bubble", @@ -1865,7 +1896,7 @@ suite('Blocks', function () { parentBlock.setCollapsed(true); - chai.assert.isTrue( + assert.isTrue( icon.bubbleIsVisible(), 'Expected collapsing the parent block to not hide the next ' + "block's bubble", @@ -1876,45 +1907,45 @@ suite('Blocks', function () { suite('Collapsing and Expanding', function () { function assertCollapsed(block, opt_string) { - chai.assert.isTrue(block.isCollapsed()); + assert.isTrue(block.isCollapsed()); for (let i = 0, input; (input = block.inputList[i]); i++) { if (input.name == Blockly.Block.COLLAPSED_INPUT_NAME) { continue; } - chai.assert.isFalse(input.isVisible()); + assert.isFalse(input.isVisible()); for (let j = 0, field; (field = input.fieldRow[j]); j++) { - chai.assert.isFalse(field.isVisible()); + assert.isFalse(field.isVisible()); } } const icons = block.getIcons(); for (let i = 0, icon; (icon = icons[i]); i++) { - chai.assert.isFalse(icon.bubbleIsVisible()); + assert.isFalse(icon.bubbleIsVisible()); } const input = block.getInput(Blockly.Block.COLLAPSED_INPUT_NAME); - chai.assert.isNotNull(input); - chai.assert.isTrue(input.isVisible()); + assert.isNotNull(input); + assert.isTrue(input.isVisible()); const field = block.getField(Blockly.Block.COLLAPSED_FIELD_NAME); - chai.assert.isNotNull(field); - chai.assert.isTrue(field.isVisible()); + assert.isNotNull(field); + assert.isTrue(field.isVisible()); if (opt_string) { - chai.assert.equal(field.getText(), opt_string); + assert.equal(field.getText(), opt_string); } } function assertNotCollapsed(block) { - chai.assert.isFalse(block.isCollapsed()); + assert.isFalse(block.isCollapsed()); for (let i = 0, input; (input = block.inputList[i]); i++) { - chai.assert.isTrue(input.isVisible()); + assert.isTrue(input.isVisible()); for (let j = 0, field; (field = input.fieldRow[j]); j++) { - chai.assert.isTrue(field.isVisible()); + assert.isTrue(field.isVisible()); } } const input = block.getInput(Blockly.Block.COLLAPSED_INPUT_NAME); - chai.assert.isNull(input); + assert.isNull(input); const field = block.getField(Blockly.Block.COLLAPSED_FIELD_NAME); - chai.assert.isNull(field); + assert.isNull(field); } function isBlockHidden(block) { let node = block.getSvgRoot(); @@ -1967,10 +1998,10 @@ suite('Blocks', function () { blockA.setCollapsed(true); assertCollapsed(blockA); blockA.getInput('INPUT').connection.connect(blockB.outputConnection); - chai.assert.isTrue(isBlockHidden(blockB)); + assert.isTrue(isBlockHidden(blockB)); blockA.setCollapsed(false); assertNotCollapsed(blockA); - chai.assert.isFalse(isBlockHidden(blockB)); + assert.isFalse(isBlockHidden(blockB)); }); test('Connect Block to Statement Input', function () { const blockA = createRenderedBlock(this.workspace, 'statement_block'); @@ -1981,10 +2012,10 @@ suite('Blocks', function () { blockA .getInput('STATEMENT') .connection.connect(blockB.previousConnection); - chai.assert.isTrue(isBlockHidden(blockB)); + assert.isTrue(isBlockHidden(blockB)); blockA.setCollapsed(false); assertNotCollapsed(blockA); - chai.assert.isFalse(isBlockHidden(blockB)); + assert.isFalse(isBlockHidden(blockB)); }); test('Connect Block to Child of Collapsed - Input', function () { const blockA = createRenderedBlock(this.workspace, 'row_block'); @@ -1994,14 +2025,14 @@ suite('Blocks', function () { blockA.getInput('INPUT').connection.connect(blockB.outputConnection); blockA.setCollapsed(true); assertCollapsed(blockA); - chai.assert.isTrue(isBlockHidden(blockB)); + assert.isTrue(isBlockHidden(blockB)); blockB.getInput('INPUT').connection.connect(blockC.outputConnection); - chai.assert.isTrue(isBlockHidden(blockC)); + assert.isTrue(isBlockHidden(blockC)); blockA.setCollapsed(false); assertNotCollapsed(blockA); - chai.assert.isFalse(isBlockHidden(blockB)); - chai.assert.isFalse(isBlockHidden(blockC)); + assert.isFalse(isBlockHidden(blockB)); + assert.isFalse(isBlockHidden(blockC)); }); test('Connect Block to Child of Collapsed - Next', function () { const blockA = createRenderedBlock(this.workspace, 'statement_block'); @@ -2013,14 +2044,14 @@ suite('Blocks', function () { .connection.connect(blockB.previousConnection); blockA.setCollapsed(true); assertCollapsed(blockA); - chai.assert.isTrue(isBlockHidden(blockB)); + assert.isTrue(isBlockHidden(blockB)); blockB.nextConnection.connect(blockC.previousConnection); - chai.assert.isTrue(isBlockHidden(blockC)); + assert.isTrue(isBlockHidden(blockC)); blockA.setCollapsed(false); assertNotCollapsed(blockA); - chai.assert.isFalse(isBlockHidden(blockB)); - chai.assert.isFalse(isBlockHidden(blockC)); + assert.isFalse(isBlockHidden(blockB)); + assert.isFalse(isBlockHidden(blockC)); }); test('Connect Block to Value Input Already Taken', function () { const blockA = createRenderedBlock(this.workspace, 'row_block'); @@ -2030,16 +2061,16 @@ suite('Blocks', function () { blockA.getInput('INPUT').connection.connect(blockB.outputConnection); blockA.setCollapsed(true); assertCollapsed(blockA); - chai.assert.isTrue(isBlockHidden(blockB)); + assert.isTrue(isBlockHidden(blockB)); blockA.getInput('INPUT').connection.connect(blockC.outputConnection); - chai.assert.isTrue(isBlockHidden(blockC)); + assert.isTrue(isBlockHidden(blockC)); // Still hidden after C is inserted between. - chai.assert.isTrue(isBlockHidden(blockB)); + assert.isTrue(isBlockHidden(blockB)); blockA.setCollapsed(false); assertNotCollapsed(blockA); - chai.assert.isFalse(isBlockHidden(blockB)); - chai.assert.isFalse(isBlockHidden(blockC)); + assert.isFalse(isBlockHidden(blockB)); + assert.isFalse(isBlockHidden(blockC)); }); test('Connect Block to Statement Input Already Taken', function () { const blockA = createRenderedBlock(this.workspace, 'statement_block'); @@ -2051,18 +2082,18 @@ suite('Blocks', function () { .connection.connect(blockB.previousConnection); blockA.setCollapsed(true); assertCollapsed(blockA); - chai.assert.isTrue(isBlockHidden(blockB)); + assert.isTrue(isBlockHidden(blockB)); blockA .getInput('STATEMENT') .connection.connect(blockC.previousConnection); - chai.assert.isTrue(isBlockHidden(blockC)); + assert.isTrue(isBlockHidden(blockC)); // Still hidden after C is inserted between. - chai.assert.isTrue(isBlockHidden(blockB)); + assert.isTrue(isBlockHidden(blockB)); blockA.setCollapsed(false); assertNotCollapsed(blockA); - chai.assert.isFalse(isBlockHidden(blockB)); - chai.assert.isFalse(isBlockHidden(blockC)); + assert.isFalse(isBlockHidden(blockB)); + assert.isFalse(isBlockHidden(blockC)); }); test('Connect Block with Child - Input', function () { const blockA = createRenderedBlock(this.workspace, 'row_block'); @@ -2073,13 +2104,13 @@ suite('Blocks', function () { blockA.setCollapsed(true); assertCollapsed(blockA); blockA.getInput('INPUT').connection.connect(blockB.outputConnection); - chai.assert.isTrue(isBlockHidden(blockC)); - chai.assert.isTrue(isBlockHidden(blockB)); + assert.isTrue(isBlockHidden(blockC)); + assert.isTrue(isBlockHidden(blockB)); blockA.setCollapsed(false); assertNotCollapsed(blockA); - chai.assert.isFalse(isBlockHidden(blockB)); - chai.assert.isFalse(isBlockHidden(blockC)); + assert.isFalse(isBlockHidden(blockB)); + assert.isFalse(isBlockHidden(blockC)); }); test('Connect Block with Child - Statement', function () { const blockA = createRenderedBlock(this.workspace, 'statement_block'); @@ -2092,13 +2123,13 @@ suite('Blocks', function () { blockA .getInput('STATEMENT') .connection.connect(blockB.previousConnection); - chai.assert.isTrue(isBlockHidden(blockC)); - chai.assert.isTrue(isBlockHidden(blockB)); + assert.isTrue(isBlockHidden(blockC)); + assert.isTrue(isBlockHidden(blockB)); blockA.setCollapsed(false); assertNotCollapsed(blockA); - chai.assert.isFalse(isBlockHidden(blockB)); - chai.assert.isFalse(isBlockHidden(blockC)); + assert.isFalse(isBlockHidden(blockB)); + assert.isFalse(isBlockHidden(blockC)); }); test('Disconnect Block from Value Input', function () { const blockA = createRenderedBlock(this.workspace, 'row_block'); @@ -2107,9 +2138,9 @@ suite('Blocks', function () { blockA.getInput('INPUT').connection.connect(blockB.outputConnection); blockA.setCollapsed(true); assertCollapsed(blockA); - chai.assert.isTrue(isBlockHidden(blockB)); + assert.isTrue(isBlockHidden(blockB)); blockB.outputConnection.disconnect(); - chai.assert.isFalse(isBlockHidden(blockB)); + assert.isFalse(isBlockHidden(blockB)); }); test('Disconnect Block from Statement Input', function () { const blockA = createRenderedBlock(this.workspace, 'statement_block'); @@ -2120,9 +2151,9 @@ suite('Blocks', function () { .connection.connect(blockB.previousConnection); blockA.setCollapsed(true); assertCollapsed(blockA); - chai.assert.isTrue(isBlockHidden(blockB)); + assert.isTrue(isBlockHidden(blockB)); blockB.previousConnection.disconnect(); - chai.assert.isFalse(isBlockHidden(blockB)); + assert.isFalse(isBlockHidden(blockB)); }); test('Disconnect Block from Child of Collapsed - Input', function () { const blockA = createRenderedBlock(this.workspace, 'row_block'); @@ -2133,11 +2164,11 @@ suite('Blocks', function () { blockB.getInput('INPUT').connection.connect(blockC.outputConnection); blockA.setCollapsed(true); assertCollapsed(blockA); - chai.assert.isTrue(isBlockHidden(blockB)); - chai.assert.isTrue(isBlockHidden(blockC)); + assert.isTrue(isBlockHidden(blockB)); + assert.isTrue(isBlockHidden(blockC)); blockC.outputConnection.disconnect(); - chai.assert.isFalse(isBlockHidden(blockC)); + assert.isFalse(isBlockHidden(blockC)); }); test('Disconnect Block from Child of Collapsed - Next', function () { const blockA = createRenderedBlock(this.workspace, 'statement_block'); @@ -2150,11 +2181,11 @@ suite('Blocks', function () { blockB.nextConnection.connect(blockC.previousConnection); blockA.setCollapsed(true); assertCollapsed(blockA); - chai.assert.isTrue(isBlockHidden(blockB)); - chai.assert.isTrue(isBlockHidden(blockC)); + assert.isTrue(isBlockHidden(blockB)); + assert.isTrue(isBlockHidden(blockC)); blockC.previousConnection.disconnect(); - chai.assert.isFalse(isBlockHidden(blockC)); + assert.isFalse(isBlockHidden(blockC)); }); test('Disconnect Block with Child - Input', function () { const blockA = createRenderedBlock(this.workspace, 'row_block'); @@ -2165,12 +2196,12 @@ suite('Blocks', function () { blockA.getInput('INPUT').connection.connect(blockB.outputConnection); blockA.setCollapsed(true); assertCollapsed(blockA); - chai.assert.isTrue(isBlockHidden(blockB)); - chai.assert.isTrue(isBlockHidden(blockC)); + assert.isTrue(isBlockHidden(blockB)); + assert.isTrue(isBlockHidden(blockC)); blockB.outputConnection.disconnect(); - chai.assert.isFalse(isBlockHidden(blockB)); - chai.assert.isFalse(isBlockHidden(blockC)); + assert.isFalse(isBlockHidden(blockB)); + assert.isFalse(isBlockHidden(blockC)); }); test('Disconnect Block with Child - Statement', function () { const blockA = createRenderedBlock(this.workspace, 'statement_block'); @@ -2183,12 +2214,12 @@ suite('Blocks', function () { .connection.connect(blockB.previousConnection); blockA.setCollapsed(true); assertCollapsed(blockA); - chai.assert.isTrue(isBlockHidden(blockC)); - chai.assert.isTrue(isBlockHidden(blockB)); + assert.isTrue(isBlockHidden(blockC)); + assert.isTrue(isBlockHidden(blockB)); blockB.previousConnection.disconnect(); - chai.assert.isFalse(isBlockHidden(blockB)); - chai.assert.isFalse(isBlockHidden(blockC)); + assert.isFalse(isBlockHidden(blockB)); + assert.isFalse(isBlockHidden(blockC)); }); }); suite('Adding and Removing Block Parts', function () { @@ -2198,7 +2229,7 @@ suite('Blocks', function () { assertCollapsed(blockA); blockA.setPreviousStatement(true); assertCollapsed(blockA); - chai.assert.isNotNull(blockA.previousConnection); + assert.isNotNull(blockA.previousConnection); }); test('Add Next Connection', function () { const blockA = createRenderedBlock(this.workspace, 'empty_block'); @@ -2206,7 +2237,7 @@ suite('Blocks', function () { assertCollapsed(blockA); blockA.setNextStatement(true); assertCollapsed(blockA); - chai.assert.isNotNull(blockA.nextConnection); + assert.isNotNull(blockA.nextConnection); }); test('Add Input', function () { const blockA = createRenderedBlock(this.workspace, 'empty_block'); @@ -2216,7 +2247,7 @@ suite('Blocks', function () { this.clock.runAll(); assertCollapsed(blockA); - chai.assert.isNotNull(blockA.getInput('NAME')); + assert.isNotNull(blockA.getInput('NAME')); }); test('Add Field', function () { const blockA = createRenderedBlock(this.workspace, 'empty_block'); @@ -2226,8 +2257,8 @@ suite('Blocks', function () { input.appendField(new Blockly.FieldLabel('test'), 'FIELD'); assertCollapsed(blockA); const field = blockA.getField('FIELD'); - chai.assert.isNotNull(field); - chai.assert.equal(field.getText(), 'test'); + assert.isNotNull(field); + assert.equal(field.getText(), 'test'); }); test('Add Icon', function () { const blockA = createRenderedBlock(this.workspace, 'empty_block'); @@ -2243,7 +2274,7 @@ suite('Blocks', function () { assertCollapsed(blockA); blockA.setPreviousStatement(false); assertCollapsed(blockA); - chai.assert.isNull(blockA.previousConnection); + assert.isNull(blockA.previousConnection); }); test('Remove Next Connection', function () { const blockA = createRenderedBlock(this.workspace, 'empty_block'); @@ -2252,7 +2283,7 @@ suite('Blocks', function () { assertCollapsed(blockA); blockA.setNextStatement(false); assertCollapsed(blockA); - chai.assert.isNull(blockA.nextConnection); + assert.isNull(blockA.nextConnection); }); test('Remove Input', function () { const blockA = createRenderedBlock(this.workspace, 'empty_block'); @@ -2261,7 +2292,7 @@ suite('Blocks', function () { assertCollapsed(blockA); blockA.removeInput('NAME'); assertCollapsed(blockA); - chai.assert.isNull(blockA.getInput('NAME')); + assert.isNull(blockA.getInput('NAME')); }); test('Remove Field', function () { const blockA = createRenderedBlock(this.workspace, 'empty_block'); @@ -2272,7 +2303,7 @@ suite('Blocks', function () { input.removeField('FIELD'); assertCollapsed(blockA); const field = blockA.getField('FIELD'); - chai.assert.isNull(field); + assert.isNull(field); }); test('Remove Icon', function () { const blockA = createRenderedBlock(this.workspace, 'empty_block'); @@ -2321,8 +2352,8 @@ suite('Blocks', function () { blockA.setCollapsed(false); // The child blocks should be enabled. - chai.assert.isTrue(blockB.isEnabled()); - chai.assert.isFalse( + assert.isTrue(blockB.isEnabled()); + assert.isFalse( blockB.getSvgRoot().classList.contains('blocklyDisabled'), ); }); @@ -2345,7 +2376,7 @@ suite('Blocks', function () { blockA.setCollapsed(true); // Child blocks should stay disabled if they have been set. - chai.assert.isFalse(blockB.isEnabled()); + assert.isFalse(blockB.isEnabled()); }); test('Disabled blocks from JSON should have proper disabled status', function () { // Nested c-shaped blocks, inner block is disabled @@ -2364,11 +2395,11 @@ suite('Blocks', function () { const innerBlock = this.workspace .getTopBlocks(false)[0] .getChildren()[0]; - chai.assert.isTrue( + assert.isTrue( innerBlock.visuallyDisabled, 'block should have visuallyDisabled set because it is disabled', ); - chai.assert.isFalse( + assert.isFalse( innerBlock.isEnabled(), 'block should be marked disabled because enabled json property was set to false', ); @@ -2389,11 +2420,11 @@ suite('Blocks', function () { const innerBlock = this.workspace .getTopBlocks(false)[0] .getChildren()[0]; - chai.assert.isTrue( + assert.isTrue( innerBlock.visuallyDisabled, 'block should have visuallyDisabled set because it is disabled', ); - chai.assert.isFalse( + assert.isFalse( innerBlock.isEnabled(), 'block should be marked disabled because enabled xml property was set to false', ); @@ -2443,7 +2474,7 @@ suite('Blocks', function () { this.parent.setDisabledReason(true, 'test reason'); await Blockly.renderManagement.finishQueuedRenders(); for (const child of this.parent.getDescendants(false)) { - chai.assert.isTrue( + assert.isTrue( child.visuallyDisabled, `block ${child.id} should be visually disabled`, ); @@ -2456,38 +2487,26 @@ suite('Blocks', function () { await Blockly.renderManagement.finishQueuedRenders(); // child2 is disabled, rest should be enabled - chai.assert.isTrue( - this.child1.isEnabled(), - 'child1 should be enabled', - ); - chai.assert.isFalse( + assert.isTrue(this.child1.isEnabled(), 'child1 should be enabled'); + assert.isFalse( this.child1.visuallyDisabled, 'child1 should not be visually disabled', ); - chai.assert.isFalse( - this.child2.isEnabled(), - 'child2 should be disabled', - ); - chai.assert.isTrue( + assert.isFalse(this.child2.isEnabled(), 'child2 should be disabled'); + assert.isTrue( this.child2.visuallyDisabled, 'child2 should be visually disabled', ); - chai.assert.isTrue( - this.child3.isEnabled(), - 'child3 should be enabled', - ); - chai.assert.isFalse( + assert.isTrue(this.child3.isEnabled(), 'child3 should be enabled'); + assert.isFalse( this.child3.visuallyDisabled, 'child3 should not be visually disabled', ); - chai.assert.isTrue( - this.child4.isEnabled(), - 'child34 should be enabled', - ); - chai.assert.isFalse( + assert.isTrue(this.child4.isEnabled(), 'child34 should be enabled'); + assert.isFalse( this.child4.visuallyDisabled, 'child4 should not be visually disabled', ); @@ -2506,16 +2525,16 @@ suite('Blocks', function () { }); test('Set colour', function () { this.block.setColour('20'); - chai.assert.equal(this.block.getColour(), '#a5745b'); - chai.assert.equal(this.block.colour_, this.block.getColour()); - chai.assert.equal(this.block.hue_, '20'); + assert.equal(this.block.getColour(), '#a5745b'); + assert.equal(this.block.colour_, this.block.getColour()); + assert.equal(this.block.getHue(), '20'); }); test('Set style', function () { this.block.setStyle('styleOne'); - chai.assert.equal(this.block.getStyleName(), 'styleOne'); - chai.assert.isNull(this.block.hue_); + assert.equal(this.block.getStyleName(), 'styleOne'); + assert.isNull(this.block.getHue()); // Calling setStyle does not update the colour on a headless block. - chai.assert.equal(this.block.getColour(), '#000000'); + assert.equal(this.block.getColour(), '#000000'); }); }); suite('Rendered', function () { @@ -2544,23 +2563,23 @@ suite('Blocks', function () { }); test('Set colour hue', function () { this.block.setColour('20'); - chai.assert.equal(this.block.getStyleName(), 'auto_#a5745b'); - chai.assert.equal(this.block.getColour(), '#a5745b'); - chai.assert.equal(this.block.colour_, this.block.getColour()); - chai.assert.equal(this.block.hue_, '20'); + assert.equal(this.block.getStyleName(), 'auto_#a5745b'); + assert.equal(this.block.getColour(), '#a5745b'); + assert.equal(this.block.colour_, this.block.getColour()); + assert.equal(this.block.getHue(), '20'); }); test('Set colour hex', function () { this.block.setColour('#000000'); - chai.assert.equal(this.block.getStyleName(), 'auto_#000000'); - chai.assert.equal(this.block.getColour(), '#000000'); - chai.assert.equal(this.block.colour_, this.block.getColour()); - chai.assert.isNull(this.block.hue_); + assert.equal(this.block.getStyleName(), 'auto_#000000'); + assert.equal(this.block.getColour(), '#000000'); + assert.equal(this.block.colour_, this.block.getColour()); + assert.isNull(this.block.getHue()); }); test('Set style', function () { this.block.setStyle('styleOne'); - chai.assert.equal(this.block.getStyleName(), 'styleOne'); - chai.assert.equal(this.block.getColour(), '#000000'); - chai.assert.equal(this.block.colour_, this.block.getColour()); + assert.equal(this.block.getStyleName(), 'styleOne'); + assert.equal(this.block.getColour(), '#000000'); + assert.equal(this.block.colour_, this.block.getColour()); }); }); }); @@ -2689,7 +2708,7 @@ suite('Blocks', function () { Blockly.utils.xml.textToDom(t.xml), this.workspace, ); - chai.assert.equal(block.toString(), t.toString); + assert.equal(block.toString(), t.toString); }); }); }); @@ -2713,20 +2732,20 @@ suite('Blocks', function () { recordUndoDuringInit = eventUtils.getRecordUndo(); throw new Error(); }; - chai.assert.throws( + assert.throws( function () { this.workspace.newBlock('init_test_block'); }.bind(this), ); - chai.assert.isFalse( + assert.isFalse( recordUndoDuringInit, 'recordUndo should be false during block init function', ); - chai.assert.isTrue( + assert.isTrue( eventUtils.getRecordUndo(), 'recordUndo should be reset to true after init', ); - chai.assert.isTrue(initCalled, 'expected init function to be called'); + assert.isTrue(initCalled, 'expected init function to be called'); }); }); @@ -2742,12 +2761,12 @@ suite('Blocks', function () { }); test('Newline is converted to an end-row input', function () { const block = this.workspace.newBlock('end_row_test_block'); - chai.assert.equal(block.inputList[0].fieldRow[0].getValue(), 'Row1'); - chai.assert.isTrue( + assert.equal(block.inputList[0].fieldRow[0].getValue(), 'Row1'); + assert.isTrue( block.inputList[0] instanceof EndRowInput, 'newline should be converted to an end-row input', ); - chai.assert.equal(block.inputList[1].fieldRow[0].getValue(), 'Row2'); + assert.equal(block.inputList[1].fieldRow[0].getValue(), 'Row2'); }); }); }); diff --git a/tests/mocha/blocks/lists_test.js b/tests/mocha/blocks/lists_test.js index 07510513b07..0c7a92bf65a 100644 --- a/tests/mocha/blocks/lists_test.js +++ b/tests/mocha/blocks/lists_test.js @@ -4,13 +4,14 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {ConnectionType} from '../../../build/src/core/connection_type.js'; +import {assert} from '../../../node_modules/chai/chai.js'; +import {defineStatementBlock} from '../test_helpers/block_definitions.js'; import {runSerializationTestSuite} from '../test_helpers/serialization.js'; import { sharedTestSetup, sharedTestTeardown, } from '../test_helpers/setup_teardown.js'; -import {ConnectionType} from '../../../build/src/core/connection_type.js'; -import {defineStatementBlock} from '../test_helpers/block_definitions.js'; suite('Lists', function () { setup(function () { @@ -37,8 +38,8 @@ suite('Lists', function () { fields: {MODE: 'GET', WHERE: 'FIRST'}, }, assertBlockStructure: (block) => { - chai.assert.equal(block.type, 'lists_getIndex'); - chai.assert.exists(block.outputConnection); + assert.equal(block.type, 'lists_getIndex'); + assert.exists(block.outputConnection); }, }, { @@ -50,9 +51,9 @@ suite('Lists', function () { fields: {MODE: 'REMOVE', WHERE: 'FROM_START'}, }, assertBlockStructure: (block) => { - chai.assert.equal(block.type, 'lists_getIndex'); - chai.assert.isNotTrue(block.outputConnection); - chai.assert.isTrue( + assert.equal(block.type, 'lists_getIndex'); + assert.isNotTrue(block.outputConnection); + assert.isTrue( block.getInput('AT').type === ConnectionType.INPUT_VALUE, ); }, @@ -122,7 +123,7 @@ suite('Lists', function () { title: 'JSON not requiring mutations', json: serializedJson, assertBlockStructure: (block) => { - chai.assert.equal(block.type, serializedJson.type); + assert.equal(block.type, serializedJson.type); }, }, { diff --git a/tests/mocha/blocks/logic_ternary_test.js b/tests/mocha/blocks/logic_ternary_test.js index 2afa51f7aaf..71920935981 100644 --- a/tests/mocha/blocks/logic_ternary_test.js +++ b/tests/mocha/blocks/logic_ternary_test.js @@ -5,6 +5,7 @@ */ import * as eventUtils from '../../../build/src/core/events/utils.js'; +import {assert} from '../../../node_modules/chai/chai.js'; import {runSerializationTestSuite} from '../test_helpers/serialization.js'; import { sharedTestSetup, @@ -28,21 +29,21 @@ suite('Logic ternary', function () { * inline. */ function assertBlockStructure(block, inputsInline = false) { - chai.assert.equal(block.type, 'logic_ternary'); + assert.equal(block.type, 'logic_ternary'); const inputs = block.inputList; - chai.assert.exists(inputs, 'Has inputList'); - chai.assert.lengthOf(inputs, 3); + assert.exists(inputs, 'Has inputList'); + assert.lengthOf(inputs, 3); const ifInput = block.getInput('IF'); - chai.assert.exists(ifInput, 'Has "IF" input'); + assert.exists(ifInput, 'Has "IF" input'); const checkList = ifInput.connection.getCheck(); - chai.assert.equal(checkList.length, 1); - chai.assert.equal(checkList[0], 'Boolean'); - chai.assert.exists(block.onchangeWrapper_, 'Has onchange handler'); + assert.equal(checkList.length, 1); + assert.equal(checkList[0], 'Boolean'); + assert.exists(block.onchangeWrapper, 'Has onchange handler'); if (inputsInline) { - chai.assert.isTrue(block.inputsInline); + assert.isTrue(block.inputsInline); } else { // inputsInline can be undefined - chai.assert.isNotTrue(block.inputsInline); + assert.isNotTrue(block.inputsInline); } } @@ -90,20 +91,20 @@ suite('Logic ternary', function () { .getInput(parentInputName) .connection.connect(block.outputConnection); eventUtils.TEST_ONLY.fireNow(); // Force synchronous onchange() call. - chai.assert.equal( + assert.equal( block.getParent(), parent, 'Successful connection to parent', ); if (opt_thenInput) { - chai.assert.equal( + assert.equal( opt_thenInput.getParent(), block, 'Input THEN still connected after connecting parent', ); } if (opt_elseInput) { - chai.assert.equal( + assert.equal( opt_elseInput.getParent(), block, 'Input ELSE still connected after connecting parent', @@ -118,16 +119,16 @@ suite('Logic ternary', function () { ) { block.getInput('THEN').connection.connect(thenInput.outputConnection); eventUtils.TEST_ONLY.fireNow(); // Force synchronous onchange() call. - chai.assert.equal(thenInput.getParent(), block, 'THEN is connected'); + assert.equal(thenInput.getParent(), block, 'THEN is connected'); if (opt_parent) { - chai.assert.equal( + assert.equal( block.getParent(), opt_parent, 'Still connected to parent after connecting THEN', ); } if (opt_elseInput) { - chai.assert.equal( + assert.equal( opt_elseInput.getParent(), block, 'Input ELSE still connected after connecting THEN', @@ -142,16 +143,16 @@ suite('Logic ternary', function () { ) { block.getInput('ELSE').connection.connect(elseInput.outputConnection); eventUtils.TEST_ONLY.fireNow(); // Force synchronous onchange() call. - chai.assert.equal(elseInput.getParent(), block, 'ELSE is connected'); + assert.equal(elseInput.getParent(), block, 'ELSE is connected'); if (opt_parent) { - chai.assert.equal( + assert.equal( block.getParent(), opt_parent, 'Still connected to parent after connecting ELSE', ); } if (opt_thenInput) { - chai.assert.equal( + assert.equal( opt_thenInput.getParent(), block, 'Input THEN still connected after connecting ELSE', @@ -232,7 +233,7 @@ suite('Logic ternary', function () { // Adding mismatching number. connectThenInputAndCheckConnections(this.block, number, string); - chai.assert.equal( + assert.equal( this.block.getRootBlock(), this.block, 'Disconnected from parent', @@ -250,7 +251,7 @@ suite('Logic ternary', function () { // Adding mismatching number. connectElseInputAndCheckConnections(this.block, number, string); - chai.assert.equal( + assert.equal( this.block.getRootBlock(), this.block, 'Disconnected from parent', @@ -302,11 +303,7 @@ suite('Logic ternary', function () { null, string, ); - chai.assert.equal( - number.getRootBlock(), - number, - 'Input THEN disconnected', - ); + assert.equal(number.getRootBlock(), number, 'Input THEN disconnected'); }); test('Mismatch with else causes break with else', function () { const string = this.workspace.newBlock('text'); @@ -316,11 +313,7 @@ suite('Logic ternary', function () { const parent = this.workspace.newBlock('text_trim'); connectParentAndCheckConnections(this.block, parent, 'TEXT', string); - chai.assert.equal( - number.getRootBlock(), - number, - 'Input ELSE disconnected', - ); + assert.equal(number.getRootBlock(), number, 'Input ELSE disconnected'); }); }); }); diff --git a/tests/mocha/blocks/loops_test.js b/tests/mocha/blocks/loops_test.js index 3bbfdac1084..f8d74916c29 100644 --- a/tests/mocha/blocks/loops_test.js +++ b/tests/mocha/blocks/loops_test.js @@ -5,6 +5,7 @@ */ import * as Blockly from '../../../build/src/core/blockly.js'; +import {assert} from '../../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -27,7 +28,7 @@ suite('Loops', function () { this.workspace, ); this.clock.runAll(); - chai.assert.isFalse( + assert.isFalse( breakBlock.isEnabled(), 'Expected the break block to be disabled', ); @@ -46,7 +47,7 @@ suite('Loops', function () { .getInput('DO') .connection.connect(breakBlock.previousConnection); this.clock.runAll(); - chai.assert.isTrue( + assert.isTrue( breakBlock.isEnabled(), 'Expected the break block to be enabled', ); diff --git a/tests/mocha/blocks/procedures_test.js b/tests/mocha/blocks/procedures_test.js index 109d3b2d4eb..4b20662cf93 100644 --- a/tests/mocha/blocks/procedures_test.js +++ b/tests/mocha/blocks/procedures_test.js @@ -5,11 +5,13 @@ */ import * as Blockly from '../../../build/src/core/blockly.js'; +import {assert} from '../../../node_modules/chai/chai.js'; +import {defineRowBlock} from '../test_helpers/block_definitions.js'; import { assertCallBlockStructure, assertDefBlockStructure, - createProcDefBlock, createProcCallBlock, + createProcDefBlock, MockProcedureModel, } from '../test_helpers/procedures.js'; import {runSerializationTestSuite} from '../test_helpers/serialization.js'; @@ -19,7 +21,6 @@ import { sharedTestTeardown, workspaceTeardown, } from '../test_helpers/setup_teardown.js'; -import {defineRowBlock} from '../test_helpers/block_definitions.js'; suite('Procedures', function () { setup(function () { @@ -45,7 +46,7 @@ suite('Procedures', function () { defBlock.setFieldValue('new name', 'NAME'); - chai.assert.equal( + assert.equal( callBlock.getFieldValue('NAME'), 'new name', 'Expected the procedure block to be renamed', @@ -71,12 +72,12 @@ suite('Procedures', function () { defBlockB.setFieldValue('procA', 'NAME'); - chai.assert.notEqual( + assert.notEqual( defBlockB.getFieldValue('NAME'), 'procA', 'Expected the procedure def block to have a legal name', ); - chai.assert.notEqual( + assert.notEqual( callBlockB.getFieldValue('NAME'), 'procA', 'Expected the procedure call block to have a legal name', @@ -112,7 +113,7 @@ suite('Procedures', function () { .getWorkspace() .getTopBlocks(true)[0] .getFieldValue('NAME'); - chai.assert.notEqual( + assert.notEqual( newFlyoutParamName, origFlyoutParamName, 'Expected the flyout param to have updated to not conflict', @@ -133,11 +134,11 @@ suite('Procedures', function () { .connection.connect(paramBlock.previousConnection); this.clock.runAll(); - chai.assert.isNotNull( + assert.isNotNull( defBlock.getField('PARAMS'), 'Expected the params field to exist', ); - chai.assert.isTrue( + assert.isTrue( defBlock.getFieldValue('PARAMS').includes('param1'), 'Expected the params field to contain the name of the new param', ); @@ -158,11 +159,11 @@ suite('Procedures', function () { .connection.connect(paramBlock.previousConnection); this.clock.runAll(); - chai.assert.isNotNull( + assert.isNotNull( callBlock.getInput('ARG0'), 'Expected the param input to exist', ); - chai.assert.equal( + assert.equal( callBlock.getFieldValue('ARGNAME0'), 'param1', 'Expected the params field to match the name of the new param', @@ -185,7 +186,7 @@ suite('Procedures', function () { this.workspace.undo(); - chai.assert.isFalse( + assert.isFalse( defBlock.getFieldValue('PARAMS').includes('param1'), 'Expected the params field to not contain the name of the new param', ); @@ -211,11 +212,11 @@ suite('Procedures', function () { this.workspace.undo(); this.workspace.undo(/* redo= */ true); - chai.assert.isNotNull( + assert.isNotNull( defBlock.getField('PARAMS'), 'Expected the params field to exist', ); - chai.assert.isTrue( + assert.isTrue( defBlock.getFieldValue('PARAMS').includes('param1'), 'Expected the params field to contain the name of the new param', ); @@ -241,7 +242,7 @@ suite('Procedures', function () { paramBlock.checkAndDelete(); this.clock.runAll(); - chai.assert.isFalse( + assert.isFalse( defBlock.getFieldValue('PARAMS').includes('param1'), 'Expected the params field to not contain the name of the new param', ); @@ -265,7 +266,7 @@ suite('Procedures', function () { paramBlock.checkAndDelete(); this.clock.runAll(); - chai.assert.isNull( + assert.isNull( callBlock.getInput('ARG0'), 'Expected the param input to not exist', ); @@ -289,7 +290,7 @@ suite('Procedures', function () { this.workspace.undo(); - chai.assert.isTrue( + assert.isTrue( defBlock.getFieldValue('PARAMS').includes('param1'), 'Expected the params field to contain the name of the new param', ); @@ -317,7 +318,7 @@ suite('Procedures', function () { this.workspace.undo(); this.workspace.undo(/* redo= */ true); - chai.assert.isFalse( + assert.isFalse( defBlock.getFieldValue('PARAMS').includes('param1'), 'Expected the params field to not contain the name of the new param', ); @@ -343,11 +344,11 @@ suite('Procedures', function () { paramBlock.setFieldValue('new name', 'NAME'); this.clock.runAll(); - chai.assert.isNotNull( + assert.isNotNull( defBlock.getField('PARAMS'), 'Expected the params field to exist', ); - chai.assert.isTrue( + assert.isTrue( defBlock.getFieldValue('PARAMS').includes('new name'), 'Expected the params field to contain the new name of the param', ); @@ -373,11 +374,11 @@ suite('Procedures', function () { paramBlock1.setFieldValue('new name', 'NAME'); this.clock.runAll(); - chai.assert.isNotNull( + assert.isNotNull( defBlock.getField('PARAMS'), 'Expected the params field to exist', ); - chai.assert.isTrue( + assert.isTrue( defBlock.getFieldValue('PARAMS').includes('new name'), 'Expected the params field to contain the new name of the param', ); @@ -401,11 +402,11 @@ suite('Procedures', function () { paramBlock.setFieldValue('new name', 'NAME'); this.clock.runAll(); - chai.assert.isNotNull( + assert.isNotNull( callBlock.getInput('ARG0'), 'Expected the param input to exist', ); - chai.assert.equal( + assert.equal( callBlock.getFieldValue('ARGNAME0'), 'new name', 'Expected the params field to match the name of the new param', @@ -430,7 +431,7 @@ suite('Procedures', function () { paramBlock.setFieldValue('param2', 'NAME'); this.clock.runAll(); - chai.assert.isNotNull( + assert.isNotNull( this.workspace.getVariable('param1', ''), 'Expected the old variable to continue to exist', ); @@ -454,11 +455,11 @@ suite('Procedures', function () { const variable = this.workspace.getVariable('param1', ''); this.workspace.renameVariableById(variable.getId(), 'new name'); - chai.assert.isNotNull( + assert.isNotNull( defBlock.getField('PARAMS'), 'Expected the params field to exist', ); - chai.assert.isTrue( + assert.isTrue( defBlock.getFieldValue('PARAMS').includes('new name'), 'Expected the params field to contain the new name of the param', ); @@ -481,7 +482,7 @@ suite('Procedures', function () { const variable = this.workspace.getVariable('param1', ''); this.workspace.renameVariableById(variable.getId(), 'new name'); - chai.assert.equal( + assert.equal( paramBlock.getFieldValue('NAME'), 'new name', 'Expected the params field to contain the new name of the param', @@ -507,11 +508,11 @@ suite('Procedures', function () { const variable = this.workspace.getVariable('param1', ''); this.workspace.renameVariableById(variable.getId(), 'new name'); - chai.assert.isNotNull( + assert.isNotNull( callBlock.getInput('ARG0'), 'Expected the param input to exist', ); - chai.assert.equal( + assert.equal( callBlock.getFieldValue('ARGNAME0'), 'new name', 'Expected the params field to match the name of the new param', @@ -536,11 +537,11 @@ suite('Procedures', function () { const variable = this.workspace.getVariable('param1', ''); this.workspace.renameVariableById(variable.getId(), 'preCreatedVar'); - chai.assert.isNotNull( + assert.isNotNull( defBlock.getField('PARAMS'), 'Expected the params field to exist', ); - chai.assert.isTrue( + assert.isTrue( defBlock.getFieldValue('PARAMS').includes('preCreatedVar'), 'Expected the params field to contain the new name of the param', ); @@ -563,7 +564,7 @@ suite('Procedures', function () { const variable = this.workspace.getVariable('param1', ''); this.workspace.renameVariableById(variable.getId(), 'preCreatedVar'); - chai.assert.equal( + assert.equal( paramBlock.getFieldValue('NAME'), 'preCreatedVar', 'Expected the params field to contain the new name of the param', @@ -589,11 +590,11 @@ suite('Procedures', function () { const variable = this.workspace.getVariable('param1', ''); this.workspace.renameVariableById(variable.getId(), 'preCreatedVar'); - chai.assert.isNotNull( + assert.isNotNull( callBlock.getInput('ARG0'), 'Expected the param input to exist', ); - chai.assert.equal( + assert.equal( callBlock.getFieldValue('ARGNAME0'), 'preCreatedVar', 'Expected the params field to match the name of the new param', @@ -631,7 +632,7 @@ suite('Procedures', function () { this.workspace.undo(); this.clock.runAll(); - chai.assert.isTrue( + assert.isTrue( defBlock.getFieldValue('PARAMS').includes('param1'), 'Expected the params field to contain the old name of the param', ); @@ -662,7 +663,7 @@ suite('Procedures', function () { this.workspace.undo(); this.workspace.undo(/* redo= */ true); - chai.assert.isTrue( + assert.isTrue( defBlock.getFieldValue('PARAMS').includes('new'), 'Expected the params field to contain the new name of the param', ); @@ -696,11 +697,11 @@ suite('Procedures', function () { paramBlock2.nextConnection.connect(paramBlock1.previousConnection); this.clock.runAll(); - chai.assert.isNotNull( + assert.isNotNull( defBlock.getField('PARAMS'), 'Expected the params field to exist', ); - chai.assert.isTrue( + assert.isTrue( defBlock.getFieldValue('PARAMS').includes('param2, param1'), 'Expected the params field order to match the parameter order', ); @@ -733,20 +734,20 @@ suite('Procedures', function () { paramBlock2.nextConnection.connect(paramBlock1.previousConnection); this.clock.runAll(); - chai.assert.isNotNull( + assert.isNotNull( callBlock.getInput('ARG0'), 'Expected the param input to exist', ); - chai.assert.equal( + assert.equal( callBlock.getFieldValue('ARGNAME0'), 'param2', 'Expected the params field to match the name of the second param', ); - chai.assert.isNotNull( + assert.isNotNull( callBlock.getInput('ARG1'), 'Expected the param input to exist', ); - chai.assert.equal( + assert.equal( callBlock.getFieldValue('ARGNAME1'), 'param1', 'Expected the params field to match the name of the first param', @@ -789,12 +790,12 @@ suite('Procedures', function () { paramBlock2.nextConnection.connect(paramBlock1.previousConnection); this.clock.runAll(); - chai.assert.equal( + assert.equal( callBlock.getInputTargetBlock('ARG0'), block2, 'Expected the second block to be in the first slot', ); - chai.assert.equal( + assert.equal( callBlock.getInputTargetBlock('ARG1'), block1, 'Expected the first block to be in the second slot', @@ -814,7 +815,7 @@ suite('Procedures', function () { defBlock.setDisabledReason(true, 'MANUALLY_DISABLED'); this.clock.runAll(); - chai.assert.isFalse( + assert.isFalse( callBlock.isEnabled(), 'Expected the caller block to be disabled', ); @@ -831,7 +832,7 @@ suite('Procedures', function () { defBlock.setDisabledReason(true, 'test reason'); this.clock.runAll(); - chai.assert.isFalse( + assert.isFalse( callBlock.isEnabled(), 'Expected the caller block to be invalid', ); @@ -850,7 +851,7 @@ suite('Procedures', function () { defBlock.setDisabledReason(false, 'MANUALLY_DISABLED'); this.clock.runAll(); - chai.assert.isTrue( + assert.isTrue( callBlock.isEnabled(), 'Expected the caller block to be enabled', ); @@ -861,6 +862,7 @@ suite('Procedures', function () { 'if a procedure caller block was already disabled before ' + 'its definition was disabled, it is not reenabled', function () { + this.workspace.options.disable = true; const defBlock = createProcDefBlock(this.workspace); const callBlock = createProcCallBlock(this.workspace); this.clock.runAll(); @@ -872,7 +874,7 @@ suite('Procedures', function () { defBlock.setDisabledReason(false, 'MANUALLY_DISABLED'); this.clock.runAll(); - chai.assert.isFalse( + assert.isFalse( callBlock.isEnabled(), 'Expected the caller block to continue to be disabled', ); @@ -887,7 +889,7 @@ suite('Procedures', function () { this.workspace, ); this.clock.runAll(); - chai.assert.isFalse( + assert.isFalse( ifreturnBlock.isEnabled(), 'Expected the ifreturn block to be invalid', ); @@ -903,7 +905,7 @@ suite('Procedures', function () { .getInput('STACK') .connection.connect(ifreturnBlock.previousConnection); this.clock.runAll(); - chai.assert.isTrue( + assert.isTrue( ifreturnBlock.isEnabled(), 'Expected the ifreturn block to be valid', ); @@ -923,11 +925,11 @@ suite('Procedures', function () { defBlock.dispose(); this.clock.runAll(); - chai.assert.isTrue( + assert.isTrue( callBlock1.disposed, 'Expected the first caller to be disposed', ); - chai.assert.isTrue( + assert.isTrue( callBlock2.disposed, 'Expected the second caller to be disposed', ); @@ -1233,7 +1235,7 @@ suite('Procedures', function () { const options = []; def.customContextMenu(options); - chai.assert.isTrue( + assert.isTrue( options[0].text.includes('test name'), 'Expected the context menu to have an option to create the caller', ); @@ -1267,11 +1269,11 @@ suite('Procedures', function () { const options = []; def.customContextMenu(options); - chai.assert.isTrue( + assert.isTrue( options[1].text.includes('testParam1'), 'Expected the context menu to have an option to create the first param', ); - chai.assert.isTrue( + assert.isTrue( options[2].text.includes('testParam2'), 'Expected the context menu to have an option to create the second param', ); @@ -1286,13 +1288,13 @@ suite('Procedures', function () { returnBlock.setFieldValue('return', 'NAME'); const allProcedures = Blockly.Procedures.allProcedures(this.workspace); - chai.assert.lengthOf(allProcedures, 2); + assert.lengthOf(allProcedures, 2); - chai.assert.lengthOf(allProcedures[0], 1); - chai.assert.equal(allProcedures[0][0][0], 'no return'); + assert.lengthOf(allProcedures[0], 1); + assert.equal(allProcedures[0][0][0], 'no return'); - chai.assert.lengthOf(allProcedures[1], 1); - chai.assert.equal(allProcedures[1][0][0], 'return'); + assert.lengthOf(allProcedures[1], 1); + assert.equal(allProcedures[1][0][0], 'return'); }); test('Multiple Blocks', function () { @@ -1305,26 +1307,26 @@ suite('Procedures', function () { const _ = this.workspace.newBlock('controls_if'); const allProcedures = Blockly.Procedures.allProcedures(this.workspace); - chai.assert.lengthOf(allProcedures, 2); + assert.lengthOf(allProcedures, 2); - chai.assert.lengthOf(allProcedures[0], 1); - chai.assert.equal(allProcedures[0][0][0], 'no return'); + assert.lengthOf(allProcedures[0], 1); + assert.equal(allProcedures[0][0][0], 'no return'); - chai.assert.lengthOf(allProcedures[1], 2); - chai.assert.equal(allProcedures[1][0][0], 'return'); - chai.assert.equal(allProcedures[1][1][0], 'return2'); + assert.lengthOf(allProcedures[1], 2); + assert.equal(allProcedures[1][0][0], 'return'); + assert.equal(allProcedures[1][1][0], 'return2'); }); test('No Procedures', function () { const _ = this.workspace.newBlock('controls_if'); const allProcedures = Blockly.Procedures.allProcedures(this.workspace); - chai.assert.lengthOf(allProcedures, 2); - chai.assert.lengthOf( + assert.lengthOf(allProcedures, 2); + assert.lengthOf( allProcedures[0], 0, 'No procedures_defnoreturn blocks expected', ); - chai.assert.lengthOf( + assert.lengthOf( allProcedures[1], 0, 'No procedures_defreturn blocks expected', @@ -1334,21 +1336,19 @@ suite('Procedures', function () { suite('isNameUsed', function () { test('returns false if no blocks or models exists', function () { - chai.assert.isFalse( + assert.isFalse( Blockly.Procedures.isNameUsed('proc name', this.workspace), ); }); test('returns true if an associated block exists', function () { createProcDefBlock(this.workspace, false, [], 'proc name'); - chai.assert.isTrue( - Blockly.Procedures.isNameUsed('proc name', this.workspace), - ); + assert.isTrue(Blockly.Procedures.isNameUsed('proc name', this.workspace)); }); test('return false if an associated block does not exist', function () { createProcDefBlock(this.workspace, false, [], 'proc name'); - chai.assert.isFalse( + assert.isFalse( Blockly.Procedures.isNameUsed('other proc name', this.workspace), ); }); @@ -1357,16 +1357,14 @@ suite('Procedures', function () { this.workspace .getProcedureMap() .add(new MockProcedureModel().setName('proc name')); - chai.assert.isTrue( - Blockly.Procedures.isNameUsed('proc name', this.workspace), - ); + assert.isTrue(Blockly.Procedures.isNameUsed('proc name', this.workspace)); }); test('returns false if an associated procedure model exists', function () { this.workspace .getProcedureMap() .add(new MockProcedureModel().setName('proc name')); - chai.assert.isFalse( + assert.isFalse( Blockly.Procedures.isNameUsed('other proc name', this.workspace), ); }); @@ -1381,20 +1379,20 @@ suite('Procedures', function () { ) { const allProcedures = Blockly.Procedures.allProcedures(workspace); const defNoReturnBlocks = allProcedures[0]; - chai.assert.lengthOf( + assert.lengthOf( defNoReturnBlocks, noReturnNames.length, `Expected the number of no return blocks to be ${noReturnNames.length}`, ); for (let i = 0; i < noReturnNames.length; i++) { const expectedName = noReturnNames[i]; - chai.assert.equal(defNoReturnBlocks[i][0], expectedName); + assert.equal(defNoReturnBlocks[i][0], expectedName); if (hasCallers) { const callers = Blockly.Procedures.getCallers( expectedName, workspace, ); - chai.assert.lengthOf( + assert.lengthOf( callers, 1, `Expected there to be one caller of the ${expectedName} block`, @@ -1402,20 +1400,20 @@ suite('Procedures', function () { } } const defReturnBlocks = allProcedures[1]; - chai.assert.lengthOf( + assert.lengthOf( defReturnBlocks, returnNames.length, `Expected the number of return blocks to be ${returnNames.length}`, ); for (let i = 0; i < returnNames.length; i++) { const expectedName = returnNames[i]; - chai.assert.equal(defReturnBlocks[i][0], expectedName); + assert.equal(defReturnBlocks[i][0], expectedName); if (hasCallers) { const callers = Blockly.Procedures.getCallers( expectedName, workspace, ); - chai.assert.lengthOf( + assert.lengthOf( callers, 1, `Expected there to be one caller of the ${expectedName} block`, @@ -1429,7 +1427,7 @@ suite('Procedures', function () { expectedCount *= 2; } const blocks = workspace.getAllBlocks(false); - chai.assert.lengthOf(blocks, expectedCount); + assert.lengthOf(blocks, expectedCount); } suite('no name renamed to unnamed', function () { @@ -1532,7 +1530,7 @@ suite('Procedures', function () { // Do not require procedures to be the built-in procedures. const defBlock = this.workspace.newBlock('new_proc'); const def = Blockly.Procedures.getDefinition('test', this.workspace); - chai.assert.equal(def, defBlock); + assert.equal(def, defBlock); }); test('Stacked procedures', function () { @@ -1542,7 +1540,7 @@ suite('Procedures', function () { blockB.name = 'b'; blockA.nextConnection.connect(blockB.previousConnection); const def = Blockly.Procedures.getDefinition('b', this.workspace); - chai.assert.equal(def, blockB); + assert.equal(def, blockB); }); }); @@ -1612,8 +1610,8 @@ suite('Procedures', function () { this.defBlock.getFieldValue('NAME') + '2', 'NAME', ); - chai.assert.equal(this.defBlock.getFieldValue('NAME'), 'proc name2'); - chai.assert.equal(this.callBlock.getFieldValue('NAME'), 'proc name2'); + assert.equal(this.defBlock.getFieldValue('NAME'), 'proc name2'); + assert.equal(this.callBlock.getFieldValue('NAME'), 'proc name2'); }); test('Simple, Input', function () { const defInput = this.defBlock.getField('NAME'); @@ -1624,9 +1622,9 @@ suite('Procedures', function () { ); defInput.htmlInput_.value = 'proc name2'; - defInput.onHtmlInputChange_(null); - chai.assert.equal(this.defBlock.getFieldValue('NAME'), 'proc name2'); - chai.assert.equal(this.callBlock.getFieldValue('NAME'), 'proc name2'); + defInput.onHtmlInputChange(null); + assert.equal(this.defBlock.getFieldValue('NAME'), 'proc name2'); + assert.equal(this.callBlock.getFieldValue('NAME'), 'proc name2'); }); test('lower -> CAPS', function () { const defInput = this.defBlock.getField('NAME'); @@ -1637,9 +1635,9 @@ suite('Procedures', function () { ); defInput.htmlInput_.value = 'PROC NAME'; - defInput.onHtmlInputChange_(null); - chai.assert.equal(this.defBlock.getFieldValue('NAME'), 'PROC NAME'); - chai.assert.equal(this.callBlock.getFieldValue('NAME'), 'PROC NAME'); + defInput.onHtmlInputChange(null); + assert.equal(this.defBlock.getFieldValue('NAME'), 'PROC NAME'); + assert.equal(this.callBlock.getFieldValue('NAME'), 'PROC NAME'); }); test('CAPS -> lower', function () { this.defBlock.setFieldValue('PROC NAME', 'NAME'); @@ -1652,9 +1650,9 @@ suite('Procedures', function () { ); defInput.htmlInput_.value = 'proc name'; - defInput.onHtmlInputChange_(null); - chai.assert.equal(this.defBlock.getFieldValue('NAME'), 'proc name'); - chai.assert.equal(this.callBlock.getFieldValue('NAME'), 'proc name'); + defInput.onHtmlInputChange(null); + assert.equal(this.defBlock.getFieldValue('NAME'), 'proc name'); + assert.equal(this.callBlock.getFieldValue('NAME'), 'proc name'); }); test('Whitespace', function () { const defInput = this.defBlock.getField('NAME'); @@ -1665,9 +1663,9 @@ suite('Procedures', function () { ); defInput.htmlInput_.value = 'proc name '; - defInput.onHtmlInputChange_(null); - chai.assert.equal(this.defBlock.getFieldValue('NAME'), 'proc name'); - chai.assert.equal(this.callBlock.getFieldValue('NAME'), 'proc name'); + defInput.onHtmlInputChange(null); + assert.equal(this.defBlock.getFieldValue('NAME'), 'proc name'); + assert.equal(this.callBlock.getFieldValue('NAME'), 'proc name'); }); test('Whitespace then Text', function () { const defInput = this.defBlock.getField('NAME'); @@ -1678,14 +1676,11 @@ suite('Procedures', function () { ); defInput.htmlInput_.value = 'proc name '; - defInput.onHtmlInputChange_(null); + defInput.onHtmlInputChange(null); defInput.htmlInput_.value = 'proc name 2'; - defInput.onHtmlInputChange_(null); - chai.assert.equal(this.defBlock.getFieldValue('NAME'), 'proc name 2'); - chai.assert.equal( - this.callBlock.getFieldValue('NAME'), - 'proc name 2', - ); + defInput.onHtmlInputChange(null); + assert.equal(this.defBlock.getFieldValue('NAME'), 'proc name 2'); + assert.equal(this.callBlock.getFieldValue('NAME'), 'proc name 2'); }); test('Set Empty', function () { const defInput = this.defBlock.getField('NAME'); @@ -1696,12 +1691,12 @@ suite('Procedures', function () { ); defInput.htmlInput_.value = ''; - defInput.onHtmlInputChange_(null); - chai.assert.equal( + defInput.onHtmlInputChange(null); + assert.equal( this.defBlock.getFieldValue('NAME'), Blockly.Msg['UNNAMED_KEY'], ); - chai.assert.equal( + assert.equal( this.callBlock.getFieldValue('NAME'), Blockly.Msg['UNNAMED_KEY'], ); @@ -1715,14 +1710,14 @@ suite('Procedures', function () { ); defInput.htmlInput_.value = ''; - defInput.onHtmlInputChange_(null); + defInput.onHtmlInputChange(null); const newDefBlock = this.workspace.newBlock(testSuite.defType); newDefBlock.setFieldValue('new name', 'NAME'); - chai.assert.equal( + assert.equal( this.defBlock.getFieldValue('NAME'), Blockly.Msg['UNNAMED_KEY'], ); - chai.assert.equal( + assert.equal( this.callBlock.getFieldValue('NAME'), Blockly.Msg['UNNAMED_KEY'], ); @@ -1754,8 +1749,8 @@ suite('Procedures', function () { 'proc name', this.workspace, ); - chai.assert.equal(callers.length, 1); - chai.assert.equal(callers[0], this.callBlock); + assert.equal(callers.length, 1); + assert.equal(callers[0], this.callBlock); }); test('Multiple Callers', function () { const caller2 = this.workspace.newBlock(testSuite.callType); @@ -1767,10 +1762,10 @@ suite('Procedures', function () { 'proc name', this.workspace, ); - chai.assert.equal(callers.length, 3); - chai.assert.equal(callers[0], this.callBlock); - chai.assert.equal(callers[1], caller2); - chai.assert.equal(callers[2], caller3); + assert.equal(callers.length, 3); + assert.equal(callers[0], this.callBlock); + assert.equal(callers[1], caller2); + assert.equal(callers[2], caller3); }); test('Multiple Procedures', function () { const def2 = this.workspace.newBlock(testSuite.defType); @@ -1782,8 +1777,8 @@ suite('Procedures', function () { 'proc name', this.workspace, ); - chai.assert.equal(callers.length, 1); - chai.assert.equal(callers[0], this.callBlock); + assert.equal(callers.length, 1); + assert.equal(callers[0], this.callBlock); }); // This can occur if you: // 1) Create an uppercase definition and call block. @@ -1799,8 +1794,8 @@ suite('Procedures', function () { 'proc name', this.workspace, ); - chai.assert.equal(callers.length, 1); - chai.assert.equal(callers[0], this.callBlock); + assert.equal(callers.length, 1); + assert.equal(callers[0], this.callBlock); }); test('Multiple Workspaces', function () { const workspace = new Blockly.Workspace(); @@ -1814,12 +1809,12 @@ suite('Procedures', function () { 'proc name', this.workspace, ); - chai.assert.equal(callers.length, 1); - chai.assert.equal(callers[0], this.callBlock); + assert.equal(callers.length, 1); + assert.equal(callers[0], this.callBlock); callers = Blockly.Procedures.getCallers('proc name', workspace); - chai.assert.equal(callers.length, 1); - chai.assert.equal(callers[0], caller2); + assert.equal(callers.length, 1); + assert.equal(callers[0], caller2); } finally { workspaceTeardown.call(this, workspace); } @@ -1851,7 +1846,7 @@ suite('Procedures', function () { 'proc name', this.workspace, ); - chai.assert.equal(def, this.defBlock); + assert.equal(def, this.defBlock); }); test('Multiple Procedures', function () { const def2 = this.workspace.newBlock(testSuite.defType); @@ -1863,7 +1858,7 @@ suite('Procedures', function () { 'proc name', this.workspace, ); - chai.assert.equal(def, this.defBlock); + assert.equal(def, this.defBlock); }); test('Multiple Workspaces', function () { const workspace = new Blockly.Workspace(); @@ -1877,10 +1872,10 @@ suite('Procedures', function () { 'proc name', this.workspace, ); - chai.assert.equal(def, this.defBlock); + assert.equal(def, this.defBlock); def = Blockly.Procedures.getDefinition('proc name', workspace); - chai.assert.equal(def, def2); + assert.equal(def, def2); } finally { workspaceTeardown.call(this, workspace); } @@ -1925,11 +1920,11 @@ suite('Procedures', function () { if (testSuite.defType === 'procedures_defreturn') { test('Has Statements', function () { setStatementValue(this.workspace, this.defBlock, true); - chai.assert.isTrue(this.defBlock.hasStatements_); + assert.isTrue(this.defBlock.hasStatements_); }); test('Has No Statements', function () { setStatementValue(this.workspace, this.defBlock, false); - chai.assert.isFalse(this.defBlock.hasStatements_); + assert.isFalse(this.defBlock.hasStatements_); }); test('Saving Statements', function () { const blockXml = Blockly.utils.xml.textToDom( @@ -1944,14 +1939,14 @@ suite('Procedures', function () { this.workspace, ); setStatementValue(this.workspace, defBlock, false); - chai.assert.isNull(defBlock.getInput('STACK')); + assert.isNull(defBlock.getInput('STACK')); setStatementValue(this.workspace, defBlock, true); - chai.assert.isNotNull(defBlock.getInput('STACK')); + assert.isNotNull(defBlock.getInput('STACK')); const statementBlocks = defBlock.getChildren(); - chai.assert.equal(statementBlocks.length, 1); + assert.equal(statementBlocks.length, 1); const block = statementBlocks[0]; - chai.assert.equal(block.type, 'procedures_ifreturn'); - chai.assert.equal(block.id, 'test'); + assert.equal(block.type, 'procedures_ifreturn'); + assert.equal(block.id, 'test'); }); } }); @@ -1976,21 +1971,21 @@ suite('Procedures', function () { this.clock.runAll(); } function assertArgs(argArray) { - chai.assert.equal( + assert.equal( this.defBlock.getVars().length, argArray.length, 'Expected the def to have the right number of arguments', ); for (let i = 0; i < argArray.length; i++) { - chai.assert.equal(this.defBlock.getVars()[i], argArray[i]); + assert.equal(this.defBlock.getVars()[i], argArray[i]); } - chai.assert.equal( + assert.equal( this.callBlock.getVars().length, argArray.length, 'Expected the call to have the right number of arguments', ); for (let i = 0; i < argArray.length; i++) { - chai.assert.equal(this.callBlock.getVars()[i], argArray[i]); + assert.equal(this.callBlock.getVars()[i], argArray[i]); } } test('Simple Add Arg', async function () { @@ -2062,7 +2057,7 @@ suite('Procedures', function () { const statementInput = mutatorWorkspace .getTopBlocks()[0] .getInput('STATEMENT_INPUT'); - chai.assert.isNotNull(statementInput); + assert.isNotNull(statementInput); }); test('Has Statements', function () { this.defBlock.hasStatements_ = true; @@ -2076,7 +2071,7 @@ suite('Procedures', function () { .getTopBlocks()[0] .getField('STATEMENTS') .getValueBoolean(); - chai.assert.isTrue(statementValue); + assert.isTrue(statementValue); }); test('No Has Statements', function () { this.defBlock.hasStatements_ = false; @@ -2090,7 +2085,7 @@ suite('Procedures', function () { .getTopBlocks()[0] .getField('STATEMENTS') .getValueBoolean(); - chai.assert.isFalse(statementValue); + assert.isFalse(statementValue); }); } else { test('Has no Statement Input', function () { @@ -2103,7 +2098,7 @@ suite('Procedures', function () { const statementInput = mutatorWorkspace .getTopBlocks()[0] .getInput('STATEMENT_INPUT'); - chai.assert.isNull(statementInput); + assert.isNull(statementInput); }); } }); diff --git a/tests/mocha/blocks/variables_test.js b/tests/mocha/blocks/variables_test.js index caee68aeca7..d12691dd476 100644 --- a/tests/mocha/blocks/variables_test.js +++ b/tests/mocha/blocks/variables_test.js @@ -4,15 +4,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { - sharedTestSetup, - sharedTestTeardown, -} from '../test_helpers/setup_teardown.js'; import {nameUsedWithConflictingParam} from '../../../build/src/core/variables.js'; +import {assert} from '../../../node_modules/chai/chai.js'; import { MockParameterModelWithVar, MockProcedureModel, } from '../test_helpers/procedures.js'; +import { + sharedTestSetup, + sharedTestTeardown, +} from '../test_helpers/setup_teardown.js'; suite('Variables', function () { setup(function () { @@ -64,7 +65,7 @@ suite('Variables', function () { createTestVarBlock(this.workspace, '3'); const result = Blockly.Variables.allUsedVarModels(this.workspace); - chai.assert.equal( + assert.equal( result.length, 3, 'Expected three variables in the list of used variables', @@ -75,12 +76,12 @@ suite('Variables', function () { createTestVarBlock(this.workspace, '2'); const result = Blockly.Variables.allUsedVarModels(this.workspace); - chai.assert.equal( + assert.equal( result.length, 1, 'Expected one variable in the list of used variables', ); - chai.assert.equal( + assert.equal( result[0].getId(), '2', 'Expected variable with ID 2 in the list of used variables', @@ -94,12 +95,12 @@ suite('Variables', function () { const result = Blockly.Variables.allUsedVarModels(this.workspace); // Using the same variable multiple times should not change the number of // elements in the list. - chai.assert.equal( + assert.equal( result.length, 1, 'Expected one variable in the list of used variables', ); - chai.assert.equal( + assert.equal( result[0].getId(), '2', 'Expected variable with ID 2 in the list of used variables', @@ -108,7 +109,7 @@ suite('Variables', function () { test('All unused', function () { const result = Blockly.Variables.allUsedVarModels(this.workspace); - chai.assert.equal( + assert.equal( result.length, 0, 'Expected no variables in the list of used variables', @@ -125,9 +126,9 @@ suite('Variables', function () { const result2 = Blockly.Variables.getVariable(this.workspace, 'id2'); const result3 = Blockly.Variables.getVariable(this.workspace, 'id3'); - chai.assert.equal(var1, result1); - chai.assert.equal(var2, result2); - chai.assert.equal(var3, result3); + assert.equal(var1, result1); + assert.equal(var2, result2); + assert.equal(var3, result3); }); test('By name and type', function () { @@ -154,9 +155,9 @@ suite('Variables', function () { ); // Searching by name + type is correct. - chai.assert.equal(var1, result1); - chai.assert.equal(var2, result2); - chai.assert.equal(var3, result3); + assert.equal(var1, result1); + assert.equal(var2, result2); + assert.equal(var3, result3); }); test('Bad ID with name and type fallback', function () { @@ -183,9 +184,9 @@ suite('Variables', function () { ); // Searching by ID failed, but falling back onto name + type is correct. - chai.assert.equal(var1, result1); - chai.assert.equal(var2, result2); - chai.assert.equal(var3, result3); + assert.equal(var1, result1); + assert.equal(var2, result2); + assert.equal(var3, result3); }); }); @@ -214,7 +215,7 @@ suite('Variables', function () { this.workspace, ); - chai.assert.equal( + assert.equal( 'test name', nameUsedWithConflictingParam('x', 'y', this.workspace), 'Expected the name of the procedure with the conflicting ' + @@ -248,7 +249,7 @@ suite('Variables', function () { this.workspace, ); - chai.assert.isNull( + assert.isNull( nameUsedWithConflictingParam('x', 'y', this.workspace), 'Expected there to be no conflict', ); @@ -270,7 +271,7 @@ suite('Variables', function () { ), ); - chai.assert.equal( + assert.equal( 'test name', nameUsedWithConflictingParam('x', 'y', this.workspace), 'Expected the name of the procedure with the conflicting ' + @@ -299,7 +300,7 @@ suite('Variables', function () { ), ); - chai.assert.isNull( + assert.isNull( nameUsedWithConflictingParam('x', 'y', this.workspace), 'Expected there to be no conflict', ); diff --git a/tests/mocha/clipboard_test.js b/tests/mocha/clipboard_test.js index fb0c4188275..6526984213f 100644 --- a/tests/mocha/clipboard_test.js +++ b/tests/mocha/clipboard_test.js @@ -4,14 +4,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { - sharedTestSetup, - sharedTestTeardown, -} from './test_helpers/setup_teardown.js'; +import {assert} from '../../node_modules/chai/chai.js'; import { assertEventFired, createChangeListenerSpy, } from './test_helpers/events.js'; +import { + sharedTestSetup, + sharedTestTeardown, +} from './test_helpers/setup_teardown.js'; suite('Clipboard', function () { setup(function () { @@ -30,7 +31,7 @@ suite('Clipboard', function () { Blockly.clipboard.registry.register('test-paster', paster); Blockly.clipboard.paste({paster: 'test-paster'}, this.workspace); - chai.assert.isTrue(paster.paste.calledOnce); + assert.isTrue(paster.paste.calledOnce); Blockly.clipboard.registry.unregister('test-paster'); }); @@ -73,7 +74,7 @@ suite('Clipboard', function () { const data = block.toCopyData(); const newBlock = Blockly.clipboard.paste(data, this.workspace); - chai.assert.deepEqual( + assert.deepEqual( newBlock.getRelativeToSurfaceXY(), new Blockly.utils.Coordinate(66, 69), ); @@ -105,7 +106,7 @@ suite('Clipboard', function () { const data = this.workspace.getBlockById('sourceBlockId').toCopyData(); const newBlock = Blockly.clipboard.paste(data, this.workspace); - chai.assert.deepEqual( + assert.deepEqual( newBlock.getRelativeToSurfaceXY(), new Blockly.utils.Coordinate(94, 125), ); @@ -126,7 +127,7 @@ suite('Clipboard', function () { const data = comment.toCopyData(); const newComment = Blockly.clipboard.paste(data, this.workspace); - chai.assert.deepEqual( + assert.deepEqual( newComment.getRelativeToSurfaceXY(), new Blockly.utils.Coordinate(60, 60), ); diff --git a/tests/mocha/comment_deserialization_test.js b/tests/mocha/comment_deserialization_test.js index 843453278e4..2517ed77982 100644 --- a/tests/mocha/comment_deserialization_test.js +++ b/tests/mocha/comment_deserialization_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -60,23 +61,23 @@ suite('Comment Deserialization', function () { icon.setBubbleVisible(true); // Check comment bubble size. const bubbleSize = icon.getBubbleSize(); - chai.assert.isNotNaN(bubbleSize.width); - chai.assert.isNotNaN(bubbleSize.height); - chai.assert.equal(icon.getText(), text); + assert.isNotNaN(bubbleSize.width); + assert.isNotNaN(bubbleSize.height); + assert.equal(icon.getText(), text); } test('Trashcan', function () { // Create block. this.block = createBlock(this.workspace); // Delete block. this.block.checkAndDelete(); - chai.assert.equal(this.workspace.getAllBlocks().length, 0); + assert.equal(this.workspace.getAllBlocks().length, 0); // Open trashcan. simulateClick(this.workspace.trashcan.svgGroup); // Place from trashcan. simulateClick( this.workspace.trashcan.flyout.svgGroup_.querySelector('.blocklyPath'), ); - chai.assert.equal(this.workspace.getAllBlocks().length, 1); + assert.equal(this.workspace.getAllBlocks().length, 1); // Check comment. assertComment(this.workspace, 'test text'); }); @@ -85,10 +86,10 @@ suite('Comment Deserialization', function () { this.block = createBlock(this.workspace); // Delete block. this.block.checkAndDelete(); - chai.assert.equal(this.workspace.getAllBlocks().length, 0); + assert.equal(this.workspace.getAllBlocks().length, 0); // Undo. this.workspace.undo(false); - chai.assert.equal(this.workspace.getAllBlocks().length, 1); + assert.equal(this.workspace.getAllBlocks().length, 1); // Check comment. assertComment(this.workspace, 'test text'); }); @@ -98,11 +99,11 @@ suite('Comment Deserialization', function () { // Undo & undo. this.workspace.undo(false); this.workspace.undo(false); - chai.assert.equal(this.workspace.getAllBlocks().length, 0); + assert.equal(this.workspace.getAllBlocks().length, 0); // Redo & redo. this.workspace.undo(true); this.workspace.undo(true); - chai.assert.equal(this.workspace.getAllBlocks().length, 1); + assert.equal(this.workspace.getAllBlocks().length, 1); // Check comment. assertComment(this.workspace, 'test text'); }); @@ -113,7 +114,7 @@ suite('Comment Deserialization', function () { simulateClick( toolbox.getFlyout().svgGroup_.querySelector('.blocklyPath'), ); - chai.assert.equal(this.workspace.getAllBlocks().length, 1); + assert.equal(this.workspace.getAllBlocks().length, 1); // Check comment. assertComment(this.workspace, 'test toolbox text'); }); diff --git a/tests/mocha/comment_test.js b/tests/mocha/comment_test.js index 452f07493cf..79b3d7de662 100644 --- a/tests/mocha/comment_test.js +++ b/tests/mocha/comment_test.js @@ -4,8 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {EventType} from '../../build/src/core/events/type.js'; +import {assert} from '../../node_modules/chai/chai.js'; import {assertEventFired} from './test_helpers/events.js'; -import * as eventUtils from '../../build/src/core/events/utils.js'; import { sharedTestSetup, sharedTestTeardown, @@ -40,21 +41,21 @@ suite('Comments', function () { }); function assertEditable(comment) { - chai.assert.isNotOk(comment.textBubble); - chai.assert.isOk(comment.textInputBubble); + assert.isOk(comment.textInputBubble); + assert.isTrue(comment.textInputBubble.isEditable()); } function assertNotEditable(comment) { - chai.assert.isNotOk(comment.textInputBubble); - chai.assert.isOk(comment.textBubble); + assert.isOk(comment.textInputBubble); + assert.isFalse(comment.textInputBubble.isEditable()); } test('Editable', async function () { await this.comment.setBubbleVisible(true); - chai.assert.isTrue(this.comment.bubbleIsVisible()); + assert.isTrue(this.comment.bubbleIsVisible()); assertEditable(this.comment); assertEventFired( this.eventsFireStub, Blockly.Events.BubbleOpen, - {bubbleType: 'comment', isOpen: true, type: eventUtils.BUBBLE_OPEN}, + {bubbleType: 'comment', isOpen: true, type: EventType.BUBBLE_OPEN}, this.workspace.id, this.block.id, ); @@ -64,12 +65,12 @@ suite('Comments', function () { await this.comment.setBubbleVisible(true); - chai.assert.isTrue(this.comment.bubbleIsVisible()); + assert.isTrue(this.comment.bubbleIsVisible()); assertNotEditable(this.comment); assertEventFired( this.eventsFireStub, Blockly.Events.BubbleOpen, - {bubbleType: 'comment', isOpen: true, type: eventUtils.BUBBLE_OPEN}, + {bubbleType: 'comment', isOpen: true, type: EventType.BUBBLE_OPEN}, this.workspace.id, this.block.id, ); @@ -80,12 +81,12 @@ suite('Comments', function () { await this.comment.updateEditable(); - chai.assert.isTrue(this.comment.bubbleIsVisible()); + assert.isTrue(this.comment.bubbleIsVisible()); assertNotEditable(this.comment); assertEventFired( this.eventsFireStub, Blockly.Events.BubbleOpen, - {bubbleType: 'comment', isOpen: true, type: eventUtils.BUBBLE_OPEN}, + {bubbleType: 'comment', isOpen: true, type: EventType.BUBBLE_OPEN}, this.workspace.id, this.block.id, ); @@ -98,12 +99,12 @@ suite('Comments', function () { editableStub.returns(true); await this.comment.updateEditable(); - chai.assert.isTrue(this.comment.bubbleIsVisible()); + assert.isTrue(this.comment.bubbleIsVisible()); assertEditable(this.comment); assertEventFired( this.eventsFireStub, Blockly.Events.BubbleOpen, - {bubbleType: 'comment', isOpen: true, type: eventUtils.BUBBLE_OPEN}, + {bubbleType: 'comment', isOpen: true, type: EventType.BUBBLE_OPEN}, this.workspace.id, this.block.id, ); @@ -115,8 +116,8 @@ suite('Comments', function () { }); function assertBubbleSize(comment, height, width) { const size = comment.getBubbleSize(); - chai.assert.equal(size.height, height); - chai.assert.equal(size.width, width); + assert.equal(size.height, height); + assert.equal(size.width, width); } function assertBubbleSizeDefault(comment) { assertBubbleSize(comment, 80, 160); diff --git a/tests/mocha/comment_view_test.js b/tests/mocha/comment_view_test.js index 6650848e51f..57a24742457 100644 --- a/tests/mocha/comment_view_test.js +++ b/tests/mocha/comment_view_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -28,11 +29,8 @@ suite('Workspace comment', function () { this.commentView.setText('test'); - chai.assert.isTrue( - spy.calledOnce, - 'Expected the spy to be called once', - ); - chai.assert.isTrue( + assert.isTrue(spy.calledOnce, 'Expected the spy to be called once'); + assert.isTrue( spy.calledWith('', 'test'), 'Expected the spy to be called with the given args', ); @@ -50,15 +48,15 @@ suite('Workspace comment', function () { this.commentView.setText('test'); - chai.assert.isTrue( + assert.isTrue( fake1.calledOnce, 'Expected the first listener to be called', ); - chai.assert.isTrue( + assert.isTrue( fake2.calledOnce, 'Expected the second listener to be called', ); - chai.assert.isTrue( + assert.isTrue( fake3.calledOnce, 'Expected the third listener to be called', ); @@ -74,11 +72,8 @@ suite('Workspace comment', function () { this.commentView.setSize(newSize); - chai.assert.isTrue( - spy.calledOnce, - 'Expected the spy to be called once', - ); - chai.assert.isTrue( + assert.isTrue(spy.calledOnce, 'Expected the spy to be called once'); + assert.isTrue( spy.calledWith(originalSize, newSize), 'Expected the spy to be called with the given args', ); @@ -97,15 +92,15 @@ suite('Workspace comment', function () { this.commentView.setSize(newSize); - chai.assert.isTrue( + assert.isTrue( fake1.calledOnce, 'Expected the first listener to be called', ); - chai.assert.isTrue( + assert.isTrue( fake2.calledOnce, 'Expected the second listener to be called', ); - chai.assert.isTrue( + assert.isTrue( fake3.calledOnce, 'Expected the third listener to be called', ); @@ -119,11 +114,8 @@ suite('Workspace comment', function () { this.commentView.setCollapsed(true); - chai.assert.isTrue( - spy.calledOnce, - 'Expected the spy to be called once', - ); - chai.assert.isTrue( + assert.isTrue(spy.calledOnce, 'Expected the spy to be called once'); + assert.isTrue( spy.calledWith(true), 'Expected the spy to be called with the given args', ); @@ -141,15 +133,15 @@ suite('Workspace comment', function () { this.commentView.setCollapsed(true); - chai.assert.isTrue( + assert.isTrue( fake1.calledOnce, 'Expected the first listener to be called', ); - chai.assert.isTrue( + assert.isTrue( fake2.calledOnce, 'Expected the second listener to be called', ); - chai.assert.isTrue( + assert.isTrue( fake3.calledOnce, 'Expected the third listener to be called', ); @@ -163,10 +155,7 @@ suite('Workspace comment', function () { this.commentView.dispose(); - chai.assert.isTrue( - spy.calledOnce, - 'Expected the spy to be called once', - ); + assert.isTrue(spy.calledOnce, 'Expected the spy to be called once'); }); test('dispose listeners can remove themselves without skipping others', function () { @@ -181,15 +170,15 @@ suite('Workspace comment', function () { this.commentView.dispose(); - chai.assert.isTrue( + assert.isTrue( fake1.calledOnce, 'Expected the first listener to be called', ); - chai.assert.isTrue( + assert.isTrue( fake2.calledOnce, 'Expected the second listener to be called', ); - chai.assert.isTrue( + assert.isTrue( fake3.calledOnce, 'Expected the third listener to be called', ); diff --git a/tests/mocha/connection_checker_test.js b/tests/mocha/connection_checker_test.js index 09797d6a772..f7aa33ba896 100644 --- a/tests/mocha/connection_checker_test.js +++ b/tests/mocha/connection_checker_test.js @@ -5,6 +5,7 @@ */ import {ConnectionType} from '../../build/src/core/connection_type.js'; +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -22,9 +23,9 @@ suite('Connection checker', function () { }); suite('Safety checks', function () { function assertReasonHelper(checker, one, two, reason) { - chai.assert.equal(checker.canConnectWithReason(one, two), reason); + assert.equal(checker.canConnectWithReason(one, two), reason); // Order should not matter. - chai.assert.equal(checker.canConnectWithReason(two, one), reason); + assert.equal(checker.canConnectWithReason(two, one), reason); } test('Target Null', function () { @@ -452,9 +453,9 @@ suite('Connection checker', function () { this.con2 = new Blockly.Connection({}, ConnectionType.NEXT_STATEMENT); }); function assertCheckTypes(checker, one, two) { - chai.assert.isTrue(checker.doTypeChecks(one, two)); + assert.isTrue(checker.doTypeChecks(one, two)); // Order should not matter. - chai.assert.isTrue(checker.doTypeChecks(one, two)); + assert.isTrue(checker.doTypeChecks(one, two)); } test('No Types', function () { assertCheckTypes(this.checker, this.con1, this.con2); @@ -481,7 +482,7 @@ suite('Connection checker', function () { test('No Compatible Types', function () { this.con1.setCheck('type1'); this.con2.setCheck('type2'); - chai.assert.isFalse(this.checker.doTypeChecks(this.con1, this.con2)); + assert.isFalse(this.checker.doTypeChecks(this.con1, this.con2)); }); }); suite('Dragging Checks', function () { @@ -509,7 +510,7 @@ suite('Connection checker', function () { test('Connect a stack', function () { // block C is not connected to block A; both are movable. - chai.assert.isTrue( + assert.isTrue( this.checker.doDragChecks( this.blockC.nextConnection, this.blockA.previousConnection, @@ -543,7 +544,7 @@ suite('Connection checker', function () { // Try to connect blockC into the input connection of blockA, replacing blockB. // This is allowed because shadow blocks can always be replaced, even though // they are unmovable. - chai.assert.isTrue( + assert.isTrue( this.checker.doDragChecks( this.blockC.previousConnection, this.blockA.nextConnection, @@ -556,7 +557,7 @@ suite('Connection checker', function () { test('Do not splice into unmovable stack', function () { // Try to connect blockC above blockB. It shouldn't work because B is not movable // and is already connected to A's nextConnection. - chai.assert.isFalse( + assert.isFalse( this.checker.doDragChecks( this.blockC.previousConnection, this.blockA.nextConnection, @@ -569,7 +570,7 @@ suite('Connection checker', function () { test('Connect to bottom of unmovable stack', function () { // Try to connect blockC below blockB. // This is allowed even though B is not movable because it is on B's nextConnection. - chai.assert.isTrue( + assert.isTrue( this.checker.doDragChecks( this.blockC.previousConnection, this.blockB.nextConnection, @@ -585,7 +586,7 @@ suite('Connection checker', function () { // Try to connect blockC above blockB. // This is allowed because we're not splicing into a stack. - chai.assert.isTrue( + assert.isTrue( this.checker.doDragChecks( this.blockC.nextConnection, this.blockB.previousConnection, @@ -620,7 +621,7 @@ suite('Connection checker', function () { // Try to connect C's output to A's input. Should fail because // A is already connected to B, which is unmovable. const inputConnection = this.blockA.inputList[0].connection; - chai.assert.isFalse( + assert.isFalse( this.checker.doDragChecks( this.blockC.outputConnection, inputConnection, @@ -635,7 +636,7 @@ suite('Connection checker', function () { this.blockC.setMovable(false); // Try to connect A's output to C's input. This is allowed. const inputConnection = this.blockC.inputList[0].connection; - chai.assert.isTrue( + assert.isTrue( this.checker.doDragChecks( this.blockA.outputConnection, inputConnection, @@ -651,7 +652,7 @@ suite('Connection checker', function () { // Try to connect C's input to B's output. Allowed because B is now unconnected. const inputConnection = this.blockC.inputList[0].connection; - chai.assert.isTrue( + assert.isTrue( this.checker.doDragChecks( inputConnection, this.blockB.outputConnection, diff --git a/tests/mocha/connection_db_test.js b/tests/mocha/connection_db_test.js index 9cf579f1b1d..e7f397d545f 100644 --- a/tests/mocha/connection_db_test.js +++ b/tests/mocha/connection_db_test.js @@ -5,6 +5,7 @@ */ import {ConnectionType} from '../../build/src/core/connection_type.js'; +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -18,7 +19,7 @@ suite('Connection Database', function () { this.assertOrder = function () { const length = this.database.connections.length; for (let i = 1; i < length; i++) { - chai.assert.isAtMost( + assert.isAtMost( this.database.connections[i - 1].y, this.database.connections[i].y, ); @@ -59,24 +60,19 @@ suite('Connection Database', function () { const y3b = {y: 3}; this.database.addConnection(y2, 2); - chai.assert.sameOrderedMembers(this.database.connections, [y2]); + assert.sameOrderedMembers(this.database.connections, [y2]); this.database.addConnection(y4, 4); - chai.assert.sameOrderedMembers(this.database.connections, [y2, y4]); + assert.sameOrderedMembers(this.database.connections, [y2, y4]); this.database.addConnection(y1, 1); - chai.assert.sameOrderedMembers(this.database.connections, [y1, y2, y4]); + assert.sameOrderedMembers(this.database.connections, [y1, y2, y4]); this.database.addConnection(y3a, 3); - chai.assert.sameOrderedMembers(this.database.connections, [ - y1, - y2, - y3a, - y4, - ]); + assert.sameOrderedMembers(this.database.connections, [y1, y2, y3a, y4]); this.database.addConnection(y3b, 3); - chai.assert.sameOrderedMembers(this.database.connections, [ + assert.sameOrderedMembers(this.database.connections, [ y1, y2, y3b, @@ -99,7 +95,7 @@ suite('Connection Database', function () { this.database.addConnection(y3b, 3); this.database.addConnection(y3a, 3); - chai.assert.sameOrderedMembers(this.database.connections, [ + assert.sameOrderedMembers(this.database.connections, [ y1, y2, y3a, @@ -109,7 +105,7 @@ suite('Connection Database', function () { ]); this.database.removeConnection(y2, 2); - chai.assert.sameOrderedMembers(this.database.connections, [ + assert.sameOrderedMembers(this.database.connections, [ y1, y3a, y3b, @@ -118,24 +114,19 @@ suite('Connection Database', function () { ]); this.database.removeConnection(y4, 4); - chai.assert.sameOrderedMembers(this.database.connections, [ - y1, - y3a, - y3b, - y3c, - ]); + assert.sameOrderedMembers(this.database.connections, [y1, y3a, y3b, y3c]); this.database.removeConnection(y1, 1); - chai.assert.sameOrderedMembers(this.database.connections, [y3a, y3b, y3c]); + assert.sameOrderedMembers(this.database.connections, [y3a, y3b, y3c]); this.database.removeConnection(y3a, 3); - chai.assert.sameOrderedMembers(this.database.connections, [y3b, y3c]); + assert.sameOrderedMembers(this.database.connections, [y3b, y3c]); this.database.removeConnection(y3c, 3); - chai.assert.sameOrderedMembers(this.database.connections, [y3b]); + assert.sameOrderedMembers(this.database.connections, [y3b]); this.database.removeConnection(y3b, 3); - chai.assert.isEmpty(this.database.connections); + assert.isEmpty(this.database.connections); }); suite('Get Neighbors', function () { test('Empty Database', function () { @@ -145,7 +136,7 @@ suite('Connection Database', function () { ConnectionType.NEXT_STATEMENT, new Blockly.ConnectionDB(), ); - chai.assert.isEmpty(this.database.getNeighbours(connection), 100); + assert.isEmpty(this.database.getNeighbours(connection), 100); }); test('Block At Top', function () { this.createSimpleTestConnections(); @@ -157,7 +148,7 @@ suite('Connection Database', function () { new Blockly.ConnectionDB(), ); const neighbors = this.database.getNeighbours(checkConnection, 4); - chai.assert.sameMembers(neighbors, this.database.connections.slice(0, 5)); + assert.sameMembers(neighbors, this.database.connections.slice(0, 5)); }); test('Block In Middle', function () { this.createSimpleTestConnections(); @@ -169,7 +160,7 @@ suite('Connection Database', function () { new Blockly.ConnectionDB(), ); const neighbors = this.database.getNeighbours(checkConnection, 2); - chai.assert.sameMembers(neighbors, this.database.connections.slice(2, 7)); + assert.sameMembers(neighbors, this.database.connections.slice(2, 7)); }); test('Block At End', function () { this.createSimpleTestConnections(); @@ -181,10 +172,7 @@ suite('Connection Database', function () { new Blockly.ConnectionDB(), ); const neighbors = this.database.getNeighbours(checkConnection, 4); - chai.assert.sameMembers( - neighbors, - this.database.connections.slice(5, 10), - ); + assert.sameMembers(neighbors, this.database.connections.slice(5, 10)); }); test('Out of Range X', function () { this.createSimpleTestConnections(); @@ -196,7 +184,7 @@ suite('Connection Database', function () { new Blockly.ConnectionDB(), ); const neighbors = this.database.getNeighbours(checkConnection, 4); - chai.assert.isEmpty(neighbors); + assert.isEmpty(neighbors); }); test('Out of Range Y', function () { this.createSimpleTestConnections(); @@ -208,7 +196,7 @@ suite('Connection Database', function () { new Blockly.ConnectionDB(), ); const neighbors = this.database.getNeighbours(checkConnection, 4); - chai.assert.isEmpty(neighbors); + assert.isEmpty(neighbors); }); test('Out of Range Diagonal', function () { this.createSimpleTestConnections(); @@ -220,7 +208,7 @@ suite('Connection Database', function () { new Blockly.ConnectionDB(), ); const neighbors = this.database.getNeighbours(checkConnection, 2); - chai.assert.isEmpty(neighbors); + assert.isEmpty(neighbors); }); }); suite('Ordering', function () { @@ -300,7 +288,7 @@ suite('Connection Database', function () { ConnectionType.NEXT_STATEMENT, new Blockly.ConnectionDB(), ); - chai.assert.isNull( + assert.isNull( this.database.searchForClosest(checkConnection, 100, {x: 0, y: 0}) .connection, ); @@ -319,7 +307,7 @@ suite('Connection Database', function () { ConnectionType.NEXT_STATEMENT, new Blockly.ConnectionDB(), ); - chai.assert.isNull( + assert.isNull( this.database.searchForClosest(checkConnection, 50, {x: 0, y: 0}) .connection, ); @@ -334,7 +322,7 @@ suite('Connection Database', function () { x: 0, y: 0, }).connection; - chai.assert.equal(last, closest); + assert.equal(last, closest); }); test('Many in Range', function () { this.createSimpleTestConnections(); @@ -346,7 +334,7 @@ suite('Connection Database', function () { x: 0, y: 0, }).connection; - chai.assert.equal(last, closest); + assert.equal(last, closest); }); test('No Y-Coord Priority', function () { const connection1 = this.createConnection( @@ -368,7 +356,7 @@ suite('Connection Database', function () { x: 0, y: 0, }).connection; - chai.assert.equal(connection2, closest); + assert.equal(connection2, closest); }); }); }); diff --git a/tests/mocha/connection_test.js b/tests/mocha/connection_test.js index afba4948cff..cefea1784e7 100644 --- a/tests/mocha/connection_test.js +++ b/tests/mocha/connection_test.js @@ -4,17 +4,18 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; +import { + defineRowBlock, + defineStackBlock, + defineStatementBlock, +} from './test_helpers/block_definitions.js'; import { createGenUidStubWithReturns, sharedTestSetup, sharedTestTeardown, workspaceTeardown, } from './test_helpers/setup_teardown.js'; -import { - defineRowBlock, - defineStatementBlock, - defineStackBlock, -} from './test_helpers/block_definitions.js'; suite('Connection', function () { setup(function () { @@ -39,19 +40,19 @@ suite('Connection', function () { suite('Set Shadow', function () { function assertBlockMatches(block, isShadow, opt_id) { - chai.assert.equal( + assert.equal( block.isShadow(), isShadow, `expected block ${block.id} to ${isShadow ? '' : 'not'} be a shadow`, ); if (opt_id) { - chai.assert.equal(block.id, opt_id); + assert.equal(block.id, opt_id); } } function assertInputHasBlock(parent, inputName, isShadow, opt_name) { const block = parent.getInputTargetBlock(inputName); - chai.assert.exists( + assert.exists( block, `expected block ${opt_name || ''} to be attached to ${inputName}`, ); @@ -60,7 +61,7 @@ suite('Connection', function () { function assertNextHasBlock(parent, isShadow, opt_name) { const block = parent.getNextBlock(); - chai.assert.exists( + assert.exists( block, `expected block ${opt_name || ''} to be attached to next connection`, ); @@ -69,7 +70,7 @@ suite('Connection', function () { function assertInputNotHasBlock(parent, inputName) { const block = parent.getInputTargetBlock(inputName); - chai.assert.notExists( + assert.notExists( block, `expected block ${ block && block.id @@ -79,7 +80,7 @@ suite('Connection', function () { function assertNextNotHasBlock(parent) { const block = parent.getNextBlock(); - chai.assert.notExists( + assert.notExists( block, `expected block ${ block && block.id @@ -92,8 +93,8 @@ suite('Connection', function () { addNextBlocks: true, }); const actualXml = Blockly.Xml.domToText(Blockly.Xml.blockToDom(block)); - chai.assert.deepEqual(actualJso, jso); - chai.assert.equal(actualXml, xmlText); + assert.deepEqual(actualJso, jso); + assert.equal(actualXml, xmlText); } const testSuites = [ @@ -1382,7 +1383,7 @@ suite('Connection', function () { suite('Invalid', function () { test('Attach to output', function () { const block = this.workspace.newBlock('row_block'); - chai.assert.throws(() => + assert.throws(() => block.outputConnection.setShadowDom( Blockly.utils.xml.textToDom(''), ), @@ -1391,7 +1392,7 @@ suite('Connection', function () { test('Attach to previous', function () { const block = this.workspace.newBlock('stack_block'); - chai.assert.throws(() => + assert.throws(() => block.previousConnection.setShadowDom( Blockly.utils.xml.textToDom(''), ), @@ -1400,7 +1401,7 @@ suite('Connection', function () { test('Missing output', function () { const block = this.workspace.newBlock('row_block'); - chai.assert.throws(() => + assert.throws(() => block.outputConnection.setShadowDom( Blockly.utils.xml.textToDom(''), ), @@ -1409,7 +1410,7 @@ suite('Connection', function () { test('Missing previous', function () { const block = this.workspace.newBlock('stack_block'); - chai.assert.throws(() => + assert.throws(() => block.previousConnection.setShadowDom( Blockly.utils.xml.textToDom(''), ), @@ -1418,7 +1419,7 @@ suite('Connection', function () { test('Invalid connection checks, output', function () { const block = this.workspace.newBlock('logic_operation'); - chai.assert.throws(() => + assert.throws(() => block .getInput('A') .connection.setShadowDom( @@ -1437,7 +1438,7 @@ suite('Connection', function () { }, ]); const block = this.workspace.newBlock('stack_checks_block'); - chai.assert.throws(() => + assert.throws(() => block.nextConnection.setShadowDom( Blockly.utils.xml.textToDom( '', @@ -2751,14 +2752,14 @@ suite('Connection', function () { suite('Invalid', function () { test('Attach to output', function () { const block = this.workspace.newBlock('row_block'); - chai.assert.throws(() => + assert.throws(() => block.outputConnection.setShadowState({'type': 'row_block'}), ); }); test('Attach to previous', function () { const block = this.workspace.newBlock('stack_block'); - chai.assert.throws(() => + assert.throws(() => block.previousConnection.setShadowState({ 'type': 'stack_block', }), @@ -2767,21 +2768,21 @@ suite('Connection', function () { test('Missing output', function () { const block = this.workspace.newBlock('row_block'); - chai.assert.throws(() => + assert.throws(() => block.outputConnection.setShadowState({'type': 'stack_block'}), ); }); test('Missing previous', function () { const block = this.workspace.newBlock('stack_block'); - chai.assert.throws(() => + assert.throws(() => block.previousConnection.setShadowState({'type': 'row_block'}), ); }); test('Invalid connection checks, output', function () { const block = this.workspace.newBlock('logic_operation'); - chai.assert.throws(() => + assert.throws(() => block .getInput('A') .connection.setShadowState({'type': 'math_number'}), @@ -2798,7 +2799,7 @@ suite('Connection', function () { }, ]); const block = this.workspace.newBlock('stack_checks_block'); - chai.assert.throws(() => + assert.throws(() => block.nextConnection.setShadowState({ 'type': 'stack_checks_block', }), @@ -2984,7 +2985,7 @@ suite('Connection', function () { // Used to make sure we don't get stray shadow blocks or anything. this.assertBlockCount = function (count) { - chai.assert.equal(this.workspace.getAllBlocks().length, count); + assert.equal(this.workspace.getAllBlocks().length, count); }; }); @@ -2997,9 +2998,7 @@ suite('Connection', function () { oldParent.getInput('INPUT').connection.connect(child.outputConnection); newParent.getInput('INPUT').connection.connect(child.outputConnection); - chai.assert.isFalse( - oldParent.getInput('INPUT').connection.isConnected(), - ); + assert.isFalse(oldParent.getInput('INPUT').connection.isConnected()); this.assertBlockCount(3); }); @@ -3011,9 +3010,7 @@ suite('Connection', function () { oldParent.getInput('NAME').connection.connect(child.previousConnection); newParent.getInput('NAME').connection.connect(child.previousConnection); - chai.assert.isFalse( - oldParent.getInput('NAME').connection.isConnected(), - ); + assert.isFalse(oldParent.getInput('NAME').connection.isConnected()); this.assertBlockCount(3); }); @@ -3025,7 +3022,7 @@ suite('Connection', function () { oldParent.nextConnection.connect(child.previousConnection); newParent.nextConnection.connect(child.previousConnection); - chai.assert.isFalse(oldParent.nextConnection.isConnected()); + assert.isFalse(oldParent.nextConnection.isConnected()); this.assertBlockCount(3); }); }); @@ -3036,11 +3033,11 @@ suite('Connection', function () { const child = this.workspace.newBlock('row_block'); const xml = Blockly.utils.xml.textToDom(''); newParent.getInput('INPUT').connection.setShadowDom(xml); - chai.assert.isTrue(newParent.getInputTargetBlock('INPUT').isShadow()); + assert.isTrue(newParent.getInputTargetBlock('INPUT').isShadow()); newParent.getInput('INPUT').connection.connect(child.outputConnection); - chai.assert.isFalse(newParent.getInputTargetBlock('INPUT').isShadow()); + assert.isFalse(newParent.getInputTargetBlock('INPUT').isShadow()); this.assertBlockCount(2); }); @@ -3049,11 +3046,11 @@ suite('Connection', function () { const child = this.workspace.newBlock('stack_block'); const xml = Blockly.utils.xml.textToDom(''); newParent.getInput('NAME').connection.setShadowDom(xml); - chai.assert.isTrue(newParent.getInputTargetBlock('NAME').isShadow()); + assert.isTrue(newParent.getInputTargetBlock('NAME').isShadow()); newParent.getInput('NAME').connection.connect(child.previousConnection); - chai.assert.isFalse(newParent.getInputTargetBlock('NAME').isShadow()); + assert.isFalse(newParent.getInputTargetBlock('NAME').isShadow()); this.assertBlockCount(2); }); @@ -3062,11 +3059,11 @@ suite('Connection', function () { const child = this.workspace.newBlock('stack_block'); const xml = Blockly.utils.xml.textToDom(''); newParent.nextConnection.setShadowDom(xml); - chai.assert.isTrue(newParent.getNextBlock().isShadow()); + assert.isTrue(newParent.getNextBlock().isShadow()); newParent.nextConnection.connect(child.previousConnection); - chai.assert.isFalse(newParent.getNextBlock().isShadow()); + assert.isFalse(newParent.getNextBlock().isShadow()); this.assertBlockCount(2); }); }); @@ -3083,8 +3080,8 @@ suite('Connection', function () { newParent.getInput('INPUT').connection.disconnect(); const target = newParent.getInputTargetBlock('INPUT'); - chai.assert.isTrue(target.isShadow()); - chai.assert.equal(target.getFieldValue('FIELD'), 'new'); + assert.isTrue(target.isShadow()); + assert.equal(target.getFieldValue('FIELD'), 'new'); this.assertBlockCount(3); }); @@ -3099,8 +3096,8 @@ suite('Connection', function () { newParent.getInput('NAME').connection.disconnect(); const target = newParent.getInputTargetBlock('NAME'); - chai.assert.isTrue(target.isShadow()); - chai.assert.equal(target.getFieldValue('FIELD'), 'new'); + assert.isTrue(target.isShadow()); + assert.equal(target.getFieldValue('FIELD'), 'new'); this.assertBlockCount(3); }); @@ -3115,8 +3112,8 @@ suite('Connection', function () { newParent.nextConnection.disconnect(); const target = newParent.getNextBlock(); - chai.assert.isTrue(target.isShadow()); - chai.assert.equal(target.getFieldValue('FIELD'), 'new'); + assert.isTrue(target.isShadow()); + assert.equal(target.getFieldValue('FIELD'), 'new'); this.assertBlockCount(3); }); }); @@ -3136,11 +3133,9 @@ suite('Connection', function () { .getInput('INPUT') .connection.connect(newChild.outputConnection); - chai.assert.isTrue( - parent.getInput('INPUT').connection.isConnected(), - ); - chai.assert.equal(parent.getInputTargetBlock('INPUT'), newChild); - chai.assert.isFalse(oldChild.outputConnection.isConnected()); + assert.isTrue(parent.getInput('INPUT').connection.isConnected()); + assert.equal(parent.getInputTargetBlock('INPUT'), newChild); + assert.isFalse(oldChild.outputConnection.isConnected()); }); test('All statements', function () { @@ -3155,11 +3150,9 @@ suite('Connection', function () { .getInput('INPUT') .connection.connect(newChild.outputConnection); - chai.assert.isTrue( - parent.getInput('INPUT').connection.isConnected(), - ); - chai.assert.equal(parent.getInputTargetBlock('INPUT'), newChild); - chai.assert.isFalse(oldChild.outputConnection.isConnected()); + assert.isTrue(parent.getInput('INPUT').connection.isConnected()); + assert.equal(parent.getInputTargetBlock('INPUT'), newChild); + assert.isFalse(oldChild.outputConnection.isConnected()); }); test('Bad checks', function () { @@ -3174,11 +3167,9 @@ suite('Connection', function () { .getInput('INPUT') .connection.connect(newChild.outputConnection); - chai.assert.isTrue( - parent.getInput('INPUT').connection.isConnected(), - ); - chai.assert.equal(parent.getInputTargetBlock('INPUT'), newChild); - chai.assert.isFalse(oldChild.outputConnection.isConnected()); + assert.isTrue(parent.getInput('INPUT').connection.isConnected()); + assert.equal(parent.getInputTargetBlock('INPUT'), newChild); + assert.isFalse(oldChild.outputConnection.isConnected()); }); test('Through different types', function () { @@ -3198,11 +3189,9 @@ suite('Connection', function () { .getInput('INPUT') .connection.connect(newChild.outputConnection); - chai.assert.isTrue( - parent.getInput('INPUT').connection.isConnected(), - ); - chai.assert.equal(parent.getInputTargetBlock('INPUT'), newChild); - chai.assert.isFalse(oldChild.outputConnection.isConnected()); + assert.isTrue(parent.getInput('INPUT').connection.isConnected()); + assert.equal(parent.getInputTargetBlock('INPUT'), newChild); + assert.isFalse(oldChild.outputConnection.isConnected()); }); }); @@ -3223,11 +3212,9 @@ suite('Connection', function () { .getInput('INPUT') .connection.connect(newChild.outputConnection); - chai.assert.isTrue( - parent.getInput('INPUT').connection.isConnected(), - ); - chai.assert.equal(parent.getInputTargetBlock('INPUT'), newChild); - chai.assert.isFalse(oldChild.outputConnection.isConnected()); + assert.isTrue(parent.getInput('INPUT').connection.isConnected()); + assert.equal(parent.getInputTargetBlock('INPUT'), newChild); + assert.isFalse(oldChild.outputConnection.isConnected()); }); test('Child blocks', function () { @@ -3253,11 +3240,9 @@ suite('Connection', function () { .getInput('INPUT') .connection.connect(newChild.outputConnection); - chai.assert.isTrue( - parent.getInput('INPUT').connection.isConnected(), - ); - chai.assert.equal(parent.getInputTargetBlock('INPUT'), newChild); - chai.assert.isFalse(oldChild.outputConnection.isConnected()); + assert.isTrue(parent.getInput('INPUT').connection.isConnected()); + assert.equal(parent.getInputTargetBlock('INPUT'), newChild); + assert.isFalse(oldChild.outputConnection.isConnected()); }); test('Spots filled', function () { @@ -3279,11 +3264,9 @@ suite('Connection', function () { .getInput('INPUT') .connection.connect(newChild.outputConnection); - chai.assert.isTrue( - parent.getInput('INPUT').connection.isConnected(), - ); - chai.assert.equal(parent.getInputTargetBlock('INPUT'), newChild); - chai.assert.isFalse(oldChild.outputConnection.isConnected()); + assert.isTrue(parent.getInput('INPUT').connection.isConnected()); + assert.equal(parent.getInputTargetBlock('INPUT'), newChild); + assert.isFalse(oldChild.outputConnection.isConnected()); }); }); @@ -3317,11 +3300,9 @@ suite('Connection', function () { .getInput('INPUT') .connection.connect(newChild.outputConnection); - chai.assert.isTrue( - parent.getInput('INPUT').connection.isConnected(), - ); - chai.assert.equal(parent.getInputTargetBlock('INPUT'), newChild); - chai.assert.isFalse(oldChild.outputConnection.isConnected()); + assert.isTrue(parent.getInput('INPUT').connection.isConnected()); + assert.equal(parent.getInputTargetBlock('INPUT'), newChild); + assert.isFalse(oldChild.outputConnection.isConnected()); }); test('Child blocks', function () { @@ -3361,11 +3342,9 @@ suite('Connection', function () { .getInput('INPUT') .connection.connect(newChild.outputConnection); - chai.assert.isTrue( - parent.getInput('INPUT').connection.isConnected(), - ); - chai.assert.equal(parent.getInputTargetBlock('INPUT'), newChild); - chai.assert.isFalse(oldChild.outputConnection.isConnected()); + assert.isTrue(parent.getInput('INPUT').connection.isConnected()); + assert.equal(parent.getInputTargetBlock('INPUT'), newChild); + assert.isFalse(oldChild.outputConnection.isConnected()); }); test('Spots filled', function () { @@ -3394,11 +3373,9 @@ suite('Connection', function () { .getInput('INPUT') .connection.connect(newChild.outputConnection); - chai.assert.isTrue( - parent.getInput('INPUT').connection.isConnected(), - ); - chai.assert.equal(parent.getInputTargetBlock('INPUT'), newChild); - chai.assert.isFalse(oldChild.outputConnection.isConnected()); + assert.isTrue(parent.getInput('INPUT').connection.isConnected()); + assert.equal(parent.getInputTargetBlock('INPUT'), newChild); + assert.isFalse(oldChild.outputConnection.isConnected()); }); }); }); @@ -3417,14 +3394,10 @@ suite('Connection', function () { .getInput('INPUT') .connection.connect(newChild.outputConnection); - chai.assert.isTrue( - parent.getInput('INPUT').connection.isConnected(), - ); - chai.assert.equal(parent.getInputTargetBlock('INPUT'), newChild); - chai.assert.isTrue( - newChild.getInput('INPUT').connection.isConnected(), - ); - chai.assert.equal(newChild.getInputTargetBlock('INPUT'), oldChild); + assert.isTrue(parent.getInput('INPUT').connection.isConnected()); + assert.equal(parent.getInputTargetBlock('INPUT'), newChild); + assert.isTrue(newChild.getInput('INPUT').connection.isConnected()); + assert.equal(newChild.getInputTargetBlock('INPUT'), oldChild); }); test('Shadows', function () { @@ -3447,14 +3420,10 @@ suite('Connection', function () { .getInput('INPUT') .connection.connect(newChild.outputConnection); - chai.assert.isTrue( - parent.getInput('INPUT').connection.isConnected(), - ); - chai.assert.equal(parent.getInputTargetBlock('INPUT'), newChild); - chai.assert.isTrue( - newChild.getInput('INPUT').connection.isConnected(), - ); - chai.assert.equal(newChild.getInputTargetBlock('INPUT'), oldChild); + assert.isTrue(parent.getInput('INPUT').connection.isConnected()); + assert.equal(parent.getInputTargetBlock('INPUT'), newChild); + assert.isTrue(newChild.getInput('INPUT').connection.isConnected()); + assert.equal(newChild.getInputTargetBlock('INPUT'), oldChild); }); }); }); @@ -3473,12 +3442,10 @@ suite('Connection', function () { .getInput('NAME') .connection.connect(newChild.previousConnection); - chai.assert.isTrue( - parent.getInput('NAME').connection.isConnected(), - ); - chai.assert.equal(parent.getInputTargetBlock('NAME'), newChild); - chai.assert.isTrue(newChild.nextConnection.isConnected()); - chai.assert.equal(newChild.getNextBlock(), oldChild); + assert.isTrue(parent.getInput('NAME').connection.isConnected()); + assert.equal(parent.getInputTargetBlock('NAME'), newChild); + assert.isTrue(newChild.nextConnection.isConnected()); + assert.equal(newChild.getNextBlock(), oldChild); this.assertBlockCount(3); }); @@ -3496,12 +3463,10 @@ suite('Connection', function () { .getInput('NAME') .connection.connect(newChild1.previousConnection); - chai.assert.isTrue( - parent.getInput('NAME').connection.isConnected(), - ); - chai.assert.equal(parent.getInputTargetBlock('NAME'), newChild1); - chai.assert.isTrue(newChild2.nextConnection.isConnected()); - chai.assert.equal(newChild2.getNextBlock(), oldChild); + assert.isTrue(parent.getInput('NAME').connection.isConnected()); + assert.equal(parent.getInputTargetBlock('NAME'), newChild1); + assert.isTrue(newChild2.nextConnection.isConnected()); + assert.equal(newChild2.getNextBlock(), oldChild); this.assertBlockCount(4); }); @@ -3521,12 +3486,10 @@ suite('Connection', function () { .getInput('NAME') .connection.connect(newChild.previousConnection); - chai.assert.isTrue( - parent.getInput('NAME').connection.isConnected(), - ); - chai.assert.equal(parent.getInputTargetBlock('NAME'), newChild); - chai.assert.isFalse(newChild.nextConnection.isConnected()); - chai.assert.isTrue(spy.calledOnce); + assert.isTrue(parent.getInput('NAME').connection.isConnected()); + assert.equal(parent.getInputTargetBlock('NAME'), newChild); + assert.isFalse(newChild.nextConnection.isConnected()); + assert.isTrue(spy.calledOnce); this.assertBlockCount(3); }); @@ -3546,11 +3509,9 @@ suite('Connection', function () { .getInput('NAME') .connection.connect(newChild.previousConnection); - chai.assert.isTrue( - parent.getInput('NAME').connection.isConnected(), - ); - chai.assert.equal(parent.getInputTargetBlock('NAME'), newChild); - chai.assert.isTrue(spy.calledOnce); + assert.isTrue(parent.getInput('NAME').connection.isConnected()); + assert.equal(parent.getInputTargetBlock('NAME'), newChild); + assert.isTrue(spy.calledOnce); this.assertBlockCount(3); }); }); @@ -3572,12 +3533,10 @@ suite('Connection', function () { .getInput('NAME') .connection.connect(newChild.previousConnection); - chai.assert.isTrue( - parent.getInput('NAME').connection.isConnected(), - ); - chai.assert.equal(parent.getInputTargetBlock('NAME'), newChild); - chai.assert.isTrue(newChild.nextConnection.isConnected()); - chai.assert.equal(newChild.getNextBlock(), oldChild); + assert.isTrue(parent.getInput('NAME').connection.isConnected()); + assert.equal(parent.getInputTargetBlock('NAME'), newChild); + assert.isTrue(newChild.nextConnection.isConnected()); + assert.equal(newChild.getNextBlock(), oldChild); this.assertBlockCount(3); }); @@ -3599,12 +3558,10 @@ suite('Connection', function () { .getInput('NAME') .connection.connect(newChild1.previousConnection); - chai.assert.isTrue( - parent.getInput('NAME').connection.isConnected(), - ); - chai.assert.equal(parent.getInputTargetBlock('NAME'), newChild1); - chai.assert.isTrue(newChild2.nextConnection.isConnected()); - chai.assert.equal(newChild2.getNextBlock(), oldChild); + assert.isTrue(parent.getInput('NAME').connection.isConnected()); + assert.equal(parent.getInputTargetBlock('NAME'), newChild1); + assert.isTrue(newChild2.nextConnection.isConnected()); + assert.equal(newChild2.getNextBlock(), oldChild); this.assertBlockCount(4); }); @@ -3628,13 +3585,11 @@ suite('Connection', function () { .getInput('NAME') .connection.connect(newChild.previousConnection); - chai.assert.isTrue( - parent.getInput('NAME').connection.isConnected(), - ); - chai.assert.equal(parent.getInputTargetBlock('NAME'), newChild); - chai.assert.isTrue(newChild.nextConnection.isConnected()); - chai.assert.isTrue(newChild.getNextBlock().isShadow()); - chai.assert.isTrue(spy.calledOnce); + assert.isTrue(parent.getInput('NAME').connection.isConnected()); + assert.equal(parent.getInputTargetBlock('NAME'), newChild); + assert.isTrue(newChild.nextConnection.isConnected()); + assert.isTrue(newChild.getNextBlock().isShadow()); + assert.isTrue(spy.calledOnce); this.assertBlockCount(4); }); }); @@ -3650,10 +3605,10 @@ suite('Connection', function () { parent.nextConnection.connect(newChild.previousConnection); - chai.assert.isTrue(parent.nextConnection.isConnected()); - chai.assert.equal(parent.getNextBlock(), newChild); - chai.assert.isTrue(newChild.nextConnection.isConnected()); - chai.assert.equal(newChild.getNextBlock(), oldChild); + assert.isTrue(parent.nextConnection.isConnected()); + assert.equal(parent.getNextBlock(), newChild); + assert.isTrue(newChild.nextConnection.isConnected()); + assert.equal(newChild.getNextBlock(), oldChild); this.assertBlockCount(3); }); @@ -3667,10 +3622,10 @@ suite('Connection', function () { parent.nextConnection.connect(newChild1.previousConnection); - chai.assert.isTrue(parent.nextConnection.isConnected()); - chai.assert.equal(parent.getNextBlock(), newChild1); - chai.assert.isTrue(newChild2.nextConnection.isConnected()); - chai.assert.equal(newChild2.getNextBlock(), oldChild); + assert.isTrue(parent.nextConnection.isConnected()); + assert.equal(parent.getNextBlock(), newChild1); + assert.isTrue(newChild2.nextConnection.isConnected()); + assert.equal(newChild2.getNextBlock(), oldChild); this.assertBlockCount(4); }); @@ -3686,10 +3641,10 @@ suite('Connection', function () { parent.nextConnection.connect(newChild.previousConnection); - chai.assert.isTrue(parent.nextConnection.isConnected()); - chai.assert.equal(parent.getNextBlock(), newChild); - chai.assert.isFalse(newChild.nextConnection.isConnected()); - chai.assert.isTrue(spy.calledOnce); + assert.isTrue(parent.nextConnection.isConnected()); + assert.equal(parent.getNextBlock(), newChild); + assert.isFalse(newChild.nextConnection.isConnected()); + assert.isTrue(spy.calledOnce); this.assertBlockCount(3); }); @@ -3705,9 +3660,9 @@ suite('Connection', function () { parent.nextConnection.connect(newChild.previousConnection); - chai.assert.isTrue(parent.nextConnection.isConnected()); - chai.assert.equal(parent.getNextBlock(), newChild); - chai.assert.isTrue(spy.calledOnce); + assert.isTrue(parent.nextConnection.isConnected()); + assert.equal(parent.getNextBlock(), newChild); + assert.isTrue(spy.calledOnce); this.assertBlockCount(3); }); }); @@ -3725,10 +3680,10 @@ suite('Connection', function () { parent.nextConnection.connect(newChild.previousConnection); - chai.assert.isTrue(parent.nextConnection.isConnected()); - chai.assert.equal(parent.getNextBlock(), newChild); - chai.assert.isTrue(newChild.nextConnection.isConnected()); - chai.assert.equal(newChild.getNextBlock(), oldChild); + assert.isTrue(parent.nextConnection.isConnected()); + assert.equal(parent.getNextBlock(), newChild); + assert.isTrue(newChild.nextConnection.isConnected()); + assert.equal(newChild.getNextBlock(), oldChild); this.assertBlockCount(3); }); @@ -3746,10 +3701,10 @@ suite('Connection', function () { parent.nextConnection.connect(newChild1.previousConnection); - chai.assert.isTrue(parent.nextConnection.isConnected()); - chai.assert.equal(parent.getNextBlock(), newChild1); - chai.assert.isTrue(newChild2.nextConnection.isConnected()); - chai.assert.equal(newChild2.getNextBlock(), oldChild); + assert.isTrue(parent.nextConnection.isConnected()); + assert.equal(parent.getNextBlock(), newChild1); + assert.isTrue(newChild2.nextConnection.isConnected()); + assert.equal(newChild2.getNextBlock(), oldChild); this.assertBlockCount(4); }); @@ -3769,11 +3724,11 @@ suite('Connection', function () { parent.nextConnection.connect(newChild.previousConnection); - chai.assert.isTrue(parent.nextConnection.isConnected()); - chai.assert.equal(parent.getNextBlock(), newChild); - chai.assert.isTrue(newChild.nextConnection.isConnected()); - chai.assert.isTrue(newChild.getNextBlock().isShadow()); - chai.assert.isTrue(spy.calledOnce); + assert.isTrue(parent.nextConnection.isConnected()); + assert.equal(parent.getNextBlock(), newChild); + assert.isTrue(newChild.nextConnection.isConnected()); + assert.isTrue(newChild.getNextBlock().isShadow()); + assert.isTrue(spy.calledOnce); this.assertBlockCount(4); }); }); diff --git a/tests/mocha/contextmenu_items_test.js b/tests/mocha/contextmenu_items_test.js index 4596513c68c..a9e2bb3de62 100644 --- a/tests/mocha/contextmenu_items_test.js +++ b/tests/mocha/contextmenu_items_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -39,7 +40,7 @@ suite('Context Menu Items', function () { test('Disabled when nothing to undo', function () { const precondition = this.undoOption.preconditionFn(this.scope); - chai.assert.equal( + assert.equal( precondition, 'disabled', 'Should be disabled when there is nothing to undo', @@ -50,7 +51,7 @@ suite('Context Menu Items', function () { // Create a new block, which should be undoable. this.workspace.newBlock('text'); const precondition = this.undoOption.preconditionFn(this.scope); - chai.assert.equal( + assert.equal( precondition, 'enabled', 'Should be enabled when there are actions to undo', @@ -59,9 +60,9 @@ suite('Context Menu Items', function () { test('Undoes adding a new block', function () { this.workspace.newBlock('text'); - chai.assert.equal(this.workspace.getTopBlocks(false).length, 1); + assert.equal(this.workspace.getTopBlocks(false).length, 1); this.undoOption.callback(this.scope); - chai.assert.equal( + assert.equal( this.workspace.getTopBlocks(false).length, 0, 'Should be no blocks after undo', @@ -69,7 +70,7 @@ suite('Context Menu Items', function () { }); test('Has correct label', function () { - chai.assert.equal(this.undoOption.displayText(), 'Undo'); + assert.equal(this.undoOption.displayText(), 'Undo'); }); }); @@ -82,7 +83,7 @@ suite('Context Menu Items', function () { // Create a new block. There should be something to undo, but not redo. this.workspace.newBlock('text'); const precondition = this.redoOption.preconditionFn(this.scope); - chai.assert.equal( + assert.equal( precondition, 'disabled', 'Should be disabled when there is nothing to redo', @@ -94,7 +95,7 @@ suite('Context Menu Items', function () { this.workspace.newBlock('text'); this.workspace.undo(false); const precondition = this.redoOption.preconditionFn(this.scope); - chai.assert.equal( + assert.equal( precondition, 'enabled', 'Should be enabled when there are actions to redo', @@ -105,9 +106,9 @@ suite('Context Menu Items', function () { // Add a new block, then undo it, then redo it. this.workspace.newBlock('text'); this.workspace.undo(false); - chai.assert.equal(this.workspace.getTopBlocks(false).length, 0); + assert.equal(this.workspace.getTopBlocks(false).length, 0); this.redoOption.callback(this.scope); - chai.assert.equal( + assert.equal( this.workspace.getTopBlocks(false).length, 1, 'Should be 1 block after redo', @@ -115,20 +116,20 @@ suite('Context Menu Items', function () { }); test('Has correct label', function () { - chai.assert.equal(this.redoOption.displayText(), 'Redo'); + assert.equal(this.redoOption.displayText(), 'Redo'); }); }); suite('Cleanup', function () { setup(function () { this.cleanupOption = this.registry.getItem('cleanWorkspace'); - this.cleanupStub = sinon.stub(this.workspace, 'cleanUp'); + this.cleanUpStub = sinon.stub(this.workspace, 'cleanUp'); }); test('Enabled when multiple blocks', function () { this.workspace.newBlock('text'); this.workspace.newBlock('text'); - chai.assert.equal( + assert.equal( this.cleanupOption.preconditionFn(this.scope), 'enabled', 'Should be enabled if there are multiple blocks', @@ -136,7 +137,7 @@ suite('Context Menu Items', function () { }); test('Disabled when no blocks', function () { - chai.assert.equal( + assert.equal( this.cleanupOption.preconditionFn(this.scope), 'disabled', 'Should be disabled if there are no blocks', @@ -145,20 +146,20 @@ suite('Context Menu Items', function () { test('Hidden when not movable', function () { sinon.stub(this.workspace, 'isMovable').returns(false); - chai.assert.equal( + assert.equal( this.cleanupOption.preconditionFn(this.scope), 'hidden', 'Should be hidden if the workspace is not movable', ); }); - test('Calls workspace cleanup', function () { + test('Calls workspace cleanUp', function () { this.cleanupOption.callback(this.scope); - sinon.assert.calledOnce(this.cleanupStub); + sinon.assert.calledOnce(this.cleanUpStub); }); test('Has correct label', function () { - chai.assert.equal(this.cleanupOption.displayText(), 'Clean up Blocks'); + assert.equal(this.cleanupOption.displayText(), 'Clean up Blocks'); }); }); @@ -171,7 +172,7 @@ suite('Context Menu Items', function () { this.workspace.newBlock('text'); const block2 = this.workspace.newBlock('text'); block2.setCollapsed(true); - chai.assert.equal( + assert.equal( this.collapseOption.preconditionFn(this.scope), 'enabled', 'Should be enabled when any blocks are expanded', @@ -180,7 +181,7 @@ suite('Context Menu Items', function () { test('Disabled when all blocks collapsed', function () { this.workspace.newBlock('text').setCollapsed(true); - chai.assert.equal( + assert.equal( this.collapseOption.preconditionFn(this.scope), 'disabled', 'Should be disabled when no blocks are expanded', @@ -194,7 +195,7 @@ suite('Context Menu Items', function () { this.scope.workspace = workspaceWithOptions; try { - chai.assert.equal( + assert.equal( this.collapseOption.preconditionFn(this.scope), 'hidden', 'Should be hidden if collapse is disabled in options', @@ -216,18 +217,18 @@ suite('Context Menu Items', function () { this.collapseOption.callback(this.scope); this.clock.runAll(); - chai.assert.isTrue( + assert.isTrue( block1.isCollapsed(), 'Previously collapsed block should still be collapsed', ); - chai.assert.isTrue( + assert.isTrue( block2.isCollapsed(), 'Previously expanded block should now be collapsed', ); }); test('Has correct label', function () { - chai.assert.equal(this.collapseOption.displayText(), 'Collapse Blocks'); + assert.equal(this.collapseOption.displayText(), 'Collapse Blocks'); }); }); @@ -241,7 +242,7 @@ suite('Context Menu Items', function () { const block2 = this.workspace.newBlock('text'); block2.setCollapsed(true); - chai.assert.equal( + assert.equal( this.expandOption.preconditionFn(this.scope), 'enabled', 'Should be enabled when any blocks are collapsed', @@ -250,7 +251,7 @@ suite('Context Menu Items', function () { test('Disabled when no collapsed blocks', function () { this.workspace.newBlock('text'); - chai.assert.equal( + assert.equal( this.expandOption.preconditionFn(this.scope), 'disabled', 'Should be disabled when no blocks are collapsed', @@ -264,7 +265,7 @@ suite('Context Menu Items', function () { this.scope.workspace = workspaceWithOptions; try { - chai.assert.equal( + assert.equal( this.expandOption.preconditionFn(this.scope), 'hidden', 'Should be hidden if collapse is disabled in options', @@ -286,18 +287,18 @@ suite('Context Menu Items', function () { this.expandOption.callback(this.scope); this.clock.runAll(); - chai.assert.isFalse( + assert.isFalse( block1.isCollapsed(), 'Previously expanded block should still be expanded', ); - chai.assert.isFalse( + assert.isFalse( block2.isCollapsed(), 'Previously collapsed block should now be expanded', ); }); test('Has correct label', function () { - chai.assert.equal(this.expandOption.displayText(), 'Expand Blocks'); + assert.equal(this.expandOption.displayText(), 'Expand Blocks'); }); }); @@ -308,17 +309,11 @@ suite('Context Menu Items', function () { test('Enabled when blocks to delete', function () { this.workspace.newBlock('text'); - chai.assert.equal( - this.deleteOption.preconditionFn(this.scope), - 'enabled', - ); + assert.equal(this.deleteOption.preconditionFn(this.scope), 'enabled'); }); test('Disabled when no blocks to delete', function () { - chai.assert.equal( - this.deleteOption.preconditionFn(this.scope), - 'disabled', - ); + assert.equal(this.deleteOption.preconditionFn(this.scope), 'disabled'); }); test('Deletes all blocks after confirming', function () { @@ -332,7 +327,7 @@ suite('Context Menu Items', function () { this.deleteOption.callback(this.scope); this.clock.runAll(); sinon.assert.calledOnce(confirmStub); - chai.assert.equal(this.workspace.getTopBlocks(false).length, 0); + assert.equal(this.workspace.getTopBlocks(false).length, 0); }); test('Does not delete blocks if not confirmed', function () { @@ -346,7 +341,7 @@ suite('Context Menu Items', function () { this.deleteOption.callback(this.scope); this.clock.runAll(); sinon.assert.calledOnce(confirmStub); - chai.assert.equal(this.workspace.getTopBlocks(false).length, 2); + assert.equal(this.workspace.getTopBlocks(false).length, 2); }); test('No dialog for single block', function () { @@ -359,14 +354,14 @@ suite('Context Menu Items', function () { this.clock.runAll(); sinon.assert.notCalled(confirmStub); - chai.assert.equal(this.workspace.getTopBlocks(false).length, 0); + assert.equal(this.workspace.getTopBlocks(false).length, 0); }); test('Has correct label for multiple blocks', function () { this.workspace.newBlock('text'); this.workspace.newBlock('text'); - chai.assert.equal( + assert.equal( this.deleteOption.displayText(this.scope), 'Delete 2 Blocks', ); @@ -374,10 +369,7 @@ suite('Context Menu Items', function () { test('Has correct label for single block', function () { this.workspace.newBlock('text'); - chai.assert.equal( - this.deleteOption.displayText(this.scope), - 'Delete Block', - ); + assert.equal(this.deleteOption.displayText(this.scope), 'Delete Block'); }); }); }); @@ -395,7 +387,7 @@ suite('Context Menu Items', function () { test('Enabled when block is duplicatable', function () { // Block is duplicatable by default - chai.assert.equal( + assert.equal( this.duplicateOption.preconditionFn(this.scope), 'enabled', ); @@ -403,7 +395,7 @@ suite('Context Menu Items', function () { test('Disabled when block is not dupicatable', function () { sinon.stub(this.block, 'isDuplicatable').returns(false); - chai.assert.equal( + assert.equal( this.duplicateOption.preconditionFn(this.scope), 'disabled', ); @@ -411,15 +403,12 @@ suite('Context Menu Items', function () { test('Hidden when in flyout', function () { this.block.isInFlyout = true; - chai.assert.equal( - this.duplicateOption.preconditionFn(this.scope), - 'hidden', - ); + assert.equal(this.duplicateOption.preconditionFn(this.scope), 'hidden'); }); test('the block is duplicated', function () { this.duplicateOption.callback(this.scope); - chai.assert.equal( + assert.equal( this.workspace.getTopBlocks(false).length, 2, 'Expected a second block', @@ -427,7 +416,7 @@ suite('Context Menu Items', function () { }); test('Has correct label', function () { - chai.assert.equal(this.duplicateOption.displayText(), 'Duplicate'); + assert.equal(this.duplicateOption.displayText(), 'Duplicate'); }); }); @@ -437,10 +426,7 @@ suite('Context Menu Items', function () { }); test('Enabled for normal block', function () { - chai.assert.equal( - this.commentOption.preconditionFn(this.scope), - 'enabled', - ); + assert.equal(this.commentOption.preconditionFn(this.scope), 'enabled'); }); test('Hidden for collapsed block', function () { @@ -449,20 +435,17 @@ suite('Context Menu Items', function () { this.block.render(); this.block.setCollapsed(true); - chai.assert.equal( - this.commentOption.preconditionFn(this.scope), - 'hidden', - ); + assert.equal(this.commentOption.preconditionFn(this.scope), 'hidden'); }); test('Creates comment if one did not exist', function () { - chai.assert.isUndefined( + assert.isUndefined( this.block.getIcon(Blockly.icons.CommentIcon.TYPE), 'New block should not have a comment', ); this.commentOption.callback(this.scope); - chai.assert.exists(this.block.getIcon(Blockly.icons.CommentIcon.TYPE)); - chai.assert.isEmpty( + assert.exists(this.block.getIcon(Blockly.icons.CommentIcon.TYPE)); + assert.isEmpty( this.block.getCommentText(), 'Block should have empty comment text', ); @@ -471,22 +454,19 @@ suite('Context Menu Items', function () { test('Removes comment if block had one', function () { this.block.setCommentText('Test comment'); this.commentOption.callback(this.scope); - chai.assert.isNull( + assert.isNull( this.block.getCommentText(), 'Block should not have comment after removal', ); }); test('Has correct label for add comment', function () { - chai.assert.equal( - this.commentOption.displayText(this.scope), - 'Add Comment', - ); + assert.equal(this.commentOption.displayText(this.scope), 'Add Comment'); }); test('Has correct label for remove comment', function () { this.block.setCommentText('Test comment'); - chai.assert.equal( + assert.equal( this.commentOption.displayText(this.scope), 'Remove Comment', ); @@ -501,10 +481,7 @@ suite('Context Menu Items', function () { test('Enabled when inputs to inline', function () { this.block.appendValueInput('test1'); this.block.appendValueInput('test2'); - chai.assert.equal( - this.inlineOption.preconditionFn(this.scope), - 'enabled', - ); + assert.equal(this.inlineOption.preconditionFn(this.scope), 'enabled'); }); }); }); diff --git a/tests/mocha/contextmenu_test.js b/tests/mocha/contextmenu_test.js index 7af9c79186d..fe6d4be997e 100644 --- a/tests/mocha/contextmenu_test.js +++ b/tests/mocha/contextmenu_test.js @@ -4,15 +4,15 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {callbackFactory} from '../../build/src/core/contextmenu.js'; +import * as xmlUtils from '../../build/src/core/utils/xml.js'; +import * as Variables from '../../build/src/core/variables.js'; +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, } from './test_helpers/setup_teardown.js'; -import {callbackFactory} from '../../build/src/core/contextmenu.js'; -import * as xmlUtils from '../../build/src/core/utils/xml.js'; -import * as Variables from '../../build/src/core/variables.js'; - suite('Context Menu', function () { setup(function () { sharedTestSetup.call(this); @@ -42,9 +42,9 @@ suite('Context Menu', function () { const callback = callbackFactory(this.forLoopBlock, xmlBlock); const getVarBlock = callback(); - chai.assert.equal(getVarBlock.type, 'variables_get'); - chai.assert.equal(getVarBlock.workspace, this.forLoopBlock.workspace); - chai.assert.equal( + assert.equal(getVarBlock.type, 'variables_get'); + assert.equal(getVarBlock.workspace, this.forLoopBlock.workspace); + assert.equal( getVarBlock.getField('VAR').getVariable().getId(), this.forLoopBlock.getField('VAR').getVariable().getId(), ); @@ -59,9 +59,9 @@ suite('Context Menu', function () { const callback = callbackFactory(this.forLoopBlock, jsonState); const getVarBlock = callback(); - chai.assert.equal(getVarBlock.type, 'variables_get'); - chai.assert.equal(getVarBlock.workspace, this.forLoopBlock.workspace); - chai.assert.equal( + assert.equal(getVarBlock.type, 'variables_get'); + assert.equal(getVarBlock.workspace, this.forLoopBlock.workspace); + assert.equal( getVarBlock.getField('VAR').getVariable().getId(), this.forLoopBlock.getField('VAR').getVariable().getId(), ); diff --git a/tests/mocha/cursor_test.js b/tests/mocha/cursor_test.js index c7b3a76afcc..bb5026d7ac3 100644 --- a/tests/mocha/cursor_test.js +++ b/tests/mocha/cursor_test.js @@ -4,11 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {ASTNode} from '../../build/src/core/keyboard_nav/ast_node.js'; +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, } from './test_helpers/setup_teardown.js'; -import {ASTNode} from '../../build/src/core/keyboard_nav/ast_node.js'; suite('Cursor', function () { setup(function () { @@ -90,7 +91,7 @@ suite('Cursor', function () { this.cursor.setCurNode(prevNode); this.cursor.next(); const curNode = this.cursor.getCurNode(); - chai.assert.equal(curNode.getLocation(), this.blocks.B.previousConnection); + assert.equal(curNode.getLocation(), this.blocks.B.previousConnection); }); test('Next - From last block in a stack go to next connection', function () { const prevNode = ASTNode.createConnectionNode( @@ -99,7 +100,7 @@ suite('Cursor', function () { this.cursor.setCurNode(prevNode); this.cursor.next(); const curNode = this.cursor.getCurNode(); - chai.assert.equal(curNode.getLocation(), this.blocks.B.nextConnection); + assert.equal(curNode.getLocation(), this.blocks.B.nextConnection); }); test('In - From output connection', function () { @@ -110,10 +111,7 @@ suite('Cursor', function () { this.cursor.setCurNode(outputNode); this.cursor.in(); const curNode = this.cursor.getCurNode(); - chai.assert.equal( - curNode.getLocation(), - fieldBlock.inputList[0].fieldRow[0], - ); + assert.equal(curNode.getLocation(), fieldBlock.inputList[0].fieldRow[0]); }); test('Prev - From previous connection skip over next connection', function () { @@ -122,7 +120,7 @@ suite('Cursor', function () { this.cursor.setCurNode(prevConnectionNode); this.cursor.prev(); const curNode = this.cursor.getCurNode(); - chai.assert.equal(curNode.getLocation(), this.blocks.A.previousConnection); + assert.equal(curNode.getLocation(), this.blocks.A.previousConnection); }); test('Out - From field skip over block node', function () { @@ -131,6 +129,6 @@ suite('Cursor', function () { this.cursor.setCurNode(fieldNode); this.cursor.out(); const curNode = this.cursor.getCurNode(); - chai.assert.equal(curNode.getLocation(), this.blocks.E.outputConnection); + assert.equal(curNode.getLocation(), this.blocks.E.outputConnection); }); }); diff --git a/tests/mocha/dropdowndiv_test.js b/tests/mocha/dropdowndiv_test.js index 22066dda4e0..32109bfcadd 100644 --- a/tests/mocha/dropdowndiv_test.js +++ b/tests/mocha/dropdowndiv_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -51,10 +52,10 @@ suite('DropDownDiv', function () { -10, ); // "Above" in value actually means below in render. - chai.assert.isAtLeast(metrics.initialY, 0); - chai.assert.isAbove(metrics.finalY, 0); - chai.assert.isTrue(metrics.arrowVisible); - chai.assert.isTrue(metrics.arrowAtTop); + assert.isAtLeast(metrics.initialY, 0); + assert.isAbove(metrics.finalY, 0); + assert.isTrue(metrics.arrowVisible); + assert.isTrue(metrics.arrowAtTop); }); test('Above, in Bounds', function () { const metrics = Blockly.DropDownDiv.TEST_ONLY.getPositionMetrics( @@ -64,10 +65,10 @@ suite('DropDownDiv', function () { 90, ); // "Below" in value actually means above in render. - chai.assert.isAtMost(metrics.initialY, 100); - chai.assert.isBelow(metrics.finalY, 100); - chai.assert.isTrue(metrics.arrowVisible); - chai.assert.isFalse(metrics.arrowAtTop); + assert.isAtMost(metrics.initialY, 100); + assert.isBelow(metrics.finalY, 100); + assert.isTrue(metrics.arrowVisible); + assert.isFalse(metrics.arrowAtTop); }); test('Below, out of Bounds', function () { const metrics = Blockly.DropDownDiv.TEST_ONLY.getPositionMetrics( @@ -77,10 +78,10 @@ suite('DropDownDiv', function () { 50, ); // "Above" in value actually means below in render. - chai.assert.isAtLeast(metrics.initialY, 60); - chai.assert.isAbove(metrics.finalY, 60); - chai.assert.isTrue(metrics.arrowVisible); - chai.assert.isTrue(metrics.arrowAtTop); + assert.isAtLeast(metrics.initialY, 60); + assert.isAbove(metrics.finalY, 60); + assert.isTrue(metrics.arrowVisible); + assert.isTrue(metrics.arrowAtTop); }); test('Above, in Bounds', function () { const metrics = Blockly.DropDownDiv.TEST_ONLY.getPositionMetrics( @@ -90,10 +91,10 @@ suite('DropDownDiv', function () { 90, ); // "Below" in value actually means above in render. - chai.assert.isAtMost(metrics.initialY, 100); - chai.assert.isBelow(metrics.finalY, 100); - chai.assert.isTrue(metrics.arrowVisible); - chai.assert.isFalse(metrics.arrowAtTop); + assert.isAtMost(metrics.initialY, 100); + assert.isBelow(metrics.finalY, 100); + assert.isTrue(metrics.arrowVisible); + assert.isFalse(metrics.arrowAtTop); }); test('No Solution, Render At Top', function () { this.clientHeightStub.get(function () { @@ -106,10 +107,10 @@ suite('DropDownDiv', function () { 50, ); // "Above" in value actually means below in render. - chai.assert.equal(metrics.initialY, 0); - chai.assert.equal(metrics.finalY, 0); - chai.assert.isFalse(metrics.arrowVisible); - chai.assert.isNotOk(metrics.arrowAtTop); + assert.equal(metrics.initialY, 0); + assert.equal(metrics.finalY, 0); + assert.isFalse(metrics.arrowVisible); + assert.isNotOk(metrics.arrowAtTop); }); }); }); diff --git a/tests/mocha/event_block_change_test.js b/tests/mocha/event_block_change_test.js index 4f4728cc32c..7de0a23b607 100644 --- a/tests/mocha/event_block_change_test.js +++ b/tests/mocha/event_block_change_test.js @@ -4,11 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; +import {defineMutatorBlocks} from './test_helpers/block_definitions.js'; import { sharedTestSetup, sharedTestTeardown, } from './test_helpers/setup_teardown.js'; -import {defineMutatorBlocks} from './test_helpers/block_definitions.js'; suite('Block Change Event', function () { setup(function () { @@ -45,7 +46,7 @@ suite('Block Change Event', function () { '', ); blockChange.run(false); - chai.assert.isFalse(block.hasInput); + assert.isFalse(block.hasInput); }); test('Redo', function () { @@ -58,7 +59,7 @@ suite('Block Change Event', function () { '', ); blockChange.run(true); - chai.assert.isTrue(block.hasInput); + assert.isTrue(block.hasInput); }); }); @@ -74,7 +75,7 @@ suite('Block Change Event', function () { '{"hasInput":true}', ); blockChange.run(false); - chai.assert.isFalse(block.hasInput); + assert.isFalse(block.hasInput); }); test('Redo', function () { @@ -87,7 +88,7 @@ suite('Block Change Event', function () { '{"hasInput":true}', ); blockChange.run(true); - chai.assert.isTrue(block.hasInput); + assert.isTrue(block.hasInput); }); }); }); @@ -119,7 +120,7 @@ suite('Block Change Event', function () { const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/event_block_create_test.js b/tests/mocha/event_block_create_test.js index f3aed672f49..f59f9435efd 100644 --- a/tests/mocha/event_block_create_test.js +++ b/tests/mocha/event_block_create_test.js @@ -4,13 +4,14 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {EventType} from '../../build/src/core/events/type.js'; +import {assert} from '../../node_modules/chai/chai.js'; +import {defineRowBlock} from './test_helpers/block_definitions.js'; import {assertEventFired} from './test_helpers/events.js'; -import * as eventUtils from '../../build/src/core/events/utils.js'; import { sharedTestSetup, sharedTestTeardown, } from './test_helpers/setup_teardown.js'; -import {defineRowBlock} from './test_helpers/block_definitions.js'; suite('Block Create Event', function () { setup(function () { @@ -47,13 +48,13 @@ suite('Block Create Event', function () { assertEventFired( this.eventsFireStub, Blockly.Events.BlockCreate, - {'recordUndo': false, 'type': eventUtils.BLOCK_CREATE}, + {'recordUndo': false, 'type': EventType.BLOCK_CREATE}, this.workspace.id, 'shadowId', ); const calls = this.eventsFireStub.getCalls(); const event = calls[calls.length - 1].args[0]; - chai.assert.equal(event.xml.tagName, 'shadow'); + assert.equal(event.xml.tagName, 'shadow'); }); test('Does not create extra shadow blocks', function () { @@ -85,7 +86,7 @@ suite('Block Create Event', function () { event.run(true); const blocksAfter = this.workspace.getAllBlocks(); - chai.assert.deepEqual( + assert.deepEqual( blocksAfter, blocksBefore, 'No new blocks should be created from an event that only creates shadow blocks', @@ -102,7 +103,7 @@ suite('Block Create Event', function () { delete origEvent.xml; // xml fails deep equals for some reason. delete newEvent.xml; // xml fails deep equals for some reason. - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/event_block_delete_test.js b/tests/mocha/event_block_delete_test.js index 1aa70c4d1ab..d74b6aa062b 100644 --- a/tests/mocha/event_block_delete_test.js +++ b/tests/mocha/event_block_delete_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import {defineRowBlock} from './test_helpers/block_definitions.js'; import { sharedTestSetup, @@ -34,7 +35,7 @@ suite('Block Delete Event', function () { testBlock.dispose(); this.clock.runAll(); - chai.assert.isFalse(spy.called); + assert.isFalse(spy.called); }); }); @@ -48,7 +49,7 @@ suite('Block Delete Event', function () { delete origEvent.oldXml; // xml fails deep equals for some reason. delete newEvent.oldXml; // xml fails deep equals for some reason. - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/event_block_drag_test.js b/tests/mocha/event_block_drag_test.js index 8a5399c8bde..9b0f2031ad0 100644 --- a/tests/mocha/event_block_drag_test.js +++ b/tests/mocha/event_block_drag_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import {defineRowBlock} from './test_helpers/block_definitions.js'; import { sharedTestSetup, @@ -29,7 +30,7 @@ suite('Block Drag Event', function () { const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/event_block_field_intermediate_change_test.js b/tests/mocha/event_block_field_intermediate_change_test.js index 4d441e5d6a4..0ff4e1bbf3c 100644 --- a/tests/mocha/event_block_field_intermediate_change_test.js +++ b/tests/mocha/event_block_field_intermediate_change_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -32,7 +33,7 @@ suite('Field Intermediate Change Event', function () { const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); @@ -47,10 +48,7 @@ suite('Field Intermediate Change Event', function () { ); origEvent.run(true); - chai.assert.deepEqual( - block.getField(origEvent.name).getValue(), - 'new value', - ); + assert.deepEqual(block.getField(origEvent.name).getValue(), 'new value'); }); test("running backward changes the block's value to old value", function () { @@ -63,10 +61,7 @@ suite('Field Intermediate Change Event', function () { ); origEvent.run(false); - chai.assert.deepEqual( - block.getField(origEvent.name).getValue(), - 'old value', - ); + assert.deepEqual(block.getField(origEvent.name).getValue(), 'old value'); }); }); }); diff --git a/tests/mocha/event_block_move_test.js b/tests/mocha/event_block_move_test.js index 2b4102de6a0..b93457e14c1 100644 --- a/tests/mocha/event_block_move_test.js +++ b/tests/mocha/event_block_move_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import {defineRowBlock} from './test_helpers/block_definitions.js'; import { sharedTestSetup, @@ -32,7 +33,7 @@ suite('Block Move Event', function () { const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/event_bubble_open_test.js b/tests/mocha/event_bubble_open_test.js index 54e48aa9cff..099a625f6e2 100644 --- a/tests/mocha/event_bubble_open_test.js +++ b/tests/mocha/event_bubble_open_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import {defineMutatorBlocks} from './test_helpers/block_definitions.js'; import { sharedTestSetup, @@ -35,7 +36,7 @@ suite('Bubble Open Event', function () { const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/event_click_test.js b/tests/mocha/event_click_test.js index ec998b62de4..6e18769485b 100644 --- a/tests/mocha/event_click_test.js +++ b/tests/mocha/event_click_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import {defineRowBlock} from './test_helpers/block_definitions.js'; import { sharedTestSetup, @@ -33,7 +34,7 @@ suite('Click Event', function () { const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/event_comment_change_test.js b/tests/mocha/event_comment_change_test.js index c2355f87462..ed5f4d9f6ae 100644 --- a/tests/mocha/event_comment_change_test.js +++ b/tests/mocha/event_comment_change_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -32,7 +33,7 @@ suite('Comment Change Event', function () { const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/event_comment_collapse_test.js b/tests/mocha/event_comment_collapse_test.js index 86b36b07588..e2d27530708 100644 --- a/tests/mocha/event_comment_collapse_test.js +++ b/tests/mocha/event_comment_collapse_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -27,7 +28,7 @@ suite('Comment Collapse Event', function () { const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/event_comment_create_test.js b/tests/mocha/event_comment_create_test.js index 57c246f1f1e..df919541d95 100644 --- a/tests/mocha/event_comment_create_test.js +++ b/tests/mocha/event_comment_create_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -31,7 +32,7 @@ suite('Comment Create Event', function () { delete origEvent.xml; // xml fails deep equals for some reason. delete newEvent.xml; // xml fails deep equals for some reason. - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/event_comment_delete_test.js b/tests/mocha/event_comment_delete_test.js index e0a8a98db33..2e2bb45c491 100644 --- a/tests/mocha/event_comment_delete_test.js +++ b/tests/mocha/event_comment_delete_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -31,7 +32,7 @@ suite('Comment Delete Event', function () { delete origEvent.xml; // xml fails deep equals for some reason. delete newEvent.xml; // xml fails deep equals for some reason. - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/event_comment_drag_test.js b/tests/mocha/event_comment_drag_test.js new file mode 100644 index 00000000000..d214e0adba1 --- /dev/null +++ b/tests/mocha/event_comment_drag_test.js @@ -0,0 +1,35 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import {assert} from '../../node_modules/chai/chai.js'; +import { + sharedTestSetup, + sharedTestTeardown, +} from './test_helpers/setup_teardown.js'; + +suite('Comment Drag Event', function () { + setup(function () { + sharedTestSetup.call(this); + this.workspace = new Blockly.Workspace(); + }); + + teardown(function () { + sharedTestTeardown.call(this); + }); + + suite('Serialization', function () { + test('events round-trip through JSON', function () { + const comment = new Blockly.comments.WorkspaceComment(this.workspace); + comment.setText('test text'); + + const origEvent = new Blockly.Events.CommentDrag(comment, true); + const json = origEvent.toJson(); + const newEvent = new Blockly.Events.fromJson(json, this.workspace); + + assert.deepEqual(newEvent, origEvent); + }); + }); +}); diff --git a/tests/mocha/event_comment_move_test.js b/tests/mocha/event_comment_move_test.js index 420bdbb52de..aae3fdfe632 100644 --- a/tests/mocha/event_comment_move_test.js +++ b/tests/mocha/event_comment_move_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -33,7 +34,7 @@ suite('Comment Move Event', function () { delete origEvent.comment_; // Ignore private properties. delete newEvent.comment_; // Ignore private properties. - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/event_comment_resize_test.js b/tests/mocha/event_comment_resize_test.js new file mode 100644 index 00000000000..b74e1abb2bf --- /dev/null +++ b/tests/mocha/event_comment_resize_test.js @@ -0,0 +1,38 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import {assert} from '../../node_modules/chai/chai.js'; +import { + sharedTestSetup, + sharedTestTeardown, +} from './test_helpers/setup_teardown.js'; + +suite('Comment Resize Event', function () { + setup(function () { + sharedTestSetup.call(this); + this.workspace = new Blockly.Workspace(); + }); + + teardown(function () { + sharedTestTeardown.call(this); + }); + + suite('Serialization', function () { + test('events round-trip through JSON', function () { + const comment = new Blockly.comments.WorkspaceComment(this.workspace); + comment.setText('test text'); + comment.setSize(new Blockly.utils.Size(100, 100)); + const origEvent = new Blockly.Events.CommentResize(comment); + comment.setSize(new Blockly.utils.Size(200, 200)); + origEvent.recordCurrentSizeAsNewSize(); + + const json = origEvent.toJson(); + const newEvent = new Blockly.Events.fromJson(json, this.workspace); + + assert.deepEqual(newEvent, origEvent); + }); + }); +}); diff --git a/tests/mocha/event_marker_move_test.js b/tests/mocha/event_marker_move_test.js index 26238dc43db..cd5609c33d7 100644 --- a/tests/mocha/event_marker_move_test.js +++ b/tests/mocha/event_marker_move_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import {defineRowBlock} from './test_helpers/block_definitions.js'; import { sharedTestSetup, @@ -37,7 +38,7 @@ suite('Marker Move Event', function () { const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/event_selected_test.js b/tests/mocha/event_selected_test.js index 3c69889f2b1..1ce8306db48 100644 --- a/tests/mocha/event_selected_test.js +++ b/tests/mocha/event_selected_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import {defineRowBlock} from './test_helpers/block_definitions.js'; import { sharedTestSetup, @@ -34,7 +35,7 @@ suite('Selected Event', function () { const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/event_test.js b/tests/mocha/event_test.js index 75688c6547e..84ea7f0d78e 100644 --- a/tests/mocha/event_test.js +++ b/tests/mocha/event_test.js @@ -5,20 +5,21 @@ */ import * as Blockly from '../../build/src/core/blockly.js'; +import * as eventUtils from '../../build/src/core/events/utils.js'; import {ASTNode} from '../../build/src/core/keyboard_nav/ast_node.js'; +import {assert} from '../../node_modules/chai/chai.js'; import { assertEventEquals, assertNthCallEventArgEquals, createChangeListenerSpy, } from './test_helpers/events.js'; -import {assertVariableValues} from './test_helpers/variables.js'; import { createGenUidStubWithReturns, sharedTestSetup, sharedTestTeardown, workspaceTeardown, } from './test_helpers/setup_teardown.js'; -import * as eventUtils from '../../build/src/core/events/utils.js'; +import {assertVariableValues} from './test_helpers/variables.js'; suite('Events', function () { setup(function () { @@ -41,6 +42,26 @@ suite('Events', function () { 'type': 'simple_test_block', 'message0': 'simple test block', }, + { + 'type': 'inputs_test_block', + 'message0': 'first %1 second %2', + 'args0': [ + { + 'type': 'input_statement', + 'name': 'STATEMENT1', + }, + { + 'type': 'input_statement', + 'name': 'STATEMENT2', + }, + ], + }, + { + 'type': 'statement_test_block', + 'message0': '', + 'previousStatement': null, + 'nextStatement': null, + }, ]); }); @@ -180,7 +201,7 @@ suite('Events', function () { suite('Block Move', function () { test('by coordinate', function () { const coordinate = new Blockly.utils.Coordinate(3, 4); - this.block.xy_ = coordinate; + this.block.xy = coordinate; const event = new Blockly.Events.BlockMove(this.block); sinon.assert.calledOnce(this.genUidStub); @@ -203,7 +224,7 @@ suite('Events', function () { try { this.parentBlock = createSimpleTestBlock(this.workspace); this.block.parentBlock_ = this.parentBlock; - this.block.xy_ = new Blockly.utils.Coordinate(3, 4); + this.block.xy = new Blockly.utils.Coordinate(3, 4); const event = new Blockly.Events.BlockMove(this.block); sinon.assert.calledTwice(this.genUidStub); assertEventEquals( @@ -310,7 +331,7 @@ suite('Events', function () { try { this.parentBlock = createSimpleTestBlock(this.workspace); this.block.parentBlock_ = this.parentBlock; - this.block.xy_ = new Blockly.utils.Coordinate(3, 4); + this.block.xy = new Blockly.utils.Coordinate(3, 4); const event = new Blockly.Events.BlockMove(this.block); sinon.assert.calledTwice(this.genUidStub); assertEventEquals( @@ -861,7 +882,30 @@ suite('Events', function () { }, }), }, + { + title: 'Comment drag start', + class: Blockly.Events.CommentDrag, + getArgs: (thisObj) => [thisObj.comment, true], + getExpectedJson: (thisObj) => ({ + type: 'comment_drag', + group: '', + isStart: true, + commentId: thisObj.comment.id, + }), + }, + { + title: 'Comment drag end', + class: Blockly.Events.CommentDrag, + getArgs: (thisObj) => [thisObj.comment, false], + getExpectedJson: (thisObj) => ({ + type: 'comment_drag', + group: '', + isStart: false, + commentId: thisObj.comment.id, + }), + }, // TODO(#4577) Test serialization of move event coordinate properties. + // TODO(#4577) Test serialization of comment resize event properties. ]; const testSuites = [ { @@ -916,10 +960,7 @@ suite('Events', function () { const json = event.toJson(); const event2 = Blockly.Events.fromJson(json, this.workspace); - chai.assert.equal( - safeStringify(event2.toJson()), - safeStringify(json), - ); + assert.equal(safeStringify(event2.toJson()), safeStringify(json)); }); }); }); @@ -931,10 +972,7 @@ suite('Events', function () { const json = event.toJson(); const expectedJson = testCase.getExpectedJson(this); - chai.assert.equal( - safeStringify(json), - safeStringify(expectedJson), - ); + assert.equal(safeStringify(json), safeStringify(expectedJson)); }); } }); @@ -958,10 +996,10 @@ suite('Events', function () { */ function checkVariableValues(container, name, type, id) { const variable = container.getVariableById(id); - chai.assert.isDefined(variable); - chai.assert.equal(name, variable.name); - chai.assert.equal(type, variable.type); - chai.assert.equal(id, variable.getId()); + assert.isDefined(variable); + assert.equal(name, variable.name); + assert.equal(type, variable.type); + assert.equal(id, variable.getId()); } suite('Constructors', function () { @@ -1036,29 +1074,29 @@ suite('Events', function () { }; const event = eventUtils.fromJson(json, this.workspace); const x = this.workspace.getVariableById('id2'); - chai.assert.isNull(x); + assert.isNull(x); event.run(true); assertVariableValues(this.workspace, 'name2', 'type2', 'id2'); }); test('Var delete', function () { const event = new Blockly.Events.VarDelete(this.variable); - chai.assert.isNotNull(this.workspace.getVariableById('id1')); + assert.isNotNull(this.workspace.getVariableById('id1')); event.run(true); - chai.assert.isNull(this.workspace.getVariableById('id1')); + assert.isNull(this.workspace.getVariableById('id1')); }); test('Var rename', function () { const event = new Blockly.Events.VarRename(this.variable, 'name2'); event.run(true); - chai.assert.isNull(this.workspace.getVariable('name1')); + assert.isNull(this.workspace.getVariable('name1')); checkVariableValues(this.workspace, 'name2', 'type1', 'id1'); }); }); suite('Run Backward', function () { test('Var create', function () { const event = new Blockly.Events.VarCreate(this.variable); - chai.assert.isNotNull(this.workspace.getVariableById('id1')); + assert.isNotNull(this.workspace.getVariableById('id1')); event.run(false); }); @@ -1070,7 +1108,7 @@ suite('Events', function () { varName: 'name2', }; const event = eventUtils.fromJson(json, this.workspace); - chai.assert.isNull(this.workspace.getVariableById('id2')); + assert.isNull(this.workspace.getVariableById('id2')); event.run(false); assertVariableValues(this.workspace, 'name2', 'type2', 'id2'); }); @@ -1078,16 +1116,175 @@ suite('Events', function () { test('Var rename', function () { const event = new Blockly.Events.VarRename(this.variable, 'name2'); event.run(false); - chai.assert.isNull(this.workspace.getVariable('name2')); + assert.isNull(this.workspace.getVariable('name2')); checkVariableValues(this.workspace, 'name1', 'type1', 'id1'); }); }); }); + suite('enqueueEvent', function () { + const {FIRE_QUEUE, enqueueEvent} = eventUtils.TEST_ONLY; + + function newDisconnectEvent(parent, child, inputName, workspaceId) { + const event = new Blockly.Events.BlockMove(child); + event.workspaceId = workspaceId; + event.oldParentId = parent.id; + event.oldInputName = inputName; + event.oldCoordinate = undefined; + event.newParentId = undefined; + event.newInputName = undefined; + event.newCoordinate = new Blockly.utils.Coordinate(0, 0); + return event; + } + + function newConnectEvent(parent, child, inputName, workspaceId) { + const event = new Blockly.Events.BlockMove(child); + event.workspaceId = workspaceId; + event.oldParentId = undefined; + event.oldInputName = undefined; + event.oldCoordinate = new Blockly.utils.Coordinate(0, 0); + event.newParentId = parent.id; + event.newInputName = inputName; + event.newCoordinate = undefined; + return event; + } + + function newMutationEvent(block, workspaceId) { + const event = new Blockly.Events.BlockChange(block); + event.workspaceId = workspaceId; + event.element = 'mutation'; + return event; + } + + test('Events are enqueued', function () { + // Disable events during block creation to avoid firing BlockCreate + // events. + eventUtils.disable(); + const block = this.workspace.newBlock('simple_test_block', '1'); + eventUtils.enable(); + + try { + assert.equal(FIRE_QUEUE.length, 0); + const events = [ + new Blockly.Events.BlockCreate(block), + new Blockly.Events.BlockMove(block), + new Blockly.Events.Click(block), + ]; + events.map((e) => enqueueEvent(e)); + assert.equal(FIRE_QUEUE.length, events.length, 'FIRE_QUEUE.length'); + for (let i = 0; i < events.length; i++) { + assert.equal(FIRE_QUEUE[i], events[i], `FIRE_QUEUE[${i}]`); + } + } finally { + FIRE_QUEUE.length = 0; + } + }); + + test('BlockChange event reordered', function () { + eventUtils.disable(); + const parent = this.workspace.newBlock('inputs_test_block', 'parent'); + const child1 = this.workspace.newBlock('statement_test_block', 'child1'); + const child2 = this.workspace.newBlock('statement_test_block', 'child2'); + eventUtils.enable(); + + try { + assert.equal(FIRE_QUEUE.length, 0); + const events = [ + newDisconnectEvent(parent, child1, 'STATEMENT1'), + newDisconnectEvent(parent, child2, 'STATEMENT2'), + newConnectEvent(parent, child1, 'STATEMENT1'), + newConnectEvent(parent, child2, 'STATEMENT2'), + newMutationEvent(parent), + ]; + events.map((e) => enqueueEvent(e)); + assert.equal(FIRE_QUEUE.length, events.length, 'FIRE_QUEUE.length'); + assert.equal(FIRE_QUEUE[0], events[0], 'FIRE_QUEUE[0]'); + assert.equal(FIRE_QUEUE[1], events[1], 'FIRE_QUEUE[1]'); + assert.equal(FIRE_QUEUE[2], events[4], 'FIRE_QUEUE[2]'); + assert.equal(FIRE_QUEUE[3], events[2], 'FIRE_QUEUE[3]'); + assert.equal(FIRE_QUEUE[4], events[3], 'FIRE_QUEUE[4]'); + } finally { + FIRE_QUEUE.length = 0; + } + }); + + test('BlockChange event for other workspace not reordered', function () { + eventUtils.disable(); + const parent = this.workspace.newBlock('inputs_test_block', 'parent'); + const child = this.workspace.newBlock('statement_test_block', 'child'); + eventUtils.enable(); + + try { + assert.equal(FIRE_QUEUE.length, 0); + const events = [ + newDisconnectEvent(parent, child, 'STATEMENT1', 'ws1'), + newConnectEvent(parent, child, 'STATEMENT1', 'ws1'), + newMutationEvent(parent, 'ws2'), + ]; + events.map((e) => enqueueEvent(e)); + assert.equal(FIRE_QUEUE.length, events.length, 'FIRE_QUEUE.length'); + for (let i = 0; i < events.length; i++) { + assert.equal(FIRE_QUEUE[i], events[i], `FIRE_QUEUE[${i}]`); + } + } finally { + FIRE_QUEUE.length = 0; + } + }); + + test('BlockChange event for other group not reordered', function () { + eventUtils.disable(); + const parent = this.workspace.newBlock('inputs_test_block', 'parent'); + const child = this.workspace.newBlock('statement_test_block', 'child'); + eventUtils.enable(); + + try { + assert.equal(FIRE_QUEUE.length, 0); + const events = []; + eventUtils.setGroup('group1'); + events.push(newDisconnectEvent(parent, child, 'STATEMENT1')); + events.push(newConnectEvent(parent, child, 'STATEMENT1')); + eventUtils.setGroup('group2'); + events.push(newMutationEvent(parent, 'ws2')); + events.map((e) => enqueueEvent(e)); + assert.equal(FIRE_QUEUE.length, events.length, 'FIRE_QUEUE.length'); + for (let i = 0; i < events.length; i++) { + assert.equal(FIRE_QUEUE[i], events[i], `FIRE_QUEUE[${i}]`); + } + } finally { + FIRE_QUEUE.length = 0; + eventUtils.setGroup(false); + } + }); + + test('BlockChange event for other parent not reordered', function () { + eventUtils.disable(); + const parent1 = this.workspace.newBlock('inputs_test_block', 'parent1'); + const parent2 = this.workspace.newBlock('inputs_test_block', 'parent2'); + const child = this.workspace.newBlock('statement_test_block', 'child'); + eventUtils.enable(); + + try { + assert.equal(FIRE_QUEUE.length, 0); + const events = [ + newDisconnectEvent(parent1, child, 'STATEMENT1', 'ws1'), + newConnectEvent(parent1, child, 'STATEMENT1', 'ws1'), + newMutationEvent(parent2, 'ws2'), + ]; + events.map((e) => enqueueEvent(e)); + assert.equal(FIRE_QUEUE.length, events.length, 'FIRE_QUEUE.length'); + for (let i = 0; i < events.length; i++) { + assert.equal(FIRE_QUEUE[i], events[i], `FIRE_QUEUE[${i}]`); + } + } finally { + FIRE_QUEUE.length = 0; + } + }); + }); + suite('Filters', function () { function addMoveEvent(events, block, newX, newY) { events.push(new Blockly.Events.BlockMove(block)); - block.xy_ = new Blockly.utils.Coordinate(newX, newY); + block.xy = new Blockly.utils.Coordinate(newX, newY); events[events.length - 1].recordNew(); } @@ -1106,16 +1303,12 @@ suite('Events', function () { new Blockly.Events.Click(block), ]; const filteredEvents = eventUtils.filter(events, true); - chai.assert.equal(filteredEvents.length, 4); // no event should have been removed. + assert.equal(filteredEvents.length, 4); // no event should have been removed. // test that the order hasn't changed - chai.assert.isTrue( - filteredEvents[0] instanceof Blockly.Events.BlockCreate, - ); - chai.assert.isTrue(filteredEvents[1] instanceof Blockly.Events.BlockMove); - chai.assert.isTrue( - filteredEvents[2] instanceof Blockly.Events.BlockChange, - ); - chai.assert.isTrue(filteredEvents[3] instanceof Blockly.Events.Click); + assert.isTrue(filteredEvents[0] instanceof Blockly.Events.BlockCreate); + assert.isTrue(filteredEvents[1] instanceof Blockly.Events.BlockMove); + assert.isTrue(filteredEvents[2] instanceof Blockly.Events.BlockChange); + assert.isTrue(filteredEvents[3] instanceof Blockly.Events.Click); }); test('Different blocks no removed', function () { @@ -1128,7 +1321,7 @@ suite('Events', function () { new Blockly.Events.BlockMove(block2), ]; const filteredEvents = eventUtils.filter(events, true); - chai.assert.equal(filteredEvents.length, 4); // no event should have been removed. + assert.equal(filteredEvents.length, 4); // no event should have been removed. }); test('Forward', function () { @@ -1138,14 +1331,12 @@ suite('Events', function () { addMoveEvent(events, block, 2, 2); addMoveEvent(events, block, 3, 3); const filteredEvents = eventUtils.filter(events, true); - chai.assert.equal(filteredEvents.length, 2); // duplicate moves should have been removed. + assert.equal(filteredEvents.length, 2); // duplicate moves should have been removed. // test that the order hasn't changed - chai.assert.isTrue( - filteredEvents[0] instanceof Blockly.Events.BlockCreate, - ); - chai.assert.isTrue(filteredEvents[1] instanceof Blockly.Events.BlockMove); - chai.assert.equal(filteredEvents[1].newCoordinate.x, 3); - chai.assert.equal(filteredEvents[1].newCoordinate.y, 3); + assert.isTrue(filteredEvents[0] instanceof Blockly.Events.BlockCreate); + assert.isTrue(filteredEvents[1] instanceof Blockly.Events.BlockMove); + assert.equal(filteredEvents[1].newCoordinate.x, 3); + assert.equal(filteredEvents[1].newCoordinate.y, 3); }); test('Backward', function () { @@ -1155,14 +1346,12 @@ suite('Events', function () { addMoveEvent(events, block, 2, 2); addMoveEvent(events, block, 3, 3); const filteredEvents = eventUtils.filter(events, false); - chai.assert.equal(filteredEvents.length, 2); // duplicate event should have been removed. + assert.equal(filteredEvents.length, 2); // duplicate event should have been removed. // test that the order hasn't changed - chai.assert.isTrue( - filteredEvents[0] instanceof Blockly.Events.BlockCreate, - ); - chai.assert.isTrue(filteredEvents[1] instanceof Blockly.Events.BlockMove); - chai.assert.equal(filteredEvents[1].newCoordinate.x, 1); - chai.assert.equal(filteredEvents[1].newCoordinate.y, 1); + assert.isTrue(filteredEvents[0] instanceof Blockly.Events.BlockCreate); + assert.isTrue(filteredEvents[1] instanceof Blockly.Events.BlockMove); + assert.equal(filteredEvents[1].newCoordinate.x, 1); + assert.equal(filteredEvents[1].newCoordinate.y, 1); }); test('Merge block move events', function () { @@ -1171,9 +1360,9 @@ suite('Events', function () { addMoveEvent(events, block, 0, 0); addMoveEvent(events, block, 1, 1); const filteredEvents = eventUtils.filter(events, true); - chai.assert.equal(filteredEvents.length, 1); // second move event merged into first - chai.assert.equal(filteredEvents[0].newCoordinate.x, 1); - chai.assert.equal(filteredEvents[0].newCoordinate.y, 1); + assert.equal(filteredEvents.length, 1); // second move event merged into first + assert.equal(filteredEvents[0].newCoordinate.x, 1); + assert.equal(filteredEvents[0].newCoordinate.y, 1); }); test('Merge block change events', function () { @@ -1189,9 +1378,9 @@ suite('Events', function () { ), ]; const filteredEvents = eventUtils.filter(events, true); - chai.assert.equal(filteredEvents.length, 1); // second change event merged into first - chai.assert.equal(filteredEvents[0].oldValue, 'item'); - chai.assert.equal(filteredEvents[0].newValue, 'item2'); + assert.equal(filteredEvents.length, 1); // second change event merged into first + assert.equal(filteredEvents[0].oldValue, 'item'); + assert.equal(filteredEvents[0].newValue, 'item2'); }); test('Merge viewport change events', function () { @@ -1200,11 +1389,11 @@ suite('Events', function () { new Blockly.Events.ViewportChange(5, 6, 7, this.workspace, 8), ]; const filteredEvents = eventUtils.filter(events, true); - chai.assert.equal(filteredEvents.length, 1); // second change event merged into first - chai.assert.equal(filteredEvents[0].viewTop, 5); - chai.assert.equal(filteredEvents[0].viewLeft, 6); - chai.assert.equal(filteredEvents[0].scale, 7); - chai.assert.equal(filteredEvents[0].oldScale, 8); + assert.equal(filteredEvents.length, 1); // second change event merged into first + assert.equal(filteredEvents[0].viewTop, 5); + assert.equal(filteredEvents[0].viewLeft, 6); + assert.equal(filteredEvents[0].scale, 7); + assert.equal(filteredEvents[0].oldScale, 8); }); test('Merge ui events', function () { @@ -1221,19 +1410,13 @@ suite('Events', function () { ]; const filteredEvents = eventUtils.filter(events, true); // click event merged into corresponding *Open event - chai.assert.equal(filteredEvents.length, 3); - chai.assert.isTrue( - filteredEvents[0] instanceof Blockly.Events.BubbleOpen, - ); - chai.assert.isTrue( - filteredEvents[1] instanceof Blockly.Events.BubbleOpen, - ); - chai.assert.isTrue( - filteredEvents[2] instanceof Blockly.Events.BubbleOpen, - ); - chai.assert.equal(filteredEvents[0].bubbleType, 'comment'); - chai.assert.equal(filteredEvents[1].bubbleType, 'mutator'); - chai.assert.equal(filteredEvents[2].bubbleType, 'warning'); + assert.equal(filteredEvents.length, 3); + assert.isTrue(filteredEvents[0] instanceof Blockly.Events.BubbleOpen); + assert.isTrue(filteredEvents[1] instanceof Blockly.Events.BubbleOpen); + assert.isTrue(filteredEvents[2] instanceof Blockly.Events.BubbleOpen); + assert.equal(filteredEvents[0].bubbleType, 'comment'); + assert.equal(filteredEvents[1].bubbleType, 'mutator'); + assert.equal(filteredEvents[2].bubbleType, 'warning'); }); test('Colliding events not dropped', function () { @@ -1246,9 +1429,9 @@ suite('Events', function () { ]; const filteredEvents = eventUtils.filter(events, true); // click and stackclick should both exist - chai.assert.equal(filteredEvents.length, 2); - chai.assert.isTrue(filteredEvents[0] instanceof Blockly.Events.Click); - chai.assert.equal(filteredEvents[1].isStart, true); + assert.equal(filteredEvents.length, 2); + assert.isTrue(filteredEvents[0] instanceof Blockly.Events.Click); + assert.equal(filteredEvents[1].isStart, true); }); test('Merging null operations dropped', function () { @@ -1267,7 +1450,7 @@ suite('Events', function () { const filteredEvents = eventUtils.filter(events, true); // The two events should be merged, but because nothing has changed // they will be filtered out. - chai.assert.equal(filteredEvents.length, 0); + assert.equal(filteredEvents.length, 0); }); test('Move events different blocks not merged', function () { @@ -1287,14 +1470,12 @@ suite('Events', function () { const filteredEvents = eventUtils.filter(events, true); // Nothing should have merged. - chai.assert.equal(filteredEvents.length, 4); + assert.equal(filteredEvents.length, 4); // test that the order hasn't changed - chai.assert.isTrue(filteredEvents[0] instanceof Blockly.Events.BlockMove); - chai.assert.isTrue(filteredEvents[1] instanceof Blockly.Events.BlockMove); - chai.assert.isTrue( - filteredEvents[2] instanceof Blockly.Events.BlockDelete, - ); - chai.assert.isTrue(filteredEvents[3] instanceof Blockly.Events.BlockMove); + assert.isTrue(filteredEvents[0] instanceof Blockly.Events.BlockMove); + assert.isTrue(filteredEvents[1] instanceof Blockly.Events.BlockMove); + assert.isTrue(filteredEvents[2] instanceof Blockly.Events.BlockDelete); + assert.isTrue(filteredEvents[3] instanceof Blockly.Events.BlockMove); }); }); @@ -1344,7 +1525,7 @@ suite('Events', function () { ); // Expect the workspace to not have a variable with ID 'test_block_id'. - chai.assert.isNull(this.workspace.getVariableById(TEST_BLOCK_ID)); + assert.isNull(this.workspace.getVariableById(TEST_BLOCK_ID)); } finally { workspaceTeardown.call(this, workspaceSvg); } @@ -1374,11 +1555,7 @@ suite('Events', function () { // Expect both events to trigger change listener. sinon.assert.calledTwice(this.changeListenerSpy); // Both events should be on undo stack - chai.assert.equal( - this.workspace.undoStack_.length, - 2, - 'Undo stack length', - ); + assert.equal(this.workspace.undoStack_.length, 2, 'Undo stack length'); assertNthCallEventArgEquals( this.changeListenerSpy, @@ -1398,7 +1575,7 @@ suite('Events', function () { ); // Expect the workspace to have a variable with ID 'test_var_id'. - chai.assert.isNotNull(this.workspace.getVariableById(TEST_VAR_ID)); + assert.isNotNull(this.workspace.getVariableById(TEST_VAR_ID)); }); test('New block new var xml', function () { @@ -1432,11 +1609,7 @@ suite('Events', function () { // The first varCreate and move event should have been ignored. sinon.assert.callCount(this.changeListenerSpy, 3); // Expect two events on undo stack: varCreate and block create. - chai.assert.equal( - this.workspace.undoStack_.length, - 2, - 'Undo stack length', - ); + assert.equal(this.workspace.undoStack_.length, 2, 'Undo stack length'); assertNthCallEventArgEquals( this.changeListenerSpy, @@ -1466,7 +1639,7 @@ suite('Events', function () { ); // Expect the workspace to have a variable with ID 'test_var_id'. - chai.assert.isNotNull(this.workspace.getVariableById(TEST_VAR_ID)); + assert.isNotNull(this.workspace.getVariableById(TEST_VAR_ID)); }); }); suite('Disable orphans', function () { @@ -1487,7 +1660,7 @@ suite('Events', function () { // Fire all events this.clock.runAll(); - chai.assert.isFalse( + assert.isFalse( block.isEnabled(), 'Expected orphan block to be disabled after creation', ); @@ -1503,7 +1676,7 @@ suite('Events', function () { // Fire all events this.clock.runAll(); - chai.assert.isTrue( + assert.isTrue( functionBlock.isEnabled(), 'Expected top-level procedure block to be enabled', ); @@ -1527,7 +1700,7 @@ suite('Events', function () { // Fire all events this.clock.runAll(); - chai.assert.isFalse( + assert.isFalse( block.isEnabled(), 'Expected disconnected block to be disabled', ); @@ -1548,7 +1721,7 @@ suite('Events', function () { // Fire all events this.clock.runAll(); - chai.assert.isTrue( + assert.isTrue( block.isEnabled(), 'Expected block to be enabled after connecting to parent', ); @@ -1572,10 +1745,10 @@ suite('Events', function () { // Fire all events this.clock.runAll(); - const disabledEvents = this.workspace.getUndoStack().filter(function (e) { - return e.element === 'disabled'; - }); - chai.assert.isEmpty( + const disabledEvents = this.workspace + .getUndoStack() + .filter((e) => e.element === 'disabled'); + assert.isEmpty( disabledEvents, 'Undo stack should not contain any disabled events', ); diff --git a/tests/mocha/event_theme_change_test.js b/tests/mocha/event_theme_change_test.js index 155e373a3f9..f20f745b6a0 100644 --- a/tests/mocha/event_theme_change_test.js +++ b/tests/mocha/event_theme_change_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -29,7 +30,7 @@ suite('Theme Change Event', function () { const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/event_toolbox_item_select_test.js b/tests/mocha/event_toolbox_item_select_test.js index 82f8e4863b2..bf6a9a46212 100644 --- a/tests/mocha/event_toolbox_item_select_test.js +++ b/tests/mocha/event_toolbox_item_select_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -57,7 +58,7 @@ suite('Toolbox Item Select Event', function () { const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/event_trashcan_open_test.js b/tests/mocha/event_trashcan_open_test.js index 84c2abd9c56..2c809f2dfad 100644 --- a/tests/mocha/event_trashcan_open_test.js +++ b/tests/mocha/event_trashcan_open_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -29,7 +30,7 @@ suite('Trashcan Open Event', function () { const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/event_var_create_test.js b/tests/mocha/event_var_create_test.js index 003cd11b5a2..e374c496541 100644 --- a/tests/mocha/event_var_create_test.js +++ b/tests/mocha/event_var_create_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -32,7 +33,7 @@ suite('Var Create Event', function () { const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); test('typed variable events round-trip through JSON', function () { @@ -47,7 +48,7 @@ suite('Var Create Event', function () { const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/event_var_delete_test.js b/tests/mocha/event_var_delete_test.js index 7bad8eb7b73..b06943d9a19 100644 --- a/tests/mocha/event_var_delete_test.js +++ b/tests/mocha/event_var_delete_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -32,7 +33,7 @@ suite('Var Delete Event', function () { const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); test('typed variable events round-trip through JSON', function () { @@ -47,7 +48,7 @@ suite('Var Delete Event', function () { const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/event_var_rename_test.js b/tests/mocha/event_var_rename_test.js index 0c8fb80cdad..7fbd185ab7b 100644 --- a/tests/mocha/event_var_rename_test.js +++ b/tests/mocha/event_var_rename_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -32,7 +33,7 @@ suite('Var Rename Event', function () { const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/event_viewport_test.js b/tests/mocha/event_viewport_test.js index 7913e7bf507..edacc0da6cb 100644 --- a/tests/mocha/event_viewport_test.js +++ b/tests/mocha/event_viewport_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -32,7 +33,7 @@ suite('Viewport Change Event', function () { const json = origEvent.toJson(); const newEvent = new Blockly.Events.fromJson(json, this.workspace); - chai.assert.deepEqual(newEvent, origEvent); + assert.deepEqual(newEvent, origEvent); }); }); }); diff --git a/tests/mocha/extensions_test.js b/tests/mocha/extensions_test.js index 8eb37e75df7..66772cbea4b 100644 --- a/tests/mocha/extensions_test.js +++ b/tests/mocha/extensions_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -27,7 +28,7 @@ suite('Extensions', function () { this.extensionsCleanup_.push('extensions_test_before'); this.extensionsCleanup_.push('extensions_test_after'); - chai.assert.isUndefined( + assert.isUndefined( Blockly.Extensions.TEST_ONLY.allExtensions['extensions_test_before'], ); const beforeCallback = sinon.spy(); @@ -42,18 +43,18 @@ suite('Extensions', function () { }, ]); - chai.assert.isUndefined( + assert.isUndefined( Blockly.Extensions.TEST_ONLY.allExtensions['extensions_test_after'], ); const afterCallback = sinon.spy(); // Extension defined after the block type (but before instantiation). Blockly.Extensions.register('extensions_test_after', afterCallback); - chai.assert.typeOf( + assert.typeOf( Blockly.Extensions.TEST_ONLY.allExtensions['extensions_test_before'], 'function', ); - chai.assert.typeOf( + assert.typeOf( Blockly.Extensions.TEST_ONLY.allExtensions['extensions_test_after'], 'function', ); @@ -98,27 +99,27 @@ suite('Extensions', function () { ); // Tooltip is dynamic after extension initialization. - chai.assert.typeOf(block.tooltip, 'function'); - chai.assert.equal(block.tooltip(), defaultTooltip); + assert.typeOf(block.tooltip, 'function'); + assert.equal(block.tooltip(), defaultTooltip); // Tooltip is normal before connected to parent. const parent = new Blockly.Block(this.workspace, 'test_parent'); - chai.assert.equal(parent.tooltip, parentTooltip); - chai.assert.notExists(parent.inputsInline); + assert.equal(parent.tooltip, parentTooltip); + assert.notExists(parent.inputsInline); // Tooltip is normal when parent is not inline. parent.getInput('INPUT').connection.connect(block.outputConnection); - chai.assert.equal(block.getParent(), parent); - chai.assert.equal(block.tooltip(), defaultTooltip); + assert.equal(block.getParent(), parent); + assert.equal(block.tooltip(), defaultTooltip); // Tooltip is parent's when parent is inline. parent.setInputsInline(true); - chai.assert.equal(block.tooltip(), parentTooltip); + assert.equal(block.tooltip(), parentTooltip); // Tooltip revert when disconnected. parent.getInput('INPUT').connection.disconnect(); - chai.assert.notExists(block.getParent()); - chai.assert.equal(block.tooltip(), defaultTooltip); + assert.notExists(block.getParent()); + assert.equal(block.tooltip(), defaultTooltip); }); suite('Mixin', function () { @@ -132,13 +133,13 @@ suite('Extensions', function () { }, }; - chai.assert.isUndefined( + assert.isUndefined( Blockly.Extensions.TEST_ONLY.allExtensions['mixin_test'], ); // Extension defined before the block type is defined. Blockly.Extensions.registerMixin('mixin_test', testMixin); - chai.assert.typeOf( + assert.typeOf( Blockly.Extensions.TEST_ONLY.allExtensions['mixin_test'], 'function', ); @@ -153,8 +154,8 @@ suite('Extensions', function () { const block = new Blockly.Block(this.workspace, 'test_block_mixin'); - chai.assert.equal(testMixin.field, block.field); - chai.assert.equal(testMixin.method, block.method); + assert.equal(testMixin.field, block.field); + assert.equal(testMixin.method, block.method); }); suite('Mutator', function () { @@ -190,10 +191,10 @@ suite('Extensions', function () { const block = new Blockly.Block(this.workspace, 'mutator_test_block'); // Make sure all of the functions were installed correctly. - chai.assert.equal(block.domToMutation(), 'domToMutationFn'); - chai.assert.equal(block.mutationToDom(), 'mutationToDomFn'); - chai.assert.equal(block.compose(), 'composeFn'); - chai.assert.equal(block.decompose(), 'decomposeFn'); + assert.equal(block.domToMutation(), 'domToMutationFn'); + assert.equal(block.mutationToDom(), 'mutationToDomFn'); + assert.equal(block.compose(), 'composeFn'); + assert.equal(block.decompose(), 'decomposeFn'); }); test('With helper function', function () { @@ -210,7 +211,7 @@ suite('Extensions', function () { // Events code calls mutationToDom and expects it to give back a // meaningful value. Blockly.Events.disable(); - chai.assert.isUndefined( + assert.isUndefined( Blockly.Extensions.TEST_ONLY.allExtensions['extensions_test'], ); const helperFunctionSpy = sinon.spy(); @@ -246,7 +247,7 @@ suite('Extensions', function () { // Events code calls mutationToDom and expects it to give back a // meaningful value. Blockly.Events.disable(); - chai.assert.isUndefined( + assert.isUndefined( Blockly.Extensions.TEST_ONLY.allExtensions['mutator_test'], ); Blockly.Extensions.registerMutator('mutator_test', { @@ -261,10 +262,10 @@ suite('Extensions', function () { const block = new Blockly.Block(this.workspace, 'mutator_test_block'); // Make sure all of the functions were installed correctly. - chai.assert.equal(block.domToMutation(), 'domToMutationFn'); - chai.assert.equal(block.mutationToDom(), 'mutationToDomFn'); - chai.assert.isUndefined(block['compose']); - chai.assert.isUndefined(block['decompose']); + assert.equal(block.domToMutation(), 'domToMutationFn'); + assert.equal(block.mutationToDom(), 'mutationToDomFn'); + assert.isUndefined(block['compose']); + assert.isUndefined(block['decompose']); }); }); }); @@ -279,11 +280,11 @@ suite('Extensions', function () { }, ]); - chai.assert.isUndefined( + assert.isUndefined( Blockly.Extensions.TEST_ONLY.allExtensions['missing_extension'], ); const workspace = this.workspace; - chai.assert.throws(function () { + assert.throws(function () { const _ = new Blockly.Block(workspace, 'missing_extension_block'); }); }); @@ -295,7 +296,7 @@ suite('Extensions', function () { inputList: 'bad inputList', // Defined in constructor }; - chai.assert.isUndefined( + assert.isUndefined( Blockly.Extensions.TEST_ONLY.allExtensions['mixin_bad_inputList'], ); // Extension defined before the block type is defined. @@ -303,7 +304,7 @@ suite('Extensions', function () { 'mixin_bad_inputList', TEST_MIXIN_BAD_INPUTLIST, ); - chai.assert.typeOf( + assert.typeOf( Blockly.Extensions.TEST_ONLY.allExtensions['mixin_bad_inputList'], 'function', ); @@ -317,7 +318,7 @@ suite('Extensions', function () { ]); const workspace = this.workspace; - chai.assert.throws(function () { + assert.throws(function () { const _ = new Blockly.Block(workspace, 'test_block_bad_inputList'); }, /inputList/); }); @@ -329,7 +330,7 @@ suite('Extensions', function () { colour_: 'bad colour_', // Defined on prototype }; - chai.assert.isUndefined( + assert.isUndefined( Blockly.Extensions.TEST_ONLY.allExtensions['mixin_bad_colour_'], ); // Extension defined before the block type is defined. @@ -337,7 +338,7 @@ suite('Extensions', function () { 'mixin_bad_colour_', TEST_MIXIN_BAD_COLOUR, ); - chai.assert.typeOf( + assert.typeOf( Blockly.Extensions.TEST_ONLY.allExtensions['mixin_bad_colour_'], 'function', ); @@ -351,7 +352,7 @@ suite('Extensions', function () { ]); const workspace = this.workspace; - chai.assert.throws(function () { + assert.throws(function () { const _ = new Blockly.Block(workspace, 'test_block_bad_colour'); }, /colour_/); }); @@ -370,7 +371,7 @@ suite('Extensions', function () { // Events code calls mutationToDom and expects it to give back a // meaningful value. Blockly.Events.disable(); - chai.assert.isUndefined( + assert.isUndefined( Blockly.Extensions.TEST_ONLY.allExtensions['mutator_test'], ); Blockly.Extensions.registerMutator('mutator_test', { @@ -383,11 +384,11 @@ suite('Extensions', function () { }); const workspace = this.workspace; - chai.assert.throws(function () { + assert.throws(function () { const _ = new Blockly.Block(workspace, 'mutator_test_block'); }); // Should have failed on apply, not on register. - chai.assert.isNotNull( + assert.isNotNull( Blockly.Extensions.TEST_ONLY.allExtensions['mutator_test'], ); }); @@ -406,7 +407,7 @@ suite('Extensions', function () { // Events code calls mutationToDom and expects it to give back a // meaningful value. Blockly.Events.disable(); - chai.assert.isUndefined( + assert.isUndefined( Blockly.Extensions.TEST_ONLY.allExtensions['mutator_test'], ); Blockly.Extensions.registerMixin('mutator_test', { @@ -419,11 +420,11 @@ suite('Extensions', function () { }); const workspace = this.workspace; - chai.assert.throws(function () { + assert.throws(function () { const _ = new Blockly.Block(workspace, 'mutator_test_block'); }); // Should have failed on apply, not on register. - chai.assert.isNotNull( + assert.isNotNull( Blockly.Extensions.TEST_ONLY.allExtensions['mutator_test'], ); }); @@ -442,7 +443,7 @@ suite('Extensions', function () { // Events code calls mutationToDom and expects it to give back a // meaningful value. Blockly.Events.disable(); - chai.assert.isUndefined( + assert.isUndefined( Blockly.Extensions.TEST_ONLY.allExtensions['extensions_test'], ); Blockly.Extensions.register('extensions_test', function () { @@ -450,11 +451,11 @@ suite('Extensions', function () { }); const workspace = this.workspace; - chai.assert.throws(function () { + assert.throws(function () { const _ = new Blockly.Block(workspace, 'mutator_test_block'); }); // Should have failed on apply, not on register. - chai.assert.isNotNull( + assert.isNotNull( Blockly.Extensions.TEST_ONLY.allExtensions['extensions_test'], ); }); @@ -462,30 +463,30 @@ suite('Extensions', function () { suite('register', function () { test('Just a string', function () { this.extensionsCleanup_.push('extension_just_a_string'); - chai.assert.isUndefined( + assert.isUndefined( Blockly.Extensions.TEST_ONLY.allExtensions['extension_just_a_string'], ); - chai.assert.throws(function () { + assert.throws(function () { Blockly.Extensions.register('extension_just_a_string', null); }); }); test('Null', function () { this.extensionsCleanup_.push('extension_is_null'); - chai.assert.isUndefined( + assert.isUndefined( Blockly.Extensions.TEST_ONLY.allExtensions['extension_is_null'], ); - chai.assert.throws(function () { + assert.throws(function () { Blockly.Extensions.register('extension_is_null', null); }); }); test('Undefined', function () { this.extensionsCleanup_.push('extension_is_undefined'); - chai.assert.isUndefined( + assert.isUndefined( Blockly.Extensions.TEST_ONLY.allExtensions['extension_is_undefined'], ); - chai.assert.throws(function () { + assert.throws(function () { Blockly.Extensions.register('extension_is_undefined', null); }); }); @@ -494,7 +495,7 @@ suite('Extensions', function () { suite('registerMutator', function () { test('No domToMutation', function () { this.extensionsCleanup_.push('mutator_test'); - chai.assert.throws(function () { + assert.throws(function () { Blockly.Extensions.registerMutator('mutator_test', { mutationToDom: function () { return 'mutationToDomFn'; @@ -511,7 +512,7 @@ suite('Extensions', function () { test('No mutationToDom', function () { this.extensionsCleanup_.push('mutator_test'); - chai.assert.throws(function () { + assert.throws(function () { Blockly.Extensions.registerMutator('mutator_test', { domToMutation: function () { return 'domToMutationFn'; @@ -528,7 +529,7 @@ suite('Extensions', function () { test('No saveExtraState', function () { this.extensionsCleanup_.push('mutator_test'); - chai.assert.throws(function () { + assert.throws(function () { Blockly.Extensions.registerMutator('mutator_test', { loadExtraState: function () { return 'loadExtraState'; @@ -545,7 +546,7 @@ suite('Extensions', function () { test('No loadExtraState', function () { this.extensionsCleanup_.push('mutator_test'); - chai.assert.throws(function () { + assert.throws(function () { Blockly.Extensions.registerMutator('mutator_test', { saveExtraState: function () { return 'saveExtraState'; @@ -562,7 +563,7 @@ suite('Extensions', function () { test('No serialization hooks', function () { this.extensionsCleanup_.push('mutator_test'); - chai.assert.throws(function () { + assert.throws(function () { Blockly.Extensions.registerMutator('mutator_test', { compose: function () { return 'composeFn'; @@ -576,7 +577,7 @@ suite('Extensions', function () { test('Has decompose but no compose', function () { this.extensionsCleanup_.push('mutator_test'); - chai.assert.throws(function () { + assert.throws(function () { Blockly.Extensions.registerMutator('mutator_test', { domToMutation: function () { return 'domToMutationFn'; @@ -593,7 +594,7 @@ suite('Extensions', function () { test('Has compose but no decompose', function () { this.extensionsCleanup_.push('mutator_test'); - chai.assert.throws(function () { + assert.throws(function () { Blockly.Extensions.registerMutator('mutator_test', { domToMutation: function () { return 'domToMutationFn'; diff --git a/tests/mocha/field_checkbox_test.js b/tests/mocha/field_checkbox_test.js index 4f9503d9c5b..08190fed823 100644 --- a/tests/mocha/field_checkbox_test.js +++ b/tests/mocha/field_checkbox_test.js @@ -5,6 +5,8 @@ */ import * as Blockly from '../../build/src/core/blockly.js'; +import {assert} from '../../node_modules/chai/chai.js'; +import {defineRowBlock} from './test_helpers/block_definitions.js'; import { assertFieldValue, runConstructorSuiteTests, @@ -16,7 +18,6 @@ import { sharedTestTeardown, workspaceTeardown, } from './test_helpers/setup_teardown.js'; -import {defineRowBlock} from './test_helpers/block_definitions.js'; suite('Checkbox Fields', function () { setup(function () { @@ -223,7 +224,7 @@ suite('Checkbox Fields', function () { }; field.initView(); field.render_(); - chai.assert(field.textContent_.nodeValue, char); + assert(field.textContent_.nodeValue, char); } test('Constant', function () { const checkChar = Blockly.FieldCheckbox.CHECK_CHAR; @@ -251,7 +252,7 @@ suite('Checkbox Fields', function () { assertCharacter(field, Blockly.FieldCheckbox.CHECK_CHAR); field.setCheckCharacter('\u2661'); // Don't call assertCharacter b/c we don't want to re-initialize. - chai.assert.equal(field.textContent_.nodeValue, '\u2661'); + assert.equal(field.textContent_.nodeValue, '\u2661'); }); test('setCheckCharacter Before Init', function () { const field = new Blockly.FieldCheckbox(); @@ -264,10 +265,7 @@ suite('Checkbox Fields', function () { }); assertCharacter(field, '\u2661'); field.setCheckCharacter(null); - chai.assert( - field.textContent_.nodeValue, - Blockly.FieldCheckbox.CHECK_CHAR, - ); + assert(field.textContent_.nodeValue, Blockly.FieldCheckbox.CHECK_CHAR); }); }); }); @@ -282,7 +280,7 @@ suite('Checkbox Fields', function () { const field = new Blockly.FieldCheckbox(value); block.getInput('INPUT').appendField(field, 'CHECK'); const jso = Blockly.serialization.blocks.save(block); - chai.assert.deepEqual(jso['fields'], {'CHECK': value}); + assert.deepEqual(jso['fields'], {'CHECK': value}); }; }); diff --git a/tests/mocha/field_colour_test.js b/tests/mocha/field_colour_test.js index fcc5041bdae..262f978f29d 100644 --- a/tests/mocha/field_colour_test.js +++ b/tests/mocha/field_colour_test.js @@ -5,16 +5,17 @@ */ import * as Blockly from '../../build/src/core/blockly.js'; +import {assert} from '../../node_modules/chai/chai.js'; +import { + createTestBlock, + defineRowBlock, +} from './test_helpers/block_definitions.js'; import { assertFieldValue, runConstructorSuiteTests, runFromJsonSuiteTests, runSetValueTests, } from './test_helpers/fields.js'; -import { - createTestBlock, - defineRowBlock, -} from './test_helpers/block_definitions.js'; import { sharedTestSetup, sharedTestTeardown, @@ -253,8 +254,8 @@ suite('Colour Fields', function () { let index = 0; let node = field.picker.firstChild.firstChild; while (node) { - chai.assert.equal(node.getAttribute('title'), titles[index]); - chai.assert.equal( + assert.equal(node.getAttribute('title'), titles[index]); + assert.equal( Blockly.utils.colour.parse(node.style.backgroundColor), colours[index], ); @@ -331,7 +332,7 @@ suite('Colour Fields', function () { suite('Columns', function () { function assertColumns(field, columns) { field.dropdownCreate(); - chai.assert.equal(field.picker.firstChild.children.length, columns); + assert.equal(field.picker.firstChild.children.length, columns); } test('Constants', function () { const columns = Blockly.FieldColour.COLUMNS; @@ -375,7 +376,7 @@ suite('Colour Fields', function () { const field = new Blockly.FieldColour(value); block.getInput('INPUT').appendField(field, 'COLOUR'); const jso = Blockly.serialization.blocks.save(block); - chai.assert.deepEqual(jso['fields'], {'COLOUR': value}); + assert.deepEqual(jso['fields'], {'COLOUR': value}); }; }); diff --git a/tests/mocha/field_dropdown_test.js b/tests/mocha/field_dropdown_test.js index 6162112876c..61deaf47f39 100644 --- a/tests/mocha/field_dropdown_test.js +++ b/tests/mocha/field_dropdown_test.js @@ -5,16 +5,17 @@ */ import * as Blockly from '../../build/src/core/blockly.js'; +import {assert} from '../../node_modules/chai/chai.js'; +import { + createTestBlock, + defineRowBlock, +} from './test_helpers/block_definitions.js'; import { assertFieldValue, runConstructorSuiteTests, runFromJsonSuiteTests, runSetValueTests, } from './test_helpers/fields.js'; -import { - createTestBlock, - defineRowBlock, -} from './test_helpers/block_definitions.js'; import { sharedTestSetup, sharedTestTeardown, @@ -252,7 +253,7 @@ suite('Dropdown Fields', function () { field.setValue(value); block.getInput('INPUT').appendField(field, 'DROPDOWN'); const jso = Blockly.serialization.blocks.save(block); - chai.assert.deepEqual(jso['fields'], {'DROPDOWN': value}); + assert.deepEqual(jso['fields'], {'DROPDOWN': value}); }; }); diff --git a/tests/mocha/field_image_test.js b/tests/mocha/field_image_test.js index ec8ad222712..89dd5fcc91b 100644 --- a/tests/mocha/field_image_test.js +++ b/tests/mocha/field_image_test.js @@ -5,6 +5,7 @@ */ import * as Blockly from '../../build/src/core/blockly.js'; +import {assert} from '../../node_modules/chai/chai.js'; import { assertFieldValue, runConstructorSuiteTests, @@ -134,23 +135,23 @@ suite('Image Fields', function () { }); test('JS Constructor', function () { const field = new Blockly.FieldImage('src', 10, 10, null, this.onClick); - chai.assert.equal(field.clickHandler, this.onClick); + assert.equal(field.clickHandler, this.onClick); }); test('setOnClickHandler', function () { const field = new Blockly.FieldImage('src', 10, 10); field.setOnClickHandler(this.onClick); - chai.assert.equal(field.clickHandler, this.onClick); + assert.equal(field.clickHandler, this.onClick); }); test('Remove Click Handler', function () { const field = new Blockly.FieldImage('src', 10, 10, null, this.onClick); field.setOnClickHandler(null); - chai.assert.isNull(field.clickHandler); + assert.isNull(field.clickHandler); }); }); suite('Alt', function () { test('JS Constructor', function () { const field = new Blockly.FieldImage('src', 10, 10, 'alt'); - chai.assert.equal(field.getText(), 'alt'); + assert.equal(field.getText(), 'alt'); }); test('JSON Definition', function () { const field = Blockly.FieldImage.fromJson({ @@ -159,7 +160,7 @@ suite('Image Fields', function () { height: 10, alt: 'alt', }); - chai.assert.equal(field.getText(), 'alt'); + assert.equal(field.getText(), 'alt'); }); suite('SetAlt', function () { setup(function () { @@ -182,31 +183,31 @@ suite('Image Fields', function () { const field = new Blockly.FieldImage('src', 10, 10, null, null, null, { alt: 'alt', }); - chai.assert.equal(field.getText(), 'alt'); + assert.equal(field.getText(), 'alt'); }); test('JS Configuration - Ignore', function () { const field = new Blockly.FieldImage('src', 10, 10, 'alt', null, null, { alt: 'configAlt', }); - chai.assert.equal(field.getText(), 'configAlt'); + assert.equal(field.getText(), 'configAlt'); }); test("JS Configuration - Ignore - ''", function () { const field = new Blockly.FieldImage('src', 10, 10, '', null, null, { alt: 'configAlt', }); - chai.assert.equal(field.getText(), 'configAlt'); + assert.equal(field.getText(), 'configAlt'); }); test("JS Configuration - Ignore - Config ''", function () { const field = new Blockly.FieldImage('src', 10, 10, 'alt', null, null, { alt: '', }); - chai.assert.equal(field.getText(), ''); + assert.equal(field.getText(), ''); }); }); suite('Flip RTL', function () { test('JS Constructor', function () { const field = new Blockly.FieldImage('src', 10, 10, null, null, true); - chai.assert.isTrue(field.getFlipRtl()); + assert.isTrue(field.getFlipRtl()); }); test('JSON Definition', function () { const field = Blockly.FieldImage.fromJson({ @@ -215,25 +216,25 @@ suite('Image Fields', function () { height: 10, flipRtl: true, }); - chai.assert.isTrue(field.getFlipRtl()); + assert.isTrue(field.getFlipRtl()); }); test('JS Configuration - Simple', function () { const field = new Blockly.FieldImage('src', 10, 10, null, null, null, { flipRtl: true, }); - chai.assert.isTrue(field.getFlipRtl()); + assert.isTrue(field.getFlipRtl()); }); test('JS Configuration - Ignore - True', function () { const field = new Blockly.FieldImage('src', 10, 10, null, null, true, { flipRtl: false, }); - chai.assert.isFalse(field.getFlipRtl()); + assert.isFalse(field.getFlipRtl()); }); test('JS Configuration - Ignore - False', function () { const field = new Blockly.FieldImage('src', 10, 10, null, null, false, { flipRtl: true, }); - chai.assert.isTrue(field.getFlipRtl()); + assert.isTrue(field.getFlipRtl()); }); }); }); diff --git a/tests/mocha/field_label_serializable_test.js b/tests/mocha/field_label_serializable_test.js index 37052f046cf..a831713412c 100644 --- a/tests/mocha/field_label_serializable_test.js +++ b/tests/mocha/field_label_serializable_test.js @@ -5,6 +5,11 @@ */ import * as Blockly from '../../build/src/core/blockly.js'; +import {assert} from '../../node_modules/chai/chai.js'; +import { + createTestBlock, + defineRowBlock, +} from './test_helpers/block_definitions.js'; import { assertFieldValue, runConstructorSuiteTests, @@ -16,10 +21,6 @@ import { sharedTestTeardown, workspaceTeardown, } from './test_helpers/setup_teardown.js'; -import { - createTestBlock, - defineRowBlock, -} from './test_helpers/block_definitions.js'; suite('Label Serializable Fields', function () { setup(function () { @@ -137,7 +138,7 @@ suite('Label Serializable Fields', function () { FIELD_TEXT_BASELINE_Y: 13, }; labelField.initView(); - chai.assert.isTrue( + assert.isTrue( Blockly.utils.dom.hasClass(labelField.textElement_, cssClass), ); } @@ -151,7 +152,7 @@ suite('Label Serializable Fields', function () { FIELD_TEXT_BASELINE_Y: 13, }; labelField.initView(); - chai.assert.isFalse( + assert.isFalse( Blockly.utils.dom.hasClass(labelField.textElement_, cssClass), ); } @@ -204,7 +205,7 @@ suite('Label Serializable Fields', function () { field.initView(); field.setClass('testClass'); // Don't call assertHasClass b/c we don't want to re-initialize. - chai.assert.isTrue( + assert.isTrue( Blockly.utils.dom.hasClass(field.textElement_, 'testClass'), ); }); @@ -219,7 +220,7 @@ suite('Label Serializable Fields', function () { }); assertHasClass(field, 'testClass'); field.setClass(null); - chai.assert.isFalse( + assert.isFalse( Blockly.utils.dom.hasClass(field.textElement_, 'testClass'), ); }); @@ -236,7 +237,7 @@ suite('Label Serializable Fields', function () { const field = new Blockly.FieldLabelSerializable(value); block.getInput('INPUT').appendField(field, 'LABEL'); const jso = Blockly.serialization.blocks.save(block); - chai.assert.deepEqual(jso['fields'], {'LABEL': value}); + assert.deepEqual(jso['fields'], {'LABEL': value}); }; }); diff --git a/tests/mocha/field_label_test.js b/tests/mocha/field_label_test.js index 368e7fd3cf7..cf5b4904493 100644 --- a/tests/mocha/field_label_test.js +++ b/tests/mocha/field_label_test.js @@ -5,6 +5,8 @@ */ import * as Blockly from '../../build/src/core/blockly.js'; +import {assert} from '../../node_modules/chai/chai.js'; +import {createTestBlock} from './test_helpers/block_definitions.js'; import { assertFieldValue, runConstructorSuiteTests, @@ -15,7 +17,6 @@ import { sharedTestSetup, sharedTestTeardown, } from './test_helpers/setup_teardown.js'; -import {createTestBlock} from './test_helpers/block_definitions.js'; suite('Label Fields', function () { setup(function () { @@ -133,7 +134,7 @@ suite('Label Fields', function () { FIELD_TEXT_BASELINE_Y: 13, }; labelField.initView(); - chai.assert.isTrue( + assert.isTrue( Blockly.utils.dom.hasClass(labelField.textElement_, cssClass), ); } @@ -147,7 +148,7 @@ suite('Label Fields', function () { FIELD_TEXT_BASELINE_Y: 13, }; labelField.initView(); - chai.assert.isFalse( + assert.isFalse( Blockly.utils.dom.hasClass(labelField.textElement_, cssClass), ); } @@ -201,7 +202,7 @@ suite('Label Fields', function () { field.initView(); field.setClass('testClass'); // Don't call assertHasClass b/c we don't want to re-initialize. - chai.assert.isTrue( + assert.isTrue( Blockly.utils.dom.hasClass(field.textElement_, 'testClass'), ); }); @@ -216,7 +217,7 @@ suite('Label Fields', function () { }); assertHasClass(field, 'testClass'); field.setClass(null); - chai.assert.isFalse( + assert.isFalse( Blockly.utils.dom.hasClass(field.textElement_, 'testClass'), ); }); diff --git a/tests/mocha/field_number_test.js b/tests/mocha/field_number_test.js index c6737668d05..768766bf013 100644 --- a/tests/mocha/field_number_test.js +++ b/tests/mocha/field_number_test.js @@ -5,19 +5,20 @@ */ import * as Blockly from '../../build/src/core/blockly.js'; +import {assert} from '../../node_modules/chai/chai.js'; +import {defineRowBlock} from './test_helpers/block_definitions.js'; +import {runTestCases} from './test_helpers/common.js'; import { assertFieldValue, runConstructorSuiteTests, runFromJsonSuiteTests, runSetValueTests, } from './test_helpers/fields.js'; -import {defineRowBlock} from './test_helpers/block_definitions.js'; import { sharedTestSetup, sharedTestTeardown, workspaceTeardown, } from './test_helpers/setup_teardown.js'; -import {runTestCases} from './test_helpers/common.js'; suite('Number Fields', function () { setup(function () { @@ -87,9 +88,9 @@ suite('Number Fields', function () { expectedValue, ) { assertFieldValue(field, expectedValue); - chai.assert.equal(field.getMin(), expectedMin, 'Min'); - chai.assert.equal(field.getMax(), expectedMax, 'Max'); - chai.assert.equal(field.getPrecision(), expectedPrecision, 'Precision'); + assert.equal(field.getMin(), expectedMin, 'Min'); + assert.equal(field.getMax(), expectedMax, 'Max'); + assert.equal(field.getPrecision(), expectedPrecision, 'Precision'); } /** * Asserts that the field property values are set to default. @@ -190,7 +191,7 @@ suite('Number Fields', function () { }); test('Null', function () { const field = Blockly.FieldNumber.fromJson({precision: null}); - chai.assert.equal(field.getPrecision(), 0); + assert.equal(field.getPrecision(), 0); }); }); const setValueBoundsTestFn = function (testCase) { @@ -226,7 +227,7 @@ suite('Number Fields', function () { runTestCases(testCases, setValueBoundsTestFn); test('Null', function () { const field = Blockly.FieldNumber.fromJson({min: null}); - chai.assert.equal(field.getMin(), -Infinity); + assert.equal(field.getMin(), -Infinity); }); }); suite('Max', function () { @@ -253,7 +254,7 @@ suite('Number Fields', function () { runTestCases(testCases, setValueBoundsTestFn); test('Null', function () { const field = Blockly.FieldNumber.fromJson({max: null}); - chai.assert.equal(field.getMax(), Infinity); + assert.equal(field.getMax(), Infinity); }); }); }); @@ -302,7 +303,7 @@ suite('Number Fields', function () { test('When Editing', function () { this.field.isBeingEdited_ = true; this.field.htmlInput_.value = String(suiteInfo.value); - this.field.onHtmlInputChange_(null); + this.field.onHtmlInputChange(null); assertFieldValue( this.field, suiteInfo.expectedValue, @@ -473,7 +474,7 @@ suite('Number Fields', function () { const field = new Blockly.FieldNumber(value); block.getInput('INPUT').appendField(field, 'NUMBER'); const jso = Blockly.serialization.blocks.save(block); - chai.assert.deepEqual(jso['fields'], {'NUMBER': value}); + assert.deepEqual(jso['fields'], {'NUMBER': value}); }; }); diff --git a/tests/mocha/field_registry_test.js b/tests/mocha/field_registry_test.js index aca5487469b..26b33c16c3d 100644 --- a/tests/mocha/field_registry_test.js +++ b/tests/mocha/field_registry_test.js @@ -5,7 +5,7 @@ */ import * as Blockly from '../../build/src/core/blockly.js'; -import {createDeprecationWarningStub} from './test_helpers/warnings.js'; +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -37,20 +37,20 @@ suite('Field Registry', function () { Blockly.fieldRegistry.register('field_custom_test', CustomFieldType); }); test('fromJson as Key', function () { - chai.assert.throws(function () { + assert.throws(function () { Blockly.fieldRegistry.register(CustomFieldType.fromJson, ''); }, 'Invalid name'); }); test('No fromJson', function () { class IncorrectField {} - chai.assert.throws(function () { + assert.throws(function () { Blockly.fieldRegistry.register('field_custom_test', IncorrectField); }, 'must have a fromJson function'); }); test('fromJson not a function', function () { const fromJson = CustomFieldType.fromJson; CustomFieldType.fromJson = true; - chai.assert.throws(function () { + assert.throws(function () { Blockly.fieldRegistry.register('field_custom_test', CustomFieldType); }, 'must have a fromJson function'); CustomFieldType.fromJson = fromJson; @@ -67,8 +67,8 @@ suite('Field Registry', function () { const field = Blockly.fieldRegistry.fromJson(json); - chai.assert.isNotNull(field); - chai.assert.equal(field.getValue(), 'ok'); + assert.isNotNull(field); + assert.equal(field.getValue(), 'ok'); }); test('Not Registered', function () { const json = { @@ -78,8 +78,8 @@ suite('Field Registry', function () { const spy = sinon.stub(console, 'warn'); const field = Blockly.fieldRegistry.fromJson(json); - chai.assert.isNull(field); - chai.assert.isTrue(spy.called); + assert.isNull(field); + assert.isTrue(spy.called); spy.restore(); }); test('Case Different', function () { @@ -92,8 +92,8 @@ suite('Field Registry', function () { const field = Blockly.fieldRegistry.fromJson(json); - chai.assert.isNotNull(field); - chai.assert.equal(field.getValue(), 'ok'); + assert.isNotNull(field); + assert.equal(field.getValue(), 'ok'); }); test('Did not override fromJson', function () { // This class will have a fromJson method, so it can be registered @@ -107,7 +107,7 @@ suite('Field Registry', function () { value: 'ok', }; - chai.assert.throws(function () { + assert.throws(function () { Blockly.fieldRegistry.fromJson(json); }, 'Attempted to instantiate a field from the registry'); }); diff --git a/tests/mocha/field_test.js b/tests/mocha/field_test.js index 7265a1bb4cd..38f9662d6d6 100644 --- a/tests/mocha/field_test.js +++ b/tests/mocha/field_test.js @@ -5,6 +5,7 @@ */ import * as Blockly from '../../build/src/core/blockly.js'; +import {assert} from '../../node_modules/chai/chai.js'; import { addBlockTypeToCleanup, addMessageToCleanup, @@ -12,7 +13,6 @@ import { sharedTestTeardown, workspaceTeardown, } from './test_helpers/setup_teardown.js'; -import {createDeprecationWarningStub} from './test_helpers/warnings.js'; suite('Abstract Fields', function () { setup(function () { @@ -65,26 +65,26 @@ suite('Abstract Fields', function () { // An old default field should be serialized. const field = new FieldDefault(); const stub = sinon.stub(console, 'warn'); - chai.assert.isTrue(field.isSerializable()); + assert.isTrue(field.isSerializable()); sinon.assert.calledOnce(stub); stub.restore(); }); test('Editable False, Serializable Default(false)', function () { // An old non-editable field should not be serialized. const field = new FieldFalseDefault(); - chai.assert.isFalse(field.isSerializable()); + assert.isFalse(field.isSerializable()); }); /* Test Other Cases */ test('Editable Default(true), Serializable True', function () { // A field that is both editable and serializable should be serialized. const field = new FieldDefaultTrue(); - chai.assert.isTrue(field.isSerializable()); + assert.isTrue(field.isSerializable()); }); test('Editable False, Serializable True', function () { // A field that is not editable, but overrides serializable to true // should be serialized (e.g. field_label_serializable) const field = new FieldFalseTrue(); - chai.assert.isTrue(field.isSerializable()); + assert.isTrue(field.isSerializable()); }); }); @@ -193,19 +193,19 @@ suite('Abstract Fields', function () { test('No implementations', function () { const field = new DefaultSerializationField('test value'); const value = field.saveState(); - chai.assert.equal(value, 'test value'); + assert.equal(value, 'test value'); }); test('Xml implementations', function () { const field = new CustomXmlField('test value'); const value = field.saveState(); - chai.assert.equal(value, 'custom value'); + assert.equal(value, 'custom value'); }); test('Xml super implementation', function () { const field = new CustomXmlCallSuperField('test value'); const value = field.saveState(); - chai.assert.equal( + assert.equal( value, 'test value', ); @@ -214,13 +214,13 @@ suite('Abstract Fields', function () { test('JSO implementations', function () { const field = new CustomJsoField('test value'); const value = field.saveState(); - chai.assert.equal(value, 'custom value'); + assert.equal(value, 'custom value'); }); test('JSO super implementations', function () { const field = new CustomJsoCallSuperField('test value'); const value = field.saveState(); - chai.assert.deepEqual(value, { + assert.deepEqual(value, { default: 'test value', val: 'custom value', }); @@ -229,7 +229,7 @@ suite('Abstract Fields', function () { test('Xml and JSO implementations', function () { const field = new CustomXmlAndJsoField('test value'); const value = field.saveState(); - chai.assert.equal(value, 'custom value'); + assert.equal(value, 'custom value'); }); }); @@ -238,7 +238,7 @@ suite('Abstract Fields', function () { const field = new DefaultSerializationField('test value'); const element = document.createElement('field'); const value = Blockly.Xml.domToText(field.toXml(element)); - chai.assert.equal( + assert.equal( value, 'test value', ); @@ -248,7 +248,7 @@ suite('Abstract Fields', function () { const field = new CustomXmlField('test value'); const element = document.createElement('field'); const value = Blockly.Xml.domToText(field.toXml(element)); - chai.assert.equal( + assert.equal( value, 'custom value', ); @@ -258,7 +258,7 @@ suite('Abstract Fields', function () { const field = new CustomXmlCallSuperField('test value'); const element = document.createElement('field'); const value = Blockly.Xml.domToText(field.toXml(element)); - chai.assert.equal( + assert.equal( value, 'test value', @@ -269,7 +269,7 @@ suite('Abstract Fields', function () { const field = new CustomXmlAndJsoField('test value'); const element = document.createElement('field'); const value = Blockly.Xml.domToText(field.toXml(element)); - chai.assert.equal( + assert.equal( value, 'custom value', ); @@ -282,13 +282,13 @@ suite('Abstract Fields', function () { test('No implementations', function () { const field = new DefaultSerializationField(''); field.loadState('test value'); - chai.assert.equal(field.getValue(), 'test value'); + assert.equal(field.getValue(), 'test value'); }); test('Xml implementations', function () { const field = new CustomXmlField(''); field.loadState('custom value'); - chai.assert.equal(field.someProperty, 'custom value'); + assert.equal(field.someProperty, 'custom value'); }); test('Xml super implementation', function () { @@ -296,27 +296,27 @@ suite('Abstract Fields', function () { field.loadState( 'test value', ); - chai.assert.equal(field.getValue(), 'test value'); - chai.assert.equal(field.someProperty, 'custom value'); + assert.equal(field.getValue(), 'test value'); + assert.equal(field.someProperty, 'custom value'); }); test('JSO implementations', function () { const field = new CustomJsoField(''); field.loadState('custom value'); - chai.assert.equal(field.someProperty, 'custom value'); + assert.equal(field.someProperty, 'custom value'); }); test('JSO super implementations', function () { const field = new CustomJsoCallSuperField(''); field.loadState({default: 'test value', val: 'custom value'}); - chai.assert.equal(field.getValue(), 'test value'); - chai.assert.equal(field.someProperty, 'custom value'); + assert.equal(field.getValue(), 'test value'); + assert.equal(field.someProperty, 'custom value'); }); test('Xml and JSO implementations', function () { const field = new CustomXmlAndJsoField(''); field.loadState('custom value'); - chai.assert.equal(field.someProperty, 'custom value'); + assert.equal(field.someProperty, 'custom value'); }); }); @@ -326,7 +326,7 @@ suite('Abstract Fields', function () { field.fromXml( Blockly.utils.xml.textToDom('test value'), ); - chai.assert.equal(field.getValue(), 'test value'); + assert.equal(field.getValue(), 'test value'); }); test('Xml implementations', function () { @@ -334,7 +334,7 @@ suite('Abstract Fields', function () { field.fromXml( Blockly.utils.xml.textToDom('custom value'), ); - chai.assert.equal(field.someProperty, 'custom value'); + assert.equal(field.someProperty, 'custom value'); }); test('Xml super implementation', function () { @@ -344,8 +344,8 @@ suite('Abstract Fields', function () { 'test value', ), ); - chai.assert.equal(field.getValue(), 'test value'); - chai.assert.equal(field.someProperty, 'custom value'); + assert.equal(field.getValue(), 'test value'); + assert.equal(field.someProperty, 'custom value'); }); test('XML andd JSO implementations', function () { @@ -353,7 +353,7 @@ suite('Abstract Fields', function () { field.fromXml( Blockly.utils.xml.textToDom('custom value'), ); - chai.assert.equal(field.someProperty, 'custom value'); + assert.equal(field.someProperty, 'custom value'); }); }); }); @@ -572,7 +572,7 @@ suite('Abstract Fields', function () { stubClassValidatorWithReturn(this.field, undefined); addSpies(this.field); this.field.setValue('value'); - chai.assert.equal(this.field.getValue(), 'value'); + assert.equal(this.field.getValue(), 'value'); sinon.assert.notCalled(this.field.doValueInvalid_); sinon.assert.calledOnce(this.field.doValueUpdate_); }); @@ -603,7 +603,7 @@ suite('Abstract Fields', function () { setLocalValidatorWithReturn(this.field, undefined); addSpies(this.field); this.field.setValue('value'); - chai.assert.equal(this.field.getValue(), 'value'); + assert.equal(this.field.getValue(), 'value'); sinon.assert.notCalled(this.field.doValueInvalid_); sinon.assert.calledOnce(this.field.doValueUpdate_); }); @@ -626,7 +626,7 @@ suite('Abstract Fields', function () { const field = new Blockly.Field('value', null, { tooltip: 'test tooltip', }); - chai.assert.equal(field.tooltip_, 'test tooltip'); + assert.equal(field.getTooltip(), 'test tooltip'); }); test('JS Constructor - Dynamic', function () { const returnTooltip = function () { @@ -635,13 +635,13 @@ suite('Abstract Fields', function () { const field = new Blockly.Field('value', null, { tooltip: returnTooltip, }); - chai.assert.equal(field.tooltip_, returnTooltip); + assert.equal(field.getTooltip(), returnTooltip()); }); test('JSON Definition', function () { const field = CustomField.fromJson({ tooltip: 'test tooltip', }); - chai.assert.equal(field.tooltip_, 'test tooltip'); + assert.equal(field.getTooltip(), 'test tooltip'); }); suite('W/ Msg References', function () { setup(function () { @@ -652,13 +652,13 @@ suite('Abstract Fields', function () { const field = new Blockly.Field('value', null, { tooltip: '%{BKY_TOOLTIP}', }); - chai.assert.equal(field.tooltip_, 'test tooltip'); + assert.equal(field.getTooltip(), 'test tooltip'); }); test('JSON Definition', function () { const field = CustomField.fromJson({ tooltip: '%{BKY_TOOLTIP}', }); - chai.assert.equal(field.tooltip_, 'test tooltip'); + assert.equal(field.getTooltip(), 'test tooltip'); }); }); suite('setTooltip', function () { @@ -687,7 +687,7 @@ suite('Abstract Fields', function () { this.workspace, ); const field = block.getField('TOOLTIP'); - chai.assert.equal(field.getClickTarget_().tooltip, 'tooltip'); + assert.equal(field.getClickTarget_().tooltip, 'tooltip'); }); test('After Append', function () { addBlockTypeToCleanup(this.sharedCleanup, 'tooltip'); @@ -707,7 +707,7 @@ suite('Abstract Fields', function () { this.workspace, ); const field = block.getField('TOOLTIP'); - chai.assert.equal(field.getClickTarget_().tooltip, 'tooltip'); + assert.equal(field.getClickTarget_().tooltip, 'tooltip'); }); test('After Block Creation', function () { addBlockTypeToCleanup(this.sharedCleanup, 'tooltip'); @@ -727,7 +727,7 @@ suite('Abstract Fields', function () { ); const field = block.getField('TOOLTIP'); field.setTooltip('tooltip'); - chai.assert.equal(field.getClickTarget_().tooltip, 'tooltip'); + assert.equal(field.getClickTarget_().tooltip, 'tooltip'); }); test('Dynamic Function', function () { addBlockTypeToCleanup(this.sharedCleanup, 'tooltip'); @@ -751,7 +751,7 @@ suite('Abstract Fields', function () { this.workspace, ); const field = block.getField('TOOLTIP'); - chai.assert.equal(field.getClickTarget_().tooltip, block.tooltipFunc); + assert.equal(field.getClickTarget_().tooltip, block.tooltipFunc); }); test('Element', function () { addBlockTypeToCleanup(this.sharedCleanup, 'tooltip'); @@ -774,7 +774,7 @@ suite('Abstract Fields', function () { this.workspace, ); const field = block.getField('TOOLTIP'); - chai.assert.equal(field.getClickTarget_().tooltip, block.element); + assert.equal(field.getClickTarget_().tooltip, block.element); }); test('Null', function () { addBlockTypeToCleanup(this.sharedCleanup, 'tooltip'); @@ -794,7 +794,7 @@ suite('Abstract Fields', function () { this.workspace, ); const field = block.getField('TOOLTIP'); - chai.assert.equal(field.getClickTarget_().tooltip, block); + assert.equal(field.getClickTarget_().tooltip, block); }); test('Undefined', function () { addBlockTypeToCleanup(this.sharedCleanup, 'tooltip'); @@ -813,7 +813,7 @@ suite('Abstract Fields', function () { this.workspace, ); const field = block.getField('TOOLTIP'); - chai.assert.equal(field.getClickTarget_().tooltip, block); + assert.equal(field.getClickTarget_().tooltip, block); }); }); }); diff --git a/tests/mocha/field_textinput_test.js b/tests/mocha/field_textinput_test.js index f68006e8768..7170b27ff62 100644 --- a/tests/mocha/field_textinput_test.js +++ b/tests/mocha/field_textinput_test.js @@ -5,16 +5,17 @@ */ import * as Blockly from '../../build/src/core/blockly.js'; +import {assert} from '../../node_modules/chai/chai.js'; +import { + createTestBlock, + defineRowBlock, +} from './test_helpers/block_definitions.js'; import { assertFieldValue, runConstructorSuiteTests, runFromJsonSuiteTests, runSetValueTests, } from './test_helpers/fields.js'; -import { - createTestBlock, - defineRowBlock, -} from './test_helpers/block_definitions.js'; import { sharedTestSetup, sharedTestTeardown, @@ -171,7 +172,7 @@ suite('Text Input Fields', function () { test('When Editing', function () { this.field.isBeingEdited_ = true; this.field.htmlInput_.value = suiteInfo.value; - this.field.onHtmlInputChange_(null); + this.field.onHtmlInputChange(null); assertFieldValue( this.field, suiteInfo.expectedValue, @@ -228,7 +229,7 @@ suite('Text Input Fields', function () { this.assertSpellcheck = function (field, value) { this.prepField(field); field.showEditor_(); - chai.assert.equal( + assert.equal( field.htmlInput_.getAttribute('spellcheck'), value.toString(), ); @@ -266,7 +267,7 @@ suite('Text Input Fields', function () { this.prepField(field); field.showEditor_(); field.setSpellcheck(false); - chai.assert.equal(field.htmlInput_.getAttribute('spellcheck'), 'false'); + assert.equal(field.htmlInput_.getAttribute('spellcheck'), 'false'); }); }); }); @@ -281,7 +282,7 @@ suite('Text Input Fields', function () { const field = new Blockly.FieldTextInput(value); block.getInput('INPUT').appendField(field, 'TEXT'); const jso = Blockly.serialization.blocks.save(block); - chai.assert.deepEqual(jso['fields'], {'TEXT': value}); + assert.deepEqual(jso['fields'], {'TEXT': value}); }; }); diff --git a/tests/mocha/field_variable_test.js b/tests/mocha/field_variable_test.js index 0815303c655..78dad10bac3 100644 --- a/tests/mocha/field_variable_test.js +++ b/tests/mocha/field_variable_test.js @@ -5,6 +5,11 @@ */ import * as Blockly from '../../build/src/core/blockly.js'; +import {assert} from '../../node_modules/chai/chai.js'; +import { + createTestBlock, + defineRowBlock, +} from './test_helpers/block_definitions.js'; import { assertFieldValue, runConstructorSuiteTests, @@ -17,10 +22,6 @@ import { sharedTestTeardown, workspaceTeardown, } from './test_helpers/setup_teardown.js'; -import { - createTestBlock, - defineRowBlock, -} from './test_helpers/block_definitions.js'; suite('Variable Fields', function () { const FAKE_VARIABLE_NAME = 'default_name'; @@ -135,8 +136,8 @@ suite('Variable Fields', function () { suite('initModel', function () { test('No Value Before InitModel', function () { const fieldVariable = new Blockly.FieldVariable('name1'); - chai.assert.equal(fieldVariable.getText(), ''); - chai.assert.isNull(fieldVariable.getValue()); + assert.equal(fieldVariable.getText(), ''); + assert.isNull(fieldVariable.getValue()); }); }); @@ -199,19 +200,13 @@ suite('Variable Fields', function () { const dropdownOptions = Blockly.FieldVariable.dropdownCreate.call(fieldVariable); // Expect variable options, a rename option, and a delete option. - chai.assert.lengthOf(dropdownOptions, expectedVarOptions.length + 2); + assert.lengthOf(dropdownOptions, expectedVarOptions.length + 2); for (let i = 0, option; (option = expectedVarOptions[i]); i++) { - chai.assert.deepEqual(dropdownOptions[i], option); + assert.deepEqual(dropdownOptions[i], option); } - chai.assert.include( - dropdownOptions[dropdownOptions.length - 2][0], - 'Rename', - ); + assert.include(dropdownOptions[dropdownOptions.length - 2][0], 'Rename'); - chai.assert.include( - dropdownOptions[dropdownOptions.length - 1][0], - 'Delete', - ); + assert.include(dropdownOptions[dropdownOptions.length - 1][0], 'Delete'); }; test('Contains variables created before field', function () { this.workspace.createVariable('name1', '', 'id1'); @@ -311,8 +306,8 @@ suite('Variable Fields', function () { ['Type1'], 'Type1', ); - chai.assert.deepEqual(field.variableTypes, ['Type1']); - chai.assert.equal(field.defaultType, 'Type1'); + assert.deepEqual(field.variableTypes, ['Type1']); + assert.equal(field.defaultType, 'Type1'); }); test('JSON Definition', function () { const field = Blockly.FieldVariable.fromJson({ @@ -320,8 +315,8 @@ suite('Variable Fields', function () { variableTypes: ['Type1'], defaultType: 'Type1', }); - chai.assert.deepEqual(field.variableTypes, ['Type1']); - chai.assert.equal(field.defaultType, 'Type1'); + assert.deepEqual(field.variableTypes, ['Type1']); + assert.equal(field.defaultType, 'Type1'); }); test('JS Configuration - Simple', function () { const field = new Blockly.FieldVariable( @@ -334,8 +329,8 @@ suite('Variable Fields', function () { defaultType: 'Type1', }, ); - chai.assert.deepEqual(field.variableTypes, ['Type1']); - chai.assert.equal(field.defaultType, 'Type1'); + assert.deepEqual(field.variableTypes, ['Type1']); + assert.equal(field.defaultType, 'Type1'); }); test('JS Configuration - Ignore', function () { const field = new Blockly.FieldVariable( @@ -348,8 +343,8 @@ suite('Variable Fields', function () { defaultType: 'Type1', }, ); - chai.assert.deepEqual(field.variableTypes, ['Type1']); - chai.assert.equal(field.defaultType, 'Type1'); + assert.deepEqual(field.variableTypes, ['Type1']); + assert.equal(field.defaultType, 'Type1'); }); }); }); @@ -363,7 +358,7 @@ suite('Variable Fields', function () { // will be returned (regardless of what types are available on the workspace). const fieldVariable = new Blockly.FieldVariable('name1'); const resultTypes = fieldVariable.getVariableTypes(); - chai.assert.deepEqual(resultTypes, ['']); + assert.deepEqual(resultTypes, ['']); }); test('variableTypes is explicit', function () { // Expect that since variableTypes is defined, it will be the return @@ -375,8 +370,8 @@ suite('Variable Fields', function () { 'type1', ); const resultTypes = fieldVariable.getVariableTypes(); - chai.assert.deepEqual(resultTypes, ['type1', 'type2']); - chai.assert.equal( + assert.deepEqual(resultTypes, ['type1', 'type2']); + assert.equal( fieldVariable.defaultType, 'type1', 'Default type was wrong', @@ -394,7 +389,7 @@ suite('Variable Fields', function () { const resultTypes = fieldVariable.getVariableTypes(); // The empty string is always one of the options. - chai.assert.deepEqual(resultTypes, ['type1', 'type2', '']); + assert.deepEqual(resultTypes, ['type1', 'type2', '']); }); test('variableTypes is the empty list', function () { const fieldVariable = new Blockly.FieldVariable('name1'); @@ -403,7 +398,7 @@ suite('Variable Fields', function () { fieldVariable.setSourceBlock(mockBlock); fieldVariable.variableTypes = []; - chai.assert.throws(function () { + assert.throws(function () { fieldVariable.getVariableTypes(); }); }); @@ -411,7 +406,7 @@ suite('Variable Fields', function () { suite('Default types', function () { test('Default type exists', function () { const fieldVariable = new Blockly.FieldVariable(null, null, ['b'], 'b'); - chai.assert.equal( + assert.equal( fieldVariable.defaultType, 'b', 'The variable field\'s default type should be "b"', @@ -419,25 +414,25 @@ suite('Variable Fields', function () { }); test('No default type', function () { const fieldVariable = new Blockly.FieldVariable(null); - chai.assert.equal( + assert.equal( fieldVariable.defaultType, '', "The variable field's default type should be the empty string", ); - chai.assert.isNull( + assert.isNull( fieldVariable.variableTypes, "The variable field's allowed types should be null", ); }); test('Default type mismatch', function () { // Invalid default type when creating a variable field. - chai.assert.throws(function () { + assert.throws(function () { new Blockly.FieldVariable(null, null, ['a'], 'b'); }); }); test('Default type mismatch with empty array', function () { // Invalid default type when creating a variable field. - chai.assert.throws(function () { + assert.throws(function () { new Blockly.FieldVariable(null, null, ['a']); }); }); @@ -466,14 +461,14 @@ suite('Variable Fields', function () { }); test('Rename & Keep Old ID', function () { this.workspace.renameVariableById('id1', 'name2'); - chai.assert.equal(this.variableField.getText(), 'name2'); - chai.assert.equal(this.variableField.getValue(), 'id1'); + assert.equal(this.variableField.getText(), 'name2'); + assert.equal(this.variableField.getValue(), 'id1'); }); test('Rename & Get New ID', function () { this.workspace.createVariable('name2', null, 'id2'); this.workspace.renameVariableById('id1', 'name2'); - chai.assert.equal(this.variableField.getText(), 'name2'); - chai.assert.equal(this.variableField.getValue(), 'id2'); + assert.equal(this.variableField.getText(), 'name2'); + assert.equal(this.variableField.getValue(), 'id2'); }); }); @@ -494,7 +489,7 @@ suite('Variable Fields', function () { const field = new Blockly.FieldVariable('x'); block.getInput('INPUT').appendField(field, 'VAR'); const jso = Blockly.serialization.blocks.save(block); - chai.assert.deepEqual(jso['fields'], { + assert.deepEqual(jso['fields'], { 'VAR': {'id': 'id2', 'name': 'x', 'type': ''}, }); }); @@ -509,7 +504,7 @@ suite('Variable Fields', function () { ); block.getInput('INPUT').appendField(field, 'VAR'); const jso = Blockly.serialization.blocks.save(block); - chai.assert.deepEqual(jso['fields'], { + assert.deepEqual(jso['fields'], { 'VAR': {'id': 'id2', 'name': 'x', 'type': 'String'}, }); }); @@ -523,9 +518,9 @@ suite('Variable Fields', function () { const jso = Blockly.serialization.blocks.save(block, { doFullSerialization: false, }); - chai.assert.deepEqual(jso['fields'], {'VAR': {'id': 'id2'}}); - chai.assert.isUndefined(jso['fields']['VAR']['name']); - chai.assert.isUndefined(jso['fields']['VAR']['type']); + assert.deepEqual(jso['fields'], {'VAR': {'id': 'id2'}}); + assert.isUndefined(jso['fields']['VAR']['name']); + assert.isUndefined(jso['fields']['VAR']['type']); }); test('Typed', function () { @@ -540,9 +535,9 @@ suite('Variable Fields', function () { const jso = Blockly.serialization.blocks.save(block, { doFullSerialization: false, }); - chai.assert.deepEqual(jso['fields'], {'VAR': {'id': 'id2'}}); - chai.assert.isUndefined(jso['fields']['VAR']['name']); - chai.assert.isUndefined(jso['fields']['VAR']['type']); + assert.deepEqual(jso['fields'], {'VAR': {'id': 'id2'}}); + assert.isUndefined(jso['fields']['VAR']['name']); + assert.isUndefined(jso['fields']['VAR']['type']); }); }); }); @@ -572,9 +567,9 @@ suite('Variable Fields', function () { this.workspace, ); const variable = block.getField('VAR').getVariable(); - chai.assert.equal(variable.name, 'test'); - chai.assert.equal(variable.type, ''); - chai.assert.equal(variable.getId(), 'id1'); + assert.equal(variable.name, 'test'); + assert.equal(variable.type, ''); + assert.equal(variable.getId(), 'id1'); }); test('Name, untyped', function () { @@ -590,9 +585,9 @@ suite('Variable Fields', function () { this.workspace, ); const variable = block.getField('VAR').getVariable(); - chai.assert.equal(variable.name, 'test'); - chai.assert.equal(variable.type, ''); - chai.assert.equal(variable.getId(), 'id2'); + assert.equal(variable.name, 'test'); + assert.equal(variable.type, ''); + assert.equal(variable.getId(), 'id2'); }); test('Name, typed', function () { @@ -609,9 +604,9 @@ suite('Variable Fields', function () { this.workspace, ); const variable = block.getField('VAR').getVariable(); - chai.assert.equal(variable.name, 'test'); - chai.assert.equal(variable.type, 'string'); - chai.assert.equal(variable.getId(), 'id2'); + assert.equal(variable.name, 'test'); + assert.equal(variable.type, 'string'); + assert.equal(variable.getId(), 'id2'); }); }); }); diff --git a/tests/mocha/flyout_test.js b/tests/mocha/flyout_test.js index f2fe79e3851..9be45458c51 100644 --- a/tests/mocha/flyout_test.js +++ b/tests/mocha/flyout_test.js @@ -4,21 +4,14 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, workspaceTeardown, } from './test_helpers/setup_teardown.js'; -import {defineStackBlock} from './test_helpers/block_definitions.js'; import { - getBasicToolbox, - getChildItem, - getCollapsibleItem, - getDeeplyNestedJSON, - getInjectedToolbox, - getNonCollapsibleItem, getProperSimpleJson, - getSeparator, getSimpleJson, getXmlArray, } from './test_helpers/toolbox_definitions.js'; @@ -59,7 +52,7 @@ suite('Flyout', function () { this.flyout.targetWorkspace.getMetricsManager(); }); test('y is always 0', function () { - chai.assert.equal( + assert.equal( this.flyout.getY(), 0, 'y coordinate in vertical flyout should be 0', @@ -72,7 +65,7 @@ suite('Flyout', function () { this.flyout.targetWorkspace.toolboxPosition = Blockly.utils.toolbox.Position.RIGHT; this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.RIGHT; - chai.assert.equal( + assert.equal( this.flyout.getX(), 100, 'x should be right of workspace', @@ -82,7 +75,7 @@ suite('Flyout', function () { this.flyout.targetWorkspace.toolboxPosition = Blockly.utils.toolbox.Position.LEFT; this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.LEFT; - chai.assert.equal( + assert.equal( this.flyout.getX(), 0, 'x should be 0 if the flyout is on the left', @@ -110,7 +103,7 @@ suite('Flyout', function () { this.flyout.targetWorkspace.toolboxPosition = Blockly.utils.toolbox.Position.LEFT; this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.LEFT; - chai.assert.equal( + assert.equal( this.flyout.getX(), 20, 'x should be aligned with toolbox', @@ -128,7 +121,7 @@ suite('Flyout', function () { this.flyout.targetWorkspace.toolboxPosition = Blockly.utils.toolbox.Position.RIGHT; this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.RIGHT; - chai.assert.equal( + assert.equal( this.flyout.getX(), 90, 'x + width should be aligned with toolbox', @@ -150,7 +143,7 @@ suite('Flyout', function () { this.flyout.targetWorkspace.toolboxPosition = Blockly.utils.toolbox.Position.RIGHT; this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.LEFT; - chai.assert.equal( + assert.equal( this.flyout.getX(), 0, 'x should be aligned with left edge', @@ -169,7 +162,7 @@ suite('Flyout', function () { this.flyout.targetWorkspace.toolboxPosition = Blockly.utils.toolbox.Position.LEFT; this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.RIGHT; - chai.assert.equal( + assert.equal( this.flyout.getX(), 90, 'x + width should be aligned with right edge', @@ -195,7 +188,7 @@ suite('Flyout', function () { this.flyout.targetWorkspace.getMetricsManager(); }); test('x is always 0', function () { - chai.assert.equal( + assert.equal( this.flyout.getX(), 0, 'x coordinate in horizontal flyout should be 0', @@ -205,7 +198,7 @@ suite('Flyout', function () { this.flyout.targetWorkspace.toolboxPosition = Blockly.utils.toolbox.Position.TOP; this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.TOP; - chai.assert.equal( + assert.equal( this.flyout.getY(), 0, 'y should be 0 if flyout is at the top', @@ -218,7 +211,7 @@ suite('Flyout', function () { sinon.stub(this.targetMetricsManager, 'getViewMetrics').returns({ height: 50, }); - chai.assert.equal( + assert.equal( this.flyout.getY(), 50, 'y should be below the workspace', @@ -247,7 +240,7 @@ suite('Flyout', function () { this.flyout.targetWorkspace.toolboxPosition = Blockly.utils.toolbox.Position.TOP; this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.TOP; - chai.assert.equal( + assert.equal( this.flyout.getY(), 20, 'y should be aligned with toolbox', @@ -265,7 +258,7 @@ suite('Flyout', function () { this.flyout.targetWorkspace.toolboxPosition = Blockly.utils.toolbox.Position.BOTTOM; this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.BOTTOM; - chai.assert.equal( + assert.equal( this.flyout.getY(), 70, 'y + height should be aligned with toolbox', @@ -284,11 +277,7 @@ suite('Flyout', function () { this.flyout.targetWorkspace.toolboxPosition = Blockly.utils.toolbox.Position.BOTTOM; this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.TOP; - chai.assert.equal( - this.flyout.getY(), - 0, - 'y should be aligned with top', - ); + assert.equal(this.flyout.getY(), 0, 'y should be aligned with top'); }); test('trashcan on bottom covers bottom of workspace', function () { this.flyout.targetWorkspace.toolboxPosition = @@ -302,7 +291,7 @@ suite('Flyout', function () { }); this.flyout.setVisible(true); this.flyout.height_ = 20; - chai.assert.equal( + assert.equal( this.flyout.getY(), 40, 'y + height should be aligned with bottom', @@ -324,26 +313,26 @@ suite('Flyout', function () { const gaps = flyoutInfo.gaps; const expectedGaps = [20, 24, 24]; - chai.assert.deepEqual(gaps, expectedGaps); + assert.deepEqual(gaps, expectedGaps); - chai.assert.equal(contents.length, 3, 'Contents'); + assert.equal(contents.length, 3, 'Contents'); - chai.assert.equal(contents[0].type, 'block', 'Contents'); + assert.equal(contents[0].type, 'block', 'Contents'); const block = contents[0]['block']; - chai.assert.instanceOf(block, Blockly.BlockSvg); - chai.assert.equal(block.getFieldValue('OP'), 'NEQ'); + assert.instanceOf(block, Blockly.BlockSvg); + assert.equal(block.getFieldValue('OP'), 'NEQ'); const childA = block.getInputTargetBlock('A'); const childB = block.getInputTargetBlock('B'); - chai.assert.isTrue(childA.isShadow()); - chai.assert.isFalse(childB.isShadow()); - chai.assert.equal(childA.getFieldValue('NUM'), 1); - chai.assert.equal(childB.getFieldValue('NUM'), 2); + assert.isTrue(childA.isShadow()); + assert.isFalse(childB.isShadow()); + assert.equal(childA.getFieldValue('NUM'), 1); + assert.equal(childB.getFieldValue('NUM'), 2); - chai.assert.equal(contents[1].type, 'button', 'Contents'); - chai.assert.instanceOf(contents[1]['button'], Blockly.FlyoutButton); + assert.equal(contents[1].type, 'button', 'Contents'); + assert.instanceOf(contents[1]['button'], Blockly.FlyoutButton); - chai.assert.equal(contents[2].type, 'button', 'Contents'); - chai.assert.instanceOf(contents[2]['button'], Blockly.FlyoutButton); + assert.equal(contents[2].type, 'button', 'Contents'); + assert.instanceOf(contents[2]['button'], Blockly.FlyoutButton); } suite('Direct show', function () { @@ -391,7 +380,7 @@ suite('Flyout', function () { }); test('No category available', function () { - chai.assert.throws( + assert.throws( function () { this.flyout.show('someString'); }.bind(this), @@ -431,7 +420,7 @@ suite('Flyout', function () { this.assertDisabled = function (disabled) { const block = this.flyout.getWorkspace().getTopBlocks(false)[0]; - chai.assert.equal(!block.isEnabled(), disabled); + assert.equal(!block.isEnabled(), disabled); }; }); @@ -630,7 +619,7 @@ suite('Flyout', function () { ], }); const block = this.flyout.workspace_.getAllBlocks()[0]; - chai.assert.equal(block.getFieldValue('NUM'), 321); + assert.equal(block.getFieldValue('NUM'), 321); }); test('Recycling enabled', function () { @@ -660,7 +649,7 @@ suite('Flyout', function () { ], }); const block = this.flyout.workspace_.getAllBlocks()[0]; - chai.assert.equal(block.getFieldValue('NUM'), 123); + assert.equal(block.getFieldValue('NUM'), 123); }); }); }); diff --git a/tests/mocha/generator_test.js b/tests/mocha/generator_test.js index 3a2679dca81..527448eacc9 100644 --- a/tests/mocha/generator_test.js +++ b/tests/mocha/generator_test.js @@ -10,6 +10,7 @@ import {JavascriptGenerator} from '../../build/src/generators/javascript/javascr import {LuaGenerator} from '../../build/src/generators/lua/lua_generator.js'; import {PhpGenerator} from '../../build/src/generators/php/php_generator.js'; import {PythonGenerator} from '../../build/src/generators/python/python_generator.js'; +import {assert} from '../../node_modules/chai/chai.js'; import { sharedTestSetup, sharedTestTeardown, @@ -31,22 +32,19 @@ suite('Generator', function () { }); test('Nothing', function () { - chai.assert.equal(this.generator.prefixLines('', ''), ''); + assert.equal(this.generator.prefixLines('', ''), ''); }); test('One word', function () { - chai.assert.equal(this.generator.prefixLines('Hello', '@'), '@Hello'); + assert.equal(this.generator.prefixLines('Hello', '@'), '@Hello'); }); test('One line', function () { - chai.assert.equal( - this.generator.prefixLines('Hello\n', '12'), - '12Hello\n', - ); + assert.equal(this.generator.prefixLines('Hello\n', '12'), '12Hello\n'); }); test('Two lines', function () { - chai.assert.equal( + assert.equal( this.generator.prefixLines('Hello\nWorld\n', '***'), '***Hello\n***World\n', ); @@ -97,7 +95,7 @@ suite('Generator', function () { const code = generator.blockToCode(rowBlock, opt_thisOnly); delete generator.forBlock['stack_block']; delete generator.forBlock['row_block']; - chai.assert.equal(code, expectedCode, opt_message); + assert.equal(code, expectedCode, opt_message); }; }); @@ -187,7 +185,7 @@ suite('Generator', function () { blockA.nextConnection.connect(blockC.previousConnection); const code = generator.blockToCode(blockA, opt_thisOnly); - chai.assert.equal(code, expectedCode, opt_message); + assert.equal(code, expectedCode, opt_message); }; }); @@ -214,7 +212,7 @@ suite('Generator', function () { this.generator = new TestGenerator(); }); test('No nameDB_ initialized', function () { - chai.assert.throws(() => { + assert.throws(() => { this.generator.getVariableName('foo'); }); }); @@ -222,13 +220,13 @@ suite('Generator', function () { test('Get variable name', function () { this.generator.init(); - chai.assert.equal(this.generator.getVariableName('foo'), 'foo'); + assert.equal(this.generator.getVariableName('foo'), 'foo'); }); test('Get procedure name', function () { this.generator.init(); - chai.assert.equal(this.generator.getProcedureName('foo'), 'foo'); + assert.equal(this.generator.getProcedureName('foo'), 'foo'); }); }); }); diff --git a/tests/mocha/gesture_test.js b/tests/mocha/gesture_test.js index 0572fed5b94..3f53b8894b9 100644 --- a/tests/mocha/gesture_test.js +++ b/tests/mocha/gesture_test.js @@ -4,23 +4,21 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {assertEventFired, assertEventNotFired} from './test_helpers/events.js'; +import {EventType} from '../../build/src/core/events/type.js'; +import {assert} from '../../node_modules/chai/chai.js'; import {defineBasicBlockWithField} from './test_helpers/block_definitions.js'; -import {dispatchPointerEvent} from './test_helpers/user_input.js'; -import * as eventUtils from '../../build/src/core/events/utils.js'; +import {assertEventFired, assertEventNotFired} from './test_helpers/events.js'; import { sharedTestSetup, sharedTestTeardown, } from './test_helpers/setup_teardown.js'; +import {dispatchPointerEvent} from './test_helpers/user_input.js'; suite('Gesture', function () { function testGestureIsFieldClick(block, isFieldClick, eventsFireStub) { const field = block.getField('NAME'); const eventTarget = field.getClickTarget_(); - chai.assert.exists( - eventTarget, - 'Precondition: missing click target for field', - ); + assert.exists(eventTarget, 'Precondition: missing click target for field'); eventsFireStub.resetHistory(); dispatchPointerEvent(eventTarget, 'pointerdown'); @@ -29,23 +27,23 @@ suite('Gesture', function () { // Gestures triggered on flyouts are stored on targetWorkspace. const gestureWorkspace = fieldWorkspace.targetWorkspace || fieldWorkspace; const gesture = gestureWorkspace.currentGesture_; - chai.assert.exists(gesture, 'Gesture exists after pointerdown.'); + assert.exists(gesture, 'Gesture exists after pointerdown.'); const isFieldClickSpy = sinon.spy(gesture, 'isFieldClick'); dispatchPointerEvent(eventTarget, 'pointerup'); dispatchPointerEvent(eventTarget, 'click'); sinon.assert.called(isFieldClickSpy); - chai.assert.isTrue(isFieldClickSpy.alwaysReturned(isFieldClick)); + assert.isTrue(isFieldClickSpy.alwaysReturned(isFieldClick)); assertEventFired( eventsFireStub, Blockly.Events.Selected, - {newElementId: block.id, type: eventUtils.SELECTED}, + {newElementId: block.id, type: EventType.SELECTED}, fieldWorkspace.id, ); assertEventNotFired(eventsFireStub, Blockly.Events.Click, { - type: eventUtils.CLICK, + type: EventType.CLICK, }); } @@ -67,8 +65,8 @@ suite('Gesture', function () { test('Constructor', function () { const e = {id: 'dummy_test_event'}; const gesture = new Blockly.Gesture(e, this.workspace); - chai.assert.equal(gesture.mostRecentEvent, e); - chai.assert.equal(gesture.creatorWorkspace, this.workspace); + assert.equal(gesture.mostRecentEvent, e); + assert.equal(gesture.creatorWorkspace, this.workspace); }); test('Field click - Click in workspace', function () { @@ -81,7 +79,7 @@ suite('Gesture', function () { test('Field click - Auto close flyout', function () { const flyout = this.workspace.getFlyout(true); - chai.assert.exists(flyout, 'Precondition: missing flyout'); + assert.exists(flyout, 'Precondition: missing flyout'); flyout.autoClose = true; const block = getTopFlyoutBlock(flyout); @@ -90,7 +88,7 @@ suite('Gesture', function () { test('Field click - Always open flyout', function () { const flyout = this.workspace.getFlyout(true); - chai.assert.exists(flyout, 'Precondition: missing flyout'); + assert.exists(flyout, 'Precondition: missing flyout'); flyout.autoClose = false; const block = getTopFlyoutBlock(flyout); diff --git a/tests/mocha/icon_test.js b/tests/mocha/icon_test.js index 3463d8ad83b..5855fcfc576 100644 --- a/tests/mocha/icon_test.js +++ b/tests/mocha/icon_test.js @@ -4,12 +4,13 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {assert} from '../../node_modules/chai/chai.js'; +import {defineEmptyBlock} from './test_helpers/block_definitions.js'; +import {MockIcon, MockSerializableIcon} from './test_helpers/icon_mocks.js'; import { sharedTestSetup, sharedTestTeardown, } from './test_helpers/setup_teardown.js'; -import {defineEmptyBlock} from './test_helpers/block_definitions.js'; -import {MockIcon, MockSerializableIcon} from './test_helpers/icon_mocks.js'; suite('Icon', function () { setup(function () { @@ -62,7 +63,7 @@ suite('Icon', function () { block.addIcon(icon); - chai.assert.isFalse( + assert.isFalse( initViewSpy.called, 'Expected initView to not be called', ); @@ -79,7 +80,7 @@ suite('Icon', function () { const initViewSpy = sinon.spy(icon, 'initView'); block.addIcon(icon); - chai.assert.isTrue( + assert.isTrue( initViewSpy.calledOnce, 'Expected initView to be called', ); @@ -96,7 +97,7 @@ suite('Icon', function () { block.addIcon(icon); - chai.assert.isFalse( + assert.isFalse( applyColourSpy.called, 'Expected applyColour to not be called', ); @@ -112,7 +113,7 @@ suite('Icon', function () { const applyColourSpy = sinon.spy(icon, 'applyColour'); block.addIcon(icon); - chai.assert.isTrue( + assert.isTrue( applyColourSpy.calledOnce, 'Expected applyColour to be called', ); @@ -128,7 +129,7 @@ suite('Icon', function () { block.addIcon(icon); applyColourSpy.resetHistory(); block.setColour('#cccccc'); - chai.assert.isTrue( + assert.isTrue( applyColourSpy.calledOnce, 'Expected applyColour to be called', ); @@ -143,7 +144,7 @@ suite('Icon', function () { block.addIcon(icon); applyColourSpy.resetHistory(); block.setStyle('logic_block'); - chai.assert.isTrue( + assert.isTrue( applyColourSpy.calledOnce, 'Expected applyColour to be called', ); @@ -158,7 +159,7 @@ suite('Icon', function () { block.addIcon(icon); applyColourSpy.resetHistory(); block.setDisabledReason(true, 'test reason'); - chai.assert.isTrue( + assert.isTrue( applyColourSpy.calledOnce, 'Expected applyColour to be called', ); @@ -173,7 +174,7 @@ suite('Icon', function () { block.addIcon(icon); applyColourSpy.resetHistory(); block.setShadow(true); - chai.assert.isTrue( + assert.isTrue( applyColourSpy.calledOnce, 'Expected applyColour to be called', ); @@ -189,7 +190,7 @@ suite('Icon', function () { block.addIcon(icon); - chai.assert.isFalse( + assert.isFalse( updateEditableSpy.called, 'Expected updateEditable to not be called', ); @@ -205,7 +206,7 @@ suite('Icon', function () { const updateEditableSpy = sinon.spy(icon, 'updateEditable'); block.addIcon(icon); - chai.assert.isTrue( + assert.isTrue( updateEditableSpy.calledOnce, 'Expected updateEditable to be called', ); @@ -221,7 +222,7 @@ suite('Icon', function () { block.addIcon(icon); updateEditableSpy.resetHistory(); block.setEditable(false); - chai.assert.isTrue( + assert.isTrue( updateEditableSpy.calledOnce, 'Expected updateEditable to be called', ); @@ -237,7 +238,7 @@ suite('Icon', function () { block.setEditable(false); updateEditableSpy.resetHistory(); block.setEditable(true); - chai.assert.isTrue( + assert.isTrue( updateEditableSpy.calledOnce, 'Expected updateEditable to be called', ); @@ -255,7 +256,7 @@ suite('Icon', function () { block.setCollapsed(true); block.setCollapsed(false); - chai.assert.isFalse( + assert.isFalse( updateCollapsedSpy.called, 'Expected updateCollapsed to not be called', ); @@ -272,7 +273,7 @@ suite('Icon', function () { block.setCollapsed(true); this.clock.runAll(); - chai.assert.isTrue( + assert.isTrue( updateCollapsedSpy.called, 'Expected updateCollapsed to be called', ); @@ -289,7 +290,7 @@ suite('Icon', function () { block.setCollapsed(false); this.clock.runAll(); - chai.assert.isTrue( + assert.isTrue( updateCollapsedSpy.called, 'Expected updateCollapsed to be called', ); @@ -302,7 +303,7 @@ suite('Icon', function () { const block = createHeadlessBlock(createHeadlessWorkspace()); block.addIcon(new MockSerializableIcon()); const json = Blockly.serialization.blocks.save(block); - chai.assert.deepNestedInclude( + assert.deepNestedInclude( json, {'icons': {'serializable icon': 'some state'}}, 'Expected the JSON to include the saved state of the ' + @@ -314,7 +315,7 @@ suite('Icon', function () { const block = createHeadlessBlock(createHeadlessWorkspace()); block.addIcon(new MockNonSerializableIcon()); const json = Blockly.serialization.blocks.save(block); - chai.assert.notProperty( + assert.notProperty( json, 'icons', 'Expected the JSON to not include any saved state for icons', @@ -337,7 +338,7 @@ suite('Icon', function () { }, }; const block = Blockly.serialization.blocks.append(json, workspace); - chai.assert.equal( + assert.equal( block.getIcon('serializable icon').state, 'some state', 'Expected the icon to have been properly instantiated and ' + @@ -355,7 +356,7 @@ suite('Icon', function () { 'serializable icon': 'some state', }, }; - chai.assert.throws( + assert.throws( () => { Blockly.serialization.blocks.append(json, workspace); }, diff --git a/tests/mocha/index.html b/tests/mocha/index.html index 9c7b10cabe2..adc63da4a12 100644 --- a/tests/mocha/index.html +++ b/tests/mocha/index.html @@ -21,7 +21,6 @@ -