scratch-blocks 1.1.206 → 2.0.0-beta.1

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.
Files changed (1295) hide show
  1. package/.husky/commit-msg +0 -3
  2. package/CHANGELOG.md +111 -833
  3. package/TODO.md +16 -0
  4. package/blockly-rc/.eslintignore +28 -0
  5. package/blockly-rc/.eslintrc.js +187 -0
  6. package/blockly-rc/.gitattributes +1 -0
  7. package/blockly-rc/.github/CODEOWNERS +1 -0
  8. package/blockly-rc/.github/CONTRIBUTING.md +46 -0
  9. package/blockly-rc/.github/ISSUE_TEMPLATE/bug_report.yaml +58 -0
  10. package/blockly-rc/.github/ISSUE_TEMPLATE/config.yml +7 -0
  11. package/blockly-rc/.github/ISSUE_TEMPLATE/documentation.yaml +38 -0
  12. package/blockly-rc/.github/ISSUE_TEMPLATE/feature_request.yaml +39 -0
  13. package/blockly-rc/.github/PULL_REQUEST_TEMPLATE.md +42 -0
  14. package/blockly-rc/.github/dependabot.yml +27 -0
  15. package/blockly-rc/.github/release.yml +32 -0
  16. package/blockly-rc/.github/workflows/appengine_deploy.yml +54 -0
  17. package/blockly-rc/.github/workflows/assign_reviewers.yml +41 -0
  18. package/blockly-rc/.github/workflows/browser_test.yml +55 -0
  19. package/blockly-rc/.github/workflows/build.yml +86 -0
  20. package/blockly-rc/.github/workflows/conventional-label.yml +17 -0
  21. package/blockly-rc/.github/workflows/develop_freeze.yml +26 -0
  22. package/blockly-rc/.github/workflows/tag_module_cleanup.yml +37 -0
  23. package/blockly-rc/.github/workflows/welcome_new_contributors.yml +36 -0
  24. package/blockly-rc/.prettierignore +30 -0
  25. package/blockly-rc/.prettierrc.js +13 -0
  26. package/blockly-rc/CHANGELOG.md +77 -0
  27. package/blockly-rc/LICENSE +202 -0
  28. package/blockly-rc/README.md +80 -0
  29. package/blockly-rc/_config.yml +1 -0
  30. package/blockly-rc/api-extractor.json +385 -0
  31. package/blockly-rc/appengine/.gcloudignore +20 -0
  32. package/blockly-rc/appengine/README.txt +42 -0
  33. package/blockly-rc/appengine/add_timestamps.py +69 -0
  34. package/blockly-rc/appengine/app.yaml +104 -0
  35. package/blockly-rc/appengine/apple-touch-icon.png +0 -0
  36. package/blockly-rc/appengine/blockly_compressed.js +11 -0
  37. package/blockly-rc/appengine/expiration.py +52 -0
  38. package/blockly-rc/appengine/favicon.ico +0 -0
  39. package/blockly-rc/appengine/index.yaml +11 -0
  40. package/blockly-rc/appengine/main.py +39 -0
  41. package/blockly-rc/appengine/redirect.html +107 -0
  42. package/blockly-rc/appengine/requirements.txt +1 -0
  43. package/blockly-rc/appengine/robots.txt +2 -0
  44. package/blockly-rc/appengine/storage.js +190 -0
  45. package/blockly-rc/appengine/storage.py +125 -0
  46. package/blockly-rc/blocks/blocks.ts +44 -0
  47. package/blockly-rc/blocks/lists.ts +1085 -0
  48. package/blockly-rc/blocks/logic.ts +712 -0
  49. package/blockly-rc/blocks/loops.ts +408 -0
  50. package/blockly-rc/blocks/math.ts +591 -0
  51. package/blockly-rc/blocks/procedures.ts +1364 -0
  52. package/blockly-rc/blocks/text.ts +1007 -0
  53. package/blockly-rc/blocks/variables.ts +183 -0
  54. package/blockly-rc/blocks/variables_dynamic.ts +194 -0
  55. package/blockly-rc/core/any_aliases.ts +8 -0
  56. package/blockly-rc/core/block.ts +2523 -0
  57. package/blockly-rc/core/block_animations.ts +225 -0
  58. package/blockly-rc/core/block_flyout_inflater.ts +262 -0
  59. package/blockly-rc/core/block_svg.ts +1768 -0
  60. package/blockly-rc/core/blockly.ts +605 -0
  61. package/blockly-rc/core/blockly_options.ts +71 -0
  62. package/blockly-rc/core/blocks.ts +18 -0
  63. package/blockly-rc/core/browser_events.ts +244 -0
  64. package/blockly-rc/core/bubbles/bubble.ts +658 -0
  65. package/blockly-rc/core/bubbles/mini_workspace_bubble.ts +280 -0
  66. package/blockly-rc/core/bubbles/text_bubble.ts +103 -0
  67. package/blockly-rc/core/bubbles/textinput_bubble.ts +344 -0
  68. package/blockly-rc/core/bubbles.ts +12 -0
  69. package/blockly-rc/core/bump_objects.ts +192 -0
  70. package/blockly-rc/core/button_flyout_inflater.ts +63 -0
  71. package/blockly-rc/core/clipboard/block_paster.ts +142 -0
  72. package/blockly-rc/core/clipboard/registry.ts +31 -0
  73. package/blockly-rc/core/clipboard/workspace_comment_paster.ts +94 -0
  74. package/blockly-rc/core/clipboard.ts +113 -0
  75. package/blockly-rc/core/comments/comment_view.ts +899 -0
  76. package/blockly-rc/core/comments/rendered_workspace_comment.ts +297 -0
  77. package/blockly-rc/core/comments/workspace_comment.ts +237 -0
  78. package/blockly-rc/core/comments.ts +9 -0
  79. package/blockly-rc/core/common.ts +305 -0
  80. package/blockly-rc/core/component_manager.ts +235 -0
  81. package/blockly-rc/core/config.ts +65 -0
  82. package/blockly-rc/core/connection.ts +793 -0
  83. package/blockly-rc/core/connection_checker.ts +348 -0
  84. package/blockly-rc/core/connection_db.ts +297 -0
  85. package/blockly-rc/core/connection_type.ts +21 -0
  86. package/blockly-rc/core/constants.ts +23 -0
  87. package/blockly-rc/core/contextmenu.ts +268 -0
  88. package/blockly-rc/core/contextmenu_items.ts +700 -0
  89. package/blockly-rc/core/contextmenu_registry.ts +194 -0
  90. package/blockly-rc/core/css.ts +481 -0
  91. package/blockly-rc/core/delete_area.ts +77 -0
  92. package/blockly-rc/core/dialog.ts +121 -0
  93. package/blockly-rc/core/drag_target.ts +97 -0
  94. package/blockly-rc/core/dragging/block_drag_strategy.ts +454 -0
  95. package/blockly-rc/core/dragging/bubble_drag_strategy.ts +52 -0
  96. package/blockly-rc/core/dragging/comment_drag_strategy.ts +91 -0
  97. package/blockly-rc/core/dragging/dragger.ts +163 -0
  98. package/blockly-rc/core/dragging.ts +12 -0
  99. package/blockly-rc/core/dropdowndiv.ts +768 -0
  100. package/blockly-rc/core/events/events.ts +163 -0
  101. package/blockly-rc/core/events/events_abstract.ts +130 -0
  102. package/blockly-rc/core/events/events_block_base.ts +88 -0
  103. package/blockly-rc/core/events/events_block_change.ts +259 -0
  104. package/blockly-rc/core/events/events_block_create.ts +185 -0
  105. package/blockly-rc/core/events/events_block_delete.ts +182 -0
  106. package/blockly-rc/core/events/events_block_drag.ts +116 -0
  107. package/blockly-rc/core/events/events_block_field_intermediate_change.ts +167 -0
  108. package/blockly-rc/core/events/events_block_move.ts +307 -0
  109. package/blockly-rc/core/events/events_bubble_open.ts +120 -0
  110. package/blockly-rc/core/events/events_click.ts +110 -0
  111. package/blockly-rc/core/events/events_comment_base.ts +126 -0
  112. package/blockly-rc/core/events/events_comment_change.ts +161 -0
  113. package/blockly-rc/core/events/events_comment_collapse.ts +103 -0
  114. package/blockly-rc/core/events/events_comment_create.ts +118 -0
  115. package/blockly-rc/core/events/events_comment_delete.ts +117 -0
  116. package/blockly-rc/core/events/events_comment_drag.ts +99 -0
  117. package/blockly-rc/core/events/events_comment_move.ts +207 -0
  118. package/blockly-rc/core/events/events_comment_resize.ts +174 -0
  119. package/blockly-rc/core/events/events_marker_move.ts +134 -0
  120. package/blockly-rc/core/events/events_selected.ts +98 -0
  121. package/blockly-rc/core/events/events_theme_change.ts +84 -0
  122. package/blockly-rc/core/events/events_toolbox_item_select.ts +96 -0
  123. package/blockly-rc/core/events/events_trashcan_open.ts +88 -0
  124. package/blockly-rc/core/events/events_ui_base.ts +47 -0
  125. package/blockly-rc/core/events/events_var_base.ts +89 -0
  126. package/blockly-rc/core/events/events_var_create.ts +129 -0
  127. package/blockly-rc/core/events/events_var_delete.ts +124 -0
  128. package/blockly-rc/core/events/events_var_rename.ts +133 -0
  129. package/blockly-rc/core/events/events_var_type_change.ts +122 -0
  130. package/blockly-rc/core/events/events_viewport.ts +149 -0
  131. package/blockly-rc/core/events/utils.ts +595 -0
  132. package/blockly-rc/core/events/workspace_events.ts +46 -0
  133. package/blockly-rc/core/extensions.ts +491 -0
  134. package/blockly-rc/core/field.ts +1471 -0
  135. package/blockly-rc/core/field_checkbox.ts +271 -0
  136. package/blockly-rc/core/field_dropdown.ts +857 -0
  137. package/blockly-rc/core/field_image.ts +297 -0
  138. package/blockly-rc/core/field_input.ts +755 -0
  139. package/blockly-rc/core/field_label.ts +150 -0
  140. package/blockly-rc/core/field_label_serializable.ts +73 -0
  141. package/blockly-rc/core/field_number.ts +381 -0
  142. package/blockly-rc/core/field_registry.ts +115 -0
  143. package/blockly-rc/core/field_textinput.ts +117 -0
  144. package/blockly-rc/core/field_variable.ts +651 -0
  145. package/blockly-rc/core/flyout_base.ts +968 -0
  146. package/blockly-rc/core/flyout_button.ts +416 -0
  147. package/blockly-rc/core/flyout_horizontal.ts +374 -0
  148. package/blockly-rc/core/flyout_metrics_manager.ts +90 -0
  149. package/blockly-rc/core/flyout_separator.ts +61 -0
  150. package/blockly-rc/core/flyout_vertical.ts +353 -0
  151. package/blockly-rc/core/generator.ts +611 -0
  152. package/blockly-rc/core/gesture.ts +1191 -0
  153. package/blockly-rc/core/grid.ts +252 -0
  154. package/blockly-rc/core/icons/comment_icon.ts +435 -0
  155. package/blockly-rc/core/icons/exceptions.ts +23 -0
  156. package/blockly-rc/core/icons/icon.ts +147 -0
  157. package/blockly-rc/core/icons/icon_types.ts +32 -0
  158. package/blockly-rc/core/icons/mutator_icon.ts +354 -0
  159. package/blockly-rc/core/icons/registry.ts +33 -0
  160. package/blockly-rc/core/icons/warning_icon.ts +219 -0
  161. package/blockly-rc/core/icons.ts +24 -0
  162. package/blockly-rc/core/inject.ts +428 -0
  163. package/blockly-rc/core/inputs/align.ts +14 -0
  164. package/blockly-rc/core/inputs/dummy_input.ts +26 -0
  165. package/blockly-rc/core/inputs/end_row_input.ts +31 -0
  166. package/blockly-rc/core/inputs/input.ts +318 -0
  167. package/blockly-rc/core/inputs/input_types.ts +27 -0
  168. package/blockly-rc/core/inputs/statement_input.ts +34 -0
  169. package/blockly-rc/core/inputs/value_input.ts +30 -0
  170. package/blockly-rc/core/inputs.ts +23 -0
  171. package/blockly-rc/core/insertion_marker_manager.ts +742 -0
  172. package/blockly-rc/core/insertion_marker_previewer.ts +254 -0
  173. package/blockly-rc/core/interfaces/i_ast_node_location.ts +12 -0
  174. package/blockly-rc/core/interfaces/i_ast_node_location_svg.ts +28 -0
  175. package/blockly-rc/core/interfaces/i_ast_node_location_with_block.ts +22 -0
  176. package/blockly-rc/core/interfaces/i_autohideable.ts +22 -0
  177. package/blockly-rc/core/interfaces/i_bounded_element.ts +30 -0
  178. package/blockly-rc/core/interfaces/i_bubble.ts +63 -0
  179. package/blockly-rc/core/interfaces/i_collapsible_toolbox_item.ts +33 -0
  180. package/blockly-rc/core/interfaces/i_comment_icon.ts +47 -0
  181. package/blockly-rc/core/interfaces/i_component.ts +19 -0
  182. package/blockly-rc/core/interfaces/i_connection_checker.ts +100 -0
  183. package/blockly-rc/core/interfaces/i_connection_previewer.ts +50 -0
  184. package/blockly-rc/core/interfaces/i_contextmenu.ts +16 -0
  185. package/blockly-rc/core/interfaces/i_copyable.ts +31 -0
  186. package/blockly-rc/core/interfaces/i_deletable.ts +34 -0
  187. package/blockly-rc/core/interfaces/i_delete_area.ts +28 -0
  188. package/blockly-rc/core/interfaces/i_drag_target.ts +69 -0
  189. package/blockly-rc/core/interfaces/i_draggable.ts +72 -0
  190. package/blockly-rc/core/interfaces/i_dragger.ts +35 -0
  191. package/blockly-rc/core/interfaces/i_flyout.ts +189 -0
  192. package/blockly-rc/core/interfaces/i_flyout_inflater.ts +41 -0
  193. package/blockly-rc/core/interfaces/i_has_bubble.ts +20 -0
  194. package/blockly-rc/core/interfaces/i_icon.ts +114 -0
  195. package/blockly-rc/core/interfaces/i_keyboard_accessible.ts +21 -0
  196. package/blockly-rc/core/interfaces/i_legacy_procedure_blocks.ts +50 -0
  197. package/blockly-rc/core/interfaces/i_metrics_manager.ts +149 -0
  198. package/blockly-rc/core/interfaces/i_movable.ts +19 -0
  199. package/blockly-rc/core/interfaces/i_observable.ts +24 -0
  200. package/blockly-rc/core/interfaces/i_parameter_model.ts +51 -0
  201. package/blockly-rc/core/interfaces/i_paster.ts +25 -0
  202. package/blockly-rc/core/interfaces/i_positionable.ts +33 -0
  203. package/blockly-rc/core/interfaces/i_procedure_block.ts +27 -0
  204. package/blockly-rc/core/interfaces/i_procedure_map.ts +18 -0
  205. package/blockly-rc/core/interfaces/i_procedure_model.ts +71 -0
  206. package/blockly-rc/core/interfaces/i_registrable.ts +12 -0
  207. package/blockly-rc/core/interfaces/i_rendered_element.ts +22 -0
  208. package/blockly-rc/core/interfaces/i_selectable.ts +34 -0
  209. package/blockly-rc/core/interfaces/i_selectable_toolbox_item.ts +63 -0
  210. package/blockly-rc/core/interfaces/i_serializable.ts +28 -0
  211. package/blockly-rc/core/interfaces/i_serializer.ts +55 -0
  212. package/blockly-rc/core/interfaces/i_styleable.ts +26 -0
  213. package/blockly-rc/core/interfaces/i_toolbox.ts +112 -0
  214. package/blockly-rc/core/interfaces/i_toolbox_item.ts +81 -0
  215. package/blockly-rc/core/interfaces/i_variable_backed_parameter_model.ts +23 -0
  216. package/blockly-rc/core/interfaces/i_variable_map.ts +65 -0
  217. package/blockly-rc/core/interfaces/i_variable_model.ts +57 -0
  218. package/blockly-rc/core/internal_constants.ts +47 -0
  219. package/blockly-rc/core/keyboard_nav/ast_node.ts +884 -0
  220. package/blockly-rc/core/keyboard_nav/basic_cursor.ts +223 -0
  221. package/blockly-rc/core/keyboard_nav/cursor.ts +138 -0
  222. package/blockly-rc/core/keyboard_nav/marker.ts +113 -0
  223. package/blockly-rc/core/keyboard_nav/tab_navigate_cursor.ts +46 -0
  224. package/blockly-rc/core/label_flyout_inflater.ts +59 -0
  225. package/blockly-rc/core/layer_manager.ts +186 -0
  226. package/blockly-rc/core/layers.ts +17 -0
  227. package/blockly-rc/core/main.ts +31 -0
  228. package/blockly-rc/core/marker_manager.ts +189 -0
  229. package/blockly-rc/core/menu.ts +463 -0
  230. package/blockly-rc/core/menuitem.ts +221 -0
  231. package/blockly-rc/core/metrics_manager.ts +486 -0
  232. package/blockly-rc/core/msg.ts +27 -0
  233. package/blockly-rc/core/names.ts +275 -0
  234. package/blockly-rc/core/observable_procedure_map.ts +66 -0
  235. package/blockly-rc/core/options.ts +377 -0
  236. package/blockly-rc/core/positionable_helpers.ts +186 -0
  237. package/blockly-rc/core/procedures.ts +510 -0
  238. package/blockly-rc/core/registry.ts +400 -0
  239. package/blockly-rc/core/render_management.ts +193 -0
  240. package/blockly-rc/core/rendered_connection.ts +571 -0
  241. package/blockly-rc/core/renderers/common/block_rendering.ts +120 -0
  242. package/blockly-rc/core/renderers/common/constants.ts +1198 -0
  243. package/blockly-rc/core/renderers/common/drawer.ts +518 -0
  244. package/blockly-rc/core/renderers/common/i_path_object.ts +137 -0
  245. package/blockly-rc/core/renderers/common/info.ts +767 -0
  246. package/blockly-rc/core/renderers/common/marker_svg.ts +765 -0
  247. package/blockly-rc/core/renderers/common/path_object.ts +324 -0
  248. package/blockly-rc/core/renderers/common/renderer.ts +281 -0
  249. package/blockly-rc/core/renderers/geras/constants.ts +46 -0
  250. package/blockly-rc/core/renderers/geras/drawer.ts +167 -0
  251. package/blockly-rc/core/renderers/geras/geras.ts +31 -0
  252. package/blockly-rc/core/renderers/geras/highlight_constants.ts +342 -0
  253. package/blockly-rc/core/renderers/geras/highlighter.ts +313 -0
  254. package/blockly-rc/core/renderers/geras/info.ts +478 -0
  255. package/blockly-rc/core/renderers/geras/measurables/inline_input.ts +37 -0
  256. package/blockly-rc/core/renderers/geras/measurables/statement_input.ts +36 -0
  257. package/blockly-rc/core/renderers/geras/path_object.ts +135 -0
  258. package/blockly-rc/core/renderers/geras/renderer.ts +124 -0
  259. package/blockly-rc/core/renderers/measurables/base.ts +41 -0
  260. package/blockly-rc/core/renderers/measurables/bottom_row.ts +104 -0
  261. package/blockly-rc/core/renderers/measurables/connection.ts +43 -0
  262. package/blockly-rc/core/renderers/measurables/external_value_input.ts +53 -0
  263. package/blockly-rc/core/renderers/measurables/field.ts +50 -0
  264. package/blockly-rc/core/renderers/measurables/hat.ts +33 -0
  265. package/blockly-rc/core/renderers/measurables/icon.ts +42 -0
  266. package/blockly-rc/core/renderers/measurables/in_row_spacer.ts +29 -0
  267. package/blockly-rc/core/renderers/measurables/inline_input.ts +63 -0
  268. package/blockly-rc/core/renderers/measurables/input_connection.ts +57 -0
  269. package/blockly-rc/core/renderers/measurables/input_row.ts +67 -0
  270. package/blockly-rc/core/renderers/measurables/jagged_edge.ts +28 -0
  271. package/blockly-rc/core/renderers/measurables/next_connection.ts +34 -0
  272. package/blockly-rc/core/renderers/measurables/output_connection.ts +43 -0
  273. package/blockly-rc/core/renderers/measurables/previous_connection.ts +34 -0
  274. package/blockly-rc/core/renderers/measurables/round_corner.ts +34 -0
  275. package/blockly-rc/core/renderers/measurables/row.ts +191 -0
  276. package/blockly-rc/core/renderers/measurables/spacer_row.ts +44 -0
  277. package/blockly-rc/core/renderers/measurables/square_corner.ts +32 -0
  278. package/blockly-rc/core/renderers/measurables/statement_input.ts +41 -0
  279. package/blockly-rc/core/renderers/measurables/top_row.ts +110 -0
  280. package/blockly-rc/core/renderers/measurables/types.ts +319 -0
  281. package/blockly-rc/core/renderers/thrasos/info.ts +328 -0
  282. package/blockly-rc/core/renderers/thrasos/renderer.ts +40 -0
  283. package/blockly-rc/core/renderers/thrasos/thrasos.ts +14 -0
  284. package/blockly-rc/core/renderers/zelos/constants.ts +877 -0
  285. package/blockly-rc/core/renderers/zelos/drawer.ts +274 -0
  286. package/blockly-rc/core/renderers/zelos/info.ts +652 -0
  287. package/blockly-rc/core/renderers/zelos/marker_svg.ts +145 -0
  288. package/blockly-rc/core/renderers/zelos/measurables/bottom_row.ts +44 -0
  289. package/blockly-rc/core/renderers/zelos/measurables/inputs.ts +41 -0
  290. package/blockly-rc/core/renderers/zelos/measurables/row_elements.ts +29 -0
  291. package/blockly-rc/core/renderers/zelos/measurables/top_row.ts +50 -0
  292. package/blockly-rc/core/renderers/zelos/path_object.ts +209 -0
  293. package/blockly-rc/core/renderers/zelos/renderer.ts +143 -0
  294. package/blockly-rc/core/renderers/zelos/zelos.ts +33 -0
  295. package/blockly-rc/core/scrollbar.ts +898 -0
  296. package/blockly-rc/core/scrollbar_pair.ts +349 -0
  297. package/blockly-rc/core/separator_flyout_inflater.ts +69 -0
  298. package/blockly-rc/core/serialization/blocks.ts +868 -0
  299. package/blockly-rc/core/serialization/exceptions.ts +112 -0
  300. package/blockly-rc/core/serialization/priorities.ts +25 -0
  301. package/blockly-rc/core/serialization/procedures.ts +158 -0
  302. package/blockly-rc/core/serialization/registry.ts +30 -0
  303. package/blockly-rc/core/serialization/variables.ts +68 -0
  304. package/blockly-rc/core/serialization/workspace_comments.ts +143 -0
  305. package/blockly-rc/core/serialization/workspaces.ts +94 -0
  306. package/blockly-rc/core/serialization.ts +32 -0
  307. package/blockly-rc/core/shortcut_items.ts +338 -0
  308. package/blockly-rc/core/shortcut_registry.ts +368 -0
  309. package/blockly-rc/core/sprites.ts +15 -0
  310. package/blockly-rc/core/theme/classic.ts +40 -0
  311. package/blockly-rc/core/theme/themes.ts +12 -0
  312. package/blockly-rc/core/theme/zelos.ts +80 -0
  313. package/blockly-rc/core/theme.ts +232 -0
  314. package/blockly-rc/core/theme_manager.ts +192 -0
  315. package/blockly-rc/core/toolbox/category.ts +739 -0
  316. package/blockly-rc/core/toolbox/collapsible_category.ts +288 -0
  317. package/blockly-rc/core/toolbox/separator.ts +105 -0
  318. package/blockly-rc/core/toolbox/toolbox.ts +1134 -0
  319. package/blockly-rc/core/toolbox/toolbox_item.ts +152 -0
  320. package/blockly-rc/core/tooltip.ts +466 -0
  321. package/blockly-rc/core/touch.ts +155 -0
  322. package/blockly-rc/core/trashcan.ts +748 -0
  323. package/blockly-rc/core/utils/aria.ts +144 -0
  324. package/blockly-rc/core/utils/array.ts +24 -0
  325. package/blockly-rc/core/utils/colour.ts +265 -0
  326. package/blockly-rc/core/utils/coordinate.ts +129 -0
  327. package/blockly-rc/core/utils/deprecation.ts +47 -0
  328. package/blockly-rc/core/utils/dom.ts +356 -0
  329. package/blockly-rc/core/utils/idgenerator.ts +70 -0
  330. package/blockly-rc/core/utils/keycodes.ts +154 -0
  331. package/blockly-rc/core/utils/math.ts +50 -0
  332. package/blockly-rc/core/utils/metrics.ts +86 -0
  333. package/blockly-rc/core/utils/object.ts +28 -0
  334. package/blockly-rc/core/utils/parsing.ts +287 -0
  335. package/blockly-rc/core/utils/rect.ts +69 -0
  336. package/blockly-rc/core/utils/size.ts +62 -0
  337. package/blockly-rc/core/utils/string.ts +289 -0
  338. package/blockly-rc/core/utils/style.ts +219 -0
  339. package/blockly-rc/core/utils/svg.ts +84 -0
  340. package/blockly-rc/core/utils/svg_math.ts +208 -0
  341. package/blockly-rc/core/utils/svg_paths.ts +133 -0
  342. package/blockly-rc/core/utils/toolbox.ts +419 -0
  343. package/blockly-rc/core/utils/useragent.ts +86 -0
  344. package/blockly-rc/core/utils/xml.ts +165 -0
  345. package/blockly-rc/core/utils.ts +59 -0
  346. package/blockly-rc/core/variable_map.ts +437 -0
  347. package/blockly-rc/core/variable_model.ts +149 -0
  348. package/blockly-rc/core/variables.ts +773 -0
  349. package/blockly-rc/core/variables_dynamic.ts +142 -0
  350. package/blockly-rc/core/widgetdiv.ts +319 -0
  351. package/blockly-rc/core/workspace.ts +957 -0
  352. package/blockly-rc/core/workspace_audio.ts +171 -0
  353. package/blockly-rc/core/workspace_dragger.ts +97 -0
  354. package/blockly-rc/core/workspace_svg.ts +2519 -0
  355. package/blockly-rc/core/xml.ts +1133 -0
  356. package/blockly-rc/core/zoom_controls.ts +492 -0
  357. package/blockly-rc/demos/blockfactory/analytics.js +195 -0
  358. package/blockly-rc/demos/blockfactory/app_controller.js +726 -0
  359. package/blockly-rc/demos/blockfactory/block_definition_extractor.js +742 -0
  360. package/blockly-rc/demos/blockfactory/block_exporter_controller.js +311 -0
  361. package/blockly-rc/demos/blockfactory/block_exporter_tools.js +212 -0
  362. package/blockly-rc/demos/blockfactory/block_exporter_view.js +101 -0
  363. package/blockly-rc/demos/blockfactory/block_library_controller.js +325 -0
  364. package/blockly-rc/demos/blockfactory/block_library_storage.js +149 -0
  365. package/blockly-rc/demos/blockfactory/block_library_view.js +178 -0
  366. package/blockly-rc/demos/blockfactory/block_option.js +151 -0
  367. package/blockly-rc/demos/blockfactory/blocks.js +916 -0
  368. package/blockly-rc/demos/blockfactory/cp.css +46 -0
  369. package/blockly-rc/demos/blockfactory/cp.js +179 -0
  370. package/blockly-rc/demos/blockfactory/factory.css +586 -0
  371. package/blockly-rc/demos/blockfactory/factory.js +337 -0
  372. package/blockly-rc/demos/blockfactory/factory_utils.js +1036 -0
  373. package/blockly-rc/demos/blockfactory/icon.png +0 -0
  374. package/blockly-rc/demos/blockfactory/index.html +767 -0
  375. package/blockly-rc/demos/blockfactory/link.png +0 -0
  376. package/blockly-rc/demos/blockfactory/standard_categories.js +384 -0
  377. package/blockly-rc/demos/blockfactory/workspacefactory/wfactory_controller.js +1332 -0
  378. package/blockly-rc/demos/blockfactory/workspacefactory/wfactory_generator.js +224 -0
  379. package/blockly-rc/demos/blockfactory/workspacefactory/wfactory_init.js +541 -0
  380. package/blockly-rc/demos/blockfactory/workspacefactory/wfactory_model.js +548 -0
  381. package/blockly-rc/demos/blockfactory/workspacefactory/wfactory_view.js +424 -0
  382. package/blockly-rc/demos/code/code.js +626 -0
  383. package/blockly-rc/demos/code/icon.png +0 -0
  384. package/blockly-rc/demos/code/icons.png +0 -0
  385. package/blockly-rc/demos/code/index.html +359 -0
  386. package/blockly-rc/demos/code/msg/ar.js +24 -0
  387. package/blockly-rc/demos/code/msg/be-tarask.js +24 -0
  388. package/blockly-rc/demos/code/msg/br.js +24 -0
  389. package/blockly-rc/demos/code/msg/ca.js +24 -0
  390. package/blockly-rc/demos/code/msg/cs.js +24 -0
  391. package/blockly-rc/demos/code/msg/da.js +24 -0
  392. package/blockly-rc/demos/code/msg/de.js +24 -0
  393. package/blockly-rc/demos/code/msg/el.js +24 -0
  394. package/blockly-rc/demos/code/msg/en.js +24 -0
  395. package/blockly-rc/demos/code/msg/es.js +24 -0
  396. package/blockly-rc/demos/code/msg/et.js +24 -0
  397. package/blockly-rc/demos/code/msg/fa.js +24 -0
  398. package/blockly-rc/demos/code/msg/fr.js +24 -0
  399. package/blockly-rc/demos/code/msg/he.js +24 -0
  400. package/blockly-rc/demos/code/msg/hr.js +24 -0
  401. package/blockly-rc/demos/code/msg/hrx.js +24 -0
  402. package/blockly-rc/demos/code/msg/hu.js +24 -0
  403. package/blockly-rc/demos/code/msg/ia.js +24 -0
  404. package/blockly-rc/demos/code/msg/is.js +24 -0
  405. package/blockly-rc/demos/code/msg/it.js +24 -0
  406. package/blockly-rc/demos/code/msg/ja.js +24 -0
  407. package/blockly-rc/demos/code/msg/kab.js +24 -0
  408. package/blockly-rc/demos/code/msg/ko.js +24 -0
  409. package/blockly-rc/demos/code/msg/mk.js +24 -0
  410. package/blockly-rc/demos/code/msg/ms.js +24 -0
  411. package/blockly-rc/demos/code/msg/nb.js +24 -0
  412. package/blockly-rc/demos/code/msg/nl.js +24 -0
  413. package/blockly-rc/demos/code/msg/oc.js +24 -0
  414. package/blockly-rc/demos/code/msg/pl.js +24 -0
  415. package/blockly-rc/demos/code/msg/pms.js +24 -0
  416. package/blockly-rc/demos/code/msg/pt-br.js +24 -0
  417. package/blockly-rc/demos/code/msg/ro.js +24 -0
  418. package/blockly-rc/demos/code/msg/ru.js +24 -0
  419. package/blockly-rc/demos/code/msg/sc.js +24 -0
  420. package/blockly-rc/demos/code/msg/sk.js +24 -0
  421. package/blockly-rc/demos/code/msg/sr.js +24 -0
  422. package/blockly-rc/demos/code/msg/sv.js +24 -0
  423. package/blockly-rc/demos/code/msg/ta.js +24 -0
  424. package/blockly-rc/demos/code/msg/th.js +24 -0
  425. package/blockly-rc/demos/code/msg/tlh.js +24 -0
  426. package/blockly-rc/demos/code/msg/tr.js +24 -0
  427. package/blockly-rc/demos/code/msg/uk.js +24 -0
  428. package/blockly-rc/demos/code/msg/vi.js +24 -0
  429. package/blockly-rc/demos/code/msg/zh-hans.js +24 -0
  430. package/blockly-rc/demos/code/msg/zh-hant.js +24 -0
  431. package/blockly-rc/demos/code/style.css +184 -0
  432. package/blockly-rc/demos/index.html +68 -0
  433. package/blockly-rc/demos/minimap/icon.png +0 -0
  434. package/blockly-rc/demos/minimap/index.html +91 -0
  435. package/blockly-rc/demos/minimap/minimap.js +302 -0
  436. package/blockly-rc/demos/mobile/README.md +53 -0
  437. package/blockly-rc/demos/mobile/android/README.md +45 -0
  438. package/blockly-rc/demos/mobile/android/app/build.gradle +64 -0
  439. package/blockly-rc/demos/mobile/android/app/proguard-rules.pro +21 -0
  440. package/blockly-rc/demos/mobile/android/app/src/androidTest/java/com/example/blocklywebview/ExampleInstrumentedTest.java +26 -0
  441. package/blockly-rc/demos/mobile/android/app/src/main/AndroidManifest.xml +21 -0
  442. package/blockly-rc/demos/mobile/android/app/src/main/java/com/google/blockly/android/webview/BlocklyWebViewFragment.java +40 -0
  443. package/blockly-rc/demos/mobile/android/app/src/main/java/com/google/blockly/android/webview/JsDialogHelper.java +150 -0
  444. package/blockly-rc/demos/mobile/android/app/src/main/java/com/google/blockly/android/webview/WebChromeClient.java +32 -0
  445. package/blockly-rc/demos/mobile/android/app/src/main/java/com/google/blockly/android/webview/demo/MainActivity.java +18 -0
  446. package/blockly-rc/demos/mobile/android/app/src/main/res/drawable/ic_launcher_background.xml +74 -0
  447. package/blockly-rc/demos/mobile/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +34 -0
  448. package/blockly-rc/demos/mobile/android/app/src/main/res/layout/activity_main.xml +17 -0
  449. package/blockly-rc/demos/mobile/android/app/src/main/res/layout/js_prompt.xml +37 -0
  450. package/blockly-rc/demos/mobile/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +5 -0
  451. package/blockly-rc/demos/mobile/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +5 -0
  452. package/blockly-rc/demos/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  453. package/blockly-rc/demos/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  454. package/blockly-rc/demos/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  455. package/blockly-rc/demos/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  456. package/blockly-rc/demos/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  457. package/blockly-rc/demos/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  458. package/blockly-rc/demos/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  459. package/blockly-rc/demos/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  460. package/blockly-rc/demos/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  461. package/blockly-rc/demos/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  462. package/blockly-rc/demos/mobile/android/app/src/main/res/values/colors.xml +6 -0
  463. package/blockly-rc/demos/mobile/android/app/src/main/res/values/js_dialog_helper.xml +7 -0
  464. package/blockly-rc/demos/mobile/android/app/src/main/res/values/strings.xml +3 -0
  465. package/blockly-rc/demos/mobile/android/app/src/main/res/values/styles.xml +11 -0
  466. package/blockly-rc/demos/mobile/android/app/src/test/java/com/example/blocklywebview/ExampleUnitTest.java +17 -0
  467. package/blockly-rc/demos/mobile/android/build.gradle +27 -0
  468. package/blockly-rc/demos/mobile/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  469. package/blockly-rc/demos/mobile/android/gradle/wrapper/gradle-wrapper.properties +6 -0
  470. package/blockly-rc/demos/mobile/android/gradle.properties +13 -0
  471. package/blockly-rc/demos/mobile/android/gradlew +172 -0
  472. package/blockly-rc/demos/mobile/android/gradlew.bat +84 -0
  473. package/blockly-rc/demos/mobile/android/settings.gradle +1 -0
  474. package/blockly-rc/demos/mobile/html/index.html +31 -0
  475. package/blockly-rc/demos/mobile/html/ln_resources.sh +22 -0
  476. package/blockly-rc/demos/mobile/html/toolbox_standard.js +333 -0
  477. package/blockly-rc/demos/mobile/ios/Blockly WebView/AppDelegate.swift +46 -0
  478. package/blockly-rc/demos/mobile/ios/Blockly WebView/Assets.xcassets/AppIcon.appiconset/Contents.json +98 -0
  479. package/blockly-rc/demos/mobile/ios/Blockly WebView/Assets.xcassets/Contents.json +6 -0
  480. package/blockly-rc/demos/mobile/ios/Blockly WebView/Base.lproj/LaunchScreen.storyboard +25 -0
  481. package/blockly-rc/demos/mobile/ios/Blockly WebView/Base.lproj/Main.storyboard +44 -0
  482. package/blockly-rc/demos/mobile/ios/Blockly WebView/Info.plist +45 -0
  483. package/blockly-rc/demos/mobile/ios/Blockly WebView/ViewController.swift +110 -0
  484. package/blockly-rc/demos/mobile/ios/Blockly WebView.xcodeproj/project.pbxproj +390 -0
  485. package/blockly-rc/demos/mobile/ios/Blockly WebView.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  486. package/blockly-rc/demos/mobile/ios/Blockly WebView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  487. package/blockly-rc/demos/mobile/ios/cp_resources.sh +21 -0
  488. package/blockly-rc/demos/storage/icon.png +0 -0
  489. package/blockly-rc/demos/storage/index.html +104 -0
  490. package/blockly-rc/generators/dart/dart_generator.ts +321 -0
  491. package/blockly-rc/generators/dart/lists.ts +525 -0
  492. package/blockly-rc/generators/dart/logic.ts +155 -0
  493. package/blockly-rc/generators/dart/loops.ts +217 -0
  494. package/blockly-rc/generators/dart/math.ts +559 -0
  495. package/blockly-rc/generators/dart/procedures.ts +138 -0
  496. package/blockly-rc/generators/dart/text.ts +405 -0
  497. package/blockly-rc/generators/dart/variables.ts +32 -0
  498. package/blockly-rc/generators/dart/variables_dynamic.ts +17 -0
  499. package/blockly-rc/generators/dart.ts +50 -0
  500. package/blockly-rc/generators/javascript/javascript_generator.ts +346 -0
  501. package/blockly-rc/generators/javascript/lists.ts +465 -0
  502. package/blockly-rc/generators/javascript/logic.ts +153 -0
  503. package/blockly-rc/generators/javascript/loops.ts +245 -0
  504. package/blockly-rc/generators/javascript/math.ts +450 -0
  505. package/blockly-rc/generators/javascript/procedures.ts +142 -0
  506. package/blockly-rc/generators/javascript/text.ts +418 -0
  507. package/blockly-rc/generators/javascript/variables.ts +32 -0
  508. package/blockly-rc/generators/javascript/variables_dynamic.ts +17 -0
  509. package/blockly-rc/generators/javascript.ts +46 -0
  510. package/blockly-rc/generators/lua/lists.ts +445 -0
  511. package/blockly-rc/generators/lua/logic.ts +142 -0
  512. package/blockly-rc/generators/lua/loops.ts +192 -0
  513. package/blockly-rc/generators/lua/lua_generator.ts +225 -0
  514. package/blockly-rc/generators/lua/math.ts +473 -0
  515. package/blockly-rc/generators/lua/procedures.ts +144 -0
  516. package/blockly-rc/generators/lua/text.ts +380 -0
  517. package/blockly-rc/generators/lua/variables.ts +31 -0
  518. package/blockly-rc/generators/lua/variables_dynamic.ts +17 -0
  519. package/blockly-rc/generators/lua.ts +44 -0
  520. package/blockly-rc/generators/php/lists.ts +585 -0
  521. package/blockly-rc/generators/php/logic.ts +155 -0
  522. package/blockly-rc/generators/php/loops.ts +218 -0
  523. package/blockly-rc/generators/php/math.ts +408 -0
  524. package/blockly-rc/generators/php/php_generator.ts +320 -0
  525. package/blockly-rc/generators/php/procedures.ts +159 -0
  526. package/blockly-rc/generators/php/text.ts +315 -0
  527. package/blockly-rc/generators/php/variables.ts +32 -0
  528. package/blockly-rc/generators/php/variables_dynamic.ts +17 -0
  529. package/blockly-rc/generators/php.ts +46 -0
  530. package/blockly-rc/generators/python/lists.ts +398 -0
  531. package/blockly-rc/generators/python/logic.ts +148 -0
  532. package/blockly-rc/generators/python/loops.ts +251 -0
  533. package/blockly-rc/generators/python/math.ts +434 -0
  534. package/blockly-rc/generators/python/procedures.ts +159 -0
  535. package/blockly-rc/generators/python/python_generator.ts +355 -0
  536. package/blockly-rc/generators/python/text.ts +338 -0
  537. package/blockly-rc/generators/python/variables.ts +31 -0
  538. package/blockly-rc/generators/python/variables_dynamic.ts +17 -0
  539. package/blockly-rc/generators/python.ts +51 -0
  540. package/blockly-rc/gulpfile.js +54 -0
  541. package/blockly-rc/jsconfig.json +7 -0
  542. package/blockly-rc/media/1x1.gif +0 -0
  543. package/blockly-rc/media/click.mp3 +0 -0
  544. package/blockly-rc/media/click.ogg +0 -0
  545. package/blockly-rc/media/click.wav +0 -0
  546. package/blockly-rc/media/delete-icon.svg +1 -0
  547. package/blockly-rc/media/delete.mp3 +0 -0
  548. package/blockly-rc/media/delete.ogg +0 -0
  549. package/blockly-rc/media/delete.wav +0 -0
  550. package/blockly-rc/media/disconnect.mp3 +0 -0
  551. package/blockly-rc/media/disconnect.ogg +0 -0
  552. package/blockly-rc/media/disconnect.wav +0 -0
  553. package/blockly-rc/media/dropdown-arrow.svg +1 -0
  554. package/blockly-rc/media/foldout-icon.svg +1 -0
  555. package/blockly-rc/media/handclosed.cur +0 -0
  556. package/blockly-rc/media/handdelete.cur +0 -0
  557. package/blockly-rc/media/handopen.cur +0 -0
  558. package/blockly-rc/media/pilcrow.png +0 -0
  559. package/blockly-rc/media/quote0.png +0 -0
  560. package/blockly-rc/media/quote1.png +0 -0
  561. package/blockly-rc/media/resize-handle.svg +3 -0
  562. package/blockly-rc/media/sprites.png +0 -0
  563. package/blockly-rc/media/sprites.svg +74 -0
  564. package/blockly-rc/msg/json/README.md +33 -0
  565. package/blockly-rc/msg/json/ab.json +222 -0
  566. package/blockly-rc/msg/json/ace.json +7 -0
  567. package/blockly-rc/msg/json/af.json +34 -0
  568. package/blockly-rc/msg/json/am.json +30 -0
  569. package/blockly-rc/msg/json/ar.json +355 -0
  570. package/blockly-rc/msg/json/ast.json +10 -0
  571. package/blockly-rc/msg/json/az.json +332 -0
  572. package/blockly-rc/msg/json/ba.json +211 -0
  573. package/blockly-rc/msg/json/bcc.json +290 -0
  574. package/blockly-rc/msg/json/be-tarask.json +334 -0
  575. package/blockly-rc/msg/json/be.json +324 -0
  576. package/blockly-rc/msg/json/bg.json +345 -0
  577. package/blockly-rc/msg/json/bn.json +189 -0
  578. package/blockly-rc/msg/json/br.json +334 -0
  579. package/blockly-rc/msg/json/bs.json +166 -0
  580. package/blockly-rc/msg/json/ca.json +341 -0
  581. package/blockly-rc/msg/json/cdo.json +6 -0
  582. package/blockly-rc/msg/json/ce.json +326 -0
  583. package/blockly-rc/msg/json/constants.json +12 -0
  584. package/blockly-rc/msg/json/cs.json +343 -0
  585. package/blockly-rc/msg/json/da.json +346 -0
  586. package/blockly-rc/msg/json/de.json +369 -0
  587. package/blockly-rc/msg/json/diq.json +258 -0
  588. package/blockly-rc/msg/json/dtp.json +198 -0
  589. package/blockly-rc/msg/json/dty.json +97 -0
  590. package/blockly-rc/msg/json/ee.json +160 -0
  591. package/blockly-rc/msg/json/el.json +356 -0
  592. package/blockly-rc/msg/json/en-gb.json +199 -0
  593. package/blockly-rc/msg/json/en.json +400 -0
  594. package/blockly-rc/msg/json/eo.json +337 -0
  595. package/blockly-rc/msg/json/es.json +358 -0
  596. package/blockly-rc/msg/json/et.json +326 -0
  597. package/blockly-rc/msg/json/eu.json +219 -0
  598. package/blockly-rc/msg/json/fa.json +341 -0
  599. package/blockly-rc/msg/json/fi.json +350 -0
  600. package/blockly-rc/msg/json/fo.json +46 -0
  601. package/blockly-rc/msg/json/fr.json +373 -0
  602. package/blockly-rc/msg/json/frr.json +6 -0
  603. package/blockly-rc/msg/json/gl.json +338 -0
  604. package/blockly-rc/msg/json/gn.json +54 -0
  605. package/blockly-rc/msg/json/gor.json +87 -0
  606. package/blockly-rc/msg/json/ha.json +313 -0
  607. package/blockly-rc/msg/json/hak.json +17 -0
  608. package/blockly-rc/msg/json/he.json +354 -0
  609. package/blockly-rc/msg/json/hi.json +318 -0
  610. package/blockly-rc/msg/json/hr.json +327 -0
  611. package/blockly-rc/msg/json/hrx.json +287 -0
  612. package/blockly-rc/msg/json/hsb.json +128 -0
  613. package/blockly-rc/msg/json/hu.json +349 -0
  614. package/blockly-rc/msg/json/hy.json +337 -0
  615. package/blockly-rc/msg/json/ia.json +337 -0
  616. package/blockly-rc/msg/json/id.json +335 -0
  617. package/blockly-rc/msg/json/ig.json +323 -0
  618. package/blockly-rc/msg/json/inh.json +80 -0
  619. package/blockly-rc/msg/json/is.json +331 -0
  620. package/blockly-rc/msg/json/it.json +346 -0
  621. package/blockly-rc/msg/json/ja.json +361 -0
  622. package/blockly-rc/msg/json/ka.json +14 -0
  623. package/blockly-rc/msg/json/kab.json +323 -0
  624. package/blockly-rc/msg/json/kbd-cyrl.json +84 -0
  625. package/blockly-rc/msg/json/km.json +29 -0
  626. package/blockly-rc/msg/json/kn.json +332 -0
  627. package/blockly-rc/msg/json/ko.json +372 -0
  628. package/blockly-rc/msg/json/ksh.json +43 -0
  629. package/blockly-rc/msg/json/ku-latn.json +41 -0
  630. package/blockly-rc/msg/json/ky.json +71 -0
  631. package/blockly-rc/msg/json/la.json +6 -0
  632. package/blockly-rc/msg/json/lb.json +156 -0
  633. package/blockly-rc/msg/json/lki.json +282 -0
  634. package/blockly-rc/msg/json/lo.json +92 -0
  635. package/blockly-rc/msg/json/lrc.json +123 -0
  636. package/blockly-rc/msg/json/lt.json +321 -0
  637. package/blockly-rc/msg/json/lv.json +324 -0
  638. package/blockly-rc/msg/json/mg.json +58 -0
  639. package/blockly-rc/msg/json/mk.json +178 -0
  640. package/blockly-rc/msg/json/ml.json +35 -0
  641. package/blockly-rc/msg/json/mnw.json +90 -0
  642. package/blockly-rc/msg/json/ms.json +300 -0
  643. package/blockly-rc/msg/json/my.json +57 -0
  644. package/blockly-rc/msg/json/mzn.json +6 -0
  645. package/blockly-rc/msg/json/nb.json +330 -0
  646. package/blockly-rc/msg/json/ne.json +247 -0
  647. package/blockly-rc/msg/json/nl.json +357 -0
  648. package/blockly-rc/msg/json/oc.json +194 -0
  649. package/blockly-rc/msg/json/olo.json +37 -0
  650. package/blockly-rc/msg/json/pa.json +69 -0
  651. package/blockly-rc/msg/json/pl.json +357 -0
  652. package/blockly-rc/msg/json/pms.json +324 -0
  653. package/blockly-rc/msg/json/ps.json +50 -0
  654. package/blockly-rc/msg/json/pt-br.json +369 -0
  655. package/blockly-rc/msg/json/pt.json +358 -0
  656. package/blockly-rc/msg/json/qqq.json +406 -0
  657. package/blockly-rc/msg/json/ro.json +333 -0
  658. package/blockly-rc/msg/json/ru.json +363 -0
  659. package/blockly-rc/msg/json/sc.json +283 -0
  660. package/blockly-rc/msg/json/sco.json +11 -0
  661. package/blockly-rc/msg/json/sd.json +158 -0
  662. package/blockly-rc/msg/json/shn.json +109 -0
  663. package/blockly-rc/msg/json/si.json +16 -0
  664. package/blockly-rc/msg/json/sk.json +332 -0
  665. package/blockly-rc/msg/json/skr-arab.json +117 -0
  666. package/blockly-rc/msg/json/sl.json +355 -0
  667. package/blockly-rc/msg/json/smn.json +133 -0
  668. package/blockly-rc/msg/json/sq.json +343 -0
  669. package/blockly-rc/msg/json/sr-latn.json +324 -0
  670. package/blockly-rc/msg/json/sr.json +348 -0
  671. package/blockly-rc/msg/json/sv.json +347 -0
  672. package/blockly-rc/msg/json/sw.json +12 -0
  673. package/blockly-rc/msg/json/synonyms.json +22 -0
  674. package/blockly-rc/msg/json/ta.json +306 -0
  675. package/blockly-rc/msg/json/tcy.json +316 -0
  676. package/blockly-rc/msg/json/tdd.json +109 -0
  677. package/blockly-rc/msg/json/te.json +101 -0
  678. package/blockly-rc/msg/json/th.json +333 -0
  679. package/blockly-rc/msg/json/ti.json +50 -0
  680. package/blockly-rc/msg/json/tl.json +129 -0
  681. package/blockly-rc/msg/json/tlh.json +179 -0
  682. package/blockly-rc/msg/json/tr.json +369 -0
  683. package/blockly-rc/msg/json/ug-arab.json +132 -0
  684. package/blockly-rc/msg/json/uk.json +345 -0
  685. package/blockly-rc/msg/json/ur.json +117 -0
  686. package/blockly-rc/msg/json/uz.json +36 -0
  687. package/blockly-rc/msg/json/vi.json +345 -0
  688. package/blockly-rc/msg/json/xmf.json +96 -0
  689. package/blockly-rc/msg/json/yo.json +316 -0
  690. package/blockly-rc/msg/json/zgh.json +83 -0
  691. package/blockly-rc/msg/json/zh-hans.json +372 -0
  692. package/blockly-rc/msg/json/zh-hant.json +362 -0
  693. package/blockly-rc/msg/messages.js +1616 -0
  694. package/blockly-rc/package-lock.json +12324 -0
  695. package/blockly-rc/package.json +149 -0
  696. package/blockly-rc/patches/@microsoft+api-documenter+7.22.4.patch +81 -0
  697. package/blockly-rc/scripts/goog_module/convert-file.sh +406 -0
  698. package/blockly-rc/scripts/gulpfiles/appengine_tasks.js +195 -0
  699. package/blockly-rc/scripts/gulpfiles/build_tasks.js +752 -0
  700. package/blockly-rc/scripts/gulpfiles/config.js +41 -0
  701. package/blockly-rc/scripts/gulpfiles/docs_tasks.js +147 -0
  702. package/blockly-rc/scripts/gulpfiles/git_tasks.js +181 -0
  703. package/blockly-rc/scripts/gulpfiles/helper_tasks.js +19 -0
  704. package/blockly-rc/scripts/gulpfiles/package_tasks.js +262 -0
  705. package/blockly-rc/scripts/gulpfiles/release_tasks.js +183 -0
  706. package/blockly-rc/scripts/gulpfiles/test_tasks.js +405 -0
  707. package/blockly-rc/scripts/helpers.js +74 -0
  708. package/blockly-rc/scripts/i18n/common.py +233 -0
  709. package/blockly-rc/scripts/i18n/create_messages.py +167 -0
  710. package/blockly-rc/scripts/i18n/dedup_json.py +72 -0
  711. package/blockly-rc/scripts/i18n/js_to_json.py +135 -0
  712. package/blockly-rc/scripts/i18n/tests.py +46 -0
  713. package/blockly-rc/scripts/migration/cjs2esm +162 -0
  714. package/blockly-rc/scripts/migration/js2ts +168 -0
  715. package/blockly-rc/scripts/migration/renamings.json5 +1599 -0
  716. package/blockly-rc/scripts/package/README.md +93 -0
  717. package/blockly-rc/scripts/package/core-node.js +31 -0
  718. package/blockly-rc/scripts/package/index.js +23 -0
  719. package/blockly-rc/scripts/package/templates/umd-msg.template +16 -0
  720. package/blockly-rc/scripts/package/templates/umd.template +13 -0
  721. package/blockly-rc/scripts/themes/blockStyles_example.json +11 -0
  722. package/blockly-rc/scripts/themes/create_blockStyles.py +181 -0
  723. package/blockly-rc/scripts/tsick.js +86 -0
  724. package/blockly-rc/tests/.eslintrc.json +10 -0
  725. package/blockly-rc/tests/browser/.eslintrc.json +29 -0
  726. package/blockly-rc/tests/browser/.mocharc.js +6 -0
  727. package/blockly-rc/tests/browser/test/basic_block_factory_test.mjs +44 -0
  728. package/blockly-rc/tests/browser/test/basic_block_test.mjs +39 -0
  729. package/blockly-rc/tests/browser/test/basic_playground_test.mjs +198 -0
  730. package/blockly-rc/tests/browser/test/block_undo_test.mjs +50 -0
  731. package/blockly-rc/tests/browser/test/delete_blocks_test.mjs +211 -0
  732. package/blockly-rc/tests/browser/test/extensive_test.mjs +195 -0
  733. package/blockly-rc/tests/browser/test/field_edits_test.mjs +61 -0
  734. package/blockly-rc/tests/browser/test/hooks.mjs +23 -0
  735. package/blockly-rc/tests/browser/test/mutator_test.mjs +88 -0
  736. package/blockly-rc/tests/browser/test/procedure_test.mjs +109 -0
  737. package/blockly-rc/tests/browser/test/test_setup.mjs +589 -0
  738. package/blockly-rc/tests/browser/test/toolbox_drag_test.mjs +207 -0
  739. package/blockly-rc/tests/browser/test/workspace_comment_test.mjs +224 -0
  740. package/blockly-rc/tests/compile/index.html +43 -0
  741. package/blockly-rc/tests/compile/main.js +53 -0
  742. package/blockly-rc/tests/compile/test_blocks.js +47 -0
  743. package/blockly-rc/tests/compile/webdriver.js +81 -0
  744. package/blockly-rc/tests/generators/functions.xml +561 -0
  745. package/blockly-rc/tests/generators/golden/generated.dart +1604 -0
  746. package/blockly-rc/tests/generators/golden/generated.js +1552 -0
  747. package/blockly-rc/tests/generators/golden/generated.lua +1828 -0
  748. package/blockly-rc/tests/generators/golden/generated.php +1611 -0
  749. package/blockly-rc/tests/generators/golden/generated.py +1407 -0
  750. package/blockly-rc/tests/generators/index.html +405 -0
  751. package/blockly-rc/tests/generators/lists.xml +8675 -0
  752. package/blockly-rc/tests/generators/logic.xml +1019 -0
  753. package/blockly-rc/tests/generators/loops1.xml +345 -0
  754. package/blockly-rc/tests/generators/loops2.xml +891 -0
  755. package/blockly-rc/tests/generators/loops3.xml +735 -0
  756. package/blockly-rc/tests/generators/math.xml +2077 -0
  757. package/blockly-rc/tests/generators/text.xml +4651 -0
  758. package/blockly-rc/tests/generators/unittest.js +103 -0
  759. package/blockly-rc/tests/generators/unittest_dart.js +163 -0
  760. package/blockly-rc/tests/generators/unittest_javascript.js +167 -0
  761. package/blockly-rc/tests/generators/unittest_lua.js +165 -0
  762. package/blockly-rc/tests/generators/unittest_php.js +154 -0
  763. package/blockly-rc/tests/generators/unittest_python.js +138 -0
  764. package/blockly-rc/tests/generators/variables.xml +68 -0
  765. package/blockly-rc/tests/generators/webdriver.js +123 -0
  766. package/blockly-rc/tests/media/200px.png +0 -0
  767. package/blockly-rc/tests/media/30px.png +0 -0
  768. package/blockly-rc/tests/media/50px.png +0 -0
  769. package/blockly-rc/tests/media/a.png +0 -0
  770. package/blockly-rc/tests/media/arrow.png +0 -0
  771. package/blockly-rc/tests/media/b.png +0 -0
  772. package/blockly-rc/tests/media/c.png +0 -0
  773. package/blockly-rc/tests/media/d.png +0 -0
  774. package/blockly-rc/tests/media/e.png +0 -0
  775. package/blockly-rc/tests/media/f.png +0 -0
  776. package/blockly-rc/tests/media/g.png +0 -0
  777. package/blockly-rc/tests/media/h.png +0 -0
  778. package/blockly-rc/tests/media/i.png +0 -0
  779. package/blockly-rc/tests/media/j.png +0 -0
  780. package/blockly-rc/tests/media/k.png +0 -0
  781. package/blockly-rc/tests/media/l.png +0 -0
  782. package/blockly-rc/tests/media/m.png +0 -0
  783. package/blockly-rc/tests/migration/renamings.schema.json +59 -0
  784. package/blockly-rc/tests/migration/validate-renamings.mjs +60 -0
  785. package/blockly-rc/tests/mocha/.eslintrc.json +21 -0
  786. package/blockly-rc/tests/mocha/.mocharc.js +6 -0
  787. package/blockly-rc/tests/mocha/astnode_test.js +850 -0
  788. package/blockly-rc/tests/mocha/block_json_test.js +777 -0
  789. package/blockly-rc/tests/mocha/block_test.js +2743 -0
  790. package/blockly-rc/tests/mocha/blocks/lists_test.js +196 -0
  791. package/blockly-rc/tests/mocha/blocks/logic_ternary_test.js +320 -0
  792. package/blockly-rc/tests/mocha/blocks/loops_test.js +56 -0
  793. package/blockly-rc/tests/mocha/blocks/procedures_test.js +2495 -0
  794. package/blockly-rc/tests/mocha/blocks/variables_test.js +311 -0
  795. package/blockly-rc/tests/mocha/clipboard_test.js +136 -0
  796. package/blockly-rc/tests/mocha/comment_deserialization_test.js +122 -0
  797. package/blockly-rc/tests/mocha/comment_test.js +170 -0
  798. package/blockly-rc/tests/mocha/comment_view_test.js +188 -0
  799. package/blockly-rc/tests/mocha/connection_checker_test.js +666 -0
  800. package/blockly-rc/tests/mocha/connection_db_test.js +362 -0
  801. package/blockly-rc/tests/mocha/connection_test.js +3738 -0
  802. package/blockly-rc/tests/mocha/contextmenu_items_test.js +488 -0
  803. package/blockly-rc/tests/mocha/contextmenu_test.js +71 -0
  804. package/blockly-rc/tests/mocha/cursor_test.js +134 -0
  805. package/blockly-rc/tests/mocha/dropdowndiv_test.js +116 -0
  806. package/blockly-rc/tests/mocha/event_block_change_test.js +126 -0
  807. package/blockly-rc/tests/mocha/event_block_create_test.js +109 -0
  808. package/blockly-rc/tests/mocha/event_block_delete_test.js +55 -0
  809. package/blockly-rc/tests/mocha/event_block_drag_test.js +36 -0
  810. package/blockly-rc/tests/mocha/event_block_field_intermediate_change_test.js +67 -0
  811. package/blockly-rc/tests/mocha/event_block_move_test.js +39 -0
  812. package/blockly-rc/tests/mocha/event_bubble_open_test.js +42 -0
  813. package/blockly-rc/tests/mocha/event_click_test.js +40 -0
  814. package/blockly-rc/tests/mocha/event_comment_change_test.js +39 -0
  815. package/blockly-rc/tests/mocha/event_comment_collapse_test.js +34 -0
  816. package/blockly-rc/tests/mocha/event_comment_create_test.js +38 -0
  817. package/blockly-rc/tests/mocha/event_comment_delete_test.js +38 -0
  818. package/blockly-rc/tests/mocha/event_comment_drag_test.js +35 -0
  819. package/blockly-rc/tests/mocha/event_comment_move_test.js +40 -0
  820. package/blockly-rc/tests/mocha/event_comment_resize_test.js +38 -0
  821. package/blockly-rc/tests/mocha/event_marker_move_test.js +44 -0
  822. package/blockly-rc/tests/mocha/event_selected_test.js +41 -0
  823. package/blockly-rc/tests/mocha/event_test.js +1578 -0
  824. package/blockly-rc/tests/mocha/event_theme_change_test.js +36 -0
  825. package/blockly-rc/tests/mocha/event_toolbox_item_select_test.js +64 -0
  826. package/blockly-rc/tests/mocha/event_trashcan_open_test.js +36 -0
  827. package/blockly-rc/tests/mocha/event_var_create_test.js +54 -0
  828. package/blockly-rc/tests/mocha/event_var_delete_test.js +54 -0
  829. package/blockly-rc/tests/mocha/event_var_rename_test.js +39 -0
  830. package/blockly-rc/tests/mocha/event_var_type_change_test.js +43 -0
  831. package/blockly-rc/tests/mocha/event_viewport_test.js +39 -0
  832. package/blockly-rc/tests/mocha/extensions_test.js +613 -0
  833. package/blockly-rc/tests/mocha/field_checkbox_test.js +299 -0
  834. package/blockly-rc/tests/mocha/field_colour_test.js +395 -0
  835. package/blockly-rc/tests/mocha/field_dropdown_test.js +282 -0
  836. package/blockly-rc/tests/mocha/field_image_test.js +241 -0
  837. package/blockly-rc/tests/mocha/field_label_serializable_test.js +252 -0
  838. package/blockly-rc/tests/mocha/field_label_test.js +226 -0
  839. package/blockly-rc/tests/mocha/field_number_test.js +505 -0
  840. package/blockly-rc/tests/mocha/field_registry_test.js +116 -0
  841. package/blockly-rc/tests/mocha/field_test.js +822 -0
  842. package/blockly-rc/tests/mocha/field_textinput_test.js +297 -0
  843. package/blockly-rc/tests/mocha/field_variable_test.js +611 -0
  844. package/blockly-rc/tests/mocha/flyout_test.js +638 -0
  845. package/blockly-rc/tests/mocha/generator_test.js +233 -0
  846. package/blockly-rc/tests/mocha/gesture_test.js +97 -0
  847. package/blockly-rc/tests/mocha/icon_test.js +369 -0
  848. package/blockly-rc/tests/mocha/index.html +229 -0
  849. package/blockly-rc/tests/mocha/input_test.js +296 -0
  850. package/blockly-rc/tests/mocha/insertion_marker_manager_test.js +443 -0
  851. package/blockly-rc/tests/mocha/insertion_marker_test.js +432 -0
  852. package/blockly-rc/tests/mocha/jso_deserialization_test.js +849 -0
  853. package/blockly-rc/tests/mocha/jso_serialization_test.js +1067 -0
  854. package/blockly-rc/tests/mocha/json_test.js +315 -0
  855. package/blockly-rc/tests/mocha/keydown_test.js +364 -0
  856. package/blockly-rc/tests/mocha/layering_test.js +95 -0
  857. package/blockly-rc/tests/mocha/metrics_test.js +671 -0
  858. package/blockly-rc/tests/mocha/mutator_test.js +87 -0
  859. package/blockly-rc/tests/mocha/names_test.js +97 -0
  860. package/blockly-rc/tests/mocha/old_workspace_comment_test.js +256 -0
  861. package/blockly-rc/tests/mocha/procedure_map_test.js +57 -0
  862. package/blockly-rc/tests/mocha/registry_test.js +281 -0
  863. package/blockly-rc/tests/mocha/render_management_test.js +127 -0
  864. package/blockly-rc/tests/mocha/serializer_test.js +2104 -0
  865. package/blockly-rc/tests/mocha/shortcut_registry_test.js +450 -0
  866. package/blockly-rc/tests/mocha/test_helpers/block_definitions.js +204 -0
  867. package/blockly-rc/tests/mocha/test_helpers/code_generation.js +115 -0
  868. package/blockly-rc/tests/mocha/test_helpers/common.js +106 -0
  869. package/blockly-rc/tests/mocha/test_helpers/events.js +290 -0
  870. package/blockly-rc/tests/mocha/test_helpers/fields.js +310 -0
  871. package/blockly-rc/tests/mocha/test_helpers/icon_mocks.js +81 -0
  872. package/blockly-rc/tests/mocha/test_helpers/procedures.js +302 -0
  873. package/blockly-rc/tests/mocha/test_helpers/serialization.js +124 -0
  874. package/blockly-rc/tests/mocha/test_helpers/setup_teardown.js +209 -0
  875. package/blockly-rc/tests/mocha/test_helpers/toolbox_definitions.js +271 -0
  876. package/blockly-rc/tests/mocha/test_helpers/user_input.js +62 -0
  877. package/blockly-rc/tests/mocha/test_helpers/variables.js +23 -0
  878. package/blockly-rc/tests/mocha/test_helpers/warnings.js +83 -0
  879. package/blockly-rc/tests/mocha/test_helpers/workspace.js +1691 -0
  880. package/blockly-rc/tests/mocha/theme_test.js +307 -0
  881. package/blockly-rc/tests/mocha/toolbox_test.js +761 -0
  882. package/blockly-rc/tests/mocha/tooltip_test.js +276 -0
  883. package/blockly-rc/tests/mocha/touch_test.js +109 -0
  884. package/blockly-rc/tests/mocha/trashcan_test.js +375 -0
  885. package/blockly-rc/tests/mocha/utils_test.js +536 -0
  886. package/blockly-rc/tests/mocha/variable_map_test.js +509 -0
  887. package/blockly-rc/tests/mocha/variable_model_test.js +85 -0
  888. package/blockly-rc/tests/mocha/webdriver.js +96 -0
  889. package/blockly-rc/tests/mocha/widget_div_test.js +272 -0
  890. package/blockly-rc/tests/mocha/workspace_comment_test.js +171 -0
  891. package/blockly-rc/tests/mocha/workspace_svg_test.js +414 -0
  892. package/blockly-rc/tests/mocha/workspace_test.js +27 -0
  893. package/blockly-rc/tests/mocha/xml_test.js +951 -0
  894. package/blockly-rc/tests/mocha/zoom_controls_test.js +81 -0
  895. package/blockly-rc/tests/multi_playground.html +482 -0
  896. package/blockly-rc/tests/node/.eslintrc.json +12 -0
  897. package/blockly-rc/tests/node/.mocharc.js +6 -0
  898. package/blockly-rc/tests/node/run_node_test.mjs +72 -0
  899. package/blockly-rc/tests/playground.html +1280 -0
  900. package/blockly-rc/tests/playgrounds/advanced_playground.html +158 -0
  901. package/blockly-rc/tests/playgrounds/iframe.html +40 -0
  902. package/blockly-rc/tests/playgrounds/screenshot.js +123 -0
  903. package/blockly-rc/tests/scripts/check_metadata.sh +166 -0
  904. package/blockly-rc/tests/scripts/compile_typings.sh +32 -0
  905. package/blockly-rc/tests/scripts/load.mjs +140 -0
  906. package/blockly-rc/tests/scripts/setup_linux_env.sh +7 -0
  907. package/blockly-rc/tests/scripts/update_metadata.sh +46 -0
  908. package/blockly-rc/tests/themes/test_themes.js +62 -0
  909. package/blockly-rc/tests/typescript/README.md +4 -0
  910. package/blockly-rc/tests/typescript/src/field/different_user_input.ts +81 -0
  911. package/blockly-rc/tests/typescript/src/generators/dart.ts +24 -0
  912. package/blockly-rc/tests/typescript/src/generators/javascript.ts +28 -0
  913. package/blockly-rc/tests/typescript/src/generators/lua.ts +24 -0
  914. package/blockly-rc/tests/typescript/src/generators/php.ts +24 -0
  915. package/blockly-rc/tests/typescript/src/generators/python.ts +24 -0
  916. package/blockly-rc/tests/typescript/src/generators.ts +31 -0
  917. package/blockly-rc/tests/typescript/src/msg.ts +20 -0
  918. package/blockly-rc/tests/typescript/tsconfig.json +20 -0
  919. package/blockly-rc/tests/xml/README.txt +11 -0
  920. package/blockly-rc/tests/xml/blockly.xsd +178 -0
  921. package/blockly-rc/tests/xml/invalid.xml +6 -0
  922. package/blockly-rc/tests/xml/toolbox.xml +311 -0
  923. package/blockly-rc/tests/xml/workspace.xml +114 -0
  924. package/blockly-rc/tsconfig.json +37 -0
  925. package/blockly-rc/tsdoc.json +35 -0
  926. package/blockly-rc/typings/README.md +5 -0
  927. package/blockly-rc/typings/blocks.d.ts +17 -0
  928. package/blockly-rc/typings/core.d.ts +7 -0
  929. package/blockly-rc/typings/dart.d.ts +7 -0
  930. package/blockly-rc/typings/index.d.ts +10 -0
  931. package/blockly-rc/typings/javascript.d.ts +7 -0
  932. package/blockly-rc/typings/lua.d.ts +7 -0
  933. package/blockly-rc/typings/msg/ab.d.ts +8 -0
  934. package/blockly-rc/typings/msg/ace.d.ts +8 -0
  935. package/blockly-rc/typings/msg/af.d.ts +8 -0
  936. package/blockly-rc/typings/msg/am.d.ts +8 -0
  937. package/blockly-rc/typings/msg/ar.d.ts +8 -0
  938. package/blockly-rc/typings/msg/ast.d.ts +8 -0
  939. package/blockly-rc/typings/msg/az.d.ts +8 -0
  940. package/blockly-rc/typings/msg/ba.d.ts +8 -0
  941. package/blockly-rc/typings/msg/bcc.d.ts +8 -0
  942. package/blockly-rc/typings/msg/be-tarask.d.ts +8 -0
  943. package/blockly-rc/typings/msg/be.d.ts +8 -0
  944. package/blockly-rc/typings/msg/bg.d.ts +8 -0
  945. package/blockly-rc/typings/msg/bn.d.ts +8 -0
  946. package/blockly-rc/typings/msg/br.d.ts +8 -0
  947. package/blockly-rc/typings/msg/bs.d.ts +8 -0
  948. package/blockly-rc/typings/msg/ca.d.ts +8 -0
  949. package/blockly-rc/typings/msg/cdo.d.ts +8 -0
  950. package/blockly-rc/typings/msg/ce.d.ts +8 -0
  951. package/blockly-rc/typings/msg/cs.d.ts +8 -0
  952. package/blockly-rc/typings/msg/da.d.ts +8 -0
  953. package/blockly-rc/typings/msg/de.d.ts +8 -0
  954. package/blockly-rc/typings/msg/diq.d.ts +8 -0
  955. package/blockly-rc/typings/msg/dtp.d.ts +8 -0
  956. package/blockly-rc/typings/msg/dty.d.ts +8 -0
  957. package/blockly-rc/typings/msg/ee.d.ts +8 -0
  958. package/blockly-rc/typings/msg/el.d.ts +8 -0
  959. package/blockly-rc/typings/msg/en-gb.d.ts +8 -0
  960. package/blockly-rc/typings/msg/en.d.ts +8 -0
  961. package/blockly-rc/typings/msg/eo.d.ts +8 -0
  962. package/blockly-rc/typings/msg/es.d.ts +8 -0
  963. package/blockly-rc/typings/msg/et.d.ts +8 -0
  964. package/blockly-rc/typings/msg/eu.d.ts +8 -0
  965. package/blockly-rc/typings/msg/fa.d.ts +8 -0
  966. package/blockly-rc/typings/msg/fi.d.ts +8 -0
  967. package/blockly-rc/typings/msg/fo.d.ts +8 -0
  968. package/blockly-rc/typings/msg/fr.d.ts +8 -0
  969. package/blockly-rc/typings/msg/frr.d.ts +8 -0
  970. package/blockly-rc/typings/msg/gl.d.ts +8 -0
  971. package/blockly-rc/typings/msg/gn.d.ts +8 -0
  972. package/blockly-rc/typings/msg/gor.d.ts +8 -0
  973. package/blockly-rc/typings/msg/ha.d.ts +8 -0
  974. package/blockly-rc/typings/msg/hak.d.ts +8 -0
  975. package/blockly-rc/typings/msg/he.d.ts +8 -0
  976. package/blockly-rc/typings/msg/hi.d.ts +8 -0
  977. package/blockly-rc/typings/msg/hr.d.ts +8 -0
  978. package/blockly-rc/typings/msg/hrx.d.ts +8 -0
  979. package/blockly-rc/typings/msg/hsb.d.ts +8 -0
  980. package/blockly-rc/typings/msg/hu.d.ts +8 -0
  981. package/blockly-rc/typings/msg/hy.d.ts +8 -0
  982. package/blockly-rc/typings/msg/ia.d.ts +8 -0
  983. package/blockly-rc/typings/msg/id.d.ts +8 -0
  984. package/blockly-rc/typings/msg/ig.d.ts +8 -0
  985. package/blockly-rc/typings/msg/inh.d.ts +8 -0
  986. package/blockly-rc/typings/msg/is.d.ts +8 -0
  987. package/blockly-rc/typings/msg/it.d.ts +8 -0
  988. package/blockly-rc/typings/msg/ja.d.ts +8 -0
  989. package/blockly-rc/typings/msg/ka.d.ts +8 -0
  990. package/blockly-rc/typings/msg/kab.d.ts +8 -0
  991. package/blockly-rc/typings/msg/kbd-cyrl.d.ts +8 -0
  992. package/blockly-rc/typings/msg/km.d.ts +8 -0
  993. package/blockly-rc/typings/msg/kn.d.ts +8 -0
  994. package/blockly-rc/typings/msg/ko.d.ts +8 -0
  995. package/blockly-rc/typings/msg/ksh.d.ts +8 -0
  996. package/blockly-rc/typings/msg/ku-latn.d.ts +8 -0
  997. package/blockly-rc/typings/msg/ky.d.ts +8 -0
  998. package/blockly-rc/typings/msg/la.d.ts +8 -0
  999. package/blockly-rc/typings/msg/lb.d.ts +8 -0
  1000. package/blockly-rc/typings/msg/lki.d.ts +8 -0
  1001. package/blockly-rc/typings/msg/lo.d.ts +8 -0
  1002. package/blockly-rc/typings/msg/lrc.d.ts +8 -0
  1003. package/blockly-rc/typings/msg/lt.d.ts +8 -0
  1004. package/blockly-rc/typings/msg/lv.d.ts +8 -0
  1005. package/blockly-rc/typings/msg/mg.d.ts +8 -0
  1006. package/blockly-rc/typings/msg/mk.d.ts +8 -0
  1007. package/blockly-rc/typings/msg/ml.d.ts +8 -0
  1008. package/blockly-rc/typings/msg/mnw.d.ts +8 -0
  1009. package/blockly-rc/typings/msg/ms.d.ts +8 -0
  1010. package/blockly-rc/typings/msg/msg.d.ts +440 -0
  1011. package/blockly-rc/typings/msg/my.d.ts +8 -0
  1012. package/blockly-rc/typings/msg/mzn.d.ts +8 -0
  1013. package/blockly-rc/typings/msg/nb.d.ts +8 -0
  1014. package/blockly-rc/typings/msg/ne.d.ts +8 -0
  1015. package/blockly-rc/typings/msg/nl.d.ts +8 -0
  1016. package/blockly-rc/typings/msg/oc.d.ts +8 -0
  1017. package/blockly-rc/typings/msg/olo.d.ts +8 -0
  1018. package/blockly-rc/typings/msg/pa.d.ts +8 -0
  1019. package/blockly-rc/typings/msg/pl.d.ts +8 -0
  1020. package/blockly-rc/typings/msg/pms.d.ts +8 -0
  1021. package/blockly-rc/typings/msg/ps.d.ts +8 -0
  1022. package/blockly-rc/typings/msg/pt-br.d.ts +8 -0
  1023. package/blockly-rc/typings/msg/pt.d.ts +8 -0
  1024. package/blockly-rc/typings/msg/ro.d.ts +8 -0
  1025. package/blockly-rc/typings/msg/ru.d.ts +8 -0
  1026. package/blockly-rc/typings/msg/sc.d.ts +8 -0
  1027. package/blockly-rc/typings/msg/sco.d.ts +8 -0
  1028. package/blockly-rc/typings/msg/sd.d.ts +8 -0
  1029. package/blockly-rc/typings/msg/shn.d.ts +8 -0
  1030. package/blockly-rc/typings/msg/si.d.ts +8 -0
  1031. package/blockly-rc/typings/msg/sk.d.ts +8 -0
  1032. package/blockly-rc/typings/msg/skr-arab.d.ts +8 -0
  1033. package/blockly-rc/typings/msg/sl.d.ts +8 -0
  1034. package/blockly-rc/typings/msg/smn.d.ts +8 -0
  1035. package/blockly-rc/typings/msg/sq.d.ts +8 -0
  1036. package/blockly-rc/typings/msg/sr-latn.d.ts +8 -0
  1037. package/blockly-rc/typings/msg/sr.d.ts +8 -0
  1038. package/blockly-rc/typings/msg/sv.d.ts +8 -0
  1039. package/blockly-rc/typings/msg/sw.d.ts +8 -0
  1040. package/blockly-rc/typings/msg/ta.d.ts +8 -0
  1041. package/blockly-rc/typings/msg/tcy.d.ts +8 -0
  1042. package/blockly-rc/typings/msg/tdd.d.ts +8 -0
  1043. package/blockly-rc/typings/msg/te.d.ts +8 -0
  1044. package/blockly-rc/typings/msg/th.d.ts +8 -0
  1045. package/blockly-rc/typings/msg/ti.d.ts +8 -0
  1046. package/blockly-rc/typings/msg/tl.d.ts +8 -0
  1047. package/blockly-rc/typings/msg/tlh.d.ts +8 -0
  1048. package/blockly-rc/typings/msg/tr.d.ts +8 -0
  1049. package/blockly-rc/typings/msg/ug-arab.d.ts +8 -0
  1050. package/blockly-rc/typings/msg/uk.d.ts +8 -0
  1051. package/blockly-rc/typings/msg/ur.d.ts +8 -0
  1052. package/blockly-rc/typings/msg/uz.d.ts +8 -0
  1053. package/blockly-rc/typings/msg/vi.d.ts +8 -0
  1054. package/blockly-rc/typings/msg/xmf.d.ts +8 -0
  1055. package/blockly-rc/typings/msg/yo.d.ts +8 -0
  1056. package/blockly-rc/typings/msg/zgh.d.ts +8 -0
  1057. package/blockly-rc/typings/msg/zh-hans.d.ts +8 -0
  1058. package/blockly-rc/typings/msg/zh-hant.d.ts +8 -0
  1059. package/blockly-rc/typings/php.d.ts +7 -0
  1060. package/blockly-rc/typings/python.d.ts +7 -0
  1061. package/blockly-rc/typings/templates/blockly-header.template +11 -0
  1062. package/blockly-rc/typings/templates/blockly-interfaces.template +83 -0
  1063. package/blockly-rc/typings/templates/msg.template +15 -0
  1064. package/blockly-rc/typings/tsconfig.json +23 -0
  1065. package/continuous-toolbox.d.ts +1 -0
  1066. package/dist/main.js +2 -0
  1067. package/dist/main.js.LICENSE.txt +163 -0
  1068. package/media/delete-icon.svg +10 -0
  1069. package/media/resize-handle.svg +3 -0
  1070. package/msg/scratch_msgs.js +184 -164
  1071. package/package.json +25 -40
  1072. package/release.config.js +8 -0
  1073. package/src/block_reporting.js +31 -0
  1074. package/src/blocks/colour.js +56 -0
  1075. package/src/blocks/control.js +492 -0
  1076. package/src/blocks/data.js +690 -0
  1077. package/src/blocks/event.js +305 -0
  1078. package/src/blocks/looks.js +537 -0
  1079. package/src/blocks/math.js +137 -0
  1080. package/src/blocks/matrix.js +47 -0
  1081. package/src/blocks/motion.js +513 -0
  1082. package/src/blocks/note.js +48 -0
  1083. package/src/blocks/operators.js +463 -0
  1084. package/src/blocks/procedures.js +1009 -0
  1085. package/src/blocks/sensing.js +441 -0
  1086. package/src/blocks/sound.js +205 -0
  1087. package/src/blocks/text.js +45 -0
  1088. package/src/blocks/vertical_extensions.js +309 -0
  1089. package/src/categories.js +15 -0
  1090. package/src/checkable_continuous_flyout.js +138 -0
  1091. package/src/checkbox_bubble.js +282 -0
  1092. package/src/colours.js +77 -0
  1093. package/src/constants.js +63 -0
  1094. package/src/context_menu_items.js +150 -0
  1095. package/src/css.js +1197 -0
  1096. package/src/data_category.js +556 -0
  1097. package/src/events/events_block_comment_base.js +35 -0
  1098. package/src/events/events_block_comment_change.js +43 -0
  1099. package/src/events/events_block_comment_collapse.js +43 -0
  1100. package/src/events/events_block_comment_create.js +52 -0
  1101. package/src/events/events_block_comment_delete.js +27 -0
  1102. package/src/events/events_block_comment_move.js +54 -0
  1103. package/src/events/events_block_comment_resize.js +52 -0
  1104. package/src/events/events_block_drag_end.js +33 -0
  1105. package/src/events/events_block_drag_outside.js +30 -0
  1106. package/src/events/events_scratch_variable_create.js +67 -0
  1107. package/src/fields/field_angle.js +433 -0
  1108. package/src/fields/field_colour_slider.js +388 -0
  1109. package/src/fields/field_dropdown.js +42 -0
  1110. package/src/fields/field_matrix.js +634 -0
  1111. package/src/fields/field_note.js +937 -0
  1112. package/src/fields/field_number.js +380 -0
  1113. package/src/fields/field_textinput_removable.js +107 -0
  1114. package/src/fields/field_variable.js +171 -0
  1115. package/src/fields/field_variable_getter.js +109 -0
  1116. package/src/fields/field_vertical_separator.js +139 -0
  1117. package/src/flyout_checkbox_icon.js +88 -0
  1118. package/src/glows.js +98 -0
  1119. package/src/index.ts +137 -0
  1120. package/src/procedures.js +425 -0
  1121. package/src/recyclable_block_flyout_inflater.js +194 -0
  1122. package/src/renderer/bowler_hat.js +17 -0
  1123. package/src/renderer/constants.js +45 -0
  1124. package/src/renderer/drawer.js +51 -0
  1125. package/src/renderer/path_object.js +35 -0
  1126. package/src/renderer/render_info.js +98 -0
  1127. package/src/renderer/renderer.js +74 -0
  1128. package/src/scratch_block_paster.js +46 -0
  1129. package/src/scratch_blocks_utils.js +148 -0
  1130. package/src/scratch_comment_bubble.js +169 -0
  1131. package/src/scratch_comment_icon.js +195 -0
  1132. package/src/scratch_connection_checker.js +29 -0
  1133. package/src/scratch_continuous_category.js +80 -0
  1134. package/src/scratch_continuous_toolbox.js +78 -0
  1135. package/src/scratch_dragger.js +142 -0
  1136. package/src/scratch_variable_map.js +25 -0
  1137. package/src/scratch_variable_model.js +24 -0
  1138. package/src/shadows.js +61 -0
  1139. package/src/status_indicator_label.js +186 -0
  1140. package/src/status_indicator_label_flyout_inflater.js +42 -0
  1141. package/src/variables.js +355 -0
  1142. package/temp-use-blockly-v12-rc.sh +26 -0
  1143. package/tsconfig.json +13 -0
  1144. package/blockly_compressed_horizontal.js +0 -2255
  1145. package/blockly_compressed_vertical.js +0 -2283
  1146. package/blockly_uncompressed_horizontal.js +0 -1210
  1147. package/blockly_uncompressed_vertical.js +0 -1210
  1148. package/blocks_common/colour.js +0 -61
  1149. package/blocks_common/math.js +0 -159
  1150. package/blocks_common/matrix.js +0 -54
  1151. package/blocks_common/note.js +0 -58
  1152. package/blocks_common/text.js +0 -57
  1153. package/blocks_compressed.js +0 -36
  1154. package/blocks_compressed_horizontal.js +0 -67
  1155. package/blocks_compressed_vertical.js +0 -208
  1156. package/blocks_horizontal/control.js +0 -212
  1157. package/blocks_horizontal/default_toolbox.js +0 -139
  1158. package/blocks_horizontal/event.js +0 -190
  1159. package/blocks_horizontal/wedo.js +0 -325
  1160. package/blocks_vertical/control.js +0 -532
  1161. package/blocks_vertical/data.js +0 -666
  1162. package/blocks_vertical/default_toolbox.js +0 -564
  1163. package/blocks_vertical/event.js +0 -329
  1164. package/blocks_vertical/extensions.js +0 -294
  1165. package/blocks_vertical/looks.js +0 -591
  1166. package/blocks_vertical/motion.js +0 -587
  1167. package/blocks_vertical/operators.js +0 -470
  1168. package/blocks_vertical/procedures.js +0 -973
  1169. package/blocks_vertical/sensing.js +0 -539
  1170. package/blocks_vertical/sound.js +0 -246
  1171. package/blocks_vertical/vertical_extensions.js +0 -266
  1172. package/build/gen_blocks.js +0 -1
  1173. package/build/test_expect.js +0 -1
  1174. package/build/test_input.js +0 -1
  1175. package/build.py +0 -636
  1176. package/cleanup.sh +0 -101
  1177. package/core/block.js +0 -1837
  1178. package/core/block_animations.js +0 -107
  1179. package/core/block_drag_surface.js +0 -299
  1180. package/core/block_dragger.js +0 -421
  1181. package/core/block_events.js +0 -531
  1182. package/core/block_render_svg_horizontal.js +0 -890
  1183. package/core/block_render_svg_vertical.js +0 -1732
  1184. package/core/block_svg.js +0 -1316
  1185. package/core/blockly.js +0 -622
  1186. package/core/blocks.js +0 -37
  1187. package/core/bubble.js +0 -664
  1188. package/core/bubble_dragger.js +0 -285
  1189. package/core/colours.js +0 -160
  1190. package/core/comment.js +0 -293
  1191. package/core/comment_events.js +0 -539
  1192. package/core/connection.js +0 -766
  1193. package/core/connection_db.js +0 -300
  1194. package/core/constants.js +0 -387
  1195. package/core/contextmenu.js +0 -519
  1196. package/core/css.js +0 -1351
  1197. package/core/data_category.js +0 -490
  1198. package/core/dragged_connection_manager.js +0 -260
  1199. package/core/dropdowndiv.js +0 -408
  1200. package/core/events.js +0 -429
  1201. package/core/events_abstract.js +0 -113
  1202. package/core/extensions.js +0 -450
  1203. package/core/field.js +0 -807
  1204. package/core/field_angle.js +0 -398
  1205. package/core/field_checkbox.js +0 -133
  1206. package/core/field_colour.js +0 -253
  1207. package/core/field_colour_slider.js +0 -387
  1208. package/core/field_date.js +0 -353
  1209. package/core/field_dropdown.js +0 -483
  1210. package/core/field_iconmenu.js +0 -309
  1211. package/core/field_image.js +0 -193
  1212. package/core/field_label.js +0 -136
  1213. package/core/field_label_serializable.js +0 -125
  1214. package/core/field_matrix.js +0 -566
  1215. package/core/field_note.js +0 -850
  1216. package/core/field_number.js +0 -366
  1217. package/core/field_numberdropdown.js +0 -77
  1218. package/core/field_textdropdown.js +0 -164
  1219. package/core/field_textinput.js +0 -675
  1220. package/core/field_textinput_removable.js +0 -105
  1221. package/core/field_variable.js +0 -385
  1222. package/core/field_variable_getter.js +0 -185
  1223. package/core/field_vertical_separator.js +0 -161
  1224. package/core/flyout_base.js +0 -923
  1225. package/core/flyout_button.js +0 -322
  1226. package/core/flyout_dragger.js +0 -83
  1227. package/core/flyout_extension_category_header.js +0 -159
  1228. package/core/flyout_horizontal.js +0 -475
  1229. package/core/flyout_vertical.js +0 -770
  1230. package/core/generator.js +0 -426
  1231. package/core/gesture.js +0 -1011
  1232. package/core/grid.js +0 -227
  1233. package/core/icon.js +0 -205
  1234. package/core/inject.js +0 -491
  1235. package/core/input.js +0 -285
  1236. package/core/insertion_marker_manager.js +0 -678
  1237. package/core/msg.js +0 -62
  1238. package/core/mutator.js +0 -426
  1239. package/core/names.js +0 -198
  1240. package/core/options.js +0 -244
  1241. package/core/procedures.js +0 -577
  1242. package/core/rendered_connection.js +0 -417
  1243. package/core/scratch_block_comment.js +0 -653
  1244. package/core/scratch_blocks_utils.js +0 -244
  1245. package/core/scratch_bubble.js +0 -696
  1246. package/core/scratch_events.js +0 -131
  1247. package/core/scratch_msgs.js +0 -85
  1248. package/core/scrollbar.js +0 -875
  1249. package/core/toolbox.js +0 -801
  1250. package/core/tooltip.js +0 -337
  1251. package/core/touch.js +0 -226
  1252. package/core/trashcan.js +0 -343
  1253. package/core/ui_events.js +0 -91
  1254. package/core/ui_menu_utils.js +0 -68
  1255. package/core/utils.js +0 -948
  1256. package/core/variable_events.js +0 -259
  1257. package/core/variable_map.js +0 -415
  1258. package/core/variable_model.js +0 -116
  1259. package/core/variables.js +0 -674
  1260. package/core/warning.js +0 -199
  1261. package/core/widgetdiv.js +0 -344
  1262. package/core/workspace.js +0 -673
  1263. package/core/workspace_audio.js +0 -170
  1264. package/core/workspace_comment.js +0 -432
  1265. package/core/workspace_comment_render_svg.js +0 -723
  1266. package/core/workspace_comment_svg.js +0 -611
  1267. package/core/workspace_drag_surface_svg.js +0 -195
  1268. package/core/workspace_dragger.js +0 -132
  1269. package/core/workspace_svg.js +0 -2267
  1270. package/core/xml.js +0 -919
  1271. package/core/zoom_controls.js +0 -301
  1272. package/dist/horizontal.js +0 -222
  1273. package/dist/vertical.js +0 -222
  1274. package/dist/web/horizontal.js +0 -232
  1275. package/dist/web/vertical.js +0 -232
  1276. package/local_build.sh +0 -70
  1277. package/pack/scratch-blocks-1.1.206.tgz +0 -0
  1278. package/pull_from_blockly.sh +0 -151
  1279. package/shim/blockly_compressed_horizontal-blocks_compressed.js +0 -1
  1280. package/shim/blockly_compressed_horizontal.Blockly.js +0 -1
  1281. package/shim/blockly_compressed_horizontal.goog.js +0 -1
  1282. package/shim/blockly_compressed_horizontal.js +0 -1
  1283. package/shim/blockly_compressed_vertical-blocks_compressed.js +0 -1
  1284. package/shim/blockly_compressed_vertical.Blockly.js +0 -1
  1285. package/shim/blockly_compressed_vertical.goog.js +0 -1
  1286. package/shim/blockly_compressed_vertical.js +0 -1
  1287. package/shim/blocks_compressed_horizontal-blockly_compressed_horizontal-messages.js +0 -1
  1288. package/shim/blocks_compressed_horizontal.js +0 -1
  1289. package/shim/blocks_compressed_vertical-blockly_compressed_vertical-messages.js +0 -1
  1290. package/shim/blocks_compressed_vertical.js +0 -1
  1291. package/shim/gh-pages.js +0 -1
  1292. package/shim/horizontal.js +0 -1
  1293. package/shim/index.js +0 -17
  1294. package/shim/vertical.js +0 -1
  1295. /package/media/{comment-arrow-down.svg → foldout-icon.svg} +0 -0
@@ -0,0 +1,2743 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2019 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import {assert} from '../../node_modules/chai/chai.js';
8
+ import {ConnectionType} from '../../build/src/core/connection_type.js';
9
+ import {createDeprecationWarningStub} from './test_helpers/warnings.js';
10
+ import {createRenderedBlock} from './test_helpers/block_definitions.js';
11
+ import * as eventUtils from '../../build/src/core/events/utils.js';
12
+ import {EndRowInput} from '../../build/src/core/inputs/end_row_input.js';
13
+ import {
14
+ sharedTestSetup,
15
+ sharedTestTeardown,
16
+ workspaceTeardown,
17
+ } from './test_helpers/setup_teardown.js';
18
+ import {
19
+ createChangeListenerSpy,
20
+ createMockEvent,
21
+ } from './test_helpers/events.js';
22
+ import {MockIcon, MockBubbleIcon} from './test_helpers/icon_mocks.js';
23
+ import {IconType} from '../../build/src/core/icons/icon_types.js';
24
+
25
+ suite('Blocks', function () {
26
+ setup(function () {
27
+ this.clock = sharedTestSetup.call(this, {fireEventsNow: false}).clock;
28
+ this.workspace = new Blockly.Workspace();
29
+ Blockly.defineBlocksWithJsonArray([
30
+ {
31
+ 'type': 'empty_block',
32
+ 'message0': '',
33
+ },
34
+ {
35
+ 'type': 'stack_block',
36
+ 'message0': '',
37
+ 'previousStatement': null,
38
+ 'nextStatement': null,
39
+ },
40
+ {
41
+ 'type': 'row_block',
42
+ 'message0': '%1',
43
+ 'args0': [
44
+ {
45
+ 'type': 'input_value',
46
+ 'name': 'INPUT',
47
+ },
48
+ ],
49
+ 'output': null,
50
+ },
51
+ {
52
+ 'type': 'statement_block',
53
+ 'message0': '%1',
54
+ 'args0': [
55
+ {
56
+ 'type': 'input_statement',
57
+ 'name': 'STATEMENT',
58
+ },
59
+ ],
60
+ 'previousStatement': null,
61
+ 'nextStatement': null,
62
+ },
63
+ ]);
64
+ });
65
+
66
+ teardown(function () {
67
+ sharedTestTeardown.call(this);
68
+ });
69
+
70
+ function createTestBlocks(workspace, isRow) {
71
+ const blockType = isRow ? 'row_block' : 'stack_block';
72
+ const blockA = workspace.newBlock(blockType, 'a');
73
+ const blockB = workspace.newBlock(blockType, 'b');
74
+ const blockC = workspace.newBlock(blockType, 'c');
75
+
76
+ if (isRow) {
77
+ blockA.inputList[0].connection.connect(blockB.outputConnection);
78
+ blockB.inputList[0].connection.connect(blockC.outputConnection);
79
+ } else {
80
+ blockA.nextConnection.connect(blockB.previousConnection);
81
+ blockB.nextConnection.connect(blockC.previousConnection);
82
+ }
83
+
84
+ assert.equal(blockC.getParent(), blockB);
85
+
86
+ return {
87
+ A: blockA /* Parent */,
88
+ B: blockB /* Middle */,
89
+ C: blockC /* Child */,
90
+ };
91
+ }
92
+
93
+ suite('Unplug', function () {
94
+ function assertUnpluggedNoheal(blocks) {
95
+ // A has nothing connected to it.
96
+ assert.equal(blocks.A.getChildren().length, 0);
97
+ // B and C are still connected.
98
+ assert.equal(blocks.C.getParent(), blocks.B);
99
+ // B is the top of its stack.
100
+ assert.isNull(blocks.B.getParent());
101
+ }
102
+ function assertUnpluggedHealed(blocks) {
103
+ // A and C are connected.
104
+ assert.equal(blocks.A.getChildren().length, 1);
105
+ assert.equal(blocks.C.getParent(), blocks.A);
106
+ // B has nothing connected to it.
107
+ assert.equal(blocks.B.getChildren().length, 0);
108
+ // B is the top of its stack.
109
+ assert.isNull(blocks.B.getParent());
110
+ }
111
+ function assertUnpluggedHealFailed(blocks) {
112
+ // A has nothing connected to it.
113
+ assert.equal(blocks.A.getChildren().length, 0);
114
+ // B has nothing connected to it.
115
+ assert.equal(blocks.B.getChildren().length, 0);
116
+ // B is the top of its stack.
117
+ assert.isNull(blocks.B.getParent());
118
+ // C is the top of its stack.
119
+ assert.isNull(blocks.C.getParent());
120
+ }
121
+
122
+ suite('Row', function () {
123
+ setup(function () {
124
+ this.blocks = createTestBlocks(this.workspace, true);
125
+ });
126
+
127
+ test("Don't heal", function () {
128
+ this.blocks.B.unplug(false);
129
+ assertUnpluggedNoheal(this.blocks);
130
+ });
131
+ test('Heal', function () {
132
+ this.blocks.B.unplug(true);
133
+ // Each block has only one input, and the types work.
134
+ assertUnpluggedHealed(this.blocks);
135
+ });
136
+ test('Heal with bad checks', function () {
137
+ const blocks = this.blocks;
138
+
139
+ // A and C can't connect, but both can connect to B.
140
+ blocks.A.inputList[0].connection.setCheck('type1');
141
+ blocks.C.outputConnection.setCheck('type2');
142
+
143
+ // Each block has only one input, but the types don't work.
144
+ blocks.B.unplug(true);
145
+ assertUnpluggedHealFailed(blocks);
146
+ });
147
+ test('Parent has multiple inputs', function () {
148
+ const blocks = this.blocks;
149
+ // Add extra input to parent
150
+ blocks.A.appendValueInput('INPUT').setCheck(null);
151
+ blocks.B.unplug(true);
152
+ assertUnpluggedHealed(blocks);
153
+ });
154
+ test('Middle has multiple inputs', function () {
155
+ const blocks = this.blocks;
156
+ // Add extra input to middle block
157
+ blocks.B.appendValueInput('INPUT').setCheck(null);
158
+ blocks.B.unplug(true);
159
+ assertUnpluggedHealed(blocks);
160
+ });
161
+ test('Child has multiple inputs', function () {
162
+ const blocks = this.blocks;
163
+ // Add extra input to child block
164
+ blocks.C.appendValueInput('INPUT').setCheck(null);
165
+ // Child block input count doesn't matter.
166
+ blocks.B.unplug(true);
167
+ assertUnpluggedHealed(blocks);
168
+ });
169
+ test('Child is shadow', function () {
170
+ const blocks = this.blocks;
171
+ blocks.C.setShadow(true);
172
+ blocks.B.unplug(true);
173
+ // Even though we're asking to heal, it will appear as if it has not
174
+ // healed because shadows always stay with the parent.
175
+ assertUnpluggedNoheal(blocks);
176
+ });
177
+ });
178
+ suite('Stack', function () {
179
+ setup(function () {
180
+ this.blocks = createTestBlocks(this.workspace, false);
181
+ });
182
+
183
+ test("Don't heal", function () {
184
+ this.blocks.B.unplug();
185
+ assertUnpluggedNoheal(this.blocks);
186
+ });
187
+ test('Heal', function () {
188
+ this.blocks.B.unplug(true);
189
+ assertUnpluggedHealed(this.blocks);
190
+ });
191
+ test('Heal with bad checks', function () {
192
+ const blocks = this.blocks;
193
+ // A and C can't connect, but both can connect to B.
194
+ blocks.A.nextConnection.setCheck('type1');
195
+ blocks.C.previousConnection.setCheck('type2');
196
+
197
+ // The types don't work.
198
+ blocks.B.unplug(true);
199
+
200
+ assertUnpluggedHealFailed(blocks);
201
+ });
202
+ test('Child is shadow', function () {
203
+ const blocks = this.blocks;
204
+ blocks.C.setShadow(true);
205
+ blocks.B.unplug(true);
206
+ // Even though we're asking to heal, it will appear as if it has not
207
+ // healed because shadows always stay with the parent.
208
+ assertUnpluggedNoheal(blocks);
209
+ });
210
+ });
211
+ });
212
+
213
+ suite('Disposal', function () {
214
+ suite('calling destroy', function () {
215
+ setup(function () {
216
+ Blockly.Blocks['destroyable_block'] = {
217
+ init: function () {
218
+ this.appendStatementInput('STATEMENT');
219
+ this.setPreviousStatement(true);
220
+ this.setNextStatement(true);
221
+ },
222
+ destroy: function () {},
223
+ };
224
+ this.block = this.workspace.newBlock('destroyable_block');
225
+ });
226
+
227
+ teardown(function () {
228
+ delete Blockly.Blocks['destroyable_block'];
229
+ });
230
+
231
+ test('destroy is called', function () {
232
+ const spy = sinon.spy(this.block, 'destroy');
233
+
234
+ this.block.dispose();
235
+
236
+ assert.isTrue(spy.calledOnce, 'Expected destroy to be called.');
237
+ });
238
+
239
+ test('disposing is set before destroy', function () {
240
+ let disposing = null;
241
+ this.block.destroy = function () {
242
+ disposing = this.disposing;
243
+ };
244
+
245
+ this.block.dispose();
246
+
247
+ assert.isTrue(
248
+ disposing,
249
+ 'Expected disposing to be set to true before destroy is called.',
250
+ );
251
+ });
252
+
253
+ test('disposed is not set before destroy', function () {
254
+ let disposed = null;
255
+ this.block.destroy = function () {
256
+ disposed = this.disposed;
257
+ };
258
+
259
+ this.block.dispose();
260
+
261
+ assert.isFalse(
262
+ disposed,
263
+ 'Expected disposed to be false when destroy is called',
264
+ );
265
+ });
266
+
267
+ test('events can be fired from destroy', function () {
268
+ const mockEvent = createMockEvent(this.workspace);
269
+ this.block.destroy = function () {
270
+ Blockly.Events.fire(mockEvent);
271
+ };
272
+ const spy = createChangeListenerSpy(this.workspace);
273
+
274
+ this.block.dispose();
275
+ this.clock.runAll();
276
+
277
+ assert.isTrue(
278
+ spy.calledWith(mockEvent),
279
+ 'Expected to be able to fire events from destroy',
280
+ );
281
+ });
282
+
283
+ test('child blocks can fire events from destroy', function () {
284
+ const mockEvent = createMockEvent(this.workspace);
285
+ const childBlock = this.workspace.newBlock('destroyable_block');
286
+ this.block
287
+ .getInput('STATEMENT')
288
+ .connection.connect(childBlock.previousConnection);
289
+ childBlock.destroy = function () {
290
+ Blockly.Events.fire(mockEvent);
291
+ };
292
+ const spy = createChangeListenerSpy(this.workspace);
293
+
294
+ this.block.dispose();
295
+ this.clock.runAll();
296
+
297
+ assert.isTrue(
298
+ spy.calledWith(mockEvent),
299
+ 'Expected to be able to fire events from destroy',
300
+ );
301
+ });
302
+ });
303
+
304
+ suite('stack/row healing', function () {
305
+ function assertDisposedNoheal(blocks) {
306
+ assert.isFalse(blocks.A.disposed);
307
+ // A has nothing connected to it.
308
+ assert.equal(blocks.A.getChildren().length, 0);
309
+ // B is disposed.
310
+ assert.isTrue(blocks.B.disposed);
311
+ // And C is disposed.
312
+ assert.isTrue(blocks.C.disposed);
313
+ }
314
+
315
+ function assertDisposedHealed(blocks) {
316
+ assert.isFalse(blocks.A.disposed);
317
+ assert.isFalse(blocks.C.disposed);
318
+ // A and C are connected.
319
+ assert.equal(blocks.A.getChildren().length, 1);
320
+ assert.equal(blocks.C.getParent(), blocks.A);
321
+ // B is disposed.
322
+ assert.isTrue(blocks.B.disposed);
323
+ }
324
+
325
+ function assertDisposedHealFailed(blocks) {
326
+ assert.isFalse(blocks.A.disposed);
327
+ assert.isFalse(blocks.C.disposed);
328
+ // A has nothing connected to it.
329
+ assert.equal(blocks.A.getChildren().length, 0);
330
+ // B is disposed.
331
+ assert.isTrue(blocks.B.disposed);
332
+ // C is the top of its stack.
333
+ assert.isNull(blocks.C.getParent());
334
+ }
335
+
336
+ suite('Row', function () {
337
+ setup(function () {
338
+ this.blocks = createTestBlocks(this.workspace, true);
339
+ });
340
+
341
+ test("Don't heal", function () {
342
+ this.blocks.B.dispose(false);
343
+ assertDisposedNoheal(this.blocks);
344
+ });
345
+
346
+ test('Heal', function () {
347
+ this.blocks.B.dispose(true);
348
+ // Each block has only one input, and the types work.
349
+ assertDisposedHealed(this.blocks);
350
+ });
351
+
352
+ test('Heal with bad checks', function () {
353
+ const blocks = this.blocks;
354
+
355
+ // A and C can't connect, but both can connect to B.
356
+ blocks.A.inputList[0].connection.setCheck('type1');
357
+ blocks.C.outputConnection.setCheck('type2');
358
+
359
+ // Each block has only one input, but the types don't work.
360
+ blocks.B.dispose(true);
361
+ assertDisposedHealFailed(blocks);
362
+ });
363
+
364
+ test('Parent has multiple inputs', function () {
365
+ const blocks = this.blocks;
366
+ // Add extra input to parent
367
+ blocks.A.appendValueInput('INPUT').setCheck(null);
368
+ blocks.B.dispose(true);
369
+ assertDisposedHealed(blocks);
370
+ });
371
+
372
+ test('Middle has multiple inputs', function () {
373
+ const blocks = this.blocks;
374
+ // Add extra input to middle block
375
+ blocks.B.appendValueInput('INPUT').setCheck(null);
376
+ blocks.B.dispose(true);
377
+ assertDisposedHealed(blocks);
378
+ });
379
+
380
+ test('Child has multiple inputs', function () {
381
+ const blocks = this.blocks;
382
+ // Add extra input to child block
383
+ blocks.C.appendValueInput('INPUT').setCheck(null);
384
+ // Child block input count doesn't matter.
385
+ blocks.B.dispose(true);
386
+ assertDisposedHealed(blocks);
387
+ });
388
+
389
+ test('Child is shadow', function () {
390
+ const blocks = this.blocks;
391
+ blocks.C.dispose();
392
+ blocks.B.inputList[0].connection.setShadowState({
393
+ 'type': 'row_block',
394
+ 'id': 'c',
395
+ });
396
+
397
+ blocks.B.dispose(true);
398
+
399
+ // Even though we're asking to heal, it will appear as if it has not
400
+ // healed because shadows always get destroyed.
401
+ assertDisposedNoheal(blocks);
402
+ });
403
+ });
404
+
405
+ suite('Stack', function () {
406
+ setup(function () {
407
+ this.blocks = createTestBlocks(this.workspace, false);
408
+ });
409
+
410
+ test("Don't heal", function () {
411
+ this.blocks.B.dispose();
412
+ assertDisposedNoheal(this.blocks);
413
+ });
414
+
415
+ test('Heal', function () {
416
+ this.blocks.B.dispose(true);
417
+ assertDisposedHealed(this.blocks);
418
+ });
419
+
420
+ test('Heal with bad checks', function () {
421
+ const blocks = this.blocks;
422
+ // A and C can't connect, but both can connect to B.
423
+ blocks.A.nextConnection.setCheck('type1');
424
+ blocks.C.previousConnection.setCheck('type2');
425
+
426
+ // The types don't work.
427
+ blocks.B.dispose(true);
428
+
429
+ assertDisposedHealFailed(blocks);
430
+ });
431
+
432
+ test('Child is shadow', function () {
433
+ const blocks = this.blocks;
434
+ blocks.C.dispose();
435
+ blocks.B.nextConnection.setShadowState({
436
+ 'type': 'stack_block',
437
+ 'id': 'c',
438
+ });
439
+
440
+ blocks.B.dispose(true);
441
+
442
+ // Even though we're asking to heal, it will appear as if it has not
443
+ // healed because shadows always get destroyed.
444
+ assertDisposedNoheal(blocks);
445
+ });
446
+ });
447
+ });
448
+ });
449
+
450
+ suite('Remove Input', function () {
451
+ setup(function () {
452
+ Blockly.defineBlocksWithJsonArray([
453
+ {
454
+ 'type': 'value_block',
455
+ 'message0': '%1',
456
+ 'args0': [
457
+ {
458
+ 'type': 'input_value',
459
+ 'name': 'VALUE',
460
+ },
461
+ ],
462
+ },
463
+ ]);
464
+ });
465
+
466
+ suite('Value', function () {
467
+ setup(function () {
468
+ this.blockA = this.workspace.newBlock('value_block');
469
+ });
470
+
471
+ test('No Connected', function () {
472
+ this.blockA.removeInput('VALUE');
473
+ assert.isNull(this.blockA.getInput('VALUE'));
474
+ });
475
+ test('Block Connected', function () {
476
+ const blockB = this.workspace.newBlock('row_block');
477
+ this.blockA
478
+ .getInput('VALUE')
479
+ .connection.connect(blockB.outputConnection);
480
+
481
+ this.blockA.removeInput('VALUE');
482
+ assert.isFalse(blockB.disposed);
483
+ assert.equal(this.blockA.getChildren().length, 0);
484
+ });
485
+ test('Shadow Connected', function () {
486
+ const blockB = this.workspace.newBlock('row_block');
487
+ blockB.setShadow(true);
488
+ this.blockA
489
+ .getInput('VALUE')
490
+ .connection.connect(blockB.outputConnection);
491
+
492
+ this.blockA.removeInput('VALUE');
493
+ assert.isTrue(blockB.disposed);
494
+ assert.equal(this.blockA.getChildren().length, 0);
495
+ });
496
+ });
497
+ suite('Statement', function () {
498
+ setup(function () {
499
+ this.blockA = this.workspace.newBlock('statement_block');
500
+ });
501
+
502
+ test('No Connected', function () {
503
+ this.blockA.removeInput('STATEMENT');
504
+ assert.isNull(this.blockA.getInput('STATEMENT'));
505
+ });
506
+ test('Block Connected', function () {
507
+ const blockB = this.workspace.newBlock('stack_block');
508
+ this.blockA
509
+ .getInput('STATEMENT')
510
+ .connection.connect(blockB.previousConnection);
511
+
512
+ this.blockA.removeInput('STATEMENT');
513
+ assert.isFalse(blockB.disposed);
514
+ assert.equal(this.blockA.getChildren().length, 0);
515
+ });
516
+ test('Shadow Connected', function () {
517
+ const blockB = this.workspace.newBlock('stack_block');
518
+ blockB.setShadow(true);
519
+ this.blockA
520
+ .getInput('STATEMENT')
521
+ .connection.connect(blockB.previousConnection);
522
+
523
+ this.blockA.removeInput('STATEMENT');
524
+ assert.isTrue(blockB.disposed);
525
+ assert.equal(this.blockA.getChildren().length, 0);
526
+ });
527
+ });
528
+ });
529
+
530
+ suite('Connection Tracking', function () {
531
+ setup(function () {
532
+ this.workspace = Blockly.inject('blocklyDiv');
533
+
534
+ this.getInputs = function () {
535
+ return this.workspace.connectionDBList[ConnectionType.INPUT_VALUE]
536
+ .connections;
537
+ };
538
+ this.getOutputs = function () {
539
+ return this.workspace.connectionDBList[ConnectionType.OUTPUT_VALUE]
540
+ .connections;
541
+ };
542
+ this.getNext = function () {
543
+ return this.workspace.connectionDBList[ConnectionType.NEXT_STATEMENT]
544
+ .connections;
545
+ };
546
+ this.getPrevious = function () {
547
+ return this.workspace.connectionDBList[
548
+ ConnectionType.PREVIOUS_STATEMENT
549
+ ].connections;
550
+ };
551
+
552
+ this.assertConnectionsEmpty = function () {
553
+ assert.isEmpty(this.getInputs());
554
+ assert.isEmpty(this.getOutputs());
555
+ assert.isEmpty(this.getNext());
556
+ assert.isEmpty(this.getPrevious());
557
+ };
558
+ });
559
+ teardown(function () {
560
+ workspaceTeardown.call(this, this.workspace);
561
+ });
562
+
563
+ suite('Deserialization', function () {
564
+ setup(function () {
565
+ this.deserializationHelper = function (text) {
566
+ const dom = Blockly.utils.xml.textToDom(text);
567
+ Blockly.Xml.appendDomToWorkspace(dom, this.workspace);
568
+ this.assertConnectionsEmpty();
569
+ this.clock.runAll();
570
+ };
571
+ });
572
+ test('Stack', function () {
573
+ this.deserializationHelper(
574
+ '<xml>' + ' <block type="stack_block"/>' + '</xml>',
575
+ );
576
+ assert.equal(this.getPrevious().length, 1);
577
+ assert.equal(this.getNext().length, 1);
578
+ });
579
+ test('Multi-Stack', function () {
580
+ this.deserializationHelper(
581
+ '<xml>' +
582
+ ' <block type="stack_block">' +
583
+ ' <next>' +
584
+ ' <block type="stack_block">' +
585
+ ' <next>' +
586
+ ' <block type="stack_block"/>' +
587
+ ' </next>' +
588
+ ' </block>' +
589
+ ' </next>' +
590
+ ' </block>' +
591
+ '</xml>',
592
+ );
593
+ assert.equal(this.getPrevious().length, 3);
594
+ assert.equal(this.getNext().length, 3);
595
+ });
596
+ test('Collapsed Stack', function () {
597
+ this.deserializationHelper(
598
+ '<xml>' + ' <block type="stack_block" collapsed="true"/>' + '</xml>',
599
+ );
600
+ assert.equal(this.getPrevious().length, 1);
601
+ assert.equal(this.getNext().length, 1);
602
+ });
603
+ test('Collapsed Multi-Stack', function () {
604
+ this.deserializationHelper(
605
+ '<xml>' +
606
+ ' <block type="stack_block" collapsed="true">' +
607
+ ' <next>' +
608
+ ' <block type="stack_block" collapsed="true">' +
609
+ ' <next>' +
610
+ ' <block type="stack_block" collapsed="true"/>' +
611
+ ' </next>' +
612
+ ' </block>' +
613
+ ' </next>' +
614
+ ' </block>' +
615
+ '</xml>',
616
+ );
617
+ assert.equal(this.getPrevious().length, 3);
618
+ assert.equal(this.getNext().length, 3);
619
+ });
620
+ test('Row', function () {
621
+ this.deserializationHelper(
622
+ '<xml>' + ' <block type="row_block"/>' + '</xml>',
623
+ );
624
+ assert.equal(this.getOutputs().length, 1);
625
+ assert.equal(this.getInputs().length, 1);
626
+ });
627
+ test('Multi-Row', function () {
628
+ this.deserializationHelper(
629
+ '<xml>' +
630
+ ' <block type="row_block">' +
631
+ ' <value name="INPUT">' +
632
+ ' <block type="row_block">' +
633
+ ' <value name="INPUT">' +
634
+ ' <block type="row_block"/>' +
635
+ ' </value>' +
636
+ ' </block>' +
637
+ ' </value>' +
638
+ ' </block>' +
639
+ '</xml>',
640
+ );
641
+ assert.equal(this.getOutputs().length, 3);
642
+ assert.equal(this.getInputs().length, 3);
643
+ });
644
+ test('Collapsed Row', function () {
645
+ this.deserializationHelper(
646
+ '<xml>' + ' <block type="row_block" collapsed="true"/>' + '</xml>',
647
+ );
648
+ assert.equal(this.getOutputs().length, 1);
649
+ assert.equal(this.getInputs().length, 0);
650
+ });
651
+ test('Collapsed Multi-Row', function () {
652
+ this.deserializationHelper(
653
+ '<xml>' +
654
+ ' <block type="row_block" collapsed="true">' +
655
+ ' <value name="INPUT">' +
656
+ ' <block type="row_block">' +
657
+ ' <value name="INPUT">' +
658
+ ' <block type="row_block"/>' +
659
+ ' </value>' +
660
+ ' </block>' +
661
+ ' </value>' +
662
+ ' </block>' +
663
+ '</xml>',
664
+ );
665
+ assert.equal(this.getOutputs().length, 1);
666
+ assert.equal(this.getInputs().length, 0);
667
+ });
668
+ test('Collapsed Multi-Row Middle', function () {
669
+ Blockly.Xml.appendDomToWorkspace(
670
+ Blockly.utils.xml.textToDom(
671
+ '<xml>' +
672
+ ' <block type="row_block">' +
673
+ ' <value name="INPUT">' +
674
+ ' <block type="row_block" collapsed="true">' +
675
+ ' <value name="INPUT">' +
676
+ ' <block type="row_block"/>' +
677
+ ' </value>' +
678
+ ' </block>' +
679
+ ' </value>' +
680
+ ' </block>' +
681
+ '</xml>',
682
+ ),
683
+ this.workspace,
684
+ );
685
+ this.assertConnectionsEmpty();
686
+ this.clock.runAll();
687
+ assert.equal(this.getOutputs().length, 2);
688
+ assert.equal(this.getInputs().length, 1);
689
+ });
690
+ test('Statement', function () {
691
+ this.deserializationHelper(
692
+ '<xml>' + ' <block type="statement_block"/>' + '</xml>',
693
+ );
694
+ assert.equal(this.getPrevious().length, 1);
695
+ assert.equal(this.getNext().length, 2);
696
+ });
697
+ test('Multi-Statement', function () {
698
+ this.deserializationHelper(
699
+ '<xml>' +
700
+ ' <block type="statement_block">' +
701
+ ' <statement name="STATEMENT">' +
702
+ ' <block type="statement_block">' +
703
+ ' <statement name="STATEMENT">' +
704
+ ' <block type="statement_block"/>' +
705
+ ' </statement>' +
706
+ ' </block>' +
707
+ ' </statement>' +
708
+ ' </block>' +
709
+ '</xml>',
710
+ );
711
+ assert.equal(this.getPrevious().length, 3);
712
+ assert.equal(this.getNext().length, 6);
713
+ });
714
+ test('Collapsed Statement', function () {
715
+ this.deserializationHelper(
716
+ '<xml>' +
717
+ ' <block type="statement_block" collapsed="true"/>' +
718
+ '</xml>',
719
+ );
720
+ assert.equal(this.getPrevious().length, 1);
721
+ assert.equal(this.getNext().length, 1);
722
+ });
723
+ test('Collapsed Multi-Statement', function () {
724
+ this.deserializationHelper(
725
+ '<xml>' +
726
+ ' <block type="statement_block" collapsed="true">' +
727
+ ' <statement name="STATEMENT">' +
728
+ ' <block type="statement_block">' +
729
+ ' <statement name="STATEMENT">' +
730
+ ' <block type="statement_block"/>' +
731
+ ' </statement>' +
732
+ ' </block>' +
733
+ ' </statement>' +
734
+ ' </block>' +
735
+ '</xml>',
736
+ );
737
+ assert.equal(this.getPrevious().length, 1);
738
+ assert.equal(this.getNext().length, 1);
739
+ });
740
+ test('Collapsed Multi-Statement Middle', function () {
741
+ this.deserializationHelper(
742
+ '<xml>' +
743
+ ' <block type="statement_block">' +
744
+ ' <statement name="STATEMENT">' +
745
+ ' <block type="statement_block" collapsed="true">' +
746
+ ' <statement name="STATEMENT">' +
747
+ ' <block type="statement_block"/>' +
748
+ ' </statement>' +
749
+ ' </block>' +
750
+ ' </statement>' +
751
+ ' </block>' +
752
+ '</xml>',
753
+ );
754
+ assert.equal(this.getPrevious().length, 2);
755
+ assert.equal(this.getNext().length, 3);
756
+ });
757
+ });
758
+ suite('Programmatic Block Creation', function () {
759
+ test('Stack', function () {
760
+ const block = this.workspace.newBlock('stack_block');
761
+ this.assertConnectionsEmpty();
762
+ block.initSvg();
763
+ block.render();
764
+
765
+ assert.equal(this.getPrevious().length, 1);
766
+ assert.equal(this.getNext().length, 1);
767
+ });
768
+ test('Row', function () {
769
+ const block = this.workspace.newBlock('row_block');
770
+ this.assertConnectionsEmpty();
771
+ block.initSvg();
772
+ block.render();
773
+
774
+ assert.equal(this.getOutputs().length, 1);
775
+ assert.equal(this.getInputs().length, 1);
776
+ });
777
+ test('Statement', function () {
778
+ const block = this.workspace.newBlock('statement_block');
779
+ this.assertConnectionsEmpty();
780
+ block.initSvg();
781
+ block.render();
782
+
783
+ assert.equal(this.getPrevious().length, 1);
784
+ assert.equal(this.getNext().length, 2);
785
+ });
786
+ });
787
+ suite('setCollapsed', function () {
788
+ test('Stack', function () {
789
+ const block = Blockly.Xml.domToBlock(
790
+ Blockly.utils.xml.textToDom('<block type="stack_block"/>'),
791
+ this.workspace,
792
+ );
793
+ this.clock.runAll();
794
+ assert.equal(this.getPrevious().length, 1);
795
+ assert.equal(this.getNext().length, 1);
796
+
797
+ block.setCollapsed(true);
798
+ assert.equal(this.getPrevious().length, 1);
799
+ assert.equal(this.getNext().length, 1);
800
+
801
+ block.setCollapsed(false);
802
+ assert.equal(this.getPrevious().length, 1);
803
+ assert.equal(this.getNext().length, 1);
804
+ });
805
+ test('Multi-Stack', function () {
806
+ const block = Blockly.Xml.domToBlock(
807
+ Blockly.utils.xml.textToDom(
808
+ '<block type="stack_block">' +
809
+ ' <next>' +
810
+ ' <block type="stack_block">' +
811
+ ' <next>' +
812
+ ' <block type="stack_block"/>' +
813
+ ' </next>' +
814
+ ' </block>' +
815
+ ' </next>' +
816
+ '</block>',
817
+ ),
818
+ this.workspace,
819
+ );
820
+ this.assertConnectionsEmpty();
821
+ this.clock.runAll();
822
+ assert.equal(this.getPrevious().length, 3);
823
+ assert.equal(this.getNext().length, 3);
824
+
825
+ block.setCollapsed(true);
826
+ assert.equal(this.getPrevious().length, 3);
827
+ assert.equal(this.getNext().length, 3);
828
+
829
+ block.setCollapsed(false);
830
+ assert.equal(this.getPrevious().length, 3);
831
+ assert.equal(this.getNext().length, 3);
832
+ });
833
+ test('Row', function () {
834
+ const block = Blockly.Xml.domToBlock(
835
+ Blockly.utils.xml.textToDom('<block type="row_block"/>'),
836
+ this.workspace,
837
+ );
838
+ this.clock.runAll();
839
+ assert.equal(this.getOutputs().length, 1);
840
+ assert.equal(this.getInputs().length, 1);
841
+
842
+ block.setCollapsed(true);
843
+ assert.equal(this.getOutputs().length, 1);
844
+ assert.equal(this.getInputs().length, 0);
845
+
846
+ block.setCollapsed(false);
847
+ assert.equal(this.getOutputs().length, 1);
848
+ assert.equal(this.getInputs().length, 1);
849
+ });
850
+ test('Multi-Row', function () {
851
+ const block = Blockly.Xml.domToBlock(
852
+ Blockly.utils.xml.textToDom(
853
+ '<block type="row_block">' +
854
+ ' <value name="INPUT">' +
855
+ ' <block type="row_block">' +
856
+ ' <value name="INPUT">' +
857
+ ' <block type="row_block"/>' +
858
+ ' </value>' +
859
+ ' </block>' +
860
+ ' </value>' +
861
+ '</block>',
862
+ ),
863
+ this.workspace,
864
+ );
865
+ this.clock.runAll();
866
+ assert.equal(this.getOutputs().length, 3);
867
+ assert.equal(this.getInputs().length, 3);
868
+
869
+ block.setCollapsed(true);
870
+ assert.equal(this.getOutputs().length, 1);
871
+ assert.equal(this.getInputs().length, 0);
872
+
873
+ block.setCollapsed(false);
874
+ assert.equal(this.getOutputs().length, 3);
875
+ assert.equal(this.getInputs().length, 3);
876
+ });
877
+ test('Multi-Row Middle', function () {
878
+ let block = Blockly.Xml.domToBlock(
879
+ Blockly.utils.xml.textToDom(
880
+ '<block type="row_block">' +
881
+ ' <value name="INPUT">' +
882
+ ' <block type="row_block">' +
883
+ ' <value name="INPUT">' +
884
+ ' <block type="row_block"/>' +
885
+ ' </value>' +
886
+ ' </block>' +
887
+ ' </value>' +
888
+ '</block>',
889
+ ),
890
+ this.workspace,
891
+ );
892
+ this.clock.runAll();
893
+ assert.equal(this.getOutputs().length, 3);
894
+ assert.equal(this.getInputs().length, 3);
895
+
896
+ block = block.getInputTargetBlock('INPUT');
897
+ block.setCollapsed(true);
898
+ assert.equal(this.getOutputs().length, 2);
899
+ assert.equal(this.getInputs().length, 1);
900
+
901
+ block.setCollapsed(false);
902
+ assert.equal(this.getOutputs().length, 3);
903
+ assert.equal(this.getInputs().length, 3);
904
+ });
905
+ test('Multi-Row Double Collapse', function () {
906
+ // Collapse middle -> Collapse top ->
907
+ // Uncollapse top -> Uncollapse middle
908
+ const block = Blockly.Xml.domToBlock(
909
+ Blockly.utils.xml.textToDom(
910
+ '<block type="row_block">' +
911
+ ' <value name="INPUT">' +
912
+ ' <block type="row_block">' +
913
+ ' <value name="INPUT">' +
914
+ ' <block type="row_block"/>' +
915
+ ' </value>' +
916
+ ' </block>' +
917
+ ' </value>' +
918
+ '</block>',
919
+ ),
920
+ this.workspace,
921
+ );
922
+ this.clock.runAll();
923
+ assert.equal(this.getOutputs().length, 3);
924
+ assert.equal(this.getInputs().length, 3);
925
+
926
+ const middleBlock = block.getInputTargetBlock('INPUT');
927
+ middleBlock.setCollapsed(true);
928
+ assert.equal(this.getOutputs().length, 2);
929
+ assert.equal(this.getInputs().length, 1);
930
+
931
+ block.setCollapsed(true);
932
+ assert.equal(this.getOutputs().length, 1);
933
+ assert.equal(this.getInputs().length, 0);
934
+
935
+ block.setCollapsed(false);
936
+ assert.equal(this.getOutputs().length, 2);
937
+ assert.equal(this.getInputs().length, 1);
938
+
939
+ middleBlock.setCollapsed(false);
940
+ assert.equal(this.getOutputs().length, 3);
941
+ assert.equal(this.getInputs().length, 3);
942
+ });
943
+ test('Statement', function () {
944
+ const block = Blockly.Xml.domToBlock(
945
+ Blockly.utils.xml.textToDom('<block type="statement_block"/>'),
946
+ this.workspace,
947
+ );
948
+ this.clock.runAll();
949
+ assert.equal(this.getPrevious().length, 1);
950
+ assert.equal(this.getNext().length, 2);
951
+
952
+ block.setCollapsed(true);
953
+ assert.equal(this.getPrevious().length, 1);
954
+ assert.equal(this.getNext().length, 1);
955
+
956
+ block.setCollapsed(false);
957
+ assert.equal(this.getPrevious().length, 1);
958
+ assert.equal(this.getNext().length, 2);
959
+ });
960
+ test('Multi-Statement', function () {
961
+ const block = Blockly.Xml.domToBlock(
962
+ Blockly.utils.xml.textToDom(
963
+ '<block type="statement_block">' +
964
+ ' <statement name="STATEMENT">' +
965
+ ' <block type="statement_block">' +
966
+ ' <statement name="STATEMENT">' +
967
+ ' <block type="statement_block"/>' +
968
+ ' </statement>' +
969
+ ' </block>' +
970
+ ' </statement>' +
971
+ '</block>',
972
+ ),
973
+ this.workspace,
974
+ );
975
+ this.assertConnectionsEmpty();
976
+ this.clock.runAll();
977
+ assert.equal(this.getPrevious().length, 3);
978
+ assert.equal(this.getNext().length, 6);
979
+
980
+ block.setCollapsed(true);
981
+ assert.equal(this.getPrevious().length, 1);
982
+ assert.equal(this.getNext().length, 1);
983
+
984
+ block.setCollapsed(false);
985
+ assert.equal(this.getPrevious().length, 3);
986
+ assert.equal(this.getNext().length, 6);
987
+ });
988
+ test('Multi-Statement Middle', function () {
989
+ let block = Blockly.Xml.domToBlock(
990
+ Blockly.utils.xml.textToDom(
991
+ '<block type="statement_block">' +
992
+ ' <statement name="STATEMENT">' +
993
+ ' <block type="statement_block">' +
994
+ ' <statement name="STATEMENT">' +
995
+ ' <block type="statement_block"/>' +
996
+ ' </statement>' +
997
+ ' </block>' +
998
+ ' </statement>' +
999
+ '</block>',
1000
+ ),
1001
+ this.workspace,
1002
+ );
1003
+ this.assertConnectionsEmpty();
1004
+ this.clock.runAll();
1005
+ assert.equal(this.getPrevious().length, 3);
1006
+ assert.equal(this.getNext().length, 6);
1007
+
1008
+ block = block.getInputTargetBlock('STATEMENT');
1009
+ block.setCollapsed(true);
1010
+ assert.equal(this.getPrevious().length, 2);
1011
+ assert.equal(this.getNext().length, 3);
1012
+
1013
+ block.setCollapsed(false);
1014
+ assert.equal(this.getPrevious().length, 3);
1015
+ assert.equal(this.getNext().length, 6);
1016
+ });
1017
+ test('Multi-Statement Double Collapse', function () {
1018
+ const block = Blockly.Xml.domToBlock(
1019
+ Blockly.utils.xml.textToDom(
1020
+ '<block type="statement_block">' +
1021
+ ' <statement name="STATEMENT">' +
1022
+ ' <block type="statement_block">' +
1023
+ ' <statement name="STATEMENT">' +
1024
+ ' <block type="statement_block"/>' +
1025
+ ' </statement>' +
1026
+ ' </block>' +
1027
+ ' </statement>' +
1028
+ '</block>',
1029
+ ),
1030
+ this.workspace,
1031
+ );
1032
+ this.assertConnectionsEmpty();
1033
+ this.clock.runAll();
1034
+ assert.equal(this.getPrevious().length, 3);
1035
+ assert.equal(this.getNext().length, 6);
1036
+
1037
+ const middleBlock = block.getInputTargetBlock('STATEMENT');
1038
+ middleBlock.setCollapsed(true);
1039
+ assert.equal(this.getPrevious().length, 2);
1040
+ assert.equal(this.getNext().length, 3);
1041
+
1042
+ block.setCollapsed(true);
1043
+ assert.equal(this.getPrevious().length, 1);
1044
+ assert.equal(this.getNext().length, 1);
1045
+
1046
+ block.setCollapsed(false);
1047
+ assert.equal(this.getPrevious().length, 2);
1048
+ assert.equal(this.getNext().length, 3);
1049
+
1050
+ middleBlock.setCollapsed(false);
1051
+ assert.equal(this.getPrevious().length, 3);
1052
+ assert.equal(this.getNext().length, 6);
1053
+ });
1054
+ });
1055
+ suite('Setting Parent Block', function () {
1056
+ setup(function () {
1057
+ this.printBlock = Blockly.Xml.domToBlock(
1058
+ Blockly.utils.xml.textToDom(
1059
+ '<block type="text_print">' +
1060
+ ' <value name="TEXT">' +
1061
+ ' <block type="text_join">' +
1062
+ ' <mutation items="2"></mutation>' +
1063
+ ' <value name="ADD0">' +
1064
+ ' <block type="text">' +
1065
+ ' </block>' +
1066
+ ' </value>' +
1067
+ ' </block>' +
1068
+ ' </value>' +
1069
+ '</block>',
1070
+ ),
1071
+ this.workspace,
1072
+ );
1073
+ this.textJoinBlock = this.printBlock.getInputTargetBlock('TEXT');
1074
+ this.textBlock = this.textJoinBlock.getInputTargetBlock('ADD0');
1075
+ });
1076
+
1077
+ function assertBlockIsOnlyChild(parent, child, inputName) {
1078
+ assert.equal(parent.getChildren().length, 1);
1079
+ assert.equal(parent.getInputTargetBlock(inputName), child);
1080
+ assert.equal(child.getParent(), parent);
1081
+ }
1082
+ function assertNonParentAndOrphan(nonParent, orphan, inputName) {
1083
+ assert.equal(nonParent.getChildren().length, 0);
1084
+ assert.isNull(nonParent.getInputTargetBlock('TEXT'));
1085
+ assert.isNull(orphan.getParent());
1086
+ }
1087
+ function assertOriginalSetup() {
1088
+ assertBlockIsOnlyChild(this.printBlock, this.textJoinBlock, 'TEXT');
1089
+ assertBlockIsOnlyChild(this.textJoinBlock, this.textBlock, 'ADD0');
1090
+ }
1091
+
1092
+ test('Setting to connected parent', function () {
1093
+ assert.doesNotThrow(
1094
+ this.textJoinBlock.setParent.bind(
1095
+ this.textJoinBlock,
1096
+ this.printBlock,
1097
+ ),
1098
+ );
1099
+ assertOriginalSetup.call(this);
1100
+ });
1101
+ test('Setting to new parent after connecting to it', function () {
1102
+ this.textJoinBlock.outputConnection.disconnect();
1103
+ this.textBlock.outputConnection.connect(
1104
+ this.printBlock.getInput('TEXT').connection,
1105
+ );
1106
+ assert.doesNotThrow(
1107
+ this.textBlock.setParent.bind(this.textBlock, this.printBlock),
1108
+ );
1109
+ assertBlockIsOnlyChild(this.printBlock, this.textBlock, 'TEXT');
1110
+ });
1111
+ test('Setting to new parent while connected to other block', function () {
1112
+ // Setting to grandparent with no available input connection.
1113
+ assert.throws(
1114
+ this.textBlock.setParent.bind(this.textBlock, this.printBlock),
1115
+ );
1116
+ this.textJoinBlock.outputConnection.disconnect();
1117
+ // Setting to block with available input connection.
1118
+ assert.throws(
1119
+ this.textBlock.setParent.bind(this.textBlock, this.printBlock),
1120
+ );
1121
+ assertNonParentAndOrphan(this.printBlock, this.textJoinBlock, 'TEXT');
1122
+ assertBlockIsOnlyChild(this.textJoinBlock, this.textBlock, 'ADD0');
1123
+ });
1124
+ test('Setting to same parent after disconnecting from it', function () {
1125
+ this.textJoinBlock.outputConnection.disconnect();
1126
+ assert.throws(
1127
+ this.textJoinBlock.setParent.bind(
1128
+ this.textJoinBlock,
1129
+ this.printBlock,
1130
+ ),
1131
+ );
1132
+ assertNonParentAndOrphan(this.printBlock, this.textJoinBlock, 'TEXT');
1133
+ });
1134
+ test('Setting to new parent when orphan', function () {
1135
+ this.textBlock.outputConnection.disconnect();
1136
+ // When new parent has no available input connection.
1137
+ assert.throws(
1138
+ this.textBlock.setParent.bind(this.textBlock, this.printBlock),
1139
+ );
1140
+ this.textJoinBlock.outputConnection.disconnect();
1141
+ // When new parent has available input connection.
1142
+ assert.throws(
1143
+ this.textBlock.setParent.bind(this.textBlock, this.printBlock),
1144
+ );
1145
+
1146
+ assertNonParentAndOrphan(this.printBlock, this.textJoinBlock, 'TEXT');
1147
+ assertNonParentAndOrphan(this.printBlock, this.textBlock, 'TEXT');
1148
+ assertNonParentAndOrphan(this.textJoinBlock, this.textBlock, 'ADD0');
1149
+ });
1150
+ test('Setting parent to null after disconnecting', function () {
1151
+ this.textBlock.outputConnection.disconnect();
1152
+ assert.doesNotThrow(
1153
+ this.textBlock.setParent.bind(this.textBlock, null),
1154
+ );
1155
+ assertNonParentAndOrphan(this.textJoinBlock, this.textBlock, 'ADD0');
1156
+ });
1157
+ test('Setting parent to null without disconnecting', function () {
1158
+ assert.throws(this.textBlock.setParent.bind(this.textBlock, null));
1159
+ assertOriginalSetup.call(this);
1160
+ });
1161
+ });
1162
+ suite('Remove Connections Programmatically', function () {
1163
+ test('Output', function () {
1164
+ const block = createRenderedBlock(this.workspace, 'row_block');
1165
+
1166
+ block.setOutput(false);
1167
+
1168
+ assert.equal(this.getOutputs().length, 0);
1169
+ assert.equal(this.getInputs().length, 1);
1170
+ });
1171
+ test('Value', function () {
1172
+ const block = createRenderedBlock(this.workspace, 'row_block');
1173
+
1174
+ block.removeInput('INPUT');
1175
+
1176
+ assert.equal(this.getOutputs().length, 1);
1177
+ assert.equal(this.getInputs().length, 0);
1178
+ });
1179
+ test('Previous', function () {
1180
+ const block = createRenderedBlock(this.workspace, 'stack_block');
1181
+
1182
+ block.setPreviousStatement(false);
1183
+
1184
+ assert.equal(this.getPrevious().length, 0);
1185
+ assert.equal(this.getNext().length, 1);
1186
+ });
1187
+ test('Next', function () {
1188
+ const block = createRenderedBlock(this.workspace, 'stack_block');
1189
+
1190
+ block.setNextStatement(false);
1191
+
1192
+ assert.equal(this.getPrevious().length, 1);
1193
+ assert.equal(this.getNext().length, 0);
1194
+ });
1195
+ test('Statement', function () {
1196
+ const block = createRenderedBlock(this.workspace, 'statement_block');
1197
+
1198
+ block.removeInput('STATEMENT');
1199
+
1200
+ assert.equal(this.getPrevious().length, 1);
1201
+ assert.equal(this.getNext().length, 1);
1202
+ });
1203
+ });
1204
+ suite('Add Connections Programmatically', function () {
1205
+ test('Output', async function () {
1206
+ const block = createRenderedBlock(this.workspace, 'empty_block');
1207
+
1208
+ block.setOutput(true);
1209
+ this.clock.runAll();
1210
+
1211
+ this.clock.runAll();
1212
+ assert.equal(this.getOutputs().length, 1);
1213
+ });
1214
+ test('Value', function () {
1215
+ const block = createRenderedBlock(this.workspace, 'empty_block');
1216
+
1217
+ block.appendValueInput('INPUT');
1218
+
1219
+ this.clock.runAll();
1220
+ assert.equal(this.getInputs().length, 1);
1221
+ });
1222
+ test('Previous', function () {
1223
+ const block = createRenderedBlock(this.workspace, 'empty_block');
1224
+
1225
+ block.setPreviousStatement(true);
1226
+ this.clock.runAll();
1227
+
1228
+ this.clock.runAll();
1229
+ assert.equal(this.getPrevious().length, 1);
1230
+ });
1231
+ test('Next', function () {
1232
+ const block = createRenderedBlock(this.workspace, 'empty_block');
1233
+
1234
+ block.setNextStatement(true);
1235
+ this.clock.runAll();
1236
+
1237
+ this.clock.runAll();
1238
+ assert.equal(this.getNext().length, 1);
1239
+ });
1240
+ test('Statement', function () {
1241
+ const block = createRenderedBlock(this.workspace, 'empty_block');
1242
+
1243
+ block.appendStatementInput('STATEMENT');
1244
+
1245
+ this.clock.runAll();
1246
+ assert.equal(this.getNext().length, 1);
1247
+ });
1248
+ });
1249
+ });
1250
+
1251
+ suite('Comments', function () {
1252
+ suite('Set/Get Text', function () {
1253
+ function assertCommentEvent(eventSpy, oldValue, newValue) {
1254
+ const calls = eventSpy.getCalls();
1255
+ const event = calls[calls.length - 1].args[0];
1256
+ assert.equal(event.type, eventUtils.BLOCK_CHANGE);
1257
+ assert.equal(
1258
+ event.element,
1259
+ 'comment',
1260
+ 'Expected the element to be a comment',
1261
+ );
1262
+ assert.equal(
1263
+ event.oldValue,
1264
+ oldValue,
1265
+ 'Expected the old values to match',
1266
+ );
1267
+ assert.equal(
1268
+ event.newValue,
1269
+ newValue,
1270
+ 'Expected the new values to match',
1271
+ );
1272
+ }
1273
+ function assertNoCommentEvent(eventSpy) {
1274
+ const calls = eventSpy.getCalls();
1275
+ const event = calls[calls.length - 1].args[0];
1276
+ assert.notEqual(event.type, eventUtils.BLOCK_CHANGE);
1277
+ }
1278
+ setup(function () {
1279
+ this.eventsFireSpy = sinon.spy(eventUtils.TEST_ONLY, 'fireInternal');
1280
+ });
1281
+ teardown(function () {
1282
+ this.eventsFireSpy.restore();
1283
+ });
1284
+ suite('Headless', function () {
1285
+ setup(function () {
1286
+ this.block = Blockly.Xml.domToBlock(
1287
+ Blockly.utils.xml.textToDom('<block type="empty_block"/>'),
1288
+ this.workspace,
1289
+ );
1290
+ });
1291
+ test('Text', function () {
1292
+ this.block.setCommentText('test text');
1293
+ assert.equal(this.block.getCommentText(), 'test text');
1294
+ assertCommentEvent(this.eventsFireSpy, null, 'test text');
1295
+ });
1296
+ test('Text Empty', function () {
1297
+ this.block.setCommentText('');
1298
+ assert.equal(this.block.getCommentText(), '');
1299
+ assertCommentEvent(this.eventsFireSpy, null, '');
1300
+ });
1301
+ test('Text Null', function () {
1302
+ this.block.setCommentText(null);
1303
+ assert.isNull(this.block.getCommentText());
1304
+ assertNoCommentEvent(this.eventsFireSpy);
1305
+ });
1306
+ test('Text -> Null', function () {
1307
+ this.block.setCommentText('first text');
1308
+
1309
+ this.block.setCommentText(null);
1310
+ assert.isNull(this.block.getCommentText());
1311
+ assertCommentEvent(this.eventsFireSpy, 'first text', null);
1312
+ });
1313
+ });
1314
+ suite('Rendered', function () {
1315
+ setup(function () {
1316
+ this.workspace = Blockly.inject('blocklyDiv', {
1317
+ comments: true,
1318
+ scrollbars: true,
1319
+ });
1320
+ this.block = Blockly.Xml.domToBlock(
1321
+ Blockly.utils.xml.textToDom('<block type="empty_block"/>'),
1322
+ this.workspace,
1323
+ );
1324
+ });
1325
+ teardown(function () {
1326
+ workspaceTeardown.call(this, this.workspace);
1327
+ });
1328
+ test('Text', function () {
1329
+ this.block.setCommentText('test text');
1330
+ assert.equal(this.block.getCommentText(), 'test text');
1331
+ assertCommentEvent(this.eventsFireSpy, null, 'test text');
1332
+ });
1333
+ test('Text Empty', function () {
1334
+ this.block.setCommentText('');
1335
+ assert.equal(this.block.getCommentText(), '');
1336
+ assertCommentEvent(this.eventsFireSpy, null, '');
1337
+ });
1338
+ test('Text Null', function () {
1339
+ this.block.setCommentText(null);
1340
+ assert.isNull(this.block.getCommentText());
1341
+ assertNoCommentEvent(this.eventsFireSpy);
1342
+ });
1343
+ test('Text -> Null', function () {
1344
+ this.block.setCommentText('first text');
1345
+
1346
+ this.block.setCommentText(null);
1347
+ assert.isNull(this.block.getCommentText());
1348
+ assertCommentEvent(this.eventsFireSpy, 'first text', null);
1349
+ });
1350
+ test('Set While Visible - Editable', function () {
1351
+ this.block.setCommentText('test1');
1352
+ const icon = this.block.getIcon(Blockly.icons.CommentIcon.TYPE);
1353
+ icon.setBubbleVisible(true);
1354
+
1355
+ this.block.setCommentText('test2');
1356
+ assert.equal(this.block.getCommentText(), 'test2');
1357
+ assertCommentEvent(this.eventsFireSpy, 'test1', 'test2');
1358
+ });
1359
+ test('Set While Visible - NonEditable', function () {
1360
+ this.block.setCommentText('test1');
1361
+ // Restored up by call to sinon.restore() in sharedTestTeardown()
1362
+ sinon.stub(this.block, 'isEditable').returns(false);
1363
+ const icon = this.block.getIcon(Blockly.icons.CommentIcon.TYPE);
1364
+ icon.setBubbleVisible(true);
1365
+
1366
+ this.block.setCommentText('test2');
1367
+ assert.equal(this.block.getCommentText(), 'test2');
1368
+ assertCommentEvent(this.eventsFireSpy, 'test1', 'test2');
1369
+ });
1370
+ });
1371
+ });
1372
+
1373
+ suite('Constructing registered comment classes', function () {
1374
+ class MockComment extends MockIcon {
1375
+ getType() {
1376
+ return Blockly.icons.IconType.COMMENT;
1377
+ }
1378
+
1379
+ setText() {}
1380
+
1381
+ getText() {
1382
+ return '';
1383
+ }
1384
+
1385
+ setBubbleSize() {}
1386
+
1387
+ getBubbleSize() {
1388
+ return Blockly.utils.Size(0, 0);
1389
+ }
1390
+
1391
+ setBubbleLocation() {}
1392
+
1393
+ getBubbleLocation() {}
1394
+
1395
+ bubbleIsVisible() {
1396
+ return true;
1397
+ }
1398
+
1399
+ setBubbleVisible() {}
1400
+
1401
+ saveState() {
1402
+ return {};
1403
+ }
1404
+
1405
+ loadState() {}
1406
+ }
1407
+
1408
+ setup(function () {
1409
+ this.workspace = Blockly.inject('blocklyDiv', {});
1410
+
1411
+ this.block = this.workspace.newBlock('stack_block');
1412
+ this.block.initSvg();
1413
+ this.block.render();
1414
+ });
1415
+
1416
+ teardown(function () {
1417
+ workspaceTeardown.call(this, this.workspace);
1418
+
1419
+ Blockly.icons.registry.unregister(
1420
+ Blockly.icons.IconType.COMMENT.toString(),
1421
+ );
1422
+ Blockly.icons.registry.register(
1423
+ Blockly.icons.IconType.COMMENT,
1424
+ Blockly.icons.CommentIcon,
1425
+ );
1426
+ });
1427
+
1428
+ test('setCommentText constructs the registered comment icon', function () {
1429
+ Blockly.icons.registry.unregister(
1430
+ Blockly.icons.IconType.COMMENT.toString(),
1431
+ );
1432
+ Blockly.icons.registry.register(
1433
+ Blockly.icons.IconType.COMMENT,
1434
+ MockComment,
1435
+ );
1436
+
1437
+ this.block.setCommentText('test text');
1438
+
1439
+ assert.instanceOf(
1440
+ this.block.getIcon(Blockly.icons.IconType.COMMENT),
1441
+ MockComment,
1442
+ );
1443
+ });
1444
+
1445
+ test('setCommentText throws if no icon is registered', function () {
1446
+ Blockly.icons.registry.unregister(
1447
+ Blockly.icons.IconType.COMMENT.toString(),
1448
+ );
1449
+
1450
+ assert.throws(() => {
1451
+ this.block.setCommentText('test text');
1452
+ }, 'No comment icon class is registered, so a comment cannot be set');
1453
+ });
1454
+
1455
+ test('setCommentText throws if the icon is not an ICommentIcon', function () {
1456
+ Blockly.icons.registry.unregister(
1457
+ Blockly.icons.IconType.COMMENT.toString(),
1458
+ );
1459
+ Blockly.icons.registry.register(
1460
+ Blockly.icons.IconType.COMMENT,
1461
+ MockIcon,
1462
+ );
1463
+
1464
+ assert.throws(() => {
1465
+ this.block.setCommentText('test text');
1466
+ }, 'The class registered as a comment icon does not conform to the ICommentIcon interface');
1467
+ });
1468
+ });
1469
+ });
1470
+
1471
+ suite('Getting/Setting Field (Values)', function () {
1472
+ setup(function () {
1473
+ this.workspace = Blockly.inject('blocklyDiv');
1474
+ this.block = Blockly.Xml.domToBlock(
1475
+ Blockly.utils.xml.textToDom(
1476
+ '<block type="text"><field name = "TEXT">test</field></block>',
1477
+ ),
1478
+ this.workspace,
1479
+ );
1480
+ });
1481
+
1482
+ teardown(function () {
1483
+ workspaceTeardown.call(this, this.workspace);
1484
+ });
1485
+
1486
+ test('Getting Field', function () {
1487
+ assert.instanceOf(this.block.getField('TEXT'), Blockly.Field);
1488
+ });
1489
+ test('Getting Field without Name', function () {
1490
+ assert.throws(this.block.getField.bind(this.block), TypeError);
1491
+ });
1492
+ test('Getting Value of Field without Name', function () {
1493
+ assert.throws(this.block.getFieldValue.bind(this.block), TypeError);
1494
+ });
1495
+ test('Getting Field with Wrong Type', function () {
1496
+ const testFunction = function () {
1497
+ return 'TEXT';
1498
+ };
1499
+ const inputs = [
1500
+ 1,
1501
+ null,
1502
+ testFunction,
1503
+ {toString: testFunction},
1504
+ ['TEXT'],
1505
+ ];
1506
+ for (let i = 0; i < inputs.length; i++) {
1507
+ assert.throws(
1508
+ this.block.getField.bind(this.block, inputs[i]),
1509
+ TypeError,
1510
+ );
1511
+ }
1512
+ });
1513
+ test('Getting Value of Field with Wrong Type', function () {
1514
+ const testFunction = function () {
1515
+ return 'TEXT';
1516
+ };
1517
+ const inputs = [
1518
+ 1,
1519
+ null,
1520
+ testFunction,
1521
+ {toString: testFunction},
1522
+ ['TEXT'],
1523
+ ];
1524
+ for (let i = 0; i < inputs.length; i++) {
1525
+ assert.throws(
1526
+ this.block.getFieldValue.bind(this.block, inputs[i]),
1527
+ TypeError,
1528
+ );
1529
+ }
1530
+ });
1531
+ test('Getting/Setting Field Value', function () {
1532
+ assert.equal(this.block.getFieldValue('TEXT'), 'test');
1533
+ this.block.setFieldValue('abc', 'TEXT');
1534
+ assert.equal(this.block.getFieldValue('TEXT'), 'abc');
1535
+ });
1536
+ test('Setting Field without Name', function () {
1537
+ assert.throws(this.block.setFieldValue.bind(this.block, 'test'));
1538
+ });
1539
+ test('Setting Field with Wrong Type', function () {
1540
+ const testFunction = function () {
1541
+ return 'TEXT';
1542
+ };
1543
+ const inputs = [
1544
+ 1,
1545
+ null,
1546
+ testFunction,
1547
+ {toString: testFunction},
1548
+ ['TEXT'],
1549
+ ];
1550
+ for (let i = 0; i < inputs.length; i++) {
1551
+ assert.throws(
1552
+ this.block.setFieldValue.bind(this.block, 'test', inputs[i]),
1553
+ TypeError,
1554
+ );
1555
+ }
1556
+ });
1557
+ });
1558
+
1559
+ suite('Icon management', function () {
1560
+ class MockIconA extends MockIcon {
1561
+ getType() {
1562
+ return new Blockly.icons.IconType('A');
1563
+ }
1564
+
1565
+ getWeight() {
1566
+ return 1;
1567
+ }
1568
+ }
1569
+
1570
+ class MockIconB extends MockIcon {
1571
+ getType() {
1572
+ return new Blockly.icons.IconType('B');
1573
+ }
1574
+
1575
+ getWeight() {
1576
+ return 2;
1577
+ }
1578
+ }
1579
+
1580
+ suite('Adding icons', function () {
1581
+ setup(function () {
1582
+ this.workspace = Blockly.inject('blocklyDiv', {});
1583
+
1584
+ this.block = this.workspace.newBlock('stack_block');
1585
+ this.block.initSvg();
1586
+ this.block.render();
1587
+ this.renderSpy = sinon.spy(this.block, 'queueRender');
1588
+ });
1589
+
1590
+ teardown(function () {
1591
+ this.renderSpy.restore();
1592
+ workspaceTeardown.call(this, this.workspace);
1593
+ });
1594
+
1595
+ test('icons get added to the block', function () {
1596
+ this.block.addIcon(new MockIconA());
1597
+ assert.isTrue(this.block.hasIcon('A'), 'Expected the icon to be added');
1598
+ });
1599
+
1600
+ test('adding two icons of the same type throws', function () {
1601
+ this.block.addIcon(new MockIconA());
1602
+ assert.throws(
1603
+ () => {
1604
+ this.block.addIcon(new MockIconA());
1605
+ },
1606
+ Blockly.icons.DuplicateIconType,
1607
+ '',
1608
+ 'Expected adding an icon of the same type to throw',
1609
+ );
1610
+ });
1611
+
1612
+ test('adding an icon triggers a render', function () {
1613
+ this.renderSpy.resetHistory();
1614
+ this.block.addIcon(new MockIconA());
1615
+ assert.isTrue(
1616
+ this.renderSpy.calledOnce,
1617
+ 'Expected adding an icon to trigger a render',
1618
+ );
1619
+ });
1620
+ });
1621
+
1622
+ suite('Removing icons', function () {
1623
+ setup(function () {
1624
+ this.workspace = Blockly.inject('blocklyDiv');
1625
+
1626
+ this.block = this.workspace.newBlock('stack_block');
1627
+ this.block.initSvg();
1628
+ this.block.render();
1629
+ this.renderSpy = sinon.spy(this.block, 'queueRender');
1630
+ });
1631
+
1632
+ teardown(function () {
1633
+ this.renderSpy.restore();
1634
+ workspaceTeardown.call(this, this.workspace);
1635
+ });
1636
+
1637
+ test('icons get removed from the block', function () {
1638
+ this.block.addIcon(new MockIconA());
1639
+ assert.isTrue(
1640
+ this.block.removeIcon(new Blockly.icons.IconType('A')),
1641
+ 'Expected removeIcon to return true',
1642
+ );
1643
+ assert.isFalse(
1644
+ this.block.hasIcon('A'),
1645
+ 'Expected the icon to be removed',
1646
+ );
1647
+ });
1648
+
1649
+ test('removing an icon that does not exist returns false', function () {
1650
+ assert.isFalse(
1651
+ this.block.removeIcon(new Blockly.icons.IconType('B')),
1652
+ 'Expected removeIcon to return false',
1653
+ );
1654
+ });
1655
+
1656
+ test('removing an icon triggers a render', function () {
1657
+ this.block.addIcon(new MockIconA());
1658
+ this.renderSpy.resetHistory();
1659
+ this.block.removeIcon(new Blockly.icons.IconType('A'));
1660
+ assert.isTrue(
1661
+ this.renderSpy.calledOnce,
1662
+ 'Expected removing an icon to trigger a render',
1663
+ );
1664
+ });
1665
+ });
1666
+
1667
+ suite('Getting icons', function () {
1668
+ setup(function () {
1669
+ this.block = this.workspace.newBlock('stack_block');
1670
+ });
1671
+
1672
+ test('all icons are returned from getIcons, in order of weight', function () {
1673
+ const iconA = new MockIconA();
1674
+ const iconB = new MockIconB();
1675
+ this.block.addIcon(iconB);
1676
+ this.block.addIcon(iconA);
1677
+ assert.sameOrderedMembers(
1678
+ this.block.getIcons(),
1679
+ [iconA, iconB],
1680
+ 'Expected getIcon to return both icons in order of weight',
1681
+ );
1682
+ });
1683
+
1684
+ test('if there are no icons, getIcons returns an empty array', function () {
1685
+ assert.isEmpty(
1686
+ this.block.getIcons(),
1687
+ 'Expected getIcons to return an empty array ' +
1688
+ 'for a block with no icons',
1689
+ );
1690
+ });
1691
+
1692
+ test('if there are no icons, getIcons returns an empty array', function () {
1693
+ assert.isEmpty(
1694
+ this.block.getIcons(),
1695
+ 'Expected getIcons to return an empty array ' +
1696
+ 'for a block with no icons',
1697
+ );
1698
+ });
1699
+
1700
+ test('specific icons are returned from getIcon', function () {
1701
+ const iconA = new MockIconA();
1702
+ const iconB = new MockIconB();
1703
+ this.block.addIcon(iconA);
1704
+ this.block.addIcon(iconB);
1705
+ assert.equal(
1706
+ this.block.getIcon('B'),
1707
+ iconB,
1708
+ 'Expected getIcon to return the icon with the given type',
1709
+ );
1710
+ });
1711
+
1712
+ test('if there is no matching icon, getIcon returns undefined', function () {
1713
+ this.block.addIcon(new MockIconA());
1714
+ assert.isUndefined(
1715
+ this.block.getIcon('B'),
1716
+ 'Expected getIcon to return null if there is no ' +
1717
+ 'icon with a matching type',
1718
+ );
1719
+ });
1720
+ });
1721
+
1722
+ suite('Warning icons', function () {
1723
+ setup(function () {
1724
+ this.workspace = Blockly.inject('blocklyDiv');
1725
+
1726
+ this.block = this.workspace.newBlock('stack_block');
1727
+ this.block.initSvg();
1728
+ this.block.render();
1729
+ });
1730
+
1731
+ teardown(function () {
1732
+ workspaceTeardown.call(this, this.workspace);
1733
+ });
1734
+
1735
+ test('Block with no warning text does not have warning icon', function () {
1736
+ const icon = this.block.getIcon(Blockly.icons.WarningIcon.TYPE);
1737
+
1738
+ assert.isUndefined(
1739
+ icon,
1740
+ 'Block with no warning should not have warning icon',
1741
+ );
1742
+ });
1743
+
1744
+ test('Set warning text creates new icon if none existed', function () {
1745
+ const text = 'Warning Text';
1746
+
1747
+ this.block.setWarningText(text);
1748
+
1749
+ const icon = this.block.getIcon(Blockly.icons.WarningIcon.TYPE);
1750
+ assert.equal(
1751
+ icon.getText(),
1752
+ text,
1753
+ 'Expected warning icon text to be set',
1754
+ );
1755
+ });
1756
+
1757
+ test('Set warning text adds text to existing icon if needed', function () {
1758
+ const text1 = 'Warning Text 1';
1759
+ const text2 = 'Warning Text 2';
1760
+
1761
+ this.block.setWarningText(text1, '1');
1762
+ this.block.setWarningText(text2, '2');
1763
+
1764
+ const icon = this.block.getIcon(Blockly.icons.WarningIcon.TYPE);
1765
+ assert.equal(icon.getText(), `${text1}\n${text2}`);
1766
+ });
1767
+
1768
+ test('Clearing all warning text deletes the warning icon', function () {
1769
+ const text = 'Warning Text';
1770
+ this.block.setWarningText(text);
1771
+
1772
+ this.block.setWarningText(null);
1773
+
1774
+ const icon = this.block.getIcon(Blockly.icons.WarningIcon.TYPE);
1775
+ assert.isUndefined(
1776
+ icon,
1777
+ 'Expected warning icon to be undefined after deleting all warning text',
1778
+ );
1779
+ });
1780
+
1781
+ test('Clearing specific warning does not delete the icon if other warnings present', function () {
1782
+ const text1 = 'Warning Text 1';
1783
+ const text2 = 'Warning Text 2';
1784
+
1785
+ this.block.setWarningText(text1, '1');
1786
+ this.block.setWarningText(text2, '2');
1787
+ this.block.setWarningText(null, '1');
1788
+
1789
+ const icon = this.block.getIcon(Blockly.icons.WarningIcon.TYPE);
1790
+ assert.equal(
1791
+ icon.getText(),
1792
+ text2,
1793
+ 'Expected first warning text to be deleted',
1794
+ );
1795
+ });
1796
+
1797
+ test('Clearing specific warning removes icon if it was only warning present', function () {
1798
+ const text1 = 'Warning Text 1';
1799
+ const text2 = 'Warning Text 2';
1800
+
1801
+ this.block.setWarningText(text1, '1');
1802
+ this.block.setWarningText(text2, '2');
1803
+ this.block.setWarningText(null, '1');
1804
+ this.block.setWarningText(null, '2');
1805
+
1806
+ const icon = this.block.getIcon(Blockly.icons.WarningIcon.TYPE);
1807
+ assert.isUndefined(
1808
+ icon,
1809
+ 'Expected warning icon to be deleted after all warning text is cleared',
1810
+ );
1811
+ });
1812
+ });
1813
+
1814
+ suite('Bubbles and collapsing', function () {
1815
+ setup(function () {
1816
+ this.workspace = Blockly.inject('blocklyDiv');
1817
+ });
1818
+
1819
+ teardown(function () {
1820
+ workspaceTeardown.call(this, this.workspace);
1821
+ });
1822
+
1823
+ test("Collapsing the block closes its contained children's bubbles", function () {
1824
+ const parentBlock = Blockly.serialization.blocks.append(
1825
+ {
1826
+ 'type': 'statement_block',
1827
+ 'inputs': {
1828
+ 'STATEMENT': {
1829
+ 'block': {
1830
+ 'type': 'statement_block',
1831
+ },
1832
+ },
1833
+ },
1834
+ },
1835
+ this.workspace,
1836
+ );
1837
+ const childBlock = parentBlock.getInputTargetBlock('STATEMENT');
1838
+ const icon = new MockBubbleIcon();
1839
+ childBlock.addIcon(icon);
1840
+ icon.setBubbleVisible(true);
1841
+
1842
+ parentBlock.setCollapsed(true);
1843
+
1844
+ assert.isFalse(
1845
+ icon.bubbleIsVisible(),
1846
+ "Expected collapsing the parent block to hide the child block's " +
1847
+ "icon's bubble",
1848
+ );
1849
+ });
1850
+
1851
+ test("Collapsing a block does not close its following childrens' bubbles", function () {
1852
+ const parentBlock = Blockly.serialization.blocks.append(
1853
+ {
1854
+ 'type': 'statement_block',
1855
+ 'next': {
1856
+ 'block': {
1857
+ 'type': 'statement_block',
1858
+ },
1859
+ },
1860
+ },
1861
+ this.workspace,
1862
+ );
1863
+ const nextBlock = parentBlock.getNextBlock();
1864
+ const icon = new MockBubbleIcon();
1865
+ nextBlock.addIcon(icon);
1866
+ icon.setBubbleVisible(true);
1867
+
1868
+ parentBlock.setCollapsed(true);
1869
+
1870
+ assert.isTrue(
1871
+ icon.bubbleIsVisible(),
1872
+ 'Expected collapsing the parent block to not hide the next ' +
1873
+ "block's bubble",
1874
+ );
1875
+ });
1876
+ });
1877
+ });
1878
+
1879
+ suite('Collapsing and Expanding', function () {
1880
+ function assertCollapsed(block, opt_string) {
1881
+ assert.isTrue(block.isCollapsed());
1882
+ for (let i = 0, input; (input = block.inputList[i]); i++) {
1883
+ if (input.name == Blockly.Block.COLLAPSED_INPUT_NAME) {
1884
+ continue;
1885
+ }
1886
+ assert.isFalse(input.isVisible());
1887
+ for (let j = 0, field; (field = input.fieldRow[j]); j++) {
1888
+ assert.isFalse(field.isVisible());
1889
+ }
1890
+ }
1891
+ const icons = block.getIcons();
1892
+ for (let i = 0, icon; (icon = icons[i]); i++) {
1893
+ assert.isFalse(icon.bubbleIsVisible());
1894
+ }
1895
+
1896
+ const input = block.getInput(Blockly.Block.COLLAPSED_INPUT_NAME);
1897
+ assert.isNotNull(input);
1898
+ assert.isTrue(input.isVisible());
1899
+ const field = block.getField(Blockly.Block.COLLAPSED_FIELD_NAME);
1900
+ assert.isNotNull(field);
1901
+ assert.isTrue(field.isVisible());
1902
+
1903
+ if (opt_string) {
1904
+ assert.equal(field.getText(), opt_string);
1905
+ }
1906
+ }
1907
+ function assertNotCollapsed(block) {
1908
+ assert.isFalse(block.isCollapsed());
1909
+ for (let i = 0, input; (input = block.inputList[i]); i++) {
1910
+ assert.isTrue(input.isVisible());
1911
+ for (let j = 0, field; (field = input.fieldRow[j]); j++) {
1912
+ assert.isTrue(field.isVisible());
1913
+ }
1914
+ }
1915
+
1916
+ const input = block.getInput(Blockly.Block.COLLAPSED_INPUT_NAME);
1917
+ assert.isNull(input);
1918
+ const field = block.getField(Blockly.Block.COLLAPSED_FIELD_NAME);
1919
+ assert.isNull(field);
1920
+ }
1921
+ function isBlockHidden(block) {
1922
+ let node = block.getSvgRoot();
1923
+ do {
1924
+ const visible = node.style.display != 'none';
1925
+ if (!visible) {
1926
+ return true;
1927
+ }
1928
+ node = node.parentNode;
1929
+ } while (node != document);
1930
+ return false;
1931
+ }
1932
+
1933
+ setup(function () {
1934
+ eventUtils.disable();
1935
+ // We need a visible workspace.
1936
+ this.workspace = Blockly.inject('blocklyDiv', {});
1937
+ Blockly.defineBlocksWithJsonArray([
1938
+ {
1939
+ 'type': 'variable_block',
1940
+ 'message0': '%1',
1941
+ 'args0': [
1942
+ {
1943
+ 'type': 'field_variable',
1944
+ 'name': 'NAME',
1945
+ 'variable': 'x',
1946
+ },
1947
+ ],
1948
+ },
1949
+ ]);
1950
+ });
1951
+ teardown(function () {
1952
+ eventUtils.enable();
1953
+ workspaceTeardown.call(this, this.workspace);
1954
+ });
1955
+ suite('Connecting and Disconnecting', function () {
1956
+ test('Connect Block to Next', function () {
1957
+ const blockA = createRenderedBlock(this.workspace, 'stack_block');
1958
+ const blockB = createRenderedBlock(this.workspace, 'stack_block');
1959
+
1960
+ blockA.setCollapsed(true);
1961
+ assertCollapsed(blockA);
1962
+ blockA.nextConnection.connect(blockB.previousConnection);
1963
+ assertNotCollapsed(blockB);
1964
+ });
1965
+ test('Connect Block to Value Input', function () {
1966
+ const blockA = createRenderedBlock(this.workspace, 'row_block');
1967
+ const blockB = createRenderedBlock(this.workspace, 'row_block');
1968
+
1969
+ blockA.setCollapsed(true);
1970
+ assertCollapsed(blockA);
1971
+ blockA.getInput('INPUT').connection.connect(blockB.outputConnection);
1972
+ assert.isTrue(isBlockHidden(blockB));
1973
+ blockA.setCollapsed(false);
1974
+ assertNotCollapsed(blockA);
1975
+ assert.isFalse(isBlockHidden(blockB));
1976
+ });
1977
+ test('Connect Block to Statement Input', function () {
1978
+ const blockA = createRenderedBlock(this.workspace, 'statement_block');
1979
+ const blockB = createRenderedBlock(this.workspace, 'stack_block');
1980
+
1981
+ blockA.setCollapsed(true);
1982
+ assertCollapsed(blockA);
1983
+ blockA
1984
+ .getInput('STATEMENT')
1985
+ .connection.connect(blockB.previousConnection);
1986
+ assert.isTrue(isBlockHidden(blockB));
1987
+ blockA.setCollapsed(false);
1988
+ assertNotCollapsed(blockA);
1989
+ assert.isFalse(isBlockHidden(blockB));
1990
+ });
1991
+ test('Connect Block to Child of Collapsed - Input', function () {
1992
+ const blockA = createRenderedBlock(this.workspace, 'row_block');
1993
+ const blockB = createRenderedBlock(this.workspace, 'row_block');
1994
+ const blockC = createRenderedBlock(this.workspace, 'row_block');
1995
+
1996
+ blockA.getInput('INPUT').connection.connect(blockB.outputConnection);
1997
+ blockA.setCollapsed(true);
1998
+ assertCollapsed(blockA);
1999
+ assert.isTrue(isBlockHidden(blockB));
2000
+ blockB.getInput('INPUT').connection.connect(blockC.outputConnection);
2001
+ assert.isTrue(isBlockHidden(blockC));
2002
+
2003
+ blockA.setCollapsed(false);
2004
+ assertNotCollapsed(blockA);
2005
+ assert.isFalse(isBlockHidden(blockB));
2006
+ assert.isFalse(isBlockHidden(blockC));
2007
+ });
2008
+ test('Connect Block to Child of Collapsed - Next', function () {
2009
+ const blockA = createRenderedBlock(this.workspace, 'statement_block');
2010
+ const blockB = createRenderedBlock(this.workspace, 'stack_block');
2011
+ const blockC = createRenderedBlock(this.workspace, 'stack_block');
2012
+
2013
+ blockA
2014
+ .getInput('STATEMENT')
2015
+ .connection.connect(blockB.previousConnection);
2016
+ blockA.setCollapsed(true);
2017
+ assertCollapsed(blockA);
2018
+ assert.isTrue(isBlockHidden(blockB));
2019
+ blockB.nextConnection.connect(blockC.previousConnection);
2020
+ assert.isTrue(isBlockHidden(blockC));
2021
+
2022
+ blockA.setCollapsed(false);
2023
+ assertNotCollapsed(blockA);
2024
+ assert.isFalse(isBlockHidden(blockB));
2025
+ assert.isFalse(isBlockHidden(blockC));
2026
+ });
2027
+ test('Connect Block to Value Input Already Taken', function () {
2028
+ const blockA = createRenderedBlock(this.workspace, 'row_block');
2029
+ const blockB = createRenderedBlock(this.workspace, 'row_block');
2030
+ const blockC = createRenderedBlock(this.workspace, 'row_block');
2031
+
2032
+ blockA.getInput('INPUT').connection.connect(blockB.outputConnection);
2033
+ blockA.setCollapsed(true);
2034
+ assertCollapsed(blockA);
2035
+ assert.isTrue(isBlockHidden(blockB));
2036
+ blockA.getInput('INPUT').connection.connect(blockC.outputConnection);
2037
+ assert.isTrue(isBlockHidden(blockC));
2038
+ // Still hidden after C is inserted between.
2039
+ assert.isTrue(isBlockHidden(blockB));
2040
+
2041
+ blockA.setCollapsed(false);
2042
+ assertNotCollapsed(blockA);
2043
+ assert.isFalse(isBlockHidden(blockB));
2044
+ assert.isFalse(isBlockHidden(blockC));
2045
+ });
2046
+ test('Connect Block to Statement Input Already Taken', function () {
2047
+ const blockA = createRenderedBlock(this.workspace, 'statement_block');
2048
+ const blockB = createRenderedBlock(this.workspace, 'stack_block');
2049
+ const blockC = createRenderedBlock(this.workspace, 'stack_block');
2050
+
2051
+ blockA
2052
+ .getInput('STATEMENT')
2053
+ .connection.connect(blockB.previousConnection);
2054
+ blockA.setCollapsed(true);
2055
+ assertCollapsed(blockA);
2056
+ assert.isTrue(isBlockHidden(blockB));
2057
+ blockA
2058
+ .getInput('STATEMENT')
2059
+ .connection.connect(blockC.previousConnection);
2060
+ assert.isTrue(isBlockHidden(blockC));
2061
+ // Still hidden after C is inserted between.
2062
+ assert.isTrue(isBlockHidden(blockB));
2063
+
2064
+ blockA.setCollapsed(false);
2065
+ assertNotCollapsed(blockA);
2066
+ assert.isFalse(isBlockHidden(blockB));
2067
+ assert.isFalse(isBlockHidden(blockC));
2068
+ });
2069
+ test('Connect Block with Child - Input', function () {
2070
+ const blockA = createRenderedBlock(this.workspace, 'row_block');
2071
+ const blockB = createRenderedBlock(this.workspace, 'row_block');
2072
+ const blockC = createRenderedBlock(this.workspace, 'row_block');
2073
+
2074
+ blockB.getInput('INPUT').connection.connect(blockC.outputConnection);
2075
+ blockA.setCollapsed(true);
2076
+ assertCollapsed(blockA);
2077
+ blockA.getInput('INPUT').connection.connect(blockB.outputConnection);
2078
+ assert.isTrue(isBlockHidden(blockC));
2079
+ assert.isTrue(isBlockHidden(blockB));
2080
+
2081
+ blockA.setCollapsed(false);
2082
+ assertNotCollapsed(blockA);
2083
+ assert.isFalse(isBlockHidden(blockB));
2084
+ assert.isFalse(isBlockHidden(blockC));
2085
+ });
2086
+ test('Connect Block with Child - Statement', function () {
2087
+ const blockA = createRenderedBlock(this.workspace, 'statement_block');
2088
+ const blockB = createRenderedBlock(this.workspace, 'stack_block');
2089
+ const blockC = createRenderedBlock(this.workspace, 'stack_block');
2090
+
2091
+ blockB.nextConnection.connect(blockC.previousConnection);
2092
+ blockA.setCollapsed(true);
2093
+ assertCollapsed(blockA);
2094
+ blockA
2095
+ .getInput('STATEMENT')
2096
+ .connection.connect(blockB.previousConnection);
2097
+ assert.isTrue(isBlockHidden(blockC));
2098
+ assert.isTrue(isBlockHidden(blockB));
2099
+
2100
+ blockA.setCollapsed(false);
2101
+ assertNotCollapsed(blockA);
2102
+ assert.isFalse(isBlockHidden(blockB));
2103
+ assert.isFalse(isBlockHidden(blockC));
2104
+ });
2105
+ test('Disconnect Block from Value Input', function () {
2106
+ const blockA = createRenderedBlock(this.workspace, 'row_block');
2107
+ const blockB = createRenderedBlock(this.workspace, 'row_block');
2108
+
2109
+ blockA.getInput('INPUT').connection.connect(blockB.outputConnection);
2110
+ blockA.setCollapsed(true);
2111
+ assertCollapsed(blockA);
2112
+ assert.isTrue(isBlockHidden(blockB));
2113
+ blockB.outputConnection.disconnect();
2114
+ assert.isFalse(isBlockHidden(blockB));
2115
+ });
2116
+ test('Disconnect Block from Statement Input', function () {
2117
+ const blockA = createRenderedBlock(this.workspace, 'statement_block');
2118
+ const blockB = createRenderedBlock(this.workspace, 'stack_block');
2119
+
2120
+ blockA
2121
+ .getInput('STATEMENT')
2122
+ .connection.connect(blockB.previousConnection);
2123
+ blockA.setCollapsed(true);
2124
+ assertCollapsed(blockA);
2125
+ assert.isTrue(isBlockHidden(blockB));
2126
+ blockB.previousConnection.disconnect();
2127
+ assert.isFalse(isBlockHidden(blockB));
2128
+ });
2129
+ test('Disconnect Block from Child of Collapsed - Input', function () {
2130
+ const blockA = createRenderedBlock(this.workspace, 'row_block');
2131
+ const blockB = createRenderedBlock(this.workspace, 'row_block');
2132
+ const blockC = createRenderedBlock(this.workspace, 'row_block');
2133
+
2134
+ blockA.getInput('INPUT').connection.connect(blockB.outputConnection);
2135
+ blockB.getInput('INPUT').connection.connect(blockC.outputConnection);
2136
+ blockA.setCollapsed(true);
2137
+ assertCollapsed(blockA);
2138
+ assert.isTrue(isBlockHidden(blockB));
2139
+ assert.isTrue(isBlockHidden(blockC));
2140
+
2141
+ blockC.outputConnection.disconnect();
2142
+ assert.isFalse(isBlockHidden(blockC));
2143
+ });
2144
+ test('Disconnect Block from Child of Collapsed - Next', function () {
2145
+ const blockA = createRenderedBlock(this.workspace, 'statement_block');
2146
+ const blockB = createRenderedBlock(this.workspace, 'stack_block');
2147
+ const blockC = createRenderedBlock(this.workspace, 'stack_block');
2148
+
2149
+ blockA
2150
+ .getInput('STATEMENT')
2151
+ .connection.connect(blockB.previousConnection);
2152
+ blockB.nextConnection.connect(blockC.previousConnection);
2153
+ blockA.setCollapsed(true);
2154
+ assertCollapsed(blockA);
2155
+ assert.isTrue(isBlockHidden(blockB));
2156
+ assert.isTrue(isBlockHidden(blockC));
2157
+
2158
+ blockC.previousConnection.disconnect();
2159
+ assert.isFalse(isBlockHidden(blockC));
2160
+ });
2161
+ test('Disconnect Block with Child - Input', function () {
2162
+ const blockA = createRenderedBlock(this.workspace, 'row_block');
2163
+ const blockB = createRenderedBlock(this.workspace, 'row_block');
2164
+ const blockC = createRenderedBlock(this.workspace, 'row_block');
2165
+
2166
+ blockB.getInput('INPUT').connection.connect(blockC.outputConnection);
2167
+ blockA.getInput('INPUT').connection.connect(blockB.outputConnection);
2168
+ blockA.setCollapsed(true);
2169
+ assertCollapsed(blockA);
2170
+ assert.isTrue(isBlockHidden(blockB));
2171
+ assert.isTrue(isBlockHidden(blockC));
2172
+
2173
+ blockB.outputConnection.disconnect();
2174
+ assert.isFalse(isBlockHidden(blockB));
2175
+ assert.isFalse(isBlockHidden(blockC));
2176
+ });
2177
+ test('Disconnect Block with Child - Statement', function () {
2178
+ const blockA = createRenderedBlock(this.workspace, 'statement_block');
2179
+ const blockB = createRenderedBlock(this.workspace, 'stack_block');
2180
+ const blockC = createRenderedBlock(this.workspace, 'stack_block');
2181
+
2182
+ blockB.nextConnection.connect(blockC.previousConnection);
2183
+ blockA
2184
+ .getInput('STATEMENT')
2185
+ .connection.connect(blockB.previousConnection);
2186
+ blockA.setCollapsed(true);
2187
+ assertCollapsed(blockA);
2188
+ assert.isTrue(isBlockHidden(blockC));
2189
+ assert.isTrue(isBlockHidden(blockB));
2190
+
2191
+ blockB.previousConnection.disconnect();
2192
+ assert.isFalse(isBlockHidden(blockB));
2193
+ assert.isFalse(isBlockHidden(blockC));
2194
+ });
2195
+ });
2196
+ suite('Adding and Removing Block Parts', function () {
2197
+ test('Add Previous Connection', function () {
2198
+ const blockA = createRenderedBlock(this.workspace, 'empty_block');
2199
+ blockA.setCollapsed(true);
2200
+ assertCollapsed(blockA);
2201
+ blockA.setPreviousStatement(true);
2202
+ assertCollapsed(blockA);
2203
+ assert.isNotNull(blockA.previousConnection);
2204
+ });
2205
+ test('Add Next Connection', function () {
2206
+ const blockA = createRenderedBlock(this.workspace, 'empty_block');
2207
+ blockA.setCollapsed(true);
2208
+ assertCollapsed(blockA);
2209
+ blockA.setNextStatement(true);
2210
+ assertCollapsed(blockA);
2211
+ assert.isNotNull(blockA.nextConnection);
2212
+ });
2213
+ test('Add Input', function () {
2214
+ const blockA = createRenderedBlock(this.workspace, 'empty_block');
2215
+ blockA.setCollapsed(true);
2216
+
2217
+ blockA.appendDummyInput('NAME');
2218
+
2219
+ this.clock.runAll();
2220
+ assertCollapsed(blockA);
2221
+ assert.isNotNull(blockA.getInput('NAME'));
2222
+ });
2223
+ test('Add Field', function () {
2224
+ const blockA = createRenderedBlock(this.workspace, 'empty_block');
2225
+ const input = blockA.appendDummyInput('NAME');
2226
+ blockA.setCollapsed(true);
2227
+ assertCollapsed(blockA);
2228
+ input.appendField(new Blockly.FieldLabel('test'), 'FIELD');
2229
+ assertCollapsed(blockA);
2230
+ const field = blockA.getField('FIELD');
2231
+ assert.isNotNull(field);
2232
+ assert.equal(field.getText(), 'test');
2233
+ });
2234
+ test('Add Icon', function () {
2235
+ const blockA = createRenderedBlock(this.workspace, 'empty_block');
2236
+ blockA.setCollapsed(true);
2237
+ assertCollapsed(blockA);
2238
+ blockA.setCommentText('test');
2239
+ assertCollapsed(blockA);
2240
+ });
2241
+ test('Remove Previous Connection', function () {
2242
+ const blockA = createRenderedBlock(this.workspace, 'empty_block');
2243
+ blockA.setPreviousStatement(true);
2244
+ blockA.setCollapsed(true);
2245
+ assertCollapsed(blockA);
2246
+ blockA.setPreviousStatement(false);
2247
+ assertCollapsed(blockA);
2248
+ assert.isNull(blockA.previousConnection);
2249
+ });
2250
+ test('Remove Next Connection', function () {
2251
+ const blockA = createRenderedBlock(this.workspace, 'empty_block');
2252
+ blockA.setNextStatement(true);
2253
+ blockA.setCollapsed(true);
2254
+ assertCollapsed(blockA);
2255
+ blockA.setNextStatement(false);
2256
+ assertCollapsed(blockA);
2257
+ assert.isNull(blockA.nextConnection);
2258
+ });
2259
+ test('Remove Input', function () {
2260
+ const blockA = createRenderedBlock(this.workspace, 'empty_block');
2261
+ blockA.appendDummyInput('NAME');
2262
+ blockA.setCollapsed(true);
2263
+ assertCollapsed(blockA);
2264
+ blockA.removeInput('NAME');
2265
+ assertCollapsed(blockA);
2266
+ assert.isNull(blockA.getInput('NAME'));
2267
+ });
2268
+ test('Remove Field', function () {
2269
+ const blockA = createRenderedBlock(this.workspace, 'empty_block');
2270
+ const input = blockA.appendDummyInput('NAME');
2271
+ input.appendField(new Blockly.FieldLabel('test'), 'FIELD');
2272
+ blockA.setCollapsed(true);
2273
+ assertCollapsed(blockA);
2274
+ input.removeField('FIELD');
2275
+ assertCollapsed(blockA);
2276
+ const field = blockA.getField('FIELD');
2277
+ assert.isNull(field);
2278
+ });
2279
+ test('Remove Icon', function () {
2280
+ const blockA = createRenderedBlock(this.workspace, 'empty_block');
2281
+ blockA.setCommentText('test');
2282
+ blockA.setCollapsed(true);
2283
+ assertCollapsed(blockA);
2284
+ blockA.setCommentText(null);
2285
+ assertCollapsed(blockA);
2286
+ });
2287
+ });
2288
+ suite('Renaming Vars', function () {
2289
+ test('Simple Rename', function () {
2290
+ const blockA = createRenderedBlock(this.workspace, 'variable_block');
2291
+
2292
+ blockA.setCollapsed(true);
2293
+ const variable = this.workspace.getVariable('x', '');
2294
+ this.workspace.renameVariableById(variable.getId(), 'y');
2295
+
2296
+ this.clock.runAll();
2297
+ assertCollapsed(blockA, 'y');
2298
+ });
2299
+ test('Coalesce, Different Case', function () {
2300
+ const blockA = createRenderedBlock(this.workspace, 'variable_block');
2301
+
2302
+ blockA.setCollapsed(true);
2303
+ const variable = this.workspace.createVariable('y');
2304
+ this.workspace.renameVariableById(variable.getId(), 'X');
2305
+
2306
+ this.clock.runAll();
2307
+ assertCollapsed(blockA, 'X');
2308
+ });
2309
+ });
2310
+ suite('Disabled Blocks', function () {
2311
+ test('Children of Collapsed Blocks Should Enable Properly', function () {
2312
+ const blockA = createRenderedBlock(this.workspace, 'statement_block');
2313
+ const blockB = createRenderedBlock(this.workspace, 'stack_block');
2314
+ blockA
2315
+ .getInput('STATEMENT')
2316
+ .connection.connect(blockB.previousConnection);
2317
+ // Disable the block and collapse it.
2318
+ blockA.setDisabledReason(true, 'test reason');
2319
+ blockA.setCollapsed(true);
2320
+
2321
+ // Enable the block before expanding it.
2322
+ blockA.setDisabledReason(false, 'test reason');
2323
+ blockA.setCollapsed(false);
2324
+
2325
+ // The child blocks should be enabled.
2326
+ assert.isTrue(blockB.isEnabled());
2327
+ assert.isFalse(
2328
+ blockB.getSvgRoot().classList.contains('blocklyDisabled'),
2329
+ );
2330
+ });
2331
+ test('Disabled Children of Collapsed Blocks Should Stay Disabled', function () {
2332
+ const blockA = createRenderedBlock(this.workspace, 'statement_block');
2333
+ const blockB = createRenderedBlock(this.workspace, 'stack_block');
2334
+ blockA
2335
+ .getInput('STATEMENT')
2336
+ .connection.connect(blockB.previousConnection);
2337
+
2338
+ // Disable the child block.
2339
+ blockB.setDisabledReason(true, 'test reason');
2340
+
2341
+ // Collapse and disable the parent block.
2342
+ blockA.setCollapsed(false);
2343
+ blockA.setDisabledReason(true, 'test reason');
2344
+
2345
+ // Enable the parent block.
2346
+ blockA.setDisabledReason(false, 'test reason');
2347
+ blockA.setCollapsed(true);
2348
+
2349
+ // Child blocks should stay disabled if they have been set.
2350
+ assert.isFalse(blockB.isEnabled());
2351
+ });
2352
+ test('Disabled blocks from JSON should have proper disabled status', function () {
2353
+ // Nested c-shaped blocks, inner block is disabled
2354
+ const blockJson = {
2355
+ 'type': 'controls_if',
2356
+ 'inputs': {
2357
+ 'DO0': {
2358
+ 'block': {
2359
+ 'type': 'controls_if',
2360
+ 'enabled': false,
2361
+ },
2362
+ },
2363
+ },
2364
+ };
2365
+ Blockly.serialization.blocks.append(blockJson, this.workspace);
2366
+ const innerBlock = this.workspace
2367
+ .getTopBlocks(false)[0]
2368
+ .getChildren()[0];
2369
+ assert.isTrue(
2370
+ innerBlock.visuallyDisabled,
2371
+ 'block should have visuallyDisabled set because it is disabled',
2372
+ );
2373
+ assert.isFalse(
2374
+ innerBlock.isEnabled(),
2375
+ 'block should be marked disabled because enabled json property was set to false',
2376
+ );
2377
+ });
2378
+ test('Disabled blocks from XML should have proper disabled status', function () {
2379
+ // Nested c-shaped blocks, inner block is disabled
2380
+ const blockXml = `<xml xmlns="https://developers.google.com/blockly/xml">
2381
+ <block type="controls_if" x="63" y="87">
2382
+ <statement name="DO0">
2383
+ <block type="controls_if" disabled="true"></block>
2384
+ </statement>
2385
+ </block>
2386
+ </xml>`;
2387
+ Blockly.Xml.domToWorkspace(
2388
+ Blockly.utils.xml.textToDom(blockXml),
2389
+ this.workspace,
2390
+ );
2391
+ const innerBlock = this.workspace
2392
+ .getTopBlocks(false)[0]
2393
+ .getChildren()[0];
2394
+ assert.isTrue(
2395
+ innerBlock.visuallyDisabled,
2396
+ 'block should have visuallyDisabled set because it is disabled',
2397
+ );
2398
+ assert.isFalse(
2399
+ innerBlock.isEnabled(),
2400
+ 'block should be marked disabled because enabled xml property was set to false',
2401
+ );
2402
+ });
2403
+ suite('Disabling blocks with children and neighbors', function () {
2404
+ setup(function () {
2405
+ // c-shape block with a stack of 4 blocks in the input
2406
+ const blockJson = {
2407
+ 'type': 'controls_if',
2408
+ 'id': 'parent',
2409
+ 'inputs': {
2410
+ 'DO0': {
2411
+ 'block': {
2412
+ 'type': 'controls_repeat_ext',
2413
+ 'id': 'child1',
2414
+ 'next': {
2415
+ 'block': {
2416
+ 'type': 'controls_for',
2417
+ 'id': 'child2',
2418
+ 'enabled': false,
2419
+ 'next': {
2420
+ 'block': {
2421
+ 'type': 'controls_whileUntil',
2422
+ 'id': 'child3',
2423
+ 'next': {
2424
+ 'block': {
2425
+ 'type': 'controls_forEach',
2426
+ 'id': 'child4',
2427
+ },
2428
+ },
2429
+ },
2430
+ },
2431
+ },
2432
+ },
2433
+ },
2434
+ },
2435
+ },
2436
+ };
2437
+ Blockly.serialization.blocks.append(blockJson, this.workspace);
2438
+ this.parent = this.workspace.getBlockById('parent');
2439
+ this.child1 = this.workspace.getBlockById('child1');
2440
+ this.child2 = this.workspace.getBlockById('child2');
2441
+ this.child3 = this.workspace.getBlockById('child3');
2442
+ this.child4 = this.workspace.getBlockById('child4');
2443
+ });
2444
+ test('Disabling parent block visually disables all descendants', async function () {
2445
+ this.parent.setDisabledReason(true, 'test reason');
2446
+ await Blockly.renderManagement.finishQueuedRenders();
2447
+ for (const child of this.parent.getDescendants(false)) {
2448
+ assert.isTrue(
2449
+ child.visuallyDisabled,
2450
+ `block ${child.id} should be visually disabled`,
2451
+ );
2452
+ }
2453
+ });
2454
+ test('Child blocks regain original status after parent is re-enabled', async function () {
2455
+ this.parent.setDisabledReason(true, 'test reason');
2456
+ await Blockly.renderManagement.finishQueuedRenders();
2457
+ this.parent.setDisabledReason(false, 'test reason');
2458
+ await Blockly.renderManagement.finishQueuedRenders();
2459
+
2460
+ // child2 is disabled, rest should be enabled
2461
+ assert.isTrue(this.child1.isEnabled(), 'child1 should be enabled');
2462
+ assert.isFalse(
2463
+ this.child1.visuallyDisabled,
2464
+ 'child1 should not be visually disabled',
2465
+ );
2466
+
2467
+ assert.isFalse(this.child2.isEnabled(), 'child2 should be disabled');
2468
+ assert.isTrue(
2469
+ this.child2.visuallyDisabled,
2470
+ 'child2 should be visually disabled',
2471
+ );
2472
+
2473
+ assert.isTrue(this.child3.isEnabled(), 'child3 should be enabled');
2474
+ assert.isFalse(
2475
+ this.child3.visuallyDisabled,
2476
+ 'child3 should not be visually disabled',
2477
+ );
2478
+
2479
+ assert.isTrue(this.child4.isEnabled(), 'child34 should be enabled');
2480
+ assert.isFalse(
2481
+ this.child4.visuallyDisabled,
2482
+ 'child4 should not be visually disabled',
2483
+ );
2484
+ });
2485
+ });
2486
+ });
2487
+ });
2488
+
2489
+ suite('Style', function () {
2490
+ suite('Headless', function () {
2491
+ setup(function () {
2492
+ this.block = Blockly.Xml.domToBlock(
2493
+ Blockly.utils.xml.textToDom('<block type="empty_block"/>'),
2494
+ this.workspace,
2495
+ );
2496
+ });
2497
+ test('Set colour', function () {
2498
+ this.block.setColour('20');
2499
+ assert.equal(this.block.getColour(), '#a5745b');
2500
+ assert.equal(this.block.colour_, this.block.getColour());
2501
+ assert.equal(this.block.hue_, '20');
2502
+ });
2503
+ test('Set style', function () {
2504
+ this.block.setStyle('styleOne');
2505
+ assert.equal(this.block.getStyleName(), 'styleOne');
2506
+ assert.isNull(this.block.hue_);
2507
+ // Calling setStyle does not update the colour on a headless block.
2508
+ assert.equal(this.block.getColour(), '#000000');
2509
+ });
2510
+ });
2511
+ suite('Rendered', function () {
2512
+ setup(function () {
2513
+ this.workspace = Blockly.inject('blocklyDiv', {});
2514
+ this.block = Blockly.Xml.domToBlock(
2515
+ Blockly.utils.xml.textToDom('<block type="empty_block"/>'),
2516
+ this.workspace,
2517
+ );
2518
+ this.workspace.setTheme(
2519
+ new Blockly.Theme('test', {
2520
+ 'styleOne': {
2521
+ 'colourPrimary': '#000000',
2522
+ 'colourSecondary': '#999999',
2523
+ 'colourTertiary': '#4d4d4d',
2524
+ 'hat': '',
2525
+ },
2526
+ }),
2527
+ {},
2528
+ );
2529
+ });
2530
+ teardown(function () {
2531
+ workspaceTeardown.call(this, this.workspace);
2532
+ // Clear all registered themes.
2533
+ Blockly.registry.TEST_ONLY.typeMap['theme'] = {};
2534
+ });
2535
+ test('Set colour hue', function () {
2536
+ this.block.setColour('20');
2537
+ assert.equal(this.block.getStyleName(), 'auto_#a5745b');
2538
+ assert.equal(this.block.getColour(), '#a5745b');
2539
+ assert.equal(this.block.colour_, this.block.getColour());
2540
+ assert.equal(this.block.hue_, '20');
2541
+ });
2542
+ test('Set colour hex', function () {
2543
+ this.block.setColour('#000000');
2544
+ assert.equal(this.block.getStyleName(), 'auto_#000000');
2545
+ assert.equal(this.block.getColour(), '#000000');
2546
+ assert.equal(this.block.colour_, this.block.getColour());
2547
+ assert.isNull(this.block.hue_);
2548
+ });
2549
+ test('Set style', function () {
2550
+ this.block.setStyle('styleOne');
2551
+ assert.equal(this.block.getStyleName(), 'styleOne');
2552
+ assert.equal(this.block.getColour(), '#000000');
2553
+ assert.equal(this.block.colour_, this.block.getColour());
2554
+ });
2555
+ });
2556
+ });
2557
+
2558
+ suite('toString', function () {
2559
+ const toStringTests = [
2560
+ {
2561
+ name: 'statement block',
2562
+ xml:
2563
+ '<block type="controls_repeat_ext">' +
2564
+ '<value name="TIMES">' +
2565
+ '<shadow type="math_number">' +
2566
+ '<field name="NUM">10</field>' +
2567
+ '</shadow>' +
2568
+ '</value>' +
2569
+ '</block>',
2570
+ toString: 'repeat 10 times do ?',
2571
+ },
2572
+ {
2573
+ name: 'nested statement blocks',
2574
+ xml:
2575
+ '<block type="controls_repeat_ext">' +
2576
+ '<value name="TIMES">' +
2577
+ '<shadow type="math_number">' +
2578
+ '<field name="NUM">10</field>' +
2579
+ '</shadow>' +
2580
+ '</value>' +
2581
+ '<statement name="DO">' +
2582
+ '<block type="controls_if"></block>' +
2583
+ '</statement>' +
2584
+ '</block>',
2585
+ toString: 'repeat 10 times do if ? do ?',
2586
+ },
2587
+ {
2588
+ name: 'nested Boolean output blocks',
2589
+ xml:
2590
+ '<block type="controls_if">' +
2591
+ '<value name="IF0">' +
2592
+ '<block type="logic_compare">' +
2593
+ '<field name="OP">EQ</field>' +
2594
+ '<value name="A">' +
2595
+ '<block type="logic_operation">' +
2596
+ '<field name="OP">AND</field>' +
2597
+ '</block>' +
2598
+ '</value>' +
2599
+ '</block>' +
2600
+ '</value>' +
2601
+ '</block>',
2602
+ toString: 'if ((? and ?) = ?) do ?',
2603
+ },
2604
+ {
2605
+ name: 'output block',
2606
+ xml:
2607
+ '<block type="math_single">' +
2608
+ '<field name="OP">ROOT</field>' +
2609
+ '<value name="NUM">' +
2610
+ '<shadow type="math_number">' +
2611
+ '<field name="NUM">9</field>' +
2612
+ '</shadow>' +
2613
+ '</value>' +
2614
+ '</block>',
2615
+ toString: 'square root 9',
2616
+ },
2617
+ {
2618
+ name: 'nested Number output blocks',
2619
+ xml:
2620
+ '<block type="math_arithmetic">' +
2621
+ '<field name="OP">ADD</field>' +
2622
+ '<value name="A">' +
2623
+ '<shadow type="math_number">' +
2624
+ '<field name="NUM">1</field>' +
2625
+ '</shadow>' +
2626
+ '<block type="math_arithmetic">' +
2627
+ '<field name="OP">MULTIPLY</field>' +
2628
+ '<value name="A">' +
2629
+ '<shadow type="math_number">' +
2630
+ '<field name="NUM">10</field>' +
2631
+ '</shadow>' +
2632
+ '</value>' +
2633
+ '<value name="B">' +
2634
+ '<shadow type="math_number">' +
2635
+ '<field name="NUM">5</field>' +
2636
+ '</shadow>' +
2637
+ '</value>' +
2638
+ '</block>' +
2639
+ '</value>' +
2640
+ '<value name="B">' +
2641
+ '<shadow type="math_number">' +
2642
+ '<field name="NUM">3</field>' +
2643
+ '</shadow>' +
2644
+ '</value>' +
2645
+ '</block>',
2646
+ toString: '(10 × 5) + 3',
2647
+ },
2648
+ {
2649
+ name: 'nested String output blocks',
2650
+ xml:
2651
+ '<block type="text_join">' +
2652
+ '<mutation items="2"></mutation>' +
2653
+ '<value name="ADD0">' +
2654
+ '<block type="text">' +
2655
+ '<field name="TEXT">Hello</field>' +
2656
+ '</block>' +
2657
+ '</value>' +
2658
+ '<value name="ADD1">' +
2659
+ '<block type="text">' +
2660
+ '<field name="TEXT">World</field>' +
2661
+ '</block>' +
2662
+ '</value>' +
2663
+ '</block>',
2664
+ toString: 'create text with “ Hello ” “ World ”',
2665
+ },
2666
+ {
2667
+ name: 'parentheses in string literal',
2668
+ xml:
2669
+ '<block type="text">' +
2670
+ '<field name="TEXT">foo ( bar ) baz</field>' +
2671
+ '</block>',
2672
+ toString: '“ foo ( bar ) baz ”',
2673
+ },
2674
+ ];
2675
+ // Create mocha test cases for each toString test.
2676
+ toStringTests.forEach(function (t) {
2677
+ test(t.name, function () {
2678
+ const block = Blockly.Xml.domToBlock(
2679
+ Blockly.utils.xml.textToDom(t.xml),
2680
+ this.workspace,
2681
+ );
2682
+ assert.equal(block.toString(), t.toString);
2683
+ });
2684
+ });
2685
+ });
2686
+
2687
+ suite('Initialization', function () {
2688
+ setup(function () {
2689
+ Blockly.defineBlocksWithJsonArray([
2690
+ {
2691
+ 'type': 'init_test_block',
2692
+ 'message0': '',
2693
+ },
2694
+ ]);
2695
+ });
2696
+ test('recordUndo is reset even if init throws', function () {
2697
+ // The test could pass if init is never called,
2698
+ // so we assert init was called to be safe.
2699
+ let initCalled = false;
2700
+ let recordUndoDuringInit;
2701
+ Blockly.Blocks['init_test_block'].init = function () {
2702
+ initCalled = true;
2703
+ recordUndoDuringInit = eventUtils.getRecordUndo();
2704
+ throw new Error();
2705
+ };
2706
+ assert.throws(
2707
+ function () {
2708
+ this.workspace.newBlock('init_test_block');
2709
+ }.bind(this),
2710
+ );
2711
+ assert.isFalse(
2712
+ recordUndoDuringInit,
2713
+ 'recordUndo should be false during block init function',
2714
+ );
2715
+ assert.isTrue(
2716
+ eventUtils.getRecordUndo(),
2717
+ 'recordUndo should be reset to true after init',
2718
+ );
2719
+ assert.isTrue(initCalled, 'expected init function to be called');
2720
+ });
2721
+ });
2722
+
2723
+ suite('EndOfRow', function () {
2724
+ setup(function () {
2725
+ Blockly.defineBlocksWithJsonArray([
2726
+ {
2727
+ 'type': 'end_row_test_block',
2728
+ 'message0': 'Row1\nRow2',
2729
+ 'inputsInline': true,
2730
+ },
2731
+ ]);
2732
+ });
2733
+ test('Newline is converted to an end-row input', function () {
2734
+ const block = this.workspace.newBlock('end_row_test_block');
2735
+ assert.equal(block.inputList[0].fieldRow[0].getValue(), 'Row1');
2736
+ assert.isTrue(
2737
+ block.inputList[0] instanceof EndRowInput,
2738
+ 'newline should be converted to an end-row input',
2739
+ );
2740
+ assert.equal(block.inputList[1].fieldRow[0].getValue(), 'Row2');
2741
+ });
2742
+ });
2743
+ });