From 9283c4e6e8e4a9cc107745d4b2aa2973f2100afe Mon Sep 17 00:00:00 2001 From: Ben Henning Date: Fri, 6 Dec 2024 00:33:58 +0000 Subject: [PATCH 01/28] Improve the robustness of workspace SVG tests. This largely reduces the dependence on direct value testing and instead updates clean-up tests to verify logic based on relative positioning. This guards against potential system-specific flakes that can occur when there are subtle calculation differences on different systems. --- tests/mocha/workspace_svg_test.js | 276 ++++++++++++------------------ 1 file changed, 108 insertions(+), 168 deletions(-) diff --git a/tests/mocha/workspace_svg_test.js b/tests/mocha/workspace_svg_test.js index 0cd6da828..207cad45d 100644 --- a/tests/mocha/workspace_svg_test.js +++ b/tests/mocha/workspace_svg_test.js @@ -408,6 +408,53 @@ suite('WorkspaceSvg', function () { }); suite('cleanUp', function () { + assert.blockIsAtOrigin = function (actual, message) { + assert.blockHasPosition(actual, 0, 0, message || 'block is at origin'); + }; + + assert.blockHasPositionX = function (actual, expectedX, message) { + const position = actual.getRelativeToSurfaceXY(); + message = message || 'block has x value of ' + expectedX; + assert.equal(position.x, expectedX, message); + }; + + assert.blockHasPositionY = function (actual, expectedY, message) { + const position = actual.getRelativeToSurfaceXY(); + message = message || 'block has y value of ' + expectedY; + assert.equal(position.y, expectedY, message); + }; + + assert.blockHasPosition = function (actual, expectedX, expectedY, message) { + assert.blockHasPositionX(actual, expectedX, message); + assert.blockHasPositionY(actual, expectedY, message); + }; + + assert.blockIsAtNotOrigin = function (actual, message) { + const position = actual.getRelativeToSurfaceXY(); + message = message || 'block is not at origin'; + assert.isTrue(position.x != 0 || position.y != 0, message); + }; + + assert.blocksDoNotIntersect = function (a, b, message) { + const rectA = a.getBoundingRectangle(); + const rectB = b.getBoundingRectangle(); + assert.isFalse(rectA.intersects(rectB), message || "a,b don't intersect"); + }; + + assert.blockIsAbove = function (a, b, message) { + // Block a is above b iff a's bottom extreme is < b's top extreme. + const rectA = a.getBoundingRectangle(); + const rectB = b.getBoundingRectangle(); + assert.isBelow(rectA.bottom, rectB.top, message || 'a is above b'); + }; + + assert.blockIsBelow = function (a, b, message) { + // Block a is below b iff a's top extreme is > b's bottom extreme. + const rectA = a.getBoundingRectangle(); + const rectB = b.getBoundingRectangle(); + assert.isAbove(rectA.top, rectB.bottom, message || 'a is below b'); + }; + test('empty workspace does not change', function () { this.workspace.cleanUp(); @@ -429,13 +476,8 @@ suite('WorkspaceSvg', function () { this.workspace.cleanUp(); const blocks = this.workspace.getTopBlocks(true); - const origin = new Blockly.utils.Coordinate(0, 0); assert.equal(blocks.length, 1, 'workspace has one top-level block'); - assert.deepEqual( - blocks[0].getRelativeToSurfaceXY(), - origin, - 'block is at origin', - ); + assert.blockIsAtOrigin(blocks[0]); }); test('single block at (10, 15) is moved to (0, 0)', function () { @@ -453,14 +495,9 @@ suite('WorkspaceSvg', function () { const topBlocks = this.workspace.getTopBlocks(true); const allBlocks = this.workspace.getAllBlocks(false); - const origin = new Blockly.utils.Coordinate(0, 0); assert.equal(topBlocks.length, 1, 'workspace has one top-level block'); assert.equal(allBlocks.length, 1, 'workspace has one block overall'); - assert.deepEqual( - topBlocks[0].getRelativeToSurfaceXY(), - origin, - 'block is at origin', - ); + assert.blockIsAtOrigin(topBlocks[0]); }); test('single block at (10, 15) with child is moved as unit to (0, 0)', function () { @@ -487,19 +524,10 @@ suite('WorkspaceSvg', function () { const topBlocks = this.workspace.getTopBlocks(true); const allBlocks = this.workspace.getAllBlocks(false); - const origin = new Blockly.utils.Coordinate(0, 0); assert.equal(topBlocks.length, 1, 'workspace has one top-level block'); assert.equal(allBlocks.length, 2, 'workspace has two blocks overall'); - assert.deepEqual( - topBlocks[0].getRelativeToSurfaceXY(), - origin, - 'block is at origin', - ); - assert.notDeepEqual( - allBlocks[1].getRelativeToSurfaceXY(), - origin, - 'child is not at origin', - ); + assert.blockIsAtOrigin(topBlocks[0]); // Parent block. + assert.blockIsAtNotOrigin(allBlocks[1]); // Child block. }); // TODO(#8676): Reenable once test passes reliably. @@ -524,19 +552,9 @@ suite('WorkspaceSvg', function () { const topBlocks = this.workspace.getTopBlocks(true); const block1 = this.workspace.getBlockById('block1'); const block2 = this.workspace.getBlockById('block2'); - const origin = new Blockly.utils.Coordinate(0, 0); - const belowBlock2 = new Blockly.utils.Coordinate(0, 50); assert.equal(topBlocks.length, 2, 'workspace has two top-level blocks'); - assert.deepEqual( - block2.getRelativeToSurfaceXY(), - origin, - 'block2 is at origin', - ); - assert.deepEqual( - block1.getRelativeToSurfaceXY(), - belowBlock2, - 'block1 is below block2', - ); + assert.blockIsAtOrigin(block2); + assert.blockIsBelow(block1, block2); }); // TODO(#8676): Reenable once test passes reliably. @@ -564,19 +582,9 @@ suite('WorkspaceSvg', function () { const topBlocks = this.workspace.getTopBlocks(true); const block1 = this.workspace.getBlockById('block1'); const block2 = this.workspace.getBlockById('block2'); - const origin = new Blockly.utils.Coordinate(0, 0); - const belowBlock1 = new Blockly.utils.Coordinate(0, 50); assert.equal(topBlocks.length, 2, 'workspace has two top-level blocks'); - assert.deepEqual( - block1.getRelativeToSurfaceXY(), - origin, - 'block1 is at origin', - ); - assert.deepEqual( - block2.getRelativeToSurfaceXY(), - belowBlock1, - 'block2 is below block1', - ); + assert.blockIsAtOrigin(block1); + assert.blockIsBelow(block2, block1); }); test('two overlapping blocks with snapping are moved to grid-aligned positions', function () { @@ -605,19 +613,9 @@ suite('WorkspaceSvg', function () { const topBlocks = this.workspace.getTopBlocks(true); const block1 = this.workspace.getBlockById('block1'); const block2 = this.workspace.getBlockById('block2'); - const snappedOffOrigin = new Blockly.utils.Coordinate(10, 10); - const belowBlock1 = new Blockly.utils.Coordinate(10, 70); assert.equal(topBlocks.length, 2, 'workspace has two top-level blocks'); - assert.deepEqual( - block1.getRelativeToSurfaceXY(), - snappedOffOrigin, - 'block1 is near origin', - ); - assert.deepEqual( - block2.getRelativeToSurfaceXY(), - belowBlock1, - 'block2 is below block1', - ); + assert.blockHasPosition(block1, 10, 10, 'block1 is at snapped origin'); + assert.blockIsBelow(block2, block1); }); // TODO(#8676): Reenable once test passes reliably. @@ -653,36 +651,28 @@ suite('WorkspaceSvg', function () { const allBlocks = this.workspace.getAllBlocks(false); const block1 = this.workspace.getBlockById('block1'); const block2 = this.workspace.getBlockById('block2'); - const origin = new Blockly.utils.Coordinate(0, 0); - const belowBlock1 = new Blockly.utils.Coordinate(0, 50); - const block1Pos = block1.getRelativeToSurfaceXY(); - const block2Pos = block2.getRelativeToSurfaceXY(); - const block1ChildPos = block1.getChildren()[0].getRelativeToSurfaceXY(); - const block2ChildPos = block2.getChildren()[0].getRelativeToSurfaceXY(); + const block1Child = block1.getChildren()[0]; + const block2Child = block2.getChildren()[0]; + + // Note that the x position tests below are verifying that each block's + // child isn't exactly aligned with it (however, they does overlap since + // the child block has an input connection with its parent). assert.equal(topBlocks.length, 2, 'workspace has two top-level block2'); assert.equal(allBlocks.length, 4, 'workspace has four blocks overall'); - assert.deepEqual(block1Pos, origin, 'block1 is at origin'); - assert.deepEqual(block2Pos, belowBlock1, 'block2 is below block1'); + assert.blockIsAtOrigin(block1); + assert.blockIsBelow(block2, block1); assert.isAbove( - block1ChildPos.x, - block1Pos.x, - "block1's child is right of it", - ); - assert.isBelow( - block1ChildPos.y, - block2Pos.y, - "block1's child is above block 2", + block1.getChildren()[0].getRelativeToSurfaceXY().x, + block1.getRelativeToSurfaceXY().x, + "block1's child is right of its start", ); + assert.blockIsAbove(block1Child, block2); assert.isAbove( - block2ChildPos.x, - block2Pos.x, - "block2's child is right of it", - ); - assert.isAbove( - block2ChildPos.y, - block1Pos.y, - "block2's child is below block 1", + block2.getChildren()[0].getRelativeToSurfaceXY().x, + block2.getRelativeToSurfaceXY().x, + "block2's child is right of its start", ); + assert.blockIsBelow(block2Child, block1); }); // TODO(#8676): Reenable once test passes reliably. @@ -742,19 +732,9 @@ suite('WorkspaceSvg', function () { const topBlocks = this.workspace.getTopBlocks(true); const block1 = this.workspace.getBlockById('block1'); const block2 = this.workspace.getBlockById('block2'); - const origin = new Blockly.utils.Coordinate(0, 0); - const belowBlock1 = new Blockly.utils.Coordinate(0, 144); assert.equal(topBlocks.length, 2, 'workspace has two top-level blocks'); - assert.deepEqual( - block1.getRelativeToSurfaceXY(), - origin, - 'block1 is at origin', - ); - assert.deepEqual( - block2.getRelativeToSurfaceXY(), - belowBlock1, - 'block2 is below block1', - ); + assert.blockIsAtOrigin(block1); + assert.blockIsBelow(block2, block1); }); test('five overlapping blocks are moved in-order as one column', function () { @@ -780,32 +760,21 @@ suite('WorkspaceSvg', function () { this.workspace.cleanUp(); const topBlocks = this.workspace.getTopBlocks(true); - const block1Pos = this.workspace - .getBlockById('block1') - .getRelativeToSurfaceXY(); - const block2Pos = this.workspace - .getBlockById('block2') - .getRelativeToSurfaceXY(); - const block3Pos = this.workspace - .getBlockById('block3') - .getRelativeToSurfaceXY(); - const block4Pos = this.workspace - .getBlockById('block4') - .getRelativeToSurfaceXY(); - const block5Pos = this.workspace - .getBlockById('block5') - .getRelativeToSurfaceXY(); - const origin = new Blockly.utils.Coordinate(0, 0); + const block1 = this.workspace.getBlockById('block1'); + const block2 = this.workspace.getBlockById('block2'); + const block3 = this.workspace.getBlockById('block3'); + const block4 = this.workspace.getBlockById('block4'); + const block5 = this.workspace.getBlockById('block5'); assert.equal(topBlocks.length, 5, 'workspace has five top-level blocks'); - assert.deepEqual(block1Pos, origin, 'block1 is at origin'); - assert.equal(block2Pos.x, 0, 'block2.x is at 0'); - assert.equal(block3Pos.x, 0, 'block3.x is at 0'); - assert.equal(block4Pos.x, 0, 'block4.x is at 0'); - assert.equal(block5Pos.x, 0, 'block5.x is at 0'); - assert.isAbove(block2Pos.y, block1Pos.y, 'block2 is below block1'); - assert.isAbove(block3Pos.y, block2Pos.y, 'block3 is below block2'); - assert.isAbove(block4Pos.y, block3Pos.y, 'block4 is below block3'); - assert.isAbove(block5Pos.y, block4Pos.y, 'block5 is below block4'); + assert.blockIsAtOrigin(block1); + assert.blockHasPositionX(block2, 0); + assert.blockHasPositionX(block3, 0); + assert.blockHasPositionX(block4, 0); + assert.blockHasPositionX(block5, 0); + assert.blockIsBelow(block2, block1); + assert.blockIsBelow(block3, block2); + assert.blockIsBelow(block4, block3); + assert.blockIsBelow(block5, block4); }); test('single immovable block at (10, 15) is not moved', function () { @@ -824,14 +793,9 @@ suite('WorkspaceSvg', function () { const topBlocks = this.workspace.getTopBlocks(true); const allBlocks = this.workspace.getAllBlocks(false); - const origPos = new Blockly.utils.Coordinate(10, 15); assert.equal(topBlocks.length, 1, 'workspace has one top-level block'); assert.equal(allBlocks.length, 1, 'workspace has one block overall'); - assert.deepEqual( - topBlocks[0].getRelativeToSurfaceXY(), - origPos, - 'block is at (10, 15)', - ); + assert.blockHasPosition(topBlocks[0], 10, 15); }); test('multiple block types immovable blocks are not moved', function () { @@ -914,53 +878,29 @@ suite('WorkspaceSvg', function () { this.workspace.cleanUp(); const topBlocks = this.workspace.getTopBlocks(true); - const block1Rect = this.workspace - .getBlockById('block1') - .getBoundingRectangle(); - const block2Rect = this.workspace - .getBlockById('block2') - .getBoundingRectangle(); - const block3Rect = this.workspace - .getBlockById('block3') - .getBoundingRectangle(); - const block4Rect = this.workspace - .getBlockById('block4') - .getBoundingRectangle(); - const block5Rect = this.workspace - .getBlockById('block5') - .getBoundingRectangle(); + const block1 = this.workspace.getBlockById('block1'); + const block2 = this.workspace.getBlockById('block2'); + const block3 = this.workspace.getBlockById('block3'); + const block4 = this.workspace.getBlockById('block4'); + const block5 = this.workspace.getBlockById('block5'); assert.equal(topBlocks.length, 5, 'workspace has five top-level blocks'); // Check that immovable blocks haven't moved. - assert.equal(block2Rect.left, 10, 'block2.x is at 10'); - assert.equal(block2Rect.top, 20, 'block2.y is at 20'); - assert.equal(block5Rect.left, 20, 'block5.x is at 20'); - assert.equal(block5Rect.top, 200, 'block5.y is at 200'); + assert.blockHasPosition(block2, 10, 20); + assert.blockHasPosition(block5, 20, 200); // Check that movable positions have correctly been left-aligned. - assert.equal(block1Rect.left, 0, 'block1.x is at 0'); - assert.equal(block3Rect.left, 0, 'block3.x is at 0'); - assert.equal(block4Rect.left, 0, 'block4.x is at 0'); + assert.blockHasPositionX(block1, 0); + assert.blockHasPositionX(block3, 0); + assert.blockHasPositionX(block4, 0); // Block order should be: 2, 1, 3, 5, 4 since 2 and 5 are immovable. - assert.isAbove(block1Rect.top, block2Rect.top, 'block1 is below block2'); - assert.isAbove(block3Rect.top, block1Rect.top, 'block3 is below block1'); - assert.isAbove(block5Rect.top, block3Rect.top, 'block5 is below block3'); - assert.isAbove(block4Rect.top, block5Rect.top, 'block4 is below block5'); + assert.blockIsBelow(block1, block2); + assert.blockIsBelow(block3, block1); + assert.blockIsBelow(block5, block3); + assert.blockIsBelow(block4, block5); // Ensure no blocks intersect (can check in order due to the position verification above). - assert.isFalse( - block2Rect.intersects(block1Rect), - 'block2/block1 do not intersect', - ); - assert.isFalse( - block1Rect.intersects(block3Rect), - 'block1/block3 do not intersect', - ); - assert.isFalse( - block3Rect.intersects(block5Rect), - 'block3/block5 do not intersect', - ); - assert.isFalse( - block5Rect.intersects(block4Rect), - 'block5/block4 do not intersect', - ); + assert.blocksDoNotIntersect(block2, block1); + assert.blocksDoNotIntersect(block1, block3); + assert.blocksDoNotIntersect(block3, block5); + assert.blocksDoNotIntersect(block5, block4); }); }); From 3a52aad1b1fb075d4ba3def10eda2257d97ad343 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Jan 2025 08:13:06 -0800 Subject: [PATCH 02/28] chore(deps): bump @blockly/theme-modern from 6.0.7 to 6.0.10 (#8728) Bumps [@blockly/theme-modern](https://github.com/google/blockly-samples/tree/HEAD/plugins/theme-modern) from 6.0.7 to 6.0.10. - [Release notes](https://github.com/google/blockly-samples/releases) - [Changelog](https://github.com/google/blockly-samples/blob/master/plugins/theme-modern/CHANGELOG.md) - [Commits](https://github.com/google/blockly-samples/commits/@blockly/theme-modern@6.0.10/plugins/theme-modern) --- updated-dependencies: - dependency-name: "@blockly/theme-modern" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3135424e9..883c319ca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -212,9 +212,9 @@ } }, "node_modules/@blockly/theme-modern": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/@blockly/theme-modern/-/theme-modern-6.0.7.tgz", - "integrity": "sha512-RUEmunGe1L6So0sTpBd1yUz3foUAzjTj1x0y3P4iyuGu0HzfLIacqUpdU4wQNteGPbKSBp7qDFRXaH/V2eJ6QA==", + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/@blockly/theme-modern/-/theme-modern-6.0.10.tgz", + "integrity": "sha512-xOVf5Vq5ACgbVsaNAKWb5cE0msUfBxj1G1asp0aBmWo1QCr3Yze4rUtFDaNIoeCd8EsRpuWZgBYg74zPL9eAow==", "dev": true, "engines": { "node": ">=8.17.0" From f9ef78521eaefc65a854d4bd3f062a5da9796215 Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Tue, 14 Jan 2025 13:19:30 -0800 Subject: [PATCH 03/28] fix: Listen for keyboard shortcuts when the widget or dropdown divs have focus. (#8731) --- core/inject.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/core/inject.ts b/core/inject.ts index b425d77b7..40016bc23 100644 --- a/core/inject.ts +++ b/core/inject.ts @@ -77,6 +77,16 @@ export function inject( }); browserEvents.conditionalBind(subContainer, 'keydown', null, onKeyDown); + browserEvents.conditionalBind( + dropDownDiv.getContentDiv(), + 'keydown', + null, + onKeyDown, + ); + const widgetContainer = WidgetDiv.getDiv(); + if (widgetContainer) { + browserEvents.conditionalBind(widgetContainer, 'keydown', null, onKeyDown); + } return workspace; } From 640410752d3afd4c55966cfb409259e01cd3a39d Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Tue, 14 Jan 2025 14:50:15 -0800 Subject: [PATCH 04/28] fix: Fix display of multiline RTL strings in bubbles on Webkit. (#8733) * fix: Fix display of multiline RTL strings in bubbles on Webkit. * chore: Remove references to spans. --- core/bubbles/text_bubble.ts | 47 ++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/core/bubbles/text_bubble.ts b/core/bubbles/text_bubble.ts index 7ac5fa029..6db81cd99 100644 --- a/core/bubbles/text_bubble.ts +++ b/core/bubbles/text_bubble.ts @@ -16,7 +16,7 @@ import {Bubble} from './bubble.js'; * A bubble that displays non-editable text. Used by the warning icon. */ export class TextBubble extends Bubble { - private paragraph: SVGTextElement; + private paragraph: SVGGElement; constructor( private text: string, @@ -48,43 +48,52 @@ export class TextBubble extends Bubble { */ private stringToSvg(text: string, container: SVGGElement) { const paragraph = this.createParagraph(container); - const spans = this.createSpans(paragraph, text); + const fragments = this.createTextFragments(paragraph, text); if (this.workspace.RTL) - this.rightAlignSpans(paragraph.getBBox().width, spans); + this.rightAlignTextFragments(paragraph.getBBox().width, fragments); return paragraph; } - /** Creates the paragraph container for this bubble's view's spans. */ - private createParagraph(container: SVGGElement): SVGTextElement { + /** Creates the paragraph container for this bubble's view's text fragments. */ + private createParagraph(container: SVGGElement): SVGGElement { return dom.createSvgElement( - Svg.TEXT, + Svg.G, { 'class': 'blocklyText blocklyBubbleText blocklyNoPointerEvents', - 'y': Bubble.BORDER_WIDTH, + 'transform': `translate(0,${Bubble.BORDER_WIDTH})`, + 'style': `direction: ${this.workspace.RTL ? 'rtl' : 'ltr'}`, }, container, ); } - /** Creates the spans visualizing the text of this bubble. */ - private createSpans(parent: SVGTextElement, text: string): SVGTSpanElement[] { + /** Creates the text fragments visualizing the text of this bubble. */ + private createTextFragments( + parent: SVGGElement, + text: string, + ): SVGTextElement[] { + let lineNum = 1; return text.split('\n').map((line) => { - const tspan = dom.createSvgElement( - Svg.TSPAN, - {'dy': '1em', 'x': Bubble.BORDER_WIDTH}, + const fragment = dom.createSvgElement( + Svg.TEXT, + {'y': `${lineNum}em`, 'x': Bubble.BORDER_WIDTH}, parent, ); const textNode = document.createTextNode(line); - tspan.appendChild(textNode); - return tspan; + fragment.appendChild(textNode); + lineNum += 1; + return fragment; }); } - /** Right aligns the given spans. */ - private rightAlignSpans(maxWidth: number, spans: SVGTSpanElement[]) { - for (const span of spans) { - span.setAttribute('text-anchor', 'end'); - span.setAttribute('x', `${maxWidth + Bubble.BORDER_WIDTH}`); + /** Right aligns the given text fragments. */ + private rightAlignTextFragments( + maxWidth: number, + fragments: SVGTextElement[], + ) { + for (const text of fragments) { + text.setAttribute('text-anchor', 'start'); + text.setAttribute('x', `${maxWidth + Bubble.BORDER_WIDTH}`); } } From 2a36de148b39aeacfc40366d907211ac3eb2f4f3 Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Tue, 14 Jan 2025 13:19:30 -0800 Subject: [PATCH 05/28] fix: Listen for keyboard shortcuts when the widget or dropdown divs have focus. (#8731) (cherry picked from commit f9ef78521eaefc65a854d4bd3f062a5da9796215) --- core/inject.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/core/inject.ts b/core/inject.ts index b425d77b7..40016bc23 100644 --- a/core/inject.ts +++ b/core/inject.ts @@ -77,6 +77,16 @@ export function inject( }); browserEvents.conditionalBind(subContainer, 'keydown', null, onKeyDown); + browserEvents.conditionalBind( + dropDownDiv.getContentDiv(), + 'keydown', + null, + onKeyDown, + ); + const widgetContainer = WidgetDiv.getDiv(); + if (widgetContainer) { + browserEvents.conditionalBind(widgetContainer, 'keydown', null, onKeyDown); + } return workspace; } From 44e783ccc6544a8ac83b4ec6cd06963677575d1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20Fedory=C5=84ski?= Date: Mon, 6 Jan 2025 17:48:17 +0100 Subject: [PATCH 06/28] fix: treat media files as binary while packaging them (#8706) By default gulp's src() treats files as UTF-8, which corrupts binary files like MP3s when copying them for packaging. This makes it treat them as binary. (cherry picked from commit dd6be31a8eabd027aa83a242880d3814f57e6ed6) --- scripts/gulpfiles/package_tasks.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/gulpfiles/package_tasks.js b/scripts/gulpfiles/package_tasks.js index 48dfd5b84..89264a0e3 100644 --- a/scripts/gulpfiles/package_tasks.js +++ b/scripts/gulpfiles/package_tasks.js @@ -159,7 +159,7 @@ module.exports = require('./${bundle}'); * This task copies all the media/* files into the release directory. */ function packageMedia() { - return gulp.src('media/*') + return gulp.src('media/*', {encoding: false}) .pipe(gulp.dest(`${RELEASE_DIR}/media`)); }; From f166b677c0d323d1793060b8b7ddca5d2076ca69 Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Fri, 10 Jan 2025 10:38:30 -0800 Subject: [PATCH 07/28] fix: Fix bug that preventing scrolling menu items into view. (#8726) * fix: Fix bug that preventing scrolling menu items into view. * chore: Deprecate now-unused-in-core functions in style. (cherry picked from commit 0c20129a26ec111fc36a711e2a54553f4b726804) --- core/field_dropdown.ts | 6 ------ core/menu.ts | 9 +++++---- core/utils/style.ts | 14 ++++++++++++++ 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/core/field_dropdown.ts b/core/field_dropdown.ts index b1e3b5af2..a79deaee5 100644 --- a/core/field_dropdown.ts +++ b/core/field_dropdown.ts @@ -29,7 +29,6 @@ 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'; /** @@ -304,11 +303,6 @@ export class FieldDropdown extends Field { if (this.selectedMenuItem) { this.menu_!.setHighlighted(this.selectedMenuItem); - style.scrollIntoContainerView( - this.selectedMenuItem.getElement()!, - dropDownDiv.getContentDiv(), - true, - ); } this.applyColour(); diff --git a/core/menu.ts b/core/menu.ts index b0fb55573..cce7d7bde 100644 --- a/core/menu.ts +++ b/core/menu.ts @@ -260,10 +260,11 @@ export class Menu { this.highlightedItem = item; // Bring the highlighted item into view. This has no effect if the menu is // not scrollable. - const el = this.getElement() as Element; - style.scrollIntoContainerView(item.getElement() as Element, el); - - aria.setState(el, aria.State.ACTIVEDESCENDANT, item.getId()); + const el = this.getElement(); + if (el) { + aria.setState(el, aria.State.ACTIVEDESCENDANT, item.getId()); + } + item.getElement()?.scrollIntoView(); } } diff --git a/core/utils/style.ts b/core/utils/style.ts index 4f8324be5..5de69001f 100644 --- a/core/utils/style.ts +++ b/core/utils/style.ts @@ -7,6 +7,7 @@ // Former goog.module ID: Blockly.utils.style import {Coordinate} from './coordinate.js'; +import * as deprecation from './deprecation.js'; import {Rect} from './rect.js'; import {Size} from './size.js'; @@ -58,6 +59,7 @@ function getSizeInternal(element: Element): Size { * @returns Object with width/height properties. */ function getSizeWithDisplay(element: Element): Size { + deprecation.warn(`Blockly.utils.style.getSizeWithDisplay()`, 'v11.2', 'v13'); const offsetWidth = (element as HTMLElement).offsetWidth; const offsetHeight = (element as HTMLElement).offsetHeight; return new Size(offsetWidth, offsetHeight); @@ -130,6 +132,7 @@ export function getViewportPageOffset(): Coordinate { * @returns The computed border widths. */ export function getBorderBox(element: Element): Rect { + deprecation.warn(`Blockly.utils.style.getBorderBox()`, 'v11.2', 'v13'); const left = parseFloat(getComputedStyle(element, 'borderLeftWidth')); const right = parseFloat(getComputedStyle(element, 'borderRightWidth')); const top = parseFloat(getComputedStyle(element, 'borderTopWidth')); @@ -156,6 +159,12 @@ export function scrollIntoContainerView( container: Element, opt_center?: boolean, ) { + deprecation.warn( + `Blockly.utils.style.scrollIntoContainerView()`, + 'v11.2', + 'v13', + 'the native Element.scrollIntoView()', + ); const offset = getContainerOffsetToScrollInto(element, container, opt_center); container.scrollLeft = offset.x; container.scrollTop = offset.y; @@ -180,6 +189,11 @@ export function getContainerOffsetToScrollInto( container: Element, opt_center?: boolean, ): Coordinate { + deprecation.warn( + `Blockly.utils.style.getContainerOffsetToScrollInto()`, + 'v11.2', + 'v13', + ); // Absolute position of the element's border's top left corner. const elementPos = getPageOffset(element); // Absolute position of the container's border's top left corner. From d95039db97a0a881cedba487100cad223246d3ea Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Wed, 15 Jan 2025 09:04:24 -0800 Subject: [PATCH 08/28] release: Update version number to 11.2.1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9b070fb54..c44ddbfef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "blockly", - "version": "11.2.0", + "version": "11.2.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "blockly", - "version": "11.2.0", + "version": "11.2.1", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { diff --git a/package.json b/package.json index ca6de2f07..332338eac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "blockly", - "version": "11.2.0", + "version": "11.2.1", "description": "Blockly is a library for building visual programming editors.", "keywords": [ "blockly" From a86ba151546bb3b34176fcf222207e7618a6f094 Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Thu, 16 Jan 2025 10:37:24 -0800 Subject: [PATCH 09/28] fix: Fix the browser tests. (#8735) --- core/menu.ts | 5 ++++- tests/browser/test/basic_playground_test.mjs | 2 +- tests/browser/test/delete_blocks_test.mjs | 12 ++++++++---- tests/browser/test/procedure_test.mjs | 3 +++ tests/browser/test/test_setup.mjs | 6 +++--- tests/browser/test/workspace_comment_test.mjs | 3 --- 6 files changed, 19 insertions(+), 12 deletions(-) diff --git a/core/menu.ts b/core/menu.ts index cce7d7bde..d1c86a802 100644 --- a/core/menu.ts +++ b/core/menu.ts @@ -264,7 +264,10 @@ export class Menu { if (el) { aria.setState(el, aria.State.ACTIVEDESCENDANT, item.getId()); } - item.getElement()?.scrollIntoView(); + item.getElement()?.scrollIntoView({ + block: 'nearest', + inline: 'start', + }); } } diff --git a/tests/browser/test/basic_playground_test.mjs b/tests/browser/test/basic_playground_test.mjs index 55ff58e4b..c0a1f8930 100644 --- a/tests/browser/test/basic_playground_test.mjs +++ b/tests/browser/test/basic_playground_test.mjs @@ -137,7 +137,7 @@ suite('Disabling', function () { 110, ); await connect(this.browser, child, 'OUTPUT', parent, 'IF0'); - + await this.browser.pause(PAUSE_TIME); await contextMenuSelect(this.browser, parent, 'Disable Block'); chai.assert.isTrue(await getIsDisabled(this.browser, child.id)); diff --git a/tests/browser/test/delete_blocks_test.mjs b/tests/browser/test/delete_blocks_test.mjs index 27e17054d..a5df88705 100644 --- a/tests/browser/test/delete_blocks_test.mjs +++ b/tests/browser/test/delete_blocks_test.mjs @@ -123,10 +123,14 @@ suite('Delete blocks', function (done) { ) .waitForExist({timeout: 2000, reverse: true}); - // Load the start blocks - await this.browser.execute((blocks) => { - Blockly.serialization.workspaces.load(blocks, Blockly.getMainWorkspace()); - }, startBlocks); + // Load the start blocks. This hangs indefinitely if `startBlocks` is + // passed without being stringified. + this.browser.execute((blocks) => { + Blockly.serialization.workspaces.load( + JSON.parse(blocks), + Blockly.getMainWorkspace(), + ); + }, JSON.stringify(startBlocks)); // Wait for there to be a block on the main workspace before continuing (await getBlockElementById(this.browser, firstBlockId)).waitForExist({ timeout: 2000, diff --git a/tests/browser/test/procedure_test.mjs b/tests/browser/test/procedure_test.mjs index 34368c732..c01eb4956 100644 --- a/tests/browser/test/procedure_test.mjs +++ b/tests/browser/test/procedure_test.mjs @@ -26,6 +26,9 @@ suite('Testing Connecting Blocks', function (done) { // Setup Selenium for all of the tests suiteSetup(async function () { this.browser = await testSetup(testFileLocations.CODE_DEMO); + // Prevent WebDriver from suppressing alerts + // https://github.com/webdriverio/webdriverio/issues/13610#issuecomment-2357768103 + this.browser.on('dialog', (dialog) => {}); }); test('Testing Procedure', async function () { diff --git a/tests/browser/test/test_setup.mjs b/tests/browser/test/test_setup.mjs index 523a5d851..f07d559ad 100644 --- a/tests/browser/test/test_setup.mjs +++ b/tests/browser/test/test_setup.mjs @@ -254,9 +254,9 @@ export async function getCategory(browser, categoryName) { export async function getNthBlockOfCategory(browser, categoryName, n) { const category = await getCategory(browser, categoryName); await category.click(); - const block = await browser.$( - `.blocklyFlyout .blocklyBlockCanvas > g:nth-child(${3 + n * 2})`, - ); + const block = ( + await browser.$$(`.blocklyFlyout .blocklyBlockCanvas > .blocklyDraggable`) + )[n]; return block; } diff --git a/tests/browser/test/workspace_comment_test.mjs b/tests/browser/test/workspace_comment_test.mjs index 5719948d0..516523276 100644 --- a/tests/browser/test/workspace_comment_test.mjs +++ b/tests/browser/test/workspace_comment_test.mjs @@ -5,7 +5,6 @@ */ import * as chai from 'chai'; -import * as sinon from 'sinon'; import {testFileLocations, testSetup} from './test_setup.mjs'; suite('Workspace comments', function () { @@ -20,8 +19,6 @@ suite('Workspace comments', function () { }); teardown(async function () { - sinon.restore(); - await this.browser.execute(() => { Blockly.getMainWorkspace().clear(); }); From 6daa162a8c41caed7efd8559bec0ed426f343520 Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Thu, 16 Jan 2025 10:37:24 -0800 Subject: [PATCH 10/28] fix: Fix the browser tests. (#8735) (cherry picked from commit a86ba151546bb3b34176fcf222207e7618a6f094) --- core/menu.ts | 5 ++++- tests/browser/test/basic_playground_test.mjs | 2 +- tests/browser/test/delete_blocks_test.mjs | 12 ++++++++---- tests/browser/test/procedure_test.mjs | 3 +++ tests/browser/test/test_setup.mjs | 6 +++--- tests/browser/test/workspace_comment_test.mjs | 3 --- 6 files changed, 19 insertions(+), 12 deletions(-) diff --git a/core/menu.ts b/core/menu.ts index cce7d7bde..d1c86a802 100644 --- a/core/menu.ts +++ b/core/menu.ts @@ -264,7 +264,10 @@ export class Menu { if (el) { aria.setState(el, aria.State.ACTIVEDESCENDANT, item.getId()); } - item.getElement()?.scrollIntoView(); + item.getElement()?.scrollIntoView({ + block: 'nearest', + inline: 'start', + }); } } diff --git a/tests/browser/test/basic_playground_test.mjs b/tests/browser/test/basic_playground_test.mjs index 55ff58e4b..c0a1f8930 100644 --- a/tests/browser/test/basic_playground_test.mjs +++ b/tests/browser/test/basic_playground_test.mjs @@ -137,7 +137,7 @@ suite('Disabling', function () { 110, ); await connect(this.browser, child, 'OUTPUT', parent, 'IF0'); - + await this.browser.pause(PAUSE_TIME); await contextMenuSelect(this.browser, parent, 'Disable Block'); chai.assert.isTrue(await getIsDisabled(this.browser, child.id)); diff --git a/tests/browser/test/delete_blocks_test.mjs b/tests/browser/test/delete_blocks_test.mjs index 27e17054d..a5df88705 100644 --- a/tests/browser/test/delete_blocks_test.mjs +++ b/tests/browser/test/delete_blocks_test.mjs @@ -123,10 +123,14 @@ suite('Delete blocks', function (done) { ) .waitForExist({timeout: 2000, reverse: true}); - // Load the start blocks - await this.browser.execute((blocks) => { - Blockly.serialization.workspaces.load(blocks, Blockly.getMainWorkspace()); - }, startBlocks); + // Load the start blocks. This hangs indefinitely if `startBlocks` is + // passed without being stringified. + this.browser.execute((blocks) => { + Blockly.serialization.workspaces.load( + JSON.parse(blocks), + Blockly.getMainWorkspace(), + ); + }, JSON.stringify(startBlocks)); // Wait for there to be a block on the main workspace before continuing (await getBlockElementById(this.browser, firstBlockId)).waitForExist({ timeout: 2000, diff --git a/tests/browser/test/procedure_test.mjs b/tests/browser/test/procedure_test.mjs index 34368c732..c01eb4956 100644 --- a/tests/browser/test/procedure_test.mjs +++ b/tests/browser/test/procedure_test.mjs @@ -26,6 +26,9 @@ suite('Testing Connecting Blocks', function (done) { // Setup Selenium for all of the tests suiteSetup(async function () { this.browser = await testSetup(testFileLocations.CODE_DEMO); + // Prevent WebDriver from suppressing alerts + // https://github.com/webdriverio/webdriverio/issues/13610#issuecomment-2357768103 + this.browser.on('dialog', (dialog) => {}); }); test('Testing Procedure', async function () { diff --git a/tests/browser/test/test_setup.mjs b/tests/browser/test/test_setup.mjs index 523a5d851..f07d559ad 100644 --- a/tests/browser/test/test_setup.mjs +++ b/tests/browser/test/test_setup.mjs @@ -254,9 +254,9 @@ export async function getCategory(browser, categoryName) { export async function getNthBlockOfCategory(browser, categoryName, n) { const category = await getCategory(browser, categoryName); await category.click(); - const block = await browser.$( - `.blocklyFlyout .blocklyBlockCanvas > g:nth-child(${3 + n * 2})`, - ); + const block = ( + await browser.$$(`.blocklyFlyout .blocklyBlockCanvas > .blocklyDraggable`) + )[n]; return block; } diff --git a/tests/browser/test/workspace_comment_test.mjs b/tests/browser/test/workspace_comment_test.mjs index 5719948d0..516523276 100644 --- a/tests/browser/test/workspace_comment_test.mjs +++ b/tests/browser/test/workspace_comment_test.mjs @@ -5,7 +5,6 @@ */ import * as chai from 'chai'; -import * as sinon from 'sinon'; import {testFileLocations, testSetup} from './test_setup.mjs'; suite('Workspace comments', function () { @@ -20,8 +19,6 @@ suite('Workspace comments', function () { }); teardown(async function () { - sinon.restore(); - await this.browser.execute(() => { Blockly.getMainWorkspace().clear(); }); From 7a23c8878fe7f706971fceeea59547e7b738ef14 Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Thu, 16 Jan 2025 11:02:49 -0800 Subject: [PATCH 11/28] fix: Actually fix the browser tests. (#8736) --- tests/browser/test/test_setup.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/browser/test/test_setup.mjs b/tests/browser/test/test_setup.mjs index f07d559ad..9b48a3638 100644 --- a/tests/browser/test/test_setup.mjs +++ b/tests/browser/test/test_setup.mjs @@ -38,6 +38,7 @@ export async function driverSetup() { const options = { capabilities: { 'browserName': 'chrome', + 'unhandledPromptBehavior': 'ignore', 'goog:chromeOptions': { args: ['--allow-file-access-from-files'], }, From 50f390b57b9abeaf79c03d1109bcb7d33a85bae6 Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Thu, 16 Jan 2025 11:02:49 -0800 Subject: [PATCH 12/28] fix: Actually fix the browser tests. (#8736) (cherry picked from commit 7a23c8878fe7f706971fceeea59547e7b738ef14) --- tests/browser/test/test_setup.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/browser/test/test_setup.mjs b/tests/browser/test/test_setup.mjs index f07d559ad..9b48a3638 100644 --- a/tests/browser/test/test_setup.mjs +++ b/tests/browser/test/test_setup.mjs @@ -38,6 +38,7 @@ export async function driverSetup() { const options = { capabilities: { 'browserName': 'chrome', + 'unhandledPromptBehavior': 'ignore', 'goog:chromeOptions': { args: ['--allow-file-access-from-files'], }, From a190539bd8b67eb02e2d4bf03af4e2ea3f6f0650 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Contet?= Date: Mon, 20 Jan 2025 10:29:34 +0100 Subject: [PATCH 13/28] fix: Fix dropdown text color in Zelos (#8741) --- core/renderers/zelos/constants.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/renderers/zelos/constants.ts b/core/renderers/zelos/constants.ts index 74df72aeb..afef605eb 100644 --- a/core/renderers/zelos/constants.ts +++ b/core/renderers/zelos/constants.ts @@ -844,11 +844,11 @@ export class ConstantProvider extends BaseConstantProvider { `}`, // Widget and Dropdown Div - `${selector}.blocklyWidgetDiv .goog-menuitem,`, - `${selector}.blocklyDropDownDiv .goog-menuitem {`, + `${selector}.blocklyWidgetDiv .blocklyMenuItem,`, + `${selector}.blocklyDropDownDiv .blocklyMenuItem {`, `font-family: ${this.FIELD_TEXT_FONTFAMILY};`, `}`, - `${selector}.blocklyDropDownDiv .goog-menuitem-content {`, + `${selector}.blocklyDropDownDiv .blocklyMenuItemContent {`, `color: #fff;`, `}`, From 3e4665e5b824041867b79f0cf8b657c5e6c32236 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 19:24:16 +0000 Subject: [PATCH 14/28] chore(deps): bump globals from 15.12.0 to 15.14.0 (#8742) Bumps [globals](https://github.com/sindresorhus/globals) from 15.12.0 to 15.14.0. - [Release notes](https://github.com/sindresorhus/globals/releases) - [Commits](https://github.com/sindresorhus/globals/compare/v15.12.0...v15.14.0) --- updated-dependencies: - dependency-name: globals dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 86c603884..94530dfab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4649,10 +4649,11 @@ } }, "node_modules/globals": { - "version": "15.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.12.0.tgz", - "integrity": "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==", + "version": "15.14.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz", + "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, From 34da1da06108c8488b349cd7756463684e9d74ce Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Fri, 31 Jan 2025 08:10:33 -0800 Subject: [PATCH 15/28] fix: Fix flaky connection checker test. (#8754) --- tests/mocha/connection_checker_test.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/mocha/connection_checker_test.js b/tests/mocha/connection_checker_test.js index f7aa33ba8..f353a2b77 100644 --- a/tests/mocha/connection_checker_test.js +++ b/tests/mocha/connection_checker_test.js @@ -503,8 +503,9 @@ suite('Connection checker', function () { `), this.workspace, ); - [this.blockA, this.blockB, this.blockC] = - this.workspace.getAllBlocks(true); + this.blockA = this.workspace.getBlockById('A'); + this.blockB = this.workspace.getBlockById('B'); + this.blockC = this.workspace.getBlockById('C'); this.checker = this.workspace.connectionChecker; }); From 101ad8282650d77a2afdb27131286430a9a266ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 08:25:39 -0800 Subject: [PATCH 16/28] chore(deps): bump @microsoft/api-documenter from 7.25.14 to 7.26.7 (#8757) Bumps [@microsoft/api-documenter](https://github.com/microsoft/rushstack/tree/HEAD/apps/api-documenter) from 7.25.14 to 7.26.7. - [Changelog](https://github.com/microsoft/rushstack/blob/main/apps/api-documenter/CHANGELOG.md) - [Commits](https://github.com/microsoft/rushstack/commits/@microsoft/api-documenter_v7.26.7/apps/api-documenter) --- updated-dependencies: - dependency-name: "@microsoft/api-documenter" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 78 +++++++++++++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 27 deletions(-) diff --git a/package-lock.json b/package-lock.json index 94530dfab..f8c7dac87 100644 --- a/package-lock.json +++ b/package-lock.json @@ -699,16 +699,17 @@ } }, "node_modules/@microsoft/api-documenter": { - "version": "7.25.14", - "resolved": "https://registry.npmjs.org/@microsoft/api-documenter/-/api-documenter-7.25.14.tgz", - "integrity": "sha512-nysAB+j4l5Al3XvCdee6tw0rw4fXpnlIq9En2opcc3DgITeoehiaYYoZZqoqOQSKlSUDWF7Z55GGsvntVrcBkg==", + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@microsoft/api-documenter/-/api-documenter-7.26.7.tgz", + "integrity": "sha512-VruYlHYAhQfuBNyndvyD9GBmCRWSOZ8D9+eXicygycNPMC/SPM71WWu2OwP98CTBvq/OhG/uRvUGGdL4QvgiFQ==", "dev": true, + "license": "MIT", "dependencies": { - "@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", + "@microsoft/api-extractor-model": "7.30.3", + "@microsoft/tsdoc": "~0.15.1", + "@rushstack/node-core-library": "5.11.0", + "@rushstack/terminal": "0.14.6", + "@rushstack/ts-command-line": "4.23.4", "js-yaml": "~3.13.1", "resolve": "~1.22.1" }, @@ -763,14 +764,15 @@ } }, "node_modules/@microsoft/api-extractor-model": { - "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==", + "version": "7.30.3", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.30.3.tgz", + "integrity": "sha512-yEAvq0F78MmStXdqz9TTT4PZ05Xu5R8nqgwI5xmUmQjWBQ9E6R2n8HB/iZMRciG4rf9iwI2mtuQwIzDXBvHn1w==", "dev": true, + "license": "MIT", "dependencies": { - "@microsoft/tsdoc": "~0.15.0", - "@microsoft/tsdoc-config": "~0.17.0", - "@rushstack/node-core-library": "5.9.0" + "@microsoft/tsdoc": "~0.15.1", + "@microsoft/tsdoc-config": "~0.17.1", + "@rushstack/node-core-library": "5.11.0" } }, "node_modules/@microsoft/api-extractor/node_modules/@microsoft/api-extractor-model": { @@ -1069,15 +1071,16 @@ } }, "node_modules/@rushstack/node-core-library": { - "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==", + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.11.0.tgz", + "integrity": "sha512-I8+VzG9A0F3nH2rLpPd7hF8F7l5Xb7D+ldrWVZYegXM6CsKkvWc670RlgK3WX8/AseZfXA/vVrh0bpXe2Y2UDQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "~8.13.0", "ajv-draft-04": "~1.0.0", "ajv-formats": "~3.0.1", - "fs-extra": "~7.0.1", + "fs-extra": "~11.3.0", "import-lazy": "~4.0.0", "jju": "~1.4.0", "resolve": "~1.22.1", @@ -1097,6 +1100,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz", "integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", @@ -1108,11 +1112,27 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/@rushstack/node-core-library/node_modules/fs-extra": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", + "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "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 + "dev": true, + "license": "MIT" }, "node_modules/@rushstack/rig-package": { "version": "0.5.3", @@ -1125,12 +1145,13 @@ } }, "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==", + "version": "0.14.6", + "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.14.6.tgz", + "integrity": "sha512-4nMUy4h0u5PGXVG71kEA9uYI3l8GjVqewoHOFONiM6fuqS51ORdaJZ5ZXB2VZEGUyfg1TOTSy88MF2cdAy+lqA==", "dev": true, + "license": "MIT", "dependencies": { - "@rushstack/node-core-library": "5.9.0", + "@rushstack/node-core-library": "5.11.0", "supports-color": "~8.1.1" }, "peerDependencies": { @@ -1147,6 +1168,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -1158,12 +1180,13 @@ } }, "node_modules/@rushstack/ts-command-line": { - "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==", + "version": "4.23.4", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.23.4.tgz", + "integrity": "sha512-pqmzDJCm0TS8VyeqnzcJ7ncwXgiLDQ6LVmXXfqv2nPL6VIz+UpyTpNVfZRJpyyJ+UDxqob1vIj2liaUfBjv8/A==", "dev": true, + "license": "MIT", "dependencies": { - "@rushstack/terminal": "0.14.2", + "@rushstack/terminal": "0.14.6", "@types/argparse": "1.0.38", "argparse": "~1.0.9", "string-argv": "~0.3.1" @@ -1174,6 +1197,7 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, + "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } From 8fcc73097f854328ee520d3681afe78b2be19bbe Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Tue, 4 Feb 2025 15:47:25 -0800 Subject: [PATCH 17/28] fix: Improve menu mouse/keyboard selection interaction. (#8749) * chore: Use "pointer" instead of "mouse" in menu.ts. * fix: Only highlight menu items on hover if the pointer has moved. * fix: Don't blur menus on pointerleave. --- core/menu.ts | 91 +++++++++++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 40 deletions(-) diff --git a/core/menu.ts b/core/menu.ts index d1c86a802..7747a2973 100644 --- a/core/menu.ts +++ b/core/menu.ts @@ -31,8 +31,8 @@ export class Menu { private readonly menuItems: MenuItem[] = []; /** - * Coordinates of the mousedown event that caused this menu to open. Used to - * prevent the consequent mouseup event due to a simple click from + * Coordinates of the pointerdown event that caused this menu to open. Used to + * prevent the consequent pointerup event due to a simple click from * activating a menu item immediately. */ openingCoords: Coordinate | null = null; @@ -43,17 +43,17 @@ export class Menu { */ private highlightedItem: MenuItem | null = null; - /** Mouse over event data. */ - private mouseOverHandler: browserEvents.Data | null = null; + /** Pointer over event data. */ + private pointerMoveHandler: browserEvents.Data | null = null; /** Click event data. */ private clickHandler: browserEvents.Data | null = null; - /** Mouse enter event data. */ - private mouseEnterHandler: browserEvents.Data | null = null; + /** Pointer enter event data. */ + private pointerEnterHandler: browserEvents.Data | null = null; - /** Mouse leave event data. */ - private mouseLeaveHandler: browserEvents.Data | null = null; + /** Pointer leave event data. */ + private pointerLeaveHandler: browserEvents.Data | null = null; /** Key down event data. */ private onKeyDownHandler: browserEvents.Data | null = null; @@ -99,11 +99,11 @@ export class Menu { } // Add event handlers. - this.mouseOverHandler = browserEvents.conditionalBind( + this.pointerMoveHandler = browserEvents.conditionalBind( element, - 'pointerover', + 'pointermove', this, - this.handleMouseOver, + this.handlePointerMove, true, ); this.clickHandler = browserEvents.conditionalBind( @@ -113,18 +113,18 @@ export class Menu { this.handleClick, true, ); - this.mouseEnterHandler = browserEvents.conditionalBind( + this.pointerEnterHandler = browserEvents.conditionalBind( element, 'pointerenter', this, - this.handleMouseEnter, + this.handlePointerEnter, true, ); - this.mouseLeaveHandler = browserEvents.conditionalBind( + this.pointerLeaveHandler = browserEvents.conditionalBind( element, 'pointerleave', this, - this.handleMouseLeave, + this.handlePointerLeave, true, ); this.onKeyDownHandler = browserEvents.conditionalBind( @@ -183,21 +183,21 @@ export class Menu { /** Dispose of this menu. */ dispose() { // Remove event handlers. - if (this.mouseOverHandler) { - browserEvents.unbind(this.mouseOverHandler); - this.mouseOverHandler = null; + if (this.pointerMoveHandler) { + browserEvents.unbind(this.pointerMoveHandler); + this.pointerMoveHandler = null; } if (this.clickHandler) { browserEvents.unbind(this.clickHandler); this.clickHandler = null; } - if (this.mouseEnterHandler) { - browserEvents.unbind(this.mouseEnterHandler); - this.mouseEnterHandler = null; + if (this.pointerEnterHandler) { + browserEvents.unbind(this.pointerEnterHandler); + this.pointerEnterHandler = null; } - if (this.mouseLeaveHandler) { - browserEvents.unbind(this.mouseLeaveHandler); - this.mouseLeaveHandler = null; + if (this.pointerLeaveHandler) { + browserEvents.unbind(this.pointerLeaveHandler); + this.pointerLeaveHandler = null; } if (this.onKeyDownHandler) { browserEvents.unbind(this.onKeyDownHandler); @@ -326,14 +326,26 @@ export class Menu { } } - // Mouse events. + // Pointer events. /** - * Handles mouseover events. Highlight menuitems as the user hovers over them. + * Handles pointermove events. Highlight menu items as the user hovers over + * them. * - * @param e Mouse event to handle. + * @param e Pointer event to handle. */ - private handleMouseOver(e: PointerEvent) { + private handlePointerMove(e: PointerEvent) { + // Check whether the pointer actually did move. Move events are triggered if + // the element underneath the pointer moves, even if the pointer itself has + // remained stationary. In the case where the pointer is hovering over + // the menu but the user is navigating through the list of items via the + // keyboard and causing items off the end of the menu to scroll into view, + // a pointermove event would be triggered due to the pointer now being over + // a new child, but we don't want to highlight the item that's now under the + // pointer. + const delta = Math.max(Math.abs(e.movementX), Math.abs(e.movementY)); + if (delta === 0) return; + const menuItem = this.getMenuItem(e.target as Element); if (menuItem) { @@ -359,11 +371,11 @@ export class Menu { if (oldCoords && typeof e.clientX === 'number') { const newCoords = new Coordinate(e.clientX, e.clientY); if (Coordinate.distance(oldCoords, newCoords) < 1) { - // This menu was opened by a mousedown and we're handling the consequent - // click event. The coords haven't changed, meaning this was the same - // opening event. Don't do the usual behavior because the menu just - // popped up under the mouse and the user didn't mean to activate this - // item. + // This menu was opened by a pointerdown and we're handling the + // consequent click event. The coords haven't changed, meaning this was + // the same opening event. Don't do the usual behavior because the menu + // just popped up under the pointer and the user didn't mean to activate + // this item. return; } } @@ -375,22 +387,21 @@ export class Menu { } /** - * Handles mouse enter events. Focus the element. + * Handles pointer enter events. Focus the element. * - * @param _e Mouse event to handle. + * @param _e Pointer event to handle. */ - private handleMouseEnter(_e: PointerEvent) { + private handlePointerEnter(_e: PointerEvent) { this.focus(); } /** - * Handles mouse leave events. Blur and clear highlight. + * Handles pointer leave events by clearing the active highlight. * - * @param _e Mouse event to handle. + * @param _e Pointer event to handle. */ - private handleMouseLeave(_e: PointerEvent) { + private handlePointerLeave(_e: PointerEvent) { if (this.getElement()) { - this.blur(); this.setHighlighted(null); } } From db57976e1029e278bcc5f59121d0a798a633e666 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 08:37:15 -0800 Subject: [PATCH 18/28] chore(deps): bump typescript-eslint from 8.16.0 to 8.23.0 (#8761) Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.16.0 to 8.23.0. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.23.0/packages/typescript-eslint) --- updated-dependencies: - dependency-name: typescript-eslint dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 205 +++++++++++++++++++++++----------------------- 1 file changed, 103 insertions(+), 102 deletions(-) diff --git a/package-lock.json b/package-lock.json index f8c7dac87..090e62619 100644 --- a/package-lock.json +++ b/package-lock.json @@ -965,6 +965,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -978,6 +979,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -987,6 +989,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -1333,20 +1336,21 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "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==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.23.0.tgz", + "integrity": "sha512-vBz65tJgRrA1Q5gWlRfvoH+w943dq9K1p1yDBY2pc+a1nbBLZp7fB9+Hk8DaALUbzjqlMfgaqlVPT1REJdkt/w==", "dev": true, + "license": "MIT", "dependencies": { "@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", + "@typescript-eslint/scope-manager": "8.23.0", + "@typescript-eslint/type-utils": "8.23.0", + "@typescript-eslint/utils": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1357,24 +1361,21 @@ }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.16.0.tgz", - "integrity": "sha512-D7DbgGFtsqIPIFMPJwCad9Gfi/hC0PWErRRHFnaCWoEDYi5tQUDiJCTmGUbBiLzjqAck4KcXt9Ayj0CNlIrF+w==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.23.0.tgz", + "integrity": "sha512-h2lUByouOXFAlMec2mILeELUbME5SZRN/7R9Cw2RD2lRQQY08MWMM+PmVVKKJNK1aIwqTo9t/0CvOxwPbRIE2Q==", "dev": true, + "license": "MIT", "dependencies": { - "@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", + "@typescript-eslint/scope-manager": "8.23.0", + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/typescript-estree": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0", "debug": "^4.3.4" }, "engines": { @@ -1385,22 +1386,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.16.0.tgz", - "integrity": "sha512-mwsZWubQvBki2t5565uxF0EYvG+FwdFb8bMtDuGQLdCCnGPrDEDvm1gtfynuKlnpzeBRqdFCkMf9jg1fnAK8sg==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.23.0.tgz", + "integrity": "sha512-OGqo7+dXHqI7Hfm+WqkZjKjsiRtFUQHPdGMXzk5mYXhJUedO7e/Y7i8AK3MyLMgZR93TX4bIzYrfyVjLC+0VSw==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.16.0", - "@typescript-eslint/visitor-keys": "8.16.0" + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1411,15 +1409,16 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "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==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.23.0.tgz", + "integrity": "sha512-iIuLdYpQWZKbiH+RkCGc6iu+VwscP5rCtQ1lyQ7TYuKLrcZoeJVpcLiG8DliXVkUxirW/PWlmS+d6yD51L9jvA==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.16.0", - "@typescript-eslint/utils": "8.16.0", + "@typescript-eslint/typescript-estree": "8.23.0", + "@typescript-eslint/utils": "8.23.0", "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1429,19 +1428,16 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.16.0.tgz", - "integrity": "sha512-NzrHj6thBAOSE4d9bsuRNMvk+BvaQvmY4dDglgkgGC0EW/tB3Kelnp3tAKH87GEwzoxgeQn9fNGRyFJM/xd+GQ==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.23.0.tgz", + "integrity": "sha512-1sK4ILJbCmZOTt9k4vkoulT6/y5CHJ1qUYxqpF1K/DBAd8+ZUL4LlSCxOssuH5m4rUaaN0uS0HlVPvd45zjduQ==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -1451,19 +1447,20 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.16.0.tgz", - "integrity": "sha512-E2+9IzzXMc1iaBy9zmo+UYvluE3TW7bCGWSF41hVWUE01o8nzr1rvOQYSxelxr6StUvRcTMe633eY8mXASMaNw==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.23.0.tgz", + "integrity": "sha512-LcqzfipsB8RTvH8FX24W4UUFk1bl+0yTOf9ZA08XngFwMg4Kj8A+9hwz8Cr/ZS4KwHrmo9PJiLZkOt49vPnuvQ==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.16.0", - "@typescript-eslint/visitor-keys": "8.16.0", + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1472,10 +1469,8 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { @@ -1483,6 +1478,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -1492,6 +1488,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -1503,10 +1500,11 @@ } }, "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==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -1515,15 +1513,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.16.0.tgz", - "integrity": "sha512-C1zRy/mOL8Pj157GiX4kaw7iyRLKfJXBR3L82hk5kS/GyHcOFmy4YUq/zfZti72I9wnuQtA/+xzft4wCC8PJdA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.23.0.tgz", + "integrity": "sha512-uB/+PSo6Exu02b5ZEiVtmY6RVYO7YU5xqgzTIVZwTHvvK3HsL8tZZHFaTLFtRG3CsV4A5mhOv+NZx5BlhXPyIA==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.16.0", - "@typescript-eslint/types": "8.16.0", - "@typescript-eslint/typescript-estree": "8.16.0" + "@typescript-eslint/scope-manager": "8.23.0", + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/typescript-estree": "8.23.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1533,21 +1532,18 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.16.0.tgz", - "integrity": "sha512-pq19gbaMOmFE3CbL0ZB8J8BFCo2ckfHBfaIsaOZgBIF4EoISJIdLX5xRhd0FGB0LlHReNRuzoJoMGpTjq8F2CQ==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.23.0.tgz", + "integrity": "sha512-oWWhcWDLwDfu++BGTZcmXWqpwtkwb5o7fxUIGksMQQDSdPW9prsSnfIOZMlsj4vBOSrcnjIUZMiIjODgGosFhQ==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/types": "8.23.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -1563,6 +1559,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -4055,16 +4052,17 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -4786,7 +4784,8 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/gulp": { "version": "5.0.0", @@ -6327,15 +6326,17 @@ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -7378,7 +7379,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/queue-tick": { "version": "1.0.1", @@ -7676,6 +7678,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -8387,15 +8390,16 @@ } }, "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", + "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==", "dev": true, + "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18.12" }, "peerDependencies": { - "typescript": ">=4.2.0" + "typescript": ">=4.8.4" } }, "node_modules/tslib": { @@ -8463,14 +8467,15 @@ } }, "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==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.23.0.tgz", + "integrity": "sha512-/LBRo3HrXr5LxmrdYSOCvoAMm7p2jNizNfbIpCgvG4HMsnoprRUOce/+8VJ9BDYWW68rqIENE/haVLWPeFZBVQ==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.16.0", - "@typescript-eslint/parser": "8.16.0", - "@typescript-eslint/utils": "8.16.0" + "@typescript-eslint/eslint-plugin": "8.23.0", + "@typescript-eslint/parser": "8.23.0", + "@typescript-eslint/utils": "8.23.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -8480,12 +8485,8 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/unbzip2-stream": { From 58406af64fcf7f938b3f03975c559fa7bc5a30b6 Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Wed, 12 Feb 2025 11:53:16 -0800 Subject: [PATCH 19/28] fix: Fix menu scrolling. (#8765) * Revert "fix: Fix bug that preventing scrolling menu items into view. (#8726)" This reverts commit f166b677c0d323d1793060b8b7ddca5d2076ca69. * fix: Fix menu scrolling. --- core/field_dropdown.ts | 6 ++++++ core/menu.ts | 15 +++++++-------- core/utils/style.ts | 14 -------------- 3 files changed, 13 insertions(+), 22 deletions(-) diff --git a/core/field_dropdown.ts b/core/field_dropdown.ts index 6e8b5f8c8..bc2d2856f 100644 --- a/core/field_dropdown.ts +++ b/core/field_dropdown.ts @@ -29,6 +29,7 @@ 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'; /** @@ -303,6 +304,11 @@ export class FieldDropdown extends Field { if (this.selectedMenuItem) { this.menu_!.setHighlighted(this.selectedMenuItem); + style.scrollIntoContainerView( + this.selectedMenuItem.getElement()!, + dropDownDiv.getContentDiv(), + true, + ); } this.applyColour(); diff --git a/core/menu.ts b/core/menu.ts index 7747a2973..ee54c8cf2 100644 --- a/core/menu.ts +++ b/core/menu.ts @@ -260,14 +260,13 @@ export class Menu { this.highlightedItem = item; // Bring the highlighted item into view. This has no effect if the menu is // not scrollable. - const el = this.getElement(); - if (el) { - aria.setState(el, aria.State.ACTIVEDESCENDANT, item.getId()); - } - item.getElement()?.scrollIntoView({ - block: 'nearest', - inline: 'start', - }); + const menuElement = this.getElement(); + const scrollingParent = menuElement?.parentElement; + const menuItemElement = item.getElement(); + if (!scrollingParent || !menuItemElement) return; + + style.scrollIntoContainerView(menuItemElement, scrollingParent); + aria.setState(menuElement, aria.State.ACTIVEDESCENDANT, item.getId()); } } diff --git a/core/utils/style.ts b/core/utils/style.ts index 5de69001f..4f8324be5 100644 --- a/core/utils/style.ts +++ b/core/utils/style.ts @@ -7,7 +7,6 @@ // Former goog.module ID: Blockly.utils.style import {Coordinate} from './coordinate.js'; -import * as deprecation from './deprecation.js'; import {Rect} from './rect.js'; import {Size} from './size.js'; @@ -59,7 +58,6 @@ function getSizeInternal(element: Element): Size { * @returns Object with width/height properties. */ function getSizeWithDisplay(element: Element): Size { - deprecation.warn(`Blockly.utils.style.getSizeWithDisplay()`, 'v11.2', 'v13'); const offsetWidth = (element as HTMLElement).offsetWidth; const offsetHeight = (element as HTMLElement).offsetHeight; return new Size(offsetWidth, offsetHeight); @@ -132,7 +130,6 @@ export function getViewportPageOffset(): Coordinate { * @returns The computed border widths. */ export function getBorderBox(element: Element): Rect { - deprecation.warn(`Blockly.utils.style.getBorderBox()`, 'v11.2', 'v13'); const left = parseFloat(getComputedStyle(element, 'borderLeftWidth')); const right = parseFloat(getComputedStyle(element, 'borderRightWidth')); const top = parseFloat(getComputedStyle(element, 'borderTopWidth')); @@ -159,12 +156,6 @@ export function scrollIntoContainerView( container: Element, opt_center?: boolean, ) { - deprecation.warn( - `Blockly.utils.style.scrollIntoContainerView()`, - 'v11.2', - 'v13', - 'the native Element.scrollIntoView()', - ); const offset = getContainerOffsetToScrollInto(element, container, opt_center); container.scrollLeft = offset.x; container.scrollTop = offset.y; @@ -189,11 +180,6 @@ export function getContainerOffsetToScrollInto( container: Element, opt_center?: boolean, ): Coordinate { - deprecation.warn( - `Blockly.utils.style.getContainerOffsetToScrollInto()`, - 'v11.2', - 'v13', - ); // Absolute position of the element's border's top left corner. const elementPos = getPageOffset(element); // Absolute position of the container's border's top left corner. From 15d6ea2558d9f36e4227d8002a9c49b2a05f86b5 Mon Sep 17 00:00:00 2001 From: RoboErikG Date: Wed, 12 Feb 2025 13:16:35 -0800 Subject: [PATCH 20/28] Fix: #8194 by using a stepped animation for the wiggle (#8743) * Fix #8194 by using animation steps for the wiggle * Formatting cleanup --- core/block_animations.ts | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/core/block_animations.ts b/core/block_animations.ts index f3fc3d454..2dbf90777 100644 --- a/core/block_animations.ts +++ b/core/block_animations.ts @@ -176,7 +176,7 @@ export function disconnectUiEffect(block: BlockSvg) { } // Start the animation. wobblingBlock = block; - disconnectUiStep(block, magnitude, new Date()); + disconnectUiStep(block, magnitude, new Date(), 0); } /** @@ -184,22 +184,30 @@ export function disconnectUiEffect(block: BlockSvg) { * * @param block Block to animate. * @param magnitude Maximum degrees skew (reversed for RTL). - * @param start Date of animation's start. + * @param start Date of animation's start for deciding when to stop. + * @param step Which step of the animation we're on. */ -function disconnectUiStep(block: BlockSvg, magnitude: number, start: Date) { +function disconnectUiStep( + block: BlockSvg, + magnitude: number, + start: Date, + step: number, +) { const DURATION = 200; // Milliseconds. - const WIGGLES = 3; // Half oscillations. - - const ms = new Date().getTime() - start.getTime(); - const percent = ms / DURATION; + const WIGGLES = [0.66, 1, 0.66, 0, -0.66, -1, -0.66, 0]; // Single cycle let skew = ''; - if (percent <= 1) { - const val = Math.round( - Math.sin(percent * Math.PI * WIGGLES) * (1 - percent) * magnitude, - ); + if (start.getTime() + DURATION > new Date().getTime()) { + const val = Math.round(WIGGLES[step % WIGGLES.length] * magnitude); skew = `skewX(${val})`; - disconnectPid = setTimeout(disconnectUiStep, 10, block, magnitude, start); + disconnectPid = setTimeout( + disconnectUiStep, + 15, + block, + magnitude, + start, + step + 1, + ); } block From 29950fd8720cfe609fa5622a0cbaf06560df854a Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Wed, 12 Feb 2025 14:22:14 -0800 Subject: [PATCH 21/28] fix: Allow dragging blocks from the far lower right corner. (#8766) --- core/css.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/core/css.ts b/core/css.ts index c7443e5f0..d0e067041 100644 --- a/core/css.ts +++ b/core/css.ts @@ -353,6 +353,7 @@ input[type=number] { .blocklyScrollbarBackground { opacity: 0; + pointer-events: none; } .blocklyScrollbarHandle { From 7e44e81e4270779f7f05e57cdb3ac6ab8e343aca Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Thu, 20 Feb 2025 09:56:41 -0800 Subject: [PATCH 22/28] fix: Fix bug that prevented editing workspace comments on Firefox. (#8779) * fix: Fix bug that prevented editing workspace comments on Firefox. * chore: Add a docstring for getTextArea(). * refactor: Use isTargetInput() instead of comparing to comment textarea. --- core/comments/rendered_workspace_comment.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/core/comments/rendered_workspace_comment.ts b/core/comments/rendered_workspace_comment.ts index ff2133574..f4885df46 100644 --- a/core/comments/rendered_workspace_comment.ts +++ b/core/comments/rendered_workspace_comment.ts @@ -208,8 +208,14 @@ export class RenderedWorkspaceComment private startGesture(e: PointerEvent) { const gesture = this.workspace.getGesture(e); if (gesture) { - gesture.handleCommentStart(e, this); - this.workspace.getLayerManager()?.append(this, layers.BLOCK); + if (browserEvents.isTargetInput(e)) { + // If the text area was the focus, don't allow this event to bubble up + // and steal focus away from the editor/comment. + e.stopPropagation(); + } else { + gesture.handleCommentStart(e, this); + this.workspace.getLayerManager()?.append(this, layers.BLOCK); + } common.setSelected(this); } } From d016801089b2c580416674ab947d2bd0ddf3f854 Mon Sep 17 00:00:00 2001 From: michaela-mm <63740955+michaela-mm@users.noreply.github.com> Date: Mon, 24 Feb 2025 15:35:33 +0100 Subject: [PATCH 23/28] fix: Fix bug in IF block generators. (#8780) --- generators/dart/logic.ts | 4 +++- generators/javascript/logic.ts | 4 +++- generators/lua/logic.ts | 4 +++- generators/php/logic.ts | 4 +++- generators/python/logic.ts | 6 +++++- 5 files changed, 17 insertions(+), 5 deletions(-) diff --git a/generators/dart/logic.ts b/generators/dart/logic.ts index 45c385b86..7e8a4709b 100644 --- a/generators/dart/logic.ts +++ b/generators/dart/logic.ts @@ -46,7 +46,9 @@ export function controls_if(block: Block, generator: DartGenerator) { } while (block.getInput('IF' + n)); if (block.getInput('ELSE') || generator.STATEMENT_SUFFIX) { - branchCode = generator.statementToCode(block, 'ELSE'); + branchCode = block.getInput('ELSE') + ? generator.statementToCode(block, 'ELSE') + : ''; if (generator.STATEMENT_SUFFIX) { branchCode = generator.prefixLines( diff --git a/generators/javascript/logic.ts b/generators/javascript/logic.ts index 60174c85a..1e26f86e7 100644 --- a/generators/javascript/logic.ts +++ b/generators/javascript/logic.ts @@ -44,7 +44,9 @@ export function controls_if(block: Block, generator: JavascriptGenerator) { } while (block.getInput('IF' + n)); if (block.getInput('ELSE') || generator.STATEMENT_SUFFIX) { - let branchCode = generator.statementToCode(block, 'ELSE'); + let branchCode = block.getInput('ELSE') + ? generator.statementToCode(block, 'ELSE') + : ''; if (generator.STATEMENT_SUFFIX) { branchCode = generator.prefixLines( diff --git a/generators/lua/logic.ts b/generators/lua/logic.ts index b6448445c..8e48c741a 100644 --- a/generators/lua/logic.ts +++ b/generators/lua/logic.ts @@ -39,7 +39,9 @@ export function controls_if(block: Block, generator: LuaGenerator): string { } while (block.getInput('IF' + n)); if (block.getInput('ELSE') || generator.STATEMENT_SUFFIX) { - let branchCode = generator.statementToCode(block, 'ELSE'); + let branchCode = block.getInput('ELSE') + ? generator.statementToCode(block, 'ELSE') + : ''; if (generator.STATEMENT_SUFFIX) { branchCode = generator.prefixLines( diff --git a/generators/php/logic.ts b/generators/php/logic.ts index 731fe5708..80d4e331d 100644 --- a/generators/php/logic.ts +++ b/generators/php/logic.ts @@ -46,7 +46,9 @@ export function controls_if(block: Block, generator: PhpGenerator) { } while (block.getInput('IF' + n)); if (block.getInput('ELSE') || generator.STATEMENT_SUFFIX) { - branchCode = generator.statementToCode(block, 'ELSE'); + branchCode = block.getInput('ELSE') + ? generator.statementToCode(block, 'ELSE') + : ''; if (generator.STATEMENT_SUFFIX) { branchCode = generator.prefixLines( diff --git a/generators/python/logic.ts b/generators/python/logic.ts index 40133600d..db1f60e2a 100644 --- a/generators/python/logic.ts +++ b/generators/python/logic.ts @@ -40,7 +40,11 @@ export function controls_if(block: Block, generator: PythonGenerator) { } while (block.getInput('IF' + n)); if (block.getInput('ELSE') || generator.STATEMENT_SUFFIX) { - branchCode = generator.statementToCode(block, 'ELSE') || generator.PASS; + if (block.getInput('ELSE')) { + branchCode = generator.statementToCode(block, 'ELSE') || generator.PASS; + } else { + branchCode = generator.PASS; + } if (generator.STATEMENT_SUFFIX) { branchCode = generator.prefixLines( From dcd2d0e539f2b7aa34b58969d5dc812e7848800c Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Thu, 27 Feb 2025 13:04:37 -0800 Subject: [PATCH 24/28] fix: Fix a bug where selection outlines could be cut off when connecting blocks. (#8789) --- core/rendered_connection.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/core/rendered_connection.ts b/core/rendered_connection.ts index f73dc0628..c1d97dcdd 100644 --- a/core/rendered_connection.ts +++ b/core/rendered_connection.ts @@ -533,6 +533,21 @@ export class RenderedConnection extends Connection { childBlock.updateDisabled(); childBlock.queueRender(); + // If either block being connected was selected, visually un- and reselect + // it. This has the effect of moving the selection path to the end of the + // list of child nodes in the DOM. Since SVG z-order is determined by node + // order in the DOM, this works around an issue where the selection outline + // path could be partially obscured by a new block inserted after it in the + // DOM. + const selection = common.getSelected(); + const selectedBlock = + (selection === parentBlock && parentBlock) || + (selection === childBlock && childBlock); + if (selectedBlock) { + selectedBlock.removeSelect(); + selectedBlock.addSelect(); + } + // The input the child block is connected to (if any). const parentInput = parentBlock.getInputWithBlock(childBlock); if (parentInput) { From fd558106b134e5d3880b526f0d22ff44c3eb547b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Mar 2025 16:39:38 +0000 Subject: [PATCH 25/28] chore(deps): bump google-github-actions/deploy-appengine (#8755) Bumps [google-github-actions/deploy-appengine](https://github.com/google-github-actions/deploy-appengine) from 2.1.4 to 2.1.5. - [Release notes](https://github.com/google-github-actions/deploy-appengine/releases) - [Changelog](https://github.com/google-github-actions/deploy-appengine/blob/main/CHANGELOG.md) - [Commits](https://github.com/google-github-actions/deploy-appengine/compare/v2.1.4...v2.1.5) --- updated-dependencies: - dependency-name: google-github-actions/deploy-appengine dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/appengine_deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/appengine_deploy.yml b/.github/workflows/appengine_deploy.yml index 938a16fc7..1dd6d2ffa 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.4 + uses: google-github-actions/deploy-appengine@v2.1.5 # For parameters see: # https://github.com/google-github-actions/deploy-appengine#inputs with: From d3f0c6d58913c363a58fbb09171a34d0bf3a3692 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Mar 2025 16:40:48 +0000 Subject: [PATCH 26/28] chore(deps): bump @hyperjump/json-schema from 1.9.8 to 1.11.0 (#8760) Bumps [@hyperjump/json-schema](https://github.com/hyperjump-io/json-schema) from 1.9.8 to 1.11.0. - [Commits](https://github.com/hyperjump-io/json-schema/compare/v1.9.8...v1.11.0) --- updated-dependencies: - dependency-name: "@hyperjump/json-schema" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 090e62619..c45ce36e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -570,10 +570,11 @@ } }, "node_modules/@hyperjump/json-schema": { - "version": "1.9.8", - "resolved": "https://registry.npmjs.org/@hyperjump/json-schema/-/json-schema-1.9.8.tgz", - "integrity": "sha512-qmdMpYn8CpYR7z3fxkL6fgkDvMaAEFKtmYu3XDi6hWW2BT+rLl7T4Y4QpafEIR4wkcmCxcJf9me9FmxKpv3i9g==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@hyperjump/json-schema/-/json-schema-1.11.0.tgz", + "integrity": "sha512-gX1YNObOybUW6tgJjvb1lomNbI/VnY+EBPokmEGy9Lk8cgi+gE0vXhX1XDgIpUUA4UXfgHEn5I1mga5vHgOttg==", "dev": true, + "license": "MIT", "dependencies": { "@hyperjump/json-pointer": "^1.1.0", "@hyperjump/pact": "^1.2.0", From 810dd729709f8d30ff39ebcc6fb7f66db56a27e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Mar 2025 16:45:30 +0000 Subject: [PATCH 27/28] chore(deps): bump eslint-plugin-prettier from 5.2.1 to 5.2.3 (#8777) Bumps [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) from 5.2.1 to 5.2.3. - [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases) - [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/master/CHANGELOG.md) - [Commits](https://github.com/prettier/eslint-plugin-prettier/compare/v5.2.1...v5.2.3) --- updated-dependencies: - dependency-name: eslint-plugin-prettier dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index c45ce36e7..4678a4da0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3754,10 +3754,11 @@ } }, "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==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz", + "integrity": "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==", "dev": true, + "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.0", "synckit": "^0.9.1" From 87efad06705fe054e175d4e16a78546f679cae04 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Mar 2025 17:47:10 +0000 Subject: [PATCH 28/28] chore(deps): bump glob from 10.4.1 to 11.0.1 (#8730) Bumps [glob](https://github.com/isaacs/node-glob) from 10.4.1 to 11.0.1. - [Changelog](https://github.com/isaacs/node-glob/blob/main/changelog.md) - [Commits](https://github.com/isaacs/node-glob/compare/v10.4.1...v11.0.1) --- updated-dependencies: - dependency-name: glob dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 347 +++++++++++++++++++++++++++++++++++++++++----- package.json | 2 +- 2 files changed, 317 insertions(+), 32 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4678a4da0..68859c473 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,7 +28,7 @@ "eslint-config-prettier": "^9.1.0", "eslint-plugin-jsdoc": "^50.5.0", "eslint-plugin-prettier": "^5.2.1", - "glob": "^10.3.4", + "glob": "^11.0.1", "globals": "^15.12.0", "google-closure-compiler": "^20240317.0.0", "gulp": "^5.0.0", @@ -620,6 +620,7 @@ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -637,6 +638,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -648,13 +650,15 @@ "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@isaacs/cliui/node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, + "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -672,6 +676,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -687,6 +692,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -1004,6 +1010,7 @@ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=14" @@ -1586,6 +1593,93 @@ "node": ">=18.20.0" } }, + "node_modules/@wdio/config/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, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@wdio/config/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@wdio/config/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/@wdio/config/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@wdio/config/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@wdio/config/node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@wdio/logger": { "version": "9.1.3", "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-9.1.3.tgz", @@ -1921,6 +2015,16 @@ "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/archiver-utils/node_modules/buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", @@ -1945,6 +2049,83 @@ "ieee754": "^1.2.1" } }, + "node_modules/archiver-utils/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/archiver-utils/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/archiver-utils/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/archiver-utils/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/archiver-utils/node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "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", @@ -3404,7 +3585,8 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/edge-paths": { "version": "3.0.5", @@ -4529,22 +4711,24 @@ } }, "node_modules/glob": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", - "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.1.tgz", + "integrity": "sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==", "dev": true, + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", "minipass": "^7.1.2", - "path-scurry": "^1.11.1" + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=16 || 14 >=14.18" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -4611,20 +4795,22 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "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==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -5755,21 +5941,19 @@ } }, "node_modules/jackspeak": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz", - "integrity": "sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.0.tgz", + "integrity": "sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, "engines": { - "node": ">=14" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/jju": { @@ -6401,6 +6585,7 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, + "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } @@ -6822,6 +7007,13 @@ "node": ">= 14" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, "node_modules/pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", @@ -7062,28 +7254,30 @@ } }, "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" }, "engines": { - "node": ">=16 || 14 >=14.18" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", - "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz", + "integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==", "dev": true, + "license": "ISC", "engines": { - "node": "14 || >=16.14" + "node": "20 || >=22" } }, "node_modules/path-to-regexp": { @@ -7656,6 +7850,93 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rimraf/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, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/rimraf/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/rrweb-cssom": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", @@ -8090,6 +8371,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -8117,6 +8399,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -8129,6 +8412,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -8998,6 +9282,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", diff --git a/package.json b/package.json index 332338eac..286e04397 100644 --- a/package.json +++ b/package.json @@ -115,7 +115,7 @@ "eslint-config-prettier": "^9.1.0", "eslint-plugin-jsdoc": "^50.5.0", "eslint-plugin-prettier": "^5.2.1", - "glob": "^10.3.4", + "glob": "^11.0.1", "globals": "^15.12.0", "google-closure-compiler": "^20240317.0.0", "gulp": "^5.0.0",