scratch-blocks 2.1.16 → 2.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"checkable_continuous_flyout.d.ts","sourceRoot":"","sources":["../../../src/checkable_continuous_flyout.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,6BAA6B,CAAA;AACpF,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAsCvC,qBAAa,yBAA0B,SAAQ,gBAAgB;IAC7D,UAAkB,SAAS,EAAE,MAAM,CAAA;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IAErB;;;OAGG;gBACS,gBAAgB,EAAE,OAAO,CAAC,OAAO;IAQ7C;;;;OAIG;IACH,SAAS,CAAC,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ;IAWhD;;;;OAIG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;IAahD,cAAc;IAId,QAAQ;IAIR,SAAS,CAAC,eAAe;IAwBzB;;;;OAIG;IACH,SAAS,CAAC,kBAAkB,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,GAAG,IAAI,IAAI,eAAe;IAO/E;;OAEG;IACH,oBAAoB;IASpB,QAAQ,CAAC,QAAQ,EAAE,MAAM;CAG1B"}
1
+ {"version":3,"file":"checkable_continuous_flyout.d.ts","sourceRoot":"","sources":["../../../src/checkable_continuous_flyout.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,6BAA6B,CAAA;AACpF,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAkBvC,qBAAa,yBAA0B,SAAQ,gBAAgB;IAC7D,UAAkB,SAAS,EAAE,MAAM,CAAA;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IAErB;;;OAGG;gBACS,gBAAgB,EAAE,OAAO,CAAC,OAAO;IAQ7C;;;;OAIG;IACH,SAAS,CAAC,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ;IAUhD;;;;OAIG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;IAahD,cAAc;IAId,QAAQ;IAIR,SAAS,CAAC,eAAe;IAwBzB;;;;OAIG;IACH,SAAS,CAAC,kBAAkB,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,GAAG,IAAI,IAAI,eAAe;IAO/E;;OAEG;IACH,oBAAoB;IASpB,QAAQ,CAAC,QAAQ,EAAE,MAAM;CAG1B"}
@@ -1 +1 @@
1
- {"version":3,"file":"scratch_block_paster.d.ts","sourceRoot":"","sources":["../../../src/scratch_block_paster.ts"],"names":[],"mappings":"AA0CA;;;GAGG;AACH,wBAAgB,0BAA0B,SAGzC"}
1
+ {"version":3,"file":"scratch_block_paster.d.ts","sourceRoot":"","sources":["../../../src/scratch_block_paster.ts"],"names":[],"mappings":"AAiDA;;;GAGG;AACH,wBAAgB,0BAA0B,SAGzC"}
@@ -20,6 +20,20 @@
20
20
  * @file Utility methods for Scratch Blocks but not Blockly.
21
21
  * @author fenichel@google.com (Rachel Fenichel)
22
22
  */
23
+ import type * as Blockly from 'blockly/core';
24
+ /**
25
+ * Return a new serialized block state object with `id` properties removed
26
+ * from this block and recursively from nested `inputs`/`next` block and
27
+ * shadow states so they get fresh IDs when deserialized onto the workspace.
28
+ * The input state is NOT modified. Blockly's serialization shares shadow
29
+ * state objects by reference with the live workspace, so mutating the
30
+ * serialized tree in place would corrupt the original block's internal
31
+ * shadow state.
32
+ * @param state A serialized block state object.
33
+ * @returns A new state object with `id` properties removed from serialized
34
+ * block/shadow subtrees.
35
+ */
36
+ export declare function stripIds(state: Blockly.serialization.blocks.State): Blockly.serialization.blocks.State;
23
37
  /**
24
38
  * Compare strings with natural number sorting.
25
39
  * @param str1 First input.
@@ -1 +1 @@
1
- {"version":3,"file":"scratch_blocks_utils.d.ts","sourceRoot":"","sources":["../../../src/scratch_blocks_utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH;;;GAGG;AACH;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKjE"}
1
+ {"version":3,"file":"scratch_blocks_utils.d.ts","sourceRoot":"","sources":["../../../src/scratch_blocks_utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH;;;GAGG;AACH,OAAO,KAAK,KAAK,OAAO,MAAM,cAAc,CAAA;AAE5C;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAqBtG;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKjE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scratch-blocks",
3
- "version": "2.1.16",
3
+ "version": "2.1.18",
4
4
  "description": "Scratch Blocks is a library for building creative computing interfaces.",
5
5
  "author": "Massachusetts Institute of Technology",
6
6
  "license": "Apache-2.0",
@@ -38,10 +38,10 @@
38
38
  "devDependencies": {
39
39
  "@commitlint/cli": "20.5.0",
40
40
  "@commitlint/config-conventional": "20.5.0",
41
- "@vitest/browser": "4.1.4",
42
- "@vitest/browser-playwright": "4.1.4",
41
+ "@vitest/browser": "4.1.5",
42
+ "@vitest/browser-playwright": "4.1.5",
43
43
  "eslint": "9.39.4",
44
- "eslint-config-scratch": "14.1.11",
44
+ "eslint-config-scratch": "14.1.12",
45
45
  "husky": "9.1.7",
46
46
  "playwright": "1.59.1",
47
47
  "prettier": "3.8.3",
@@ -50,7 +50,7 @@
50
50
  "source-map-loader": "5.0.0",
51
51
  "ts-loader": "9.5.7",
52
52
  "typescript": "5.9.3",
53
- "vitest": "4.1.4",
53
+ "vitest": "4.1.5",
54
54
  "webpack": "5.106.2",
55
55
  "webpack-cli": "6.0.1",
56
56
  "webpack-dev-server": "5.2.3"
@@ -5,6 +5,7 @@
5
5
  import { ContinuousFlyout, type LabelFlyoutItem } from '@blockly/continuous-toolbox'
6
6
  import * as Blockly from 'blockly/core'
7
7
  import { CheckboxBubble } from './checkbox_bubble'
8
+ import { stripIds } from './scratch_blocks_utils'
8
9
  import { StatusIndicatorLabel } from './status_indicator_label'
9
10
  import { STATUS_INDICATOR_LABEL_TYPE } from './status_indicator_label_flyout_inflater'
10
11
 
@@ -20,27 +21,6 @@ function isCheckboxIcon(icon: Blockly.IIcon | undefined): icon is Blockly.IIcon
20
21
  return !!icon && typeof (icon as { setChecked?: unknown }).setChecked === 'function'
21
22
  }
22
23
 
23
- /**
24
- * Recursively strip `id` properties from a serialized block state tree
25
- * so that every block (including shadows and nested inputs) gets a fresh
26
- * ID when deserialized onto the workspace.
27
- * @param state A serialized block state object.
28
- */
29
- function stripIds(state: Blockly.serialization.blocks.State): void {
30
- delete state.id
31
- if (state.inputs) {
32
- for (const inputName in state.inputs) {
33
- const conn = state.inputs[inputName]
34
- if (conn.shadow) stripIds(conn.shadow)
35
- if (conn.block) stripIds(conn.block)
36
- }
37
- }
38
- if (state.next) {
39
- if (state.next.shadow) stripIds(state.next.shadow)
40
- if (state.next.block) stripIds(state.next.block)
41
- }
42
- }
43
-
44
24
  export class CheckableContinuousFlyout extends ContinuousFlyout {
45
25
  declare protected tabWidth_: number
46
26
  declare MARGIN: number
@@ -70,8 +50,7 @@ export class CheckableContinuousFlyout extends ContinuousFlyout {
70
50
  // from a previous copy can reuse the flyout's IDs, causing two workspace
71
51
  // blocks to share the same shadow in the VM. Deleting one then destroys
72
52
  // the other's shadow (bug 878291).
73
- stripIds(json)
74
- return json
53
+ return stripIds(json)
75
54
  }
76
55
 
77
56
  /**
@@ -3,6 +3,7 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
  import * as Blockly from 'blockly/core'
6
+ import { stripIds } from './scratch_blocks_utils'
6
7
  import type { ScratchCommentIcon } from './scratch_comment_icon'
7
8
 
8
9
  /**
@@ -22,6 +23,12 @@ class ScratchBlockPaster extends Blockly.clipboard.BlockPaster {
22
23
  workspace: Blockly.WorkspaceSvg,
23
24
  coordinate: Blockly.utils.Coordinate,
24
25
  ) {
26
+ // Strip all block IDs so that every block in the pasted tree (including
27
+ // shadows) gets a fresh ID. Without this, disposed shadows from the
28
+ // original block can reuse the same ID, causing the VM to think both
29
+ // blocks share the same shadow. Deleting one then destroys the other's
30
+ // shadow (forum topic 878291).
31
+ copyData = { ...copyData, blockState: stripIds(copyData.blockState) }
25
32
  const block = super.paste(copyData, workspace, coordinate)
26
33
  if (block?.type === 'argument_reporter_boolean' || block?.type === 'argument_reporter_string_number') {
27
34
  block.setDragStrategy(new Blockly.dragging.BlockDragStrategy(block))
@@ -20,6 +20,43 @@
20
20
  * @file Utility methods for Scratch Blocks but not Blockly.
21
21
  * @author fenichel@google.com (Rachel Fenichel)
22
22
  */
23
+ import type * as Blockly from 'blockly/core'
24
+
25
+ /**
26
+ * Return a new serialized block state object with `id` properties removed
27
+ * from this block and recursively from nested `inputs`/`next` block and
28
+ * shadow states so they get fresh IDs when deserialized onto the workspace.
29
+ * The input state is NOT modified. Blockly's serialization shares shadow
30
+ * state objects by reference with the live workspace, so mutating the
31
+ * serialized tree in place would corrupt the original block's internal
32
+ * shadow state.
33
+ * @param state A serialized block state object.
34
+ * @returns A new state object with `id` properties removed from serialized
35
+ * block/shadow subtrees.
36
+ */
37
+ export function stripIds(state: Blockly.serialization.blocks.State): Blockly.serialization.blocks.State {
38
+ const copy: Blockly.serialization.blocks.State = { ...state }
39
+ delete copy.id
40
+ if (copy.inputs) {
41
+ const inputs: typeof copy.inputs = {}
42
+ for (const inputName in copy.inputs) {
43
+ const conn = copy.inputs[inputName]
44
+ inputs[inputName] = {
45
+ ...(conn.shadow && { shadow: stripIds(conn.shadow) }),
46
+ ...(conn.block && { block: stripIds(conn.block) }),
47
+ }
48
+ }
49
+ copy.inputs = inputs
50
+ }
51
+ if (copy.next) {
52
+ copy.next = {
53
+ ...(copy.next.shadow && { shadow: stripIds(copy.next.shadow) }),
54
+ ...(copy.next.block && { block: stripIds(copy.next.block) }),
55
+ }
56
+ }
57
+ return copy
58
+ }
59
+
23
60
  /**
24
61
  * Compare strings with natural number sorting.
25
62
  * @param str1 First input.