diff --git a/.eslintrc.json b/.eslintrc.json index 2cfe544cd..47430bdf2 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -72,8 +72,7 @@ "balanced": true }, "exceptions": ["*"] - }], - "es5/no-es6-methods": ["warn"] + }] }, "env": { "browser": true @@ -83,7 +82,6 @@ "goog": true }, "extends": [ - "eslint:recommended", - "plugin:es5/no-es2015" + "eslint:recommended" ] } diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 3ae6170df..dcdacaedd 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -10,3 +10,9 @@ updates: target-branch: "develop" schedule: interval: "weekly" + ignore: + - dependency-name: "jsdom" + # For jsdom, ignore all updates for version 16. + # We should test that this does not cause issue + # google/blockly-samples#665 when version 17 is released. + versions: "16.x" diff --git a/blockly_uncompressed.js b/blockly_uncompressed.js index c868f4eec..c7f73b1a1 100644 --- a/blockly_uncompressed.js +++ b/blockly_uncompressed.js @@ -21,69 +21,73 @@ this.BLOCKLY_DIR = (function(root) { this.BLOCKLY_BOOT = function(root) { // Execute after Closure has loaded. -goog.addDependency('../../core/block.js', ['Blockly.Block'], ['Blockly.ASTNode', 'Blockly.Blocks', 'Blockly.Connection', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockMove', 'Blockly.Extensions', 'Blockly.Input', 'Blockly.Tooltip', 'Blockly.Workspace', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.object'], {'lang': 'es5'}); -goog.addDependency('../../core/block_animations.js', ['Blockly.blockAnimations'], ['Blockly.utils.Svg', 'Blockly.utils.dom'], {}); -goog.addDependency('../../core/block_drag_surface.js', ['Blockly.BlockDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {}); -goog.addDependency('../../core/block_dragger.js', ['Blockly.BlockDragger'], ['Blockly.Events', 'Blockly.Events.BlockDrag', 'Blockly.Events.BlockMove', 'Blockly.IBlockDragger', 'Blockly.InsertionMarkerManager', 'Blockly.blockAnimations', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.dom'], {}); -goog.addDependency('../../core/block_svg.js', ['Blockly.BlockSvg'], ['Blockly.ASTNode', 'Blockly.Block', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.Events.BlockMove', 'Blockly.Events.Selected', 'Blockly.Msg', 'Blockly.RenderedConnection', 'Blockly.TabNavigateCursor', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Xml', 'Blockly.blockAnimations', 'Blockly.blockRendering.IPathObject', 'Blockly.browserEvents', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {}); -goog.addDependency('../../core/blockly.js', ['Blockly'], ['Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.FinishedLoading', 'Blockly.Events.Ui', 'Blockly.Events.UiBase', 'Blockly.Events.VarCreate', 'Blockly.Procedures', 'Blockly.ShortcutRegistry', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Variables', 'Blockly.WidgetDiv', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.inject', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.colour', 'Blockly.utils.deprecation', 'Blockly.utils.toolbox'], {}); -goog.addDependency('../../core/blocks.js', ['Blockly.Blocks'], [], {}); -goog.addDependency('../../core/browser_events.js', ['Blockly.browserEvents'], ['Blockly.Touch'], {}); -goog.addDependency('../../core/bubble.js', ['Blockly.Bubble'], ['Blockly.Scrollbar', 'Blockly.Touch', 'Blockly.Workspace', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.userAgent'], {}); -goog.addDependency('../../core/bubble_dragger.js', ['Blockly.BubbleDragger'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.CommentMove', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate'], {}); -goog.addDependency('../../core/comment.js', ['Blockly.Comment'], ['Blockly.Bubble', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.Warning', 'Blockly.browserEvents', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {}); -goog.addDependency('../../core/connection.js', ['Blockly.Connection'], ['Blockly.Events', 'Blockly.Events.BlockMove', 'Blockly.Xml', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.deprecation'], {}); -goog.addDependency('../../core/connection_checker.js', ['Blockly.ConnectionChecker'], ['Blockly.Connection', 'Blockly.IConnectionChecker', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.registry'], {}); -goog.addDependency('../../core/connection_db.js', ['Blockly.ConnectionDB'], ['Blockly.RenderedConnection', 'Blockly.connectionTypes', 'Blockly.constants'], {}); -goog.addDependency('../../core/connection_types.js', ['Blockly.connectionTypes'], [], {}); -goog.addDependency('../../core/constants.js', ['Blockly.constants'], ['Blockly.connectionTypes'], {}); -goog.addDependency('../../core/contextmenu.js', ['Blockly.ContextMenu'], ['Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.Msg', 'Blockly.WidgetDiv', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.userAgent'], {}); +goog.addDependency('../../core/block.js', ['Blockly.Block'], ['Blockly.ASTNode', 'Blockly.Blocks', 'Blockly.Connection', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockMove', 'Blockly.Extensions', 'Blockly.IASTNodeLocation', 'Blockly.Input', 'Blockly.Tooltip', 'Blockly.Workspace', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.object'], {'lang': 'es5'}); +goog.addDependency('../../core/block_animations.js', ['Blockly.blockAnimations'], ['Blockly.utils.Svg', 'Blockly.utils.dom']); +goog.addDependency('../../core/block_drag_surface.js', ['Blockly.BlockDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom']); +goog.addDependency('../../core/block_dragger.js', ['Blockly.BlockDragger'], ['Blockly.Events', 'Blockly.Events.BlockDrag', 'Blockly.Events.BlockMove', 'Blockly.InsertionMarkerManager', 'Blockly.blockAnimations', 'Blockly.constants', 'Blockly.utils.Coordinate', 'Blockly.utils.dom']); +goog.addDependency('../../core/block_svg.js', ['Blockly.BlockSvg'], ['Blockly.ASTNode', 'Blockly.Block', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.Events.BlockMove', 'Blockly.Events.Selected', 'Blockly.IASTNodeLocationSvg', 'Blockly.IBoundedElement', 'Blockly.ICopyable', 'Blockly.Msg', 'Blockly.RenderedConnection', 'Blockly.TabNavigateCursor', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Xml', 'Blockly.blockAnimations', 'Blockly.blockRendering.IPathObject', 'Blockly.browserEvents', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent']); +goog.addDependency('../../core/blockly.js', ['Blockly'], ['Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.FinishedLoading', 'Blockly.Events.Ui', 'Blockly.Events.UiBase', 'Blockly.Events.VarCreate', 'Blockly.Procedures', 'Blockly.ShortcutRegistry', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Variables', 'Blockly.WidgetDiv', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.inject', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.colour', 'Blockly.utils.deprecation', 'Blockly.utils.toolbox']); +goog.addDependency('../../core/blocks.js', ['Blockly.Blocks'], []); +goog.addDependency('../../core/browser_events.js', ['Blockly.browserEvents'], ['Blockly.Touch', 'Blockly.utils.global']); +goog.addDependency('../../core/bubble.js', ['Blockly.Bubble'], ['Blockly.IBubble', 'Blockly.Scrollbar', 'Blockly.Touch', 'Blockly.Workspace', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.userAgent']); +goog.addDependency('../../core/bubble_dragger.js', ['Blockly.BubbleDragger'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.CommentMove', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate']); +goog.addDependency('../../core/comment.js', ['Blockly.Comment'], ['Blockly.Bubble', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.Warning', 'Blockly.browserEvents', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent']); +goog.addDependency('../../core/component_manager.js', ['Blockly.ComponentManager'], []); +goog.addDependency('../../core/connection.js', ['Blockly.Connection'], ['Blockly.Events', 'Blockly.Events.BlockMove', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.Xml', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.deprecation']); +goog.addDependency('../../core/connection_checker.js', ['Blockly.ConnectionChecker'], ['Blockly.Connection', 'Blockly.IConnectionChecker', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.registry']); +goog.addDependency('../../core/connection_db.js', ['Blockly.ConnectionDB'], ['Blockly.RenderedConnection', 'Blockly.connectionTypes', 'Blockly.constants']); +goog.addDependency('../../core/connection_types.js', ['Blockly.connectionTypes'], []); +goog.addDependency('../../core/constants.js', ['Blockly.constants'], ['Blockly.connectionTypes']); +goog.addDependency('../../core/contextmenu.js', ['Blockly.ContextMenu'], ['Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.Msg', 'Blockly.WidgetDiv', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.userAgent']); goog.addDependency('../../core/contextmenu_items.js', ['Blockly.ContextMenuItems'], ['Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.constants', 'Blockly.inputTypes'], {'lang': 'es5'}); goog.addDependency('../../core/contextmenu_registry.js', ['Blockly.ContextMenuRegistry'], [], {'lang': 'es5'}); goog.addDependency('../../core/css.js', ['Blockly.Css'], [], {'lang': 'es5'}); -goog.addDependency('../../core/dropdowndiv.js', ['Blockly.DropDownDiv'], ['Blockly.utils.Rect', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.style'], {}); -goog.addDependency('../../core/events/block_events.js', ['Blockly.Events.BlockBase', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockMove', 'Blockly.Events.Change', 'Blockly.Events.Create', 'Blockly.Events.Delete', 'Blockly.Events.Move'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.Xml', 'Blockly.connectionTypes', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.object', 'Blockly.utils.xml'], {}); -goog.addDependency('../../core/events/events.js', ['Blockly.Events'], ['Blockly.registry', 'Blockly.utils'], {}); -goog.addDependency('../../core/events/events_abstract.js', ['Blockly.Events.Abstract'], ['Blockly.Events'], {}); -goog.addDependency('../../core/events/events_block_drag.js', ['Blockly.Events.BlockDrag'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/events/events_bubble_open.js', ['Blockly.Events.BubbleOpen'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/events/events_click.js', ['Blockly.Events.Click'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/events/events_marker_move.js', ['Blockly.Events.MarkerMove'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/events/events_selected.js', ['Blockly.Events.Selected'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/events/events_theme_change.js', ['Blockly.Events.ThemeChange'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/events/events_toolbox_item_select.js', ['Blockly.Events.ToolboxItemSelect'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/events/events_trashcan_open.js', ['Blockly.Events.TrashcanOpen'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/events/events_viewport.js', ['Blockly.Events.ViewportChange'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/events/ui_events.js', ['Blockly.Events.Ui', 'Blockly.Events.UiBase'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.registry', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/events/variable_events.js', ['Blockly.Events.VarBase', 'Blockly.Events.VarCreate', 'Blockly.Events.VarDelete', 'Blockly.Events.VarRename'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.registry', 'Blockly.utils.object'], {}); +goog.addDependency('../../core/delete_area.js', ['Blockly.DeleteArea'], ['Blockly.DragTarget', 'Blockly.IDeleteArea']); +goog.addDependency('../../core/drag_target.js', ['Blockly.DragTarget'], ['Blockly.IDragTarget']); +goog.addDependency('../../core/dropdowndiv.js', ['Blockly.DropDownDiv'], ['Blockly.utils.Rect', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.style']); +goog.addDependency('../../core/events/block_events.js', ['Blockly.Events.BlockBase', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockMove', 'Blockly.Events.Change', 'Blockly.Events.Create', 'Blockly.Events.Delete', 'Blockly.Events.Move'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.Xml', 'Blockly.connectionTypes', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.object', 'Blockly.utils.xml']); +goog.addDependency('../../core/events/events.js', ['Blockly.Events'], ['Blockly.registry', 'Blockly.utils']); +goog.addDependency('../../core/events/events_abstract.js', ['Blockly.Events.Abstract'], ['Blockly.Events']); +goog.addDependency('../../core/events/events_block_drag.js', ['Blockly.Events.BlockDrag'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']); +goog.addDependency('../../core/events/events_bubble_open.js', ['Blockly.Events.BubbleOpen'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']); +goog.addDependency('../../core/events/events_click.js', ['Blockly.Events.Click'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']); +goog.addDependency('../../core/events/events_marker_move.js', ['Blockly.Events.MarkerMove'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']); +goog.addDependency('../../core/events/events_selected.js', ['Blockly.Events.Selected'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']); +goog.addDependency('../../core/events/events_theme_change.js', ['Blockly.Events.ThemeChange'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']); +goog.addDependency('../../core/events/events_toolbox_item_select.js', ['Blockly.Events.ToolboxItemSelect'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']); +goog.addDependency('../../core/events/events_trashcan_open.js', ['Blockly.Events.TrashcanOpen'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']); +goog.addDependency('../../core/events/events_viewport.js', ['Blockly.Events.ViewportChange'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']); +goog.addDependency('../../core/events/ui_events.js', ['Blockly.Events.Ui', 'Blockly.Events.UiBase'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.registry', 'Blockly.utils.object']); +goog.addDependency('../../core/events/variable_events.js', ['Blockly.Events.VarBase', 'Blockly.Events.VarCreate', 'Blockly.Events.VarDelete', 'Blockly.Events.VarRename'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.registry', 'Blockly.utils.object']); goog.addDependency('../../core/events/workspace_events.js', ['Blockly.Events.FinishedLoading'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es5'}); -goog.addDependency('../../core/events/ws_comment_events.js', ['Blockly.Events.CommentBase', 'Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.Xml', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.object', 'Blockly.utils.xml'], {}); -goog.addDependency('../../core/extensions.js', ['Blockly.Extensions'], ['Blockly.utils'], {}); -goog.addDependency('../../core/field.js', ['Blockly.Field'], ['Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Gesture', 'Blockly.Tooltip', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.style', 'Blockly.utils.userAgent'], {'lang': 'es5'}); -goog.addDependency('../../core/field_angle.js', ['Blockly.FieldAngle'], ['Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.FieldTextInput', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {}); -goog.addDependency('../../core/field_checkbox.js', ['Blockly.FieldCheckbox'], ['Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils.dom', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/field_colour.js', ['Blockly.FieldColour'], ['Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils.IdGenerator', 'Blockly.utils.KeyCodes', 'Blockly.utils.Size', 'Blockly.utils.aria', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/field_dropdown.js', ['Blockly.FieldDropdown'], ['Blockly.Field', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.string', 'Blockly.utils.userAgent'], {}); -goog.addDependency('../../core/field_image.js', ['Blockly.FieldImage'], ['Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/field_label.js', ['Blockly.FieldLabel'], ['Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.dom', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/field_label_serializable.js', ['Blockly.FieldLabelSerializable'], ['Blockly.FieldLabel', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/field_multilineinput.js', ['Blockly.FieldMultilineInput'], ['Blockly.Css', 'Blockly.FieldTextInput', 'Blockly.utils', 'Blockly.utils.KeyCodes', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es5'}); -goog.addDependency('../../core/field_number.js', ['Blockly.FieldNumber'], ['Blockly.FieldTextInput', 'Blockly.fieldRegistry', 'Blockly.utils.aria', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/field_registry.js', ['Blockly.fieldRegistry'], ['Blockly.registry'], {}); -goog.addDependency('../../core/field_textinput.js', ['Blockly.FieldTextInput'], ['Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.Msg', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {}); -goog.addDependency('../../core/field_variable.js', ['Blockly.FieldVariable'], ['Blockly.Events.BlockChange', 'Blockly.FieldDropdown', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.Xml', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/flyout_base.js', ['Blockly.Flyout'], ['Blockly.Block', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.VarCreate', 'Blockly.FlyoutMetricsManager', 'Blockly.Gesture', 'Blockly.ScrollbarPair', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.blockRendering', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.toolbox', 'Blockly.utils.xml'], {}); -goog.addDependency('../../core/flyout_button.js', ['Blockly.FlyoutButton'], ['Blockly.Css', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es5'}); -goog.addDependency('../../core/flyout_horizontal.js', ['Blockly.HorizontalFlyout'], ['Blockly.Block', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.WidgetDiv', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {}); -goog.addDependency('../../core/flyout_vertical.js', ['Blockly.VerticalFlyout'], ['Blockly.Block', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.WidgetDiv', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {}); -goog.addDependency('../../core/generator.js', ['Blockly.Generator'], ['Blockly.Block', 'Blockly.constants'], {}); -goog.addDependency('../../core/gesture.js', ['Blockly.Gesture'], ['Blockly.BlockDragger', 'Blockly.BubbleDragger', 'Blockly.Events', 'Blockly.Events.Click', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.WorkspaceDragger', 'Blockly.blockAnimations', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate'], {}); -goog.addDependency('../../core/grid.js', ['Blockly.Grid'], ['Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.userAgent'], {}); -goog.addDependency('../../core/icon.js', ['Blockly.Icon'], ['Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {}); -goog.addDependency('../../core/inject.js', ['Blockly.inject'], ['Blockly.BlockDragSurfaceSvg', 'Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Grid', 'Blockly.Msg', 'Blockly.Options', 'Blockly.ScrollbarPair', 'Blockly.Tooltip', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.WorkspaceSvg', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.userAgent'], {}); +goog.addDependency('../../core/events/ws_comment_events.js', ['Blockly.Events.CommentBase', 'Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.Xml', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.object', 'Blockly.utils.xml']); +goog.addDependency('../../core/extensions.js', ['Blockly.Extensions'], ['Blockly.utils']); +goog.addDependency('../../core/field.js', ['Blockly.Field'], ['Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Gesture', 'Blockly.IASTNodeLocationSvg', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.IKeyboardAccessible', 'Blockly.IRegistrable', 'Blockly.MarkerManager', 'Blockly.Tooltip', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.style', 'Blockly.utils.userAgent'], {'lang': 'es5'}); +goog.addDependency('../../core/field_angle.js', ['Blockly.FieldAngle'], ['Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.FieldTextInput', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils.KeyCodes', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.object', 'Blockly.utils.userAgent']); +goog.addDependency('../../core/field_checkbox.js', ['Blockly.FieldCheckbox'], ['Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils.dom', 'Blockly.utils.object']); +goog.addDependency('../../core/field_colour.js', ['Blockly.FieldColour'], ['Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils.IdGenerator', 'Blockly.utils.KeyCodes', 'Blockly.utils.Size', 'Blockly.utils.aria', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object']); +goog.addDependency('../../core/field_dropdown.js', ['Blockly.FieldDropdown'], ['Blockly.DropDownDiv', 'Blockly.Field', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.string', 'Blockly.utils.userAgent']); +goog.addDependency('../../core/field_image.js', ['Blockly.FieldImage'], ['Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object']); +goog.addDependency('../../core/field_label.js', ['Blockly.FieldLabel'], ['Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.dom', 'Blockly.utils.object']); +goog.addDependency('../../core/field_label_serializable.js', ['Blockly.FieldLabelSerializable'], ['Blockly.FieldLabel', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.object']); +goog.addDependency('../../core/field_multilineinput.js', ['Blockly.FieldMultilineInput'], ['Blockly.Css', 'Blockly.Field', 'Blockly.FieldTextInput', 'Blockly.WidgetDiv', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.KeyCodes', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es5'}); +goog.addDependency('../../core/field_number.js', ['Blockly.FieldNumber'], ['Blockly.FieldTextInput', 'Blockly.fieldRegistry', 'Blockly.utils.aria', 'Blockly.utils.object']); +goog.addDependency('../../core/field_registry.js', ['Blockly.fieldRegistry'], ['Blockly.registry']); +goog.addDependency('../../core/field_textinput.js', ['Blockly.FieldTextInput'], ['Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.Msg', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent']); +goog.addDependency('../../core/field_variable.js', ['Blockly.FieldVariable'], ['Blockly.Events.BlockChange', 'Blockly.FieldDropdown', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.Xml', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.object']); +goog.addDependency('../../core/flyout_base.js', ['Blockly.Flyout'], ['Blockly.Block', 'Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.VarCreate', 'Blockly.FlyoutMetricsManager', 'Blockly.Gesture', 'Blockly.IFlyout', 'Blockly.ScrollbarPair', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.blockRendering', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.toolbox', 'Blockly.utils.xml']); +goog.addDependency('../../core/flyout_button.js', ['Blockly.FlyoutButton'], ['Blockly.Css', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.style'], {'lang': 'es5'}); +goog.addDependency('../../core/flyout_horizontal.js', ['Blockly.HorizontalFlyout'], ['Blockly.Block', 'Blockly.DropDownDiv', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.WidgetDiv', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.object', 'Blockly.utils.toolbox']); +goog.addDependency('../../core/flyout_vertical.js', ['Blockly.VerticalFlyout'], ['Blockly.Block', 'Blockly.DropDownDiv', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.WidgetDiv', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.object', 'Blockly.utils.toolbox']); +goog.addDependency('../../core/generator.js', ['Blockly.Generator'], ['Blockly.Block', 'Blockly.constants', 'Blockly.utils.deprecation']); +goog.addDependency('../../core/gesture.js', ['Blockly.Gesture'], ['Blockly.BlockDragger', 'Blockly.BubbleDragger', 'Blockly.Events', 'Blockly.Events.Click', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Workspace', 'Blockly.WorkspaceDragger', 'Blockly.blockAnimations', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate']); +goog.addDependency('../../core/grid.js', ['Blockly.Grid'], ['Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.userAgent']); +goog.addDependency('../../core/icon.js', ['Blockly.Icon'], ['Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom']); +goog.addDependency('../../core/inject.js', ['Blockly.inject'], ['Blockly.BlockDragSurfaceSvg', 'Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Grid', 'Blockly.Msg', 'Blockly.Options', 'Blockly.ScrollbarPair', 'Blockly.Tooltip', 'Blockly.WidgetDiv', 'Blockly.Workspace', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.WorkspaceSvg', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.userAgent']); goog.addDependency('../../core/input.js', ['Blockly.Input'], ['Blockly.Connection', 'Blockly.FieldLabel', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.inputTypes'], {'lang': 'es5'}); -goog.addDependency('../../core/input_types.js', ['Blockly.inputTypes'], ['Blockly.connectionTypes'], {}); +goog.addDependency('../../core/input_types.js', ['Blockly.inputTypes'], ['Blockly.connectionTypes']); goog.addDependency('../../core/insertion_marker_manager.js', ['Blockly.InsertionMarkerManager'], ['Blockly.Events', 'Blockly.blockAnimations', 'Blockly.connectionTypes', 'Blockly.constants'], {'lang': 'es5'}); +<<<<<<< HEAD goog.addDependency('../../core/interfaces/i_accessibility.js', ['Blockly.IASTNodeLocation', 'Blockly.IASTNodeLocationSvg', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.IKeyboardAccessible'], [], {}); goog.addDependency('../../core/interfaces/i_block_dragger.js', ['Blockly.IBlockDragger'], [], {}); goog.addDependency('../../core/interfaces/i_bounded_element.js', ['Blockly.IBoundedElement'], [], {}); @@ -105,120 +109,141 @@ goog.addDependency('../../core/interfaces/i_styleable.js', ['Blockly.IStyleable' goog.addDependency('../../core/interfaces/i_toolbox.js', ['Blockly.IToolbox'], [], {}); goog.addDependency('../../core/interfaces/i_toolbox_item.js', ['Blockly.ICollapsibleToolboxItem', 'Blockly.ISelectableToolboxItem', 'Blockly.IToolboxItem'], [], {}); goog.addDependency('../../core/interfaces/i_workspace_plugin.js', ['Blockly.IWorkspacePlugin'], [], {}); +======= +goog.addDependency('../../core/interfaces/i_accessibility.js', ['Blockly.IASTNodeLocation', 'Blockly.IASTNodeLocationSvg', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.IKeyboardAccessible'], []); +goog.addDependency('../../core/interfaces/i_autohideable.js', ['Blockly.IAutoHideable'], ['Blockly.IComponent']); +goog.addDependency('../../core/interfaces/i_bounded_element.js', ['Blockly.IBoundedElement'], []); +goog.addDependency('../../core/interfaces/i_bubble.js', ['Blockly.IBubble'], ['Blockly.IContextMenu', 'Blockly.IDeletable']); +goog.addDependency('../../core/interfaces/i_component.js', ['Blockly.IComponent'], []); +goog.addDependency('../../core/interfaces/i_connection_checker.js', ['Blockly.IConnectionChecker'], []); +goog.addDependency('../../core/interfaces/i_contextmenu.js', ['Blockly.IContextMenu'], []); +goog.addDependency('../../core/interfaces/i_copyable.js', ['Blockly.ICopyable'], []); +goog.addDependency('../../core/interfaces/i_deletable.js', ['Blockly.IDeletable'], []); +goog.addDependency('../../core/interfaces/i_delete_area.js', ['Blockly.IDeleteArea'], ['Blockly.IDragTarget']); +goog.addDependency('../../core/interfaces/i_drag_target.js', ['Blockly.IDragTarget'], ['Blockly.IComponent']); +goog.addDependency('../../core/interfaces/i_flyout.js', ['Blockly.IFlyout'], []); +goog.addDependency('../../core/interfaces/i_metrics_manager.js', ['Blockly.IMetricsManager'], []); +goog.addDependency('../../core/interfaces/i_movable.js', ['Blockly.IMovable'], []); +goog.addDependency('../../core/interfaces/i_positionable.js', ['Blockly.IPositionable'], ['Blockly.IComponent']); +goog.addDependency('../../core/interfaces/i_registrable.js', ['Blockly.IRegistrable'], []); +goog.addDependency('../../core/interfaces/i_registrable_field.js', ['Blockly.IRegistrableField'], []); +goog.addDependency('../../core/interfaces/i_selectable.js', ['Blockly.ISelectable'], []); +goog.addDependency('../../core/interfaces/i_styleable.js', ['Blockly.IStyleable'], []); +goog.addDependency('../../core/interfaces/i_toolbox.js', ['Blockly.IToolbox'], []); +goog.addDependency('../../core/interfaces/i_toolbox_item.js', ['Blockly.ICollapsibleToolboxItem', 'Blockly.ISelectableToolboxItem', 'Blockly.IToolboxItem'], []); +>>>>>>> 11390341b18c07b2178451e4ccd22cf9cb011add goog.addDependency('../../core/keyboard_nav/ast_node.js', ['Blockly.ASTNode'], ['Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.Coordinate'], {'lang': 'es5'}); goog.addDependency('../../core/keyboard_nav/basic_cursor.js', ['Blockly.BasicCursor'], ['Blockly.ASTNode', 'Blockly.Cursor', 'Blockly.registry'], {'lang': 'es5'}); goog.addDependency('../../core/keyboard_nav/cursor.js', ['Blockly.Cursor'], ['Blockly.ASTNode', 'Blockly.Marker', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es5'}); -goog.addDependency('../../core/keyboard_nav/marker.js', ['Blockly.Marker'], ['Blockly.ASTNode'], {}); -goog.addDependency('../../core/keyboard_nav/tab_navigate_cursor.js', ['Blockly.TabNavigateCursor'], ['Blockly.ASTNode', 'Blockly.BasicCursor', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/marker_manager.js', ['Blockly.MarkerManager'], ['Blockly.Cursor', 'Blockly.Marker'], {}); -goog.addDependency('../../core/menu.js', ['Blockly.Menu'], ['Blockly.browserEvents', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.style'], {}); -goog.addDependency('../../core/menuitem.js', ['Blockly.MenuItem'], ['Blockly.utils.IdGenerator', 'Blockly.utils.aria', 'Blockly.utils.dom'], {}); +goog.addDependency('../../core/keyboard_nav/marker.js', ['Blockly.Marker'], ['Blockly.ASTNode']); +goog.addDependency('../../core/keyboard_nav/tab_navigate_cursor.js', ['Blockly.TabNavigateCursor'], ['Blockly.ASTNode', 'Blockly.BasicCursor', 'Blockly.utils.object']); +goog.addDependency('../../core/marker_manager.js', ['Blockly.MarkerManager'], ['Blockly.Cursor', 'Blockly.Marker']); +goog.addDependency('../../core/menu.js', ['Blockly.Menu'], ['Blockly.browserEvents', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.style']); +goog.addDependency('../../core/menuitem.js', ['Blockly.MenuItem'], ['Blockly.utils.IdGenerator', 'Blockly.utils.aria', 'Blockly.utils.dom']); goog.addDependency('../../core/metrics_manager.js', ['Blockly.FlyoutMetricsManager', 'Blockly.MetricsManager'], ['Blockly.IMetricsManager', 'Blockly.registry', 'Blockly.utils.Size', 'Blockly.utils.toolbox'], {'lang': 'es5'}); -goog.addDependency('../../core/msg.js', ['Blockly.Msg'], ['Blockly.utils.global'], {}); -goog.addDependency('../../core/mutator.js', ['Blockly.Mutator'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox', 'Blockly.utils.xml'], {}); -goog.addDependency('../../core/names.js', ['Blockly.Names'], ['Blockly.Msg', 'Blockly.constants'], {}); -goog.addDependency('../../core/options.js', ['Blockly.Options'], ['Blockly.Theme', 'Blockly.Themes.Classic', 'Blockly.registry', 'Blockly.utils.IdGenerator', 'Blockly.utils.Metrics', 'Blockly.utils.toolbox'], {}); -goog.addDependency('../../core/plugin_manager.js', ['Blockly.PluginManager'], [], {}); -goog.addDependency('../../core/procedures.js', ['Blockly.Procedures'], ['Blockly.Blocks', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.Msg', 'Blockly.Names', 'Blockly.Workspace', 'Blockly.Xml', 'Blockly.constants', 'Blockly.utils.xml'], {}); -goog.addDependency('../../core/registry.js', ['Blockly.registry'], [], {}); -goog.addDependency('../../core/rendered_connection.js', ['Blockly.RenderedConnection'], ['Blockly.Connection', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/renderers/common/block_rendering.js', ['Blockly.blockRendering'], ['Blockly.registry'], {}); +goog.addDependency('../../core/msg.js', ['Blockly.Msg'], ['Blockly.utils.global']); +goog.addDependency('../../core/mutator.js', ['Blockly.Mutator'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.Options', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox', 'Blockly.utils.xml']); +goog.addDependency('../../core/names.js', ['Blockly.Names'], ['Blockly.Msg', 'Blockly.constants']); +goog.addDependency('../../core/options.js', ['Blockly.Options'], ['Blockly.Theme', 'Blockly.Themes.Classic', 'Blockly.registry', 'Blockly.utils.IdGenerator', 'Blockly.utils.Metrics', 'Blockly.utils.toolbox']); +goog.addDependency('../../core/positionable_helpers.js', ['Blockly.uiPosition'], ['Blockly.Scrollbar', 'Blockly.utils.Rect', 'Blockly.utils.toolbox']); +goog.addDependency('../../core/procedures.js', ['Blockly.Procedures'], ['Blockly.Blocks', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.Msg', 'Blockly.Names', 'Blockly.Workspace', 'Blockly.Xml', 'Blockly.constants', 'Blockly.utils.xml']); +goog.addDependency('../../core/registry.js', ['Blockly.registry'], []); +goog.addDependency('../../core/rendered_connection.js', ['Blockly.RenderedConnection'], ['Blockly.Connection', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object']); +goog.addDependency('../../core/renderers/common/block_rendering.js', ['Blockly.blockRendering'], ['Blockly.registry']); goog.addDependency('../../core/renderers/common/constants.js', ['Blockly.blockRendering.ConstantProvider'], ['Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.svgPaths', 'Blockly.utils.userAgent'], {'lang': 'es5'}); goog.addDependency('../../core/renderers/common/debugger.js', ['Blockly.blockRendering.Debug'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es5'}); -goog.addDependency('../../core/renderers/common/drawer.js', ['Blockly.blockRendering.Drawer'], ['Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.utils.svgPaths'], {}); -goog.addDependency('../../core/renderers/common/i_path_object.js', ['Blockly.blockRendering.IPathObject'], [], {}); -goog.addDependency('../../core/renderers/common/info.js', ['Blockly.blockRendering.RenderInfo'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.Hat', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.OutputConnection', 'Blockly.blockRendering.PreviousConnection', 'Blockly.blockRendering.RoundCorner', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.SquareCorner', 'Blockly.blockRendering.StatementInput', 'Blockly.blockRendering.TopRow', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.inputTypes'], {}); -goog.addDependency('../../core/renderers/common/marker_svg.js', ['Blockly.blockRendering.MarkerSvg'], ['Blockly.ASTNode', 'Blockly.Events', 'Blockly.Events.MarkerMove', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {}); -goog.addDependency('../../core/renderers/common/path_object.js', ['Blockly.blockRendering.PathObject'], ['Blockly.Theme', 'Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.IPathObject', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {}); -goog.addDependency('../../core/renderers/common/renderer.js', ['Blockly.blockRendering.Renderer'], ['Blockly.IRegistrable', 'Blockly.InsertionMarkerManager', 'Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.Debug', 'Blockly.blockRendering.Drawer', 'Blockly.blockRendering.IPathObject', 'Blockly.blockRendering.MarkerSvg', 'Blockly.blockRendering.PathObject', 'Blockly.blockRendering.RenderInfo', 'Blockly.connectionTypes', 'Blockly.constants'], {}); +goog.addDependency('../../core/renderers/common/drawer.js', ['Blockly.blockRendering.Drawer'], ['Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.utils.svgPaths']); +goog.addDependency('../../core/renderers/common/i_path_object.js', ['Blockly.blockRendering.IPathObject'], []); +goog.addDependency('../../core/renderers/common/info.js', ['Blockly.blockRendering.RenderInfo'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.Field', 'Blockly.blockRendering.Hat', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.JaggedEdge', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.OutputConnection', 'Blockly.blockRendering.PreviousConnection', 'Blockly.blockRendering.RoundCorner', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.SquareCorner', 'Blockly.blockRendering.StatementInput', 'Blockly.blockRendering.TopRow', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.inputTypes']); +goog.addDependency('../../core/renderers/common/marker_svg.js', ['Blockly.blockRendering.MarkerSvg'], ['Blockly.ASTNode', 'Blockly.Events', 'Blockly.Events.MarkerMove', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.Svg', 'Blockly.utils.dom']); +goog.addDependency('../../core/renderers/common/path_object.js', ['Blockly.blockRendering.PathObject'], ['Blockly.Theme', 'Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.IPathObject', 'Blockly.utils.Svg', 'Blockly.utils.dom']); +goog.addDependency('../../core/renderers/common/renderer.js', ['Blockly.blockRendering.Renderer'], ['Blockly.IRegistrable', 'Blockly.InsertionMarkerManager', 'Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.Debug', 'Blockly.blockRendering.Drawer', 'Blockly.blockRendering.IPathObject', 'Blockly.blockRendering.MarkerSvg', 'Blockly.blockRendering.PathObject', 'Blockly.blockRendering.RenderInfo', 'Blockly.connectionTypes', 'Blockly.constants']); goog.addDependency('../../core/renderers/geras/constants.js', ['Blockly.geras.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.utils.object'], {'lang': 'es5'}); -goog.addDependency('../../core/renderers/geras/drawer.js', ['Blockly.geras.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.geras.Highlighter', 'Blockly.geras.RenderInfo', 'Blockly.utils.object', 'Blockly.utils.svgPaths'], {}); +goog.addDependency('../../core/renderers/geras/drawer.js', ['Blockly.geras.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.geras.Highlighter', 'Blockly.geras.RenderInfo', 'Blockly.utils.object', 'Blockly.utils.svgPaths']); goog.addDependency('../../core/renderers/geras/highlight_constants.js', ['Blockly.geras.HighlightConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.utils.svgPaths'], {'lang': 'es5'}); -goog.addDependency('../../core/renderers/geras/highlighter.js', ['Blockly.geras.Highlighter'], ['Blockly.blockRendering.Types', 'Blockly.utils.svgPaths'], {}); -goog.addDependency('../../core/renderers/geras/info.js', ['Blockly.geras', 'Blockly.geras.RenderInfo'], ['Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.geras.InlineInput', 'Blockly.geras.StatementInput', 'Blockly.inputTypes', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/renderers/geras/measurables/inputs.js', ['Blockly.geras.InlineInput', 'Blockly.geras.StatementInput'], ['Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.StatementInput', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/renderers/geras/path_object.js', ['Blockly.geras.PathObject'], ['Blockly.Theme', 'Blockly.blockRendering.PathObject', 'Blockly.geras.ConstantProvider', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/renderers/geras/renderer.js', ['Blockly.geras.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.geras.ConstantProvider', 'Blockly.geras.Drawer', 'Blockly.geras.HighlightConstantProvider', 'Blockly.geras.PathObject', 'Blockly.geras.RenderInfo', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/renderers/measurables/base.js', ['Blockly.blockRendering.Measurable'], ['Blockly.blockRendering.Types'], {}); -goog.addDependency('../../core/renderers/measurables/connections.js', ['Blockly.blockRendering.Connection', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.OutputConnection', 'Blockly.blockRendering.PreviousConnection'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/renderers/measurables/inputs.js', ['Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.InputConnection', 'Blockly.blockRendering.StatementInput'], ['Blockly.blockRendering.Connection', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/renderers/measurables/row_elements.js', ['Blockly.blockRendering.Field', 'Blockly.blockRendering.Hat', 'Blockly.blockRendering.Icon', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.JaggedEdge', 'Blockly.blockRendering.RoundCorner', 'Blockly.blockRendering.SquareCorner'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/renderers/measurables/rows.js', ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.TopRow'], ['Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InputConnection', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.PreviousConnection', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/renderers/measurables/types.js', ['Blockly.blockRendering.Types'], [], {}); -goog.addDependency('../../core/renderers/minimalist/constants.js', ['Blockly.minimalist.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/renderers/minimalist/drawer.js', ['Blockly.minimalist.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.minimalist.RenderInfo', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/renderers/minimalist/info.js', ['Blockly.minimalist', 'Blockly.minimalist.RenderInfo'], ['Blockly.utils.object'], {}); -goog.addDependency('../../core/renderers/minimalist/renderer.js', ['Blockly.minimalist.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.minimalist.ConstantProvider', 'Blockly.minimalist.Drawer', 'Blockly.minimalist.RenderInfo', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/renderers/thrasos/info.js', ['Blockly.thrasos', 'Blockly.thrasos.RenderInfo'], ['Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/renderers/thrasos/renderer.js', ['Blockly.thrasos.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.thrasos.RenderInfo', 'Blockly.utils.object'], {}); +goog.addDependency('../../core/renderers/geras/highlighter.js', ['Blockly.geras.Highlighter'], ['Blockly.blockRendering.Types', 'Blockly.utils.svgPaths']); +goog.addDependency('../../core/renderers/geras/info.js', ['Blockly.geras', 'Blockly.geras.RenderInfo'], ['Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.geras.InlineInput', 'Blockly.geras.StatementInput', 'Blockly.inputTypes', 'Blockly.utils.object']); +goog.addDependency('../../core/renderers/geras/measurables/inputs.js', ['Blockly.geras.InlineInput', 'Blockly.geras.StatementInput'], ['Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.StatementInput', 'Blockly.utils.object']); +goog.addDependency('../../core/renderers/geras/path_object.js', ['Blockly.geras.PathObject'], ['Blockly.Theme', 'Blockly.blockRendering.PathObject', 'Blockly.geras.ConstantProvider', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object']); +goog.addDependency('../../core/renderers/geras/renderer.js', ['Blockly.geras.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.geras.ConstantProvider', 'Blockly.geras.Drawer', 'Blockly.geras.HighlightConstantProvider', 'Blockly.geras.PathObject', 'Blockly.geras.RenderInfo', 'Blockly.utils.object']); +goog.addDependency('../../core/renderers/measurables/base.js', ['Blockly.blockRendering.Measurable'], ['Blockly.blockRendering.Types']); +goog.addDependency('../../core/renderers/measurables/connections.js', ['Blockly.blockRendering.Connection', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.OutputConnection', 'Blockly.blockRendering.PreviousConnection'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object']); +goog.addDependency('../../core/renderers/measurables/inputs.js', ['Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.InputConnection', 'Blockly.blockRendering.StatementInput'], ['Blockly.blockRendering.Connection', 'Blockly.blockRendering.Types', 'Blockly.utils.object']); +goog.addDependency('../../core/renderers/measurables/row_elements.js', ['Blockly.blockRendering.Field', 'Blockly.blockRendering.Hat', 'Blockly.blockRendering.Icon', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.JaggedEdge', 'Blockly.blockRendering.RoundCorner', 'Blockly.blockRendering.SquareCorner'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object']); +goog.addDependency('../../core/renderers/measurables/rows.js', ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.TopRow'], ['Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InputConnection', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.PreviousConnection', 'Blockly.blockRendering.Types', 'Blockly.utils.object']); +goog.addDependency('../../core/renderers/measurables/types.js', ['Blockly.blockRendering.Types'], []); +goog.addDependency('../../core/renderers/minimalist/constants.js', ['Blockly.minimalist.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.utils.object']); +goog.addDependency('../../core/renderers/minimalist/drawer.js', ['Blockly.minimalist.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.minimalist.RenderInfo', 'Blockly.utils.object']); +goog.addDependency('../../core/renderers/minimalist/info.js', ['Blockly.minimalist', 'Blockly.minimalist.RenderInfo'], ['Blockly.utils.object']); +goog.addDependency('../../core/renderers/minimalist/renderer.js', ['Blockly.minimalist.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.minimalist.ConstantProvider', 'Blockly.minimalist.Drawer', 'Blockly.minimalist.RenderInfo', 'Blockly.utils.object']); +goog.addDependency('../../core/renderers/thrasos/info.js', ['Blockly.thrasos', 'Blockly.thrasos.RenderInfo'], ['Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.utils.object']); +goog.addDependency('../../core/renderers/thrasos/renderer.js', ['Blockly.thrasos.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.thrasos.RenderInfo', 'Blockly.utils.object']); goog.addDependency('../../core/renderers/zelos/constants.js', ['Blockly.zelos.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.svgPaths'], {'lang': 'es5'}); -goog.addDependency('../../core/renderers/zelos/drawer.js', ['Blockly.zelos.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.utils.object', 'Blockly.utils.svgPaths', 'Blockly.zelos.RenderInfo'], {}); -goog.addDependency('../../core/renderers/zelos/info.js', ['Blockly.zelos', 'Blockly.zelos.RenderInfo'], ['Blockly.FieldImage', 'Blockly.FieldLabel', 'Blockly.FieldTextInput', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.inputTypes', 'Blockly.utils.object', 'Blockly.zelos.BottomRow', 'Blockly.zelos.RightConnectionShape', 'Blockly.zelos.TopRow'], {}); -goog.addDependency('../../core/renderers/zelos/marker_svg.js', ['Blockly.zelos.MarkerSvg'], ['Blockly.blockRendering.MarkerSvg', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {}); -goog.addDependency('../../core/renderers/zelos/measurables/inputs.js', ['Blockly.zelos.StatementInput'], ['Blockly.blockRendering.StatementInput', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/renderers/zelos/measurables/row_elements.js', ['Blockly.zelos.RightConnectionShape'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/renderers/zelos/measurables/rows.js', ['Blockly.zelos.BottomRow', 'Blockly.zelos.TopRow'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.TopRow', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/renderers/zelos/path_object.js', ['Blockly.zelos.PathObject'], ['Blockly.blockRendering.PathObject', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.zelos.ConstantProvider'], {}); -goog.addDependency('../../core/renderers/zelos/renderer.js', ['Blockly.zelos.Renderer'], ['Blockly.InsertionMarkerManager', 'Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.object', 'Blockly.zelos.ConstantProvider', 'Blockly.zelos.Drawer', 'Blockly.zelos.MarkerSvg', 'Blockly.zelos.PathObject', 'Blockly.zelos.RenderInfo'], {}); -goog.addDependency('../../core/requires.js', ['Blockly.requires'], ['Blockly', 'Blockly.Comment', 'Blockly.ContextMenuItems', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldLabelSerializable', 'Blockly.FieldMultilineInput', 'Blockly.FieldNumber', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.FlyoutButton', 'Blockly.Generator', 'Blockly.HorizontalFlyout', 'Blockly.Mutator', 'Blockly.ShortcutItems', 'Blockly.Themes.Classic', 'Blockly.Themes.Dark', 'Blockly.Themes.Deuteranopia', 'Blockly.Themes.HighContrast', 'Blockly.Themes.Tritanopia', 'Blockly.Toolbox', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.VerticalFlyout', 'Blockly.Warning', 'Blockly.ZoomControls', 'Blockly.geras.Renderer', 'Blockly.thrasos.Renderer', 'Blockly.zelos.Renderer'], {}); -goog.addDependency('../../core/scrollbar.js', ['Blockly.Scrollbar', 'Blockly.ScrollbarPair'], ['Blockly.Events', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Metrics', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {}); -goog.addDependency('../../core/shortcut_items.js', ['Blockly.ShortcutItems'], ['Blockly.Gesture', 'Blockly.ShortcutRegistry', 'Blockly.utils.KeyCodes'], {}); -goog.addDependency('../../core/shortcut_registry.js', ['Blockly.ShortcutRegistry'], ['Blockly.utils.KeyCodes', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/theme.js', ['Blockly.Theme'], ['Blockly.registry', 'Blockly.utils', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/theme/classic.js', ['Blockly.Themes.Classic'], ['Blockly.Theme'], {}); -goog.addDependency('../../core/theme/dark.js', ['Blockly.Themes.Dark'], ['Blockly.Theme'], {}); -goog.addDependency('../../core/theme/deuteranopia.js', ['Blockly.Themes.Deuteranopia'], ['Blockly.Theme'], {}); -goog.addDependency('../../core/theme/highcontrast.js', ['Blockly.Themes.HighContrast'], ['Blockly.Theme'], {}); -goog.addDependency('../../core/theme/modern.js', ['Blockly.Themes.Modern'], ['Blockly.Theme'], {}); -goog.addDependency('../../core/theme/tritanopia.js', ['Blockly.Themes.Tritanopia'], ['Blockly.Theme'], {}); -goog.addDependency('../../core/theme/zelos.js', ['Blockly.Themes.Zelos'], ['Blockly.Theme'], {}); -goog.addDependency('../../core/theme_manager.js', ['Blockly.ThemeManager'], ['Blockly.Theme'], {}); -goog.addDependency('../../core/toolbox/category.js', ['Blockly.ToolboxCategory'], ['Blockly.ToolboxItem', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es5'}); -goog.addDependency('../../core/toolbox/collapsible_category.js', ['Blockly.CollapsibleToolboxCategory'], ['Blockly.ToolboxCategory', 'Blockly.ToolboxItem', 'Blockly.ToolboxSeparator', 'Blockly.registry', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {}); -goog.addDependency('../../core/toolbox/separator.js', ['Blockly.ToolboxSeparator'], ['Blockly.ToolboxItem', 'Blockly.registry', 'Blockly.utils.dom'], {'lang': 'es5'}); -goog.addDependency('../../core/toolbox/toolbox.js', ['Blockly.Toolbox'], ['Blockly.CollapsibleToolboxCategory', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.ToolboxItemSelect', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.toolbox'], {'lang': 'es5'}); -goog.addDependency('../../core/toolbox/toolbox_item.js', ['Blockly.ToolboxItem'], [], {}); -goog.addDependency('../../core/tooltip.js', ['Blockly.Tooltip'], ['Blockly.browserEvents', 'Blockly.utils.string'], {}); -goog.addDependency('../../core/touch.js', ['Blockly.Touch'], ['Blockly.constants', 'Blockly.utils', 'Blockly.utils.global', 'Blockly.utils.string'], {}); -goog.addDependency('../../core/touch_gesture.js', ['Blockly.TouchGesture'], ['Blockly.Gesture', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/trashcan.js', ['Blockly.Trashcan'], ['Blockly.Events', 'Blockly.Events.TrashcanOpen', 'Blockly.IPositionable', 'Blockly.Scrollbar', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.toolbox'], {'lang': 'es5'}); -goog.addDependency('../../core/utils.js', ['Blockly.utils'], ['Blockly.Msg', 'Blockly.constants', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.colour', 'Blockly.utils.global', 'Blockly.utils.string', 'Blockly.utils.style', 'Blockly.utils.userAgent'], {}); -goog.addDependency('../../core/utils/aria.js', ['Blockly.utils.aria'], [], {}); -goog.addDependency('../../core/utils/colour.js', ['Blockly.utils.colour'], [], {}); -goog.addDependency('../../core/utils/coordinate.js', ['Blockly.utils.Coordinate'], [], {}); -goog.addDependency('../../core/utils/deprecation.js', ['Blockly.utils.deprecation'], [], {}); -goog.addDependency('../../core/utils/dom.js', ['Blockly.utils.dom'], ['Blockly.utils.Svg', 'Blockly.utils.userAgent'], {}); -goog.addDependency('../../core/utils/global.js', ['Blockly.utils.global'], [], {}); -goog.addDependency('../../core/utils/idgenerator.js', ['Blockly.utils.IdGenerator'], [], {}); -goog.addDependency('../../core/utils/keycodes.js', ['Blockly.utils.KeyCodes'], [], {}); -goog.addDependency('../../core/utils/math.js', ['Blockly.utils.math'], [], {}); -goog.addDependency('../../core/utils/metrics.js', ['Blockly.utils.Metrics'], [], {}); -goog.addDependency('../../core/utils/object.js', ['Blockly.utils.object'], [], {}); -goog.addDependency('../../core/utils/rect.js', ['Blockly.utils.Rect'], [], {}); -goog.addDependency('../../core/utils/size.js', ['Blockly.utils.Size'], [], {}); -goog.addDependency('../../core/utils/string.js', ['Blockly.utils.string'], [], {}); -goog.addDependency('../../core/utils/style.js', ['Blockly.utils.style'], ['Blockly.utils.Coordinate', 'Blockly.utils.Size'], {}); -goog.addDependency('../../core/utils/svg.js', ['Blockly.utils.Svg'], [], {}); -goog.addDependency('../../core/utils/svg_paths.js', ['Blockly.utils.svgPaths'], [], {}); -goog.addDependency('../../core/utils/toolbox.js', ['Blockly.utils.toolbox'], ['Blockly.Xml', 'Blockly.constants'], {}); -goog.addDependency('../../core/utils/useragent.js', ['Blockly.utils.userAgent'], ['Blockly.utils.global'], {}); -goog.addDependency('../../core/utils/xml.js', ['Blockly.utils.xml'], [], {}); -goog.addDependency('../../core/variable_map.js', ['Blockly.VariableMap'], ['Blockly.Events', 'Blockly.Events.VarDelete', 'Blockly.Events.VarRename', 'Blockly.Msg', 'Blockly.utils', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/variable_model.js', ['Blockly.VariableModel'], ['Blockly.Events', 'Blockly.Events.VarCreate', 'Blockly.utils'], {}); -goog.addDependency('../../core/variables.js', ['Blockly.Variables'], ['Blockly.Blocks', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Xml', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.xml'], {}); -goog.addDependency('../../core/variables_dynamic.js', ['Blockly.VariablesDynamic'], ['Blockly.Blocks', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.utils.xml'], {}); -goog.addDependency('../../core/warning.js', ['Blockly.Warning'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/widgetdiv.js', ['Blockly.WidgetDiv'], ['Blockly.utils.dom'], {}); -goog.addDependency('../../core/workspace.js', ['Blockly.Workspace'], ['Blockly.ConnectionChecker', 'Blockly.Events', 'Blockly.Options', 'Blockly.VariableMap', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.math'], {}); +goog.addDependency('../../core/renderers/zelos/drawer.js', ['Blockly.zelos.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.utils.object', 'Blockly.utils.svgPaths', 'Blockly.zelos.RenderInfo']); +goog.addDependency('../../core/renderers/zelos/info.js', ['Blockly.zelos', 'Blockly.zelos.RenderInfo'], ['Blockly.FieldImage', 'Blockly.FieldLabel', 'Blockly.FieldTextInput', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.inputTypes', 'Blockly.utils.object', 'Blockly.zelos.BottomRow', 'Blockly.zelos.RightConnectionShape', 'Blockly.zelos.TopRow']); +goog.addDependency('../../core/renderers/zelos/marker_svg.js', ['Blockly.zelos.MarkerSvg'], ['Blockly.blockRendering.MarkerSvg', 'Blockly.utils.Svg', 'Blockly.utils.dom']); +goog.addDependency('../../core/renderers/zelos/measurables/inputs.js', ['Blockly.zelos.StatementInput'], ['Blockly.blockRendering.StatementInput', 'Blockly.utils.object']); +goog.addDependency('../../core/renderers/zelos/measurables/row_elements.js', ['Blockly.zelos.RightConnectionShape'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object']); +goog.addDependency('../../core/renderers/zelos/measurables/rows.js', ['Blockly.zelos.BottomRow', 'Blockly.zelos.TopRow'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.TopRow', 'Blockly.utils.object']); +goog.addDependency('../../core/renderers/zelos/path_object.js', ['Blockly.zelos.PathObject'], ['Blockly.blockRendering.PathObject', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.zelos.ConstantProvider']); +goog.addDependency('../../core/renderers/zelos/renderer.js', ['Blockly.zelos.Renderer'], ['Blockly.InsertionMarkerManager', 'Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.object', 'Blockly.zelos.ConstantProvider', 'Blockly.zelos.Drawer', 'Blockly.zelos.MarkerSvg', 'Blockly.zelos.PathObject', 'Blockly.zelos.RenderInfo']); +goog.addDependency('../../core/requires.js', ['Blockly.requires'], ['Blockly', 'Blockly.Comment', 'Blockly.ContextMenuItems', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldLabelSerializable', 'Blockly.FieldMultilineInput', 'Blockly.FieldNumber', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.FlyoutButton', 'Blockly.Generator', 'Blockly.HorizontalFlyout', 'Blockly.Mutator', 'Blockly.ShortcutItems', 'Blockly.Themes.Classic', 'Blockly.Themes.Deuteranopia', 'Blockly.Themes.HighContrast', 'Blockly.Themes.Tritanopia', 'Blockly.Toolbox', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.VerticalFlyout', 'Blockly.Warning', 'Blockly.ZoomControls', 'Blockly.geras.Renderer', 'Blockly.thrasos.Renderer', 'Blockly.zelos.Renderer']); +goog.addDependency('../../core/scrollbar.js', ['Blockly.Scrollbar', 'Blockly.ScrollbarPair'], ['Blockly.Events', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Metrics', 'Blockly.utils.Svg', 'Blockly.utils.dom']); +goog.addDependency('../../core/shortcut_items.js', ['Blockly.ShortcutItems'], ['Blockly.Gesture', 'Blockly.ShortcutRegistry', 'Blockly.utils.KeyCodes']); +goog.addDependency('../../core/shortcut_registry.js', ['Blockly.ShortcutRegistry'], ['Blockly.utils.KeyCodes', 'Blockly.utils.object']); +goog.addDependency('../../core/theme.js', ['Blockly.Theme'], ['Blockly.registry', 'Blockly.utils', 'Blockly.utils.object']); +goog.addDependency('../../core/theme/classic.js', ['Blockly.Themes.Classic'], ['Blockly.Theme']); +goog.addDependency('../../core/theme/deuteranopia.js', ['Blockly.Themes.Deuteranopia'], ['Blockly.Theme']); +goog.addDependency('../../core/theme/highcontrast.js', ['Blockly.Themes.HighContrast'], ['Blockly.Theme']); +goog.addDependency('../../core/theme/tritanopia.js', ['Blockly.Themes.Tritanopia'], ['Blockly.Theme']); +goog.addDependency('../../core/theme/zelos.js', ['Blockly.Themes.Zelos'], ['Blockly.Theme']); +goog.addDependency('../../core/theme_manager.js', ['Blockly.ThemeManager'], ['Blockly.Theme']); +goog.addDependency('../../core/toolbox/category.js', ['Blockly.ToolboxCategory'], ['Blockly.ISelectableToolboxItem', 'Blockly.ToolboxItem', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es5'}); +goog.addDependency('../../core/toolbox/collapsible_category.js', ['Blockly.CollapsibleToolboxCategory'], ['Blockly.ICollapsibleToolboxItem', 'Blockly.ToolboxCategory', 'Blockly.ToolboxItem', 'Blockly.ToolboxSeparator', 'Blockly.registry', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox']); +goog.addDependency('../../core/toolbox/separator.js', ['Blockly.ToolboxSeparator'], ['Blockly.IToolboxItem', 'Blockly.ToolboxItem', 'Blockly.registry', 'Blockly.utils.dom'], {'lang': 'es5'}); +goog.addDependency('../../core/toolbox/toolbox.js', ['Blockly.Toolbox'], ['Blockly.CollapsibleToolboxCategory', 'Blockly.Css', 'Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.ToolboxItemSelect', 'Blockly.IAutoHideable', 'Blockly.IKeyboardAccessible', 'Blockly.IStyleable', 'Blockly.IToolbox', 'Blockly.Options', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.toolbox'], {'lang': 'es5'}); +goog.addDependency('../../core/toolbox/toolbox_item.js', ['Blockly.ToolboxItem'], ['Blockly.IToolboxItem']); +goog.addDependency('../../core/tooltip.js', ['Blockly.Tooltip'], ['Blockly.browserEvents', 'Blockly.utils.string']); +goog.addDependency('../../core/touch.js', ['Blockly.Touch'], ['Blockly.constants', 'Blockly.utils', 'Blockly.utils.global', 'Blockly.utils.string']); +goog.addDependency('../../core/touch_gesture.js', ['Blockly.TouchGesture'], ['Blockly.Gesture', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.object']); +goog.addDependency('../../core/trashcan.js', ['Blockly.Trashcan'], ['Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.TrashcanOpen', 'Blockly.IAutoHideable', 'Blockly.IPositionable', 'Blockly.Options', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.uiPosition', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.toolbox'], {'lang': 'es5'}); +goog.addDependency('../../core/utils.js', ['Blockly.utils'], ['Blockly.Msg', 'Blockly.constants', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.colour', 'Blockly.utils.global', 'Blockly.utils.string', 'Blockly.utils.style', 'Blockly.utils.userAgent']); +goog.addDependency('../../core/utils/aria.js', ['Blockly.utils.aria'], []); +goog.addDependency('../../core/utils/colour.js', ['Blockly.utils.colour'], []); +goog.addDependency('../../core/utils/coordinate.js', ['Blockly.utils.Coordinate'], []); +goog.addDependency('../../core/utils/deprecation.js', ['Blockly.utils.deprecation'], []); +goog.addDependency('../../core/utils/dom.js', ['Blockly.utils.dom'], ['Blockly.utils.Svg', 'Blockly.utils.userAgent']); +goog.addDependency('../../core/utils/global.js', ['Blockly.utils.global'], []); +goog.addDependency('../../core/utils/idgenerator.js', ['Blockly.utils.IdGenerator'], []); +goog.addDependency('../../core/utils/keycodes.js', ['Blockly.utils.KeyCodes'], []); +goog.addDependency('../../core/utils/math.js', ['Blockly.utils.math'], []); +goog.addDependency('../../core/utils/metrics.js', ['Blockly.utils.Metrics'], []); +goog.addDependency('../../core/utils/object.js', ['Blockly.utils.object'], []); +goog.addDependency('../../core/utils/rect.js', ['Blockly.utils.Rect'], []); +goog.addDependency('../../core/utils/size.js', ['Blockly.utils.Size'], []); +goog.addDependency('../../core/utils/string.js', ['Blockly.utils.string'], []); +goog.addDependency('../../core/utils/style.js', ['Blockly.utils.style'], ['Blockly.utils.Coordinate', 'Blockly.utils.Size']); +goog.addDependency('../../core/utils/svg.js', ['Blockly.utils.Svg'], []); +goog.addDependency('../../core/utils/svg_paths.js', ['Blockly.utils.svgPaths'], []); +goog.addDependency('../../core/utils/toolbox.js', ['Blockly.utils.toolbox'], ['Blockly.Xml', 'Blockly.constants']); +goog.addDependency('../../core/utils/useragent.js', ['Blockly.utils.userAgent'], ['Blockly.utils.global']); +goog.addDependency('../../core/utils/xml.js', ['Blockly.utils.xml'], []); +goog.addDependency('../../core/variable_map.js', ['Blockly.VariableMap'], ['Blockly.Events', 'Blockly.Events.VarDelete', 'Blockly.Events.VarRename', 'Blockly.Msg', 'Blockly.utils', 'Blockly.utils.object']); +goog.addDependency('../../core/variable_model.js', ['Blockly.VariableModel'], ['Blockly.Events', 'Blockly.Events.VarCreate', 'Blockly.utils']); +goog.addDependency('../../core/variables.js', ['Blockly.Variables'], ['Blockly.Blocks', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Xml', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.xml']); +goog.addDependency('../../core/variables_dynamic.js', ['Blockly.VariablesDynamic'], ['Blockly.Blocks', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.utils.xml']); +goog.addDependency('../../core/warning.js', ['Blockly.Warning'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object']); +goog.addDependency('../../core/widgetdiv.js', ['Blockly.WidgetDiv'], ['Blockly.utils.dom']); +goog.addDependency('../../core/workspace.js', ['Blockly.Workspace'], ['Blockly.ConnectionChecker', 'Blockly.Events', 'Blockly.IASTNodeLocation', 'Blockly.Options', 'Blockly.VariableMap', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.math']); goog.addDependency('../../core/workspace_audio.js', ['Blockly.WorkspaceAudio'], ['Blockly.constants', 'Blockly.utils', 'Blockly.utils.global', 'Blockly.utils.userAgent'], {'lang': 'es5'}); -goog.addDependency('../../core/workspace_comment.js', ['Blockly.WorkspaceComment'], ['Blockly.Events', 'Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.xml'], {}); -goog.addDependency('../../core/workspace_comment_render_svg.js', ['Blockly.WorkspaceCommentSvg.render'], ['Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {}); -goog.addDependency('../../core/workspace_comment_svg.js', ['Blockly.WorkspaceCommentSvg'], ['Blockly.Css', 'Blockly.Events', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.Events.Selected', 'Blockly.WorkspaceComment', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {}); -goog.addDependency('../../core/workspace_drag_surface_svg.js', ['Blockly.WorkspaceDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {}); -goog.addDependency('../../core/workspace_dragger.js', ['Blockly.WorkspaceDragger'], ['Blockly.utils.Coordinate'], {}); -goog.addDependency('../../core/workspace_svg.js', ['Blockly.WorkspaceSvg'], ['Blockly.BlockSvg', 'Blockly.ConnectionDB', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.ThemeChange', 'Blockly.Events.ViewportChange', 'Blockly.Gesture', 'Blockly.Grid', 'Blockly.MarkerManager', 'Blockly.MetricsManager', 'Blockly.Msg', 'Blockly.Options', 'Blockly.PluginManager', 'Blockly.ThemeManager', 'Blockly.Themes.Classic', 'Blockly.TouchGesture', 'Blockly.Workspace', 'Blockly.WorkspaceAudio', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.Xml', 'Blockly.blockRendering', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Metrics', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es5'}); -goog.addDependency('../../core/xml.js', ['Blockly.Xml'], ['Blockly.Events', 'Blockly.constants', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.dom', 'Blockly.utils.xml'], {}); -goog.addDependency('../../core/zoom_controls.js', ['Blockly.ZoomControls'], ['Blockly.Css', 'Blockly.Events', 'Blockly.Events.Click', 'Blockly.IPositionable', 'Blockly.Scrollbar', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.toolbox'], {'lang': 'es5'}); +goog.addDependency('../../core/workspace_comment.js', ['Blockly.WorkspaceComment'], ['Blockly.Events', 'Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.xml']); +goog.addDependency('../../core/workspace_comment_render_svg.js', ['Blockly.WorkspaceCommentSvg.render'], ['Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom']); +goog.addDependency('../../core/workspace_comment_svg.js', ['Blockly.WorkspaceCommentSvg'], ['Blockly.Css', 'Blockly.Events', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.Events.Selected', 'Blockly.WorkspaceComment', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object']); +goog.addDependency('../../core/workspace_drag_surface_svg.js', ['Blockly.WorkspaceDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.dom']); +goog.addDependency('../../core/workspace_dragger.js', ['Blockly.WorkspaceDragger'], ['Blockly.utils.Coordinate']); +goog.addDependency('../../core/workspace_svg.js', ['Blockly.WorkspaceSvg'], ['Blockly.BlockSvg', 'Blockly.ComponentManager', 'Blockly.ConnectionDB', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.ThemeChange', 'Blockly.Events.ViewportChange', 'Blockly.Gesture', 'Blockly.Grid', 'Blockly.IASTNodeLocationSvg', 'Blockly.MarkerManager', 'Blockly.MetricsManager', 'Blockly.Msg', 'Blockly.Options', 'Blockly.ThemeManager', 'Blockly.Themes.Classic', 'Blockly.TouchGesture', 'Blockly.Workspace', 'Blockly.WorkspaceAudio', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.Xml', 'Blockly.blockRendering', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Metrics', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es5'}); +goog.addDependency('../../core/xml.js', ['Blockly.Xml'], ['Blockly.Events', 'Blockly.constants', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.dom', 'Blockly.utils.xml']); +goog.addDependency('../../core/zoom_controls.js', ['Blockly.ZoomControls'], ['Blockly.Css', 'Blockly.Events', 'Blockly.Events.Click', 'Blockly.IPositionable', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.uiPosition', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es5'}); goog.addDependency("base.js", [], []); // Load Blockly. diff --git a/blocks/logic.js b/blocks/logic.js index c45089dec..c7b6acf0c 100644 --- a/blocks/logic.js +++ b/blocks/logic.js @@ -473,9 +473,9 @@ Blockly.Constants.Logic.CONTROLS_IF_MUTATOR_MIXIN = { }, /** * Reconnects child blocks. - * @param {!Array.} valueConnections List of + * @param {!Array} valueConnections List of * value connections for 'if' input. - * @param {!Array.} statementConnections List of + * @param {!Array} statementConnections List of * statement connections for 'do' input. * @param {?Blockly.RenderedConnection} elseStatementConnection Statement * connection for else input. diff --git a/blocks/procedures.js b/blocks/procedures.js index 242fa4f0b..d6127cca0 100644 --- a/blocks/procedures.js +++ b/blocks/procedures.js @@ -264,7 +264,7 @@ Blockly.Blocks['procedures_defnoreturn'] = { }, /** * Return all variables referenced by this block. - * @return {!Array.} List of variable names. + * @return {!Array} List of variable names. * @this {Blockly.Block} */ getVars: function() { @@ -272,7 +272,7 @@ Blockly.Blocks['procedures_defnoreturn'] = { }, /** * Return all variables referenced by this block. - * @return {!Array.} List of variable models. + * @return {!Array} List of variable models. * @this {Blockly.Block} */ getVarModels: function() { @@ -634,8 +634,8 @@ Blockly.Blocks['procedures_callnoreturn'] = { }, /** * Notification that the procedure's parameters have changed. - * @param {!Array.} paramNames New param names, e.g. ['x', 'y', 'z']. - * @param {!Array.} paramIds IDs of params (consistent for each + * @param {!Array} paramNames New param names, e.g. ['x', 'y', 'z']. + * @param {!Array} paramIds IDs of params (consistent for each * parameter through the life of a mutator, regardless of param renaming), * e.g. ['piua', 'f8b_', 'oi.o']. * @private @@ -809,7 +809,7 @@ Blockly.Blocks['procedures_callnoreturn'] = { }, /** * Return all variables referenced by this block. - * @return {!Array.} List of variable names. + * @return {!Array} List of variable names. * @this {Blockly.Block} */ getVars: function() { @@ -817,7 +817,7 @@ Blockly.Blocks['procedures_callnoreturn'] = { }, /** * Return all variables referenced by this block. - * @return {!Array.} List of variable models. + * @return {!Array} List of variable models. * @this {Blockly.Block} */ getVarModels: function() { diff --git a/build.py b/build.py index 48d1502c0..2f963ce38 100755 --- a/build.py +++ b/build.py @@ -135,7 +135,7 @@ this.BLOCKLY_BOOT = function(root) { f.write('\n') f.write('// Load Blockly.\n') - f.write('goog.require(\'Blockly.requires\')\n') + f.write('goog.require(\'Blockly.requires\');\n') f.write(""" delete root.BLOCKLY_DIR; diff --git a/core/block.js b/core/block.js index a3e6b01ac..d27f5256c 100644 --- a/core/block.js +++ b/core/block.js @@ -29,6 +29,7 @@ goog.require('Blockly.Events.BlockDelete'); goog.require('Blockly.Events.BlockMove'); goog.require('Blockly.Extensions'); goog.require('Blockly.fieldRegistry'); +goog.require('Blockly.IASTNodeLocation'); goog.require('Blockly.Input'); goog.require('Blockly.inputTypes'); goog.require('Blockly.Tooltip'); @@ -41,7 +42,6 @@ goog.require('Blockly.Workspace'); goog.requireType('Blockly.Comment'); goog.requireType('Blockly.Events.Abstract'); goog.requireType('Blockly.Field'); -goog.requireType('Blockly.IASTNodeLocation'); goog.requireType('Blockly.Mutator'); goog.requireType('Blockly.utils.Size'); goog.requireType('Blockly.VariableModel'); @@ -77,7 +77,7 @@ Blockly.Block = function(workspace, prototypeName, opt_id) { this.nextConnection = null; /** @type {Blockly.Connection} */ this.previousConnection = null; - /** @type {!Array.} */ + /** @type {!Array} */ this.inputList = []; /** @type {boolean|undefined} */ this.inputsInline = undefined; @@ -98,7 +98,7 @@ Blockly.Block = function(workspace, prototypeName, opt_id) { this.parentBlock_ = null; /** - * @type {!Array.} + * @type {!Array} * @protected */ this.childBlocks_ = []; @@ -263,13 +263,13 @@ Blockly.Block = function(workspace, prototypeName, opt_id) { Blockly.Block.CommentModel; /** - * The language-neutral id given to the collapsed input. + * The language-neutral ID given to the collapsed input. * @const {string} */ Blockly.Block.COLLAPSED_INPUT_NAME = Blockly.constants.COLLAPSED_INPUT_NAME; /** - * The language-neutral id given to the collapsed field. + * The language-neutral ID given to the collapsed field. * @const {string} */ Blockly.Block.COLLAPSED_FIELD_NAME = Blockly.constants.COLLAPSED_FIELD_NAME; @@ -305,10 +305,10 @@ Blockly.Block.prototype.colour_ = '#000000'; /** * Name of the block style. - * @type {?string} + * @type {string} * @protected */ -Blockly.Block.prototype.styleName_ = null; +Blockly.Block.prototype.styleName_ = ''; /** * An optional method called during initialization. @@ -349,7 +349,7 @@ Blockly.Block.prototype.suppressPrefixSuffix; * An optional property for declaring developer variables. Return a list of * variable names for use by generators. Developer variables are never shown to * the user, but are declared as global variables in the generated code. - * @type {?function():!Array.} + * @type {?function():!Array} */ Blockly.Block.prototype.getDeveloperVariables; @@ -498,7 +498,7 @@ Blockly.Block.prototype.unplugFromRow_ = function(opt_healStack) { * Since only one block can be displaced and attached to the insertion marker * this should only ever return one connection. * - * @return {Blockly.Connection} The connection on the value input, or null. + * @return {?Blockly.Connection} The connection on the value input, or null. * @private */ Blockly.Block.prototype.getOnlyValueConnection_ = function() { @@ -509,7 +509,7 @@ Blockly.Block.prototype.getOnlyValueConnection_ = function() { thisConnection.type == Blockly.connectionTypes.INPUT_VALUE && thisConnection.targetConnection) { if (connection) { - return null; // More than one value input found. + return null; // More than one value input found. } connection = thisConnection; } @@ -549,7 +549,7 @@ Blockly.Block.prototype.unplugFromStack_ = function(opt_healStack) { /** * Returns all connections originating from this block. * @param {boolean} _all If true, return all connections even hidden ones. - * @return {!Array.} Array of connections. + * @return {!Array} Array of connections. * @package */ Blockly.Block.prototype.getConnections_ = function(_all) { @@ -573,7 +573,7 @@ Blockly.Block.prototype.getConnections_ = function(_all) { /** * Walks down a stack of blocks and finds the last next connection on the stack. - * @return {Blockly.Connection} The last next connection on the stack, or null. + * @return {?Blockly.Connection} The last next connection on the stack, or null. * @package */ Blockly.Block.prototype.lastConnectionInStack = function() { @@ -602,7 +602,7 @@ Blockly.Block.prototype.bumpNeighbours = function() { * Return the parent block or null if this block is at the top level. The parent * block is either the block connected to the previous connection (for a statement * block) or the block connected to the output connection (for a value block). - * @return {Blockly.Block} The block that holds the current block. + * @return {?Blockly.Block} The block (if any) that holds the current block. */ Blockly.Block.prototype.getParent = function() { // Look at the DOM to see if we are nested in another block. @@ -612,7 +612,8 @@ Blockly.Block.prototype.getParent = function() { /** * Return the input that connects to the specified block. * @param {!Blockly.Block} block A block connected to an input on this block. - * @return {Blockly.Input} The input that connects to the specified block. + * @return {?Blockly.Input} The input (if any) that connects to the specified + * block. */ Blockly.Block.prototype.getInputWithBlock = function(block) { for (var i = 0, input; (input = this.inputList[i]); i++) { @@ -627,7 +628,7 @@ Blockly.Block.prototype.getInputWithBlock = function(block) { * Return the parent block that surrounds the current block, or null if this * block has no surrounding block. A parent block might just be the previous * statement, whereas the surrounding block is an if statement, while loop, etc. - * @return {Blockly.Block} The block that surrounds the current block. + * @return {?Blockly.Block} The block (if any) that surrounds the current block. */ Blockly.Block.prototype.getSurroundParent = function() { var block = this; @@ -645,7 +646,7 @@ Blockly.Block.prototype.getSurroundParent = function() { /** * Return the next statement block directly connected to this block. - * @return {Blockly.Block} The next statement block or null. + * @return {?Blockly.Block} The next statement block or null. */ Blockly.Block.prototype.getNextBlock = function() { return this.nextConnection && this.nextConnection.targetBlock(); @@ -653,7 +654,7 @@ Blockly.Block.prototype.getNextBlock = function() { /** * Returns the block connected to the previous connection. - * @return {Blockly.Block} The previous statement block or null. + * @return {?Blockly.Block} The previous statement block or null. */ Blockly.Block.prototype.getPreviousBlock = function() { return this.previousConnection && this.previousConnection.targetBlock(); @@ -662,7 +663,7 @@ Blockly.Block.prototype.getPreviousBlock = function() { /** * Return the connection on the first statement input on this block, or null if * there are none. - * @return {Blockly.Connection} The first statement connection or null. + * @return {?Blockly.Connection} The first statement connection or null. * @package */ Blockly.Block.prototype.getFirstStatementConnection = function() { @@ -711,7 +712,7 @@ Blockly.Block.prototype.getTopStackBlock = function() { * Excludes any connection on an output tab or any preceding statement. * Blocks are optionally sorted by position; top to bottom. * @param {boolean} ordered Sort the list if true. - * @return {!Array.} Array of blocks. + * @return {!Array} Array of blocks. */ Blockly.Block.prototype.getChildren = function(ordered) { if (!ordered) { @@ -776,7 +777,7 @@ Blockly.Block.prototype.setParent = function(newParent) { * Excludes any connection on an output tab or any preceding statements. * Blocks are optionally sorted by position; top to bottom. * @param {boolean} ordered Sort the list if true. - * @return {!Array.} Flattened array of blocks. + * @return {!Array} Flattened array of blocks. */ Blockly.Block.prototype.getDescendants = function(ordered) { var blocks = [this]; @@ -905,7 +906,7 @@ Blockly.Block.prototype.isDisposed = function() { * Used to match connections between a block and its insertion marker. * @param {!Blockly.Block} otherBlock The other block to match against. * @param {!Blockly.Connection} conn The other connection to match. - * @return {Blockly.Connection} The matching connection on this block, or null. + * @return {?Blockly.Connection} The matching connection on this block, or null. * @package */ Blockly.Block.prototype.getMatchingConnection = function(otherBlock, conn) { @@ -943,7 +944,7 @@ Blockly.Block.prototype.setTooltip = function(newTip) { /** * Returns the tooltip text for this block. - * @returns {!string} The tooltip text for this block. + * @return {!string} The tooltip text for this block. */ Blockly.Block.prototype.getTooltip = function() { return Blockly.Tooltip.getTooltipOfObject(this); @@ -959,7 +960,7 @@ Blockly.Block.prototype.getColour = function() { /** * Get the name of the block style. - * @return {?string} Name of the block style. + * @return {string} Name of the block style. */ Blockly.Block.prototype.getStyleName = function() { return this.styleName_; @@ -986,7 +987,7 @@ Blockly.Block.prototype.setColour = function(colour) { /** * Set the style and colour values of a block. - * @param {string} blockStyleName Name of the block style + * @param {string} blockStyleName Name of the block style. */ Blockly.Block.prototype.setStyle = function(blockStyleName) { this.styleName_ = blockStyleName; @@ -1018,7 +1019,7 @@ Blockly.Block.prototype.setOnChange = function(onchangeFn) { /** * Returns the named field from a block. * @param {string} name The name of the field. - * @return {Blockly.Field} Named field, or null if field does not exist. + * @return {?Blockly.Field} Named field, or null if field does not exist. */ Blockly.Block.prototype.getField = function(name) { for (var i = 0, input; (input = this.inputList[i]); i++) { @@ -1033,7 +1034,7 @@ Blockly.Block.prototype.getField = function(name) { /** * Return all variables referenced by this block. - * @return {!Array.} List of variable names. + * @return {!Array} List of variable names. */ Blockly.Block.prototype.getVars = function() { var vars = []; @@ -1049,7 +1050,7 @@ Blockly.Block.prototype.getVars = function() { /** * Return all variables referenced by this block. - * @return {!Array.} List of variable models. + * @return {!Array} List of variable models. * @package */ Blockly.Block.prototype.getVarModels = function() { @@ -1134,7 +1135,7 @@ Blockly.Block.prototype.setFieldValue = function(newValue, name) { /** * Set whether this block can chain onto the bottom of another block. * @param {boolean} newBoolean True if there can be a previous statement. - * @param {(string|Array.|null)=} opt_check Statement type or + * @param {(string|Array|null)=} opt_check Statement type or * list of statement types. Null/undefined if any type could be connected. */ Blockly.Block.prototype.setPreviousStatement = function(newBoolean, opt_check) { @@ -1166,7 +1167,7 @@ Blockly.Block.prototype.setPreviousStatement = function(newBoolean, opt_check) { /** * Set whether another block can chain onto the bottom of this block. * @param {boolean} newBoolean True if there can be a next statement. - * @param {(string|Array.|null)=} opt_check Statement type or + * @param {(string|Array|null)=} opt_check Statement type or * list of statement types. Null/undefined if any type could be connected. */ Blockly.Block.prototype.setNextStatement = function(newBoolean, opt_check) { @@ -1194,7 +1195,7 @@ Blockly.Block.prototype.setNextStatement = function(newBoolean, opt_check) { /** * Set whether this block returns a value. * @param {boolean} newBoolean True if there is an output. - * @param {(string|Array.|null)=} opt_check Returned type or list + * @param {(string|Array|null)=} opt_check Returned type or list * of returned types. Null or undefined if any type could be returned * (e.g. variable get). */ @@ -1550,16 +1551,15 @@ Blockly.Block.prototype.jsonInit = function(json) { json['extensions'] = [json['extensions']]; // Correct and continue. } - // Add the mutator to the block + // Add the mutator to the block. if (json['mutator'] !== undefined) { Blockly.Extensions.apply(json['mutator'], this, true); } - if (Array.isArray(json['extensions'])) { - var extensionNames = json['extensions']; + var extensionNames = json['extensions']; + if (Array.isArray(extensionNames)) { for (var j = 0; j < extensionNames.length; ++j) { - var extensionName = extensionNames[j]; - Blockly.Extensions.apply(extensionName, this, false); + Blockly.Extensions.apply(extensionNames[j], this, false); } } }; @@ -1700,7 +1700,7 @@ Blockly.Block.prototype.validateTokens_ = function(tokens, argsCount) { }; /** - * Inserts args in place of numerical tokens. String args are converted to json + * Inserts args in place of numerical tokens. String args are converted to JSON * that defines a label field. If necessary an extra dummy input is added to * the end of the elements. * @param {!Array} tokens The tokens to interpolate @@ -1742,9 +1742,9 @@ Blockly.Block.prototype.interpolateArguments_ = }; /** - * Creates a field from the json definition of a field. If a field with the + * Creates a field from the JSON definition of a field. If a field with the * given type cannot be found, this attempts to create a different field using - * the 'alt' property of the json definition (if it exists). + * the 'alt' property of the JSON definition (if it exists). * @param {{alt:(string|undefined)}} element The element to try to turn into a * field. * @return {?Blockly.Field} The field defined by the JSON, or null if one @@ -1764,7 +1764,7 @@ Blockly.Block.prototype.fieldFromJson_ = function(element) { }; /** - * Creates an input from the json definition of an input. Sets the input's check + * Creates an input from the JSON definition of an input. Sets the input's check * and alignment if they are provided. * @param {!Object} element The JSON to turn into an input. * @param {string} warningPrefix The prefix to add to warnings to help the @@ -1949,15 +1949,14 @@ Blockly.Block.prototype.removeInput = function(name, opt_quiet) { } if (opt_quiet) { return false; - } else { - throw Error('Input not found: ' + name); } + throw Error('Input not found: ' + name); }; /** * Fetches the named input object. * @param {string} name The name of the input. - * @return {Blockly.Input} The input object, or null if input does not exist. + * @return {?Blockly.Input} The input object, or null if input does not exist. */ Blockly.Block.prototype.getInput = function(name) { for (var i = 0, input; (input = this.inputList[i]); i++) { @@ -1972,7 +1971,7 @@ Blockly.Block.prototype.getInput = function(name) { /** * Fetches the block attached to the named input. * @param {string} name The name of the input. - * @return {Blockly.Block} The attached value block, or null if the input is + * @return {?Blockly.Block} The attached value block, or null if the input is * either disconnected or if the input does not exist. */ Blockly.Block.prototype.getInputTargetBlock = function(name) { diff --git a/core/block_drag_surface.js b/core/block_drag_surface.js index c694fd138..e394ab7d5 100644 --- a/core/block_drag_surface.js +++ b/core/block_drag_surface.js @@ -39,7 +39,7 @@ Blockly.BlockDragSurfaceSvg = function(container) { /** * The SVG drag surface. Set once by Blockly.BlockDragSurfaceSvg.createDom. - * @type {SVGElement} + * @type {?SVGElement} * @private */ Blockly.BlockDragSurfaceSvg.prototype.SVG_ = null; @@ -47,14 +47,14 @@ Blockly.BlockDragSurfaceSvg.prototype.SVG_ = null; /** * This is where blocks live while they are being dragged if the drag surface * is enabled. - * @type {SVGElement} + * @type {?SVGElement} * @private */ Blockly.BlockDragSurfaceSvg.prototype.dragGroup_ = null; /** * Containing HTML element; parent of the workspace and the drag surface. - * @type {Element} + * @type {?Element} * @private */ Blockly.BlockDragSurfaceSvg.prototype.container_ = null; @@ -71,7 +71,7 @@ Blockly.BlockDragSurfaceSvg.prototype.scale_ = 1; * Cached value for the translation of the drag surface. * This translation is in pixel units, because the scale is applied to the * drag group rather than the top-level SVG. - * @type {Blockly.utils.Coordinate} + * @type {?Blockly.utils.Coordinate} * @private */ Blockly.BlockDragSurfaceSvg.prototype.surfaceXY_ = null; @@ -201,7 +201,7 @@ Blockly.BlockDragSurfaceSvg.prototype.getSurfaceTranslation = function() { /** * Provide a reference to the drag group (primarily for * BlockSvg.getRelativeToSurfaceXY). - * @return {SVGElement} Drag surface group element. + * @return {?SVGElement} Drag surface group element. */ Blockly.BlockDragSurfaceSvg.prototype.getGroup = function() { return this.dragGroup_; @@ -218,8 +218,7 @@ Blockly.BlockDragSurfaceSvg.prototype.getSvgRoot = function() { /** * Get the current blocks on the drag surface, if any (primarily * for BlockSvg.getRelativeToSurfaceXY). - * @return {Element} Drag surface block DOM element, or undefined if no blocks - * exist. + * @return {?Element} Drag surface block DOM element, or null if no blocks exist. */ Blockly.BlockDragSurfaceSvg.prototype.getCurrentBlock = function() { return /** @type {Element} */ (this.dragGroup_.firstChild); diff --git a/core/block_dragger.js b/core/block_dragger.js index 85e07d30e..5b2fef736 100644 --- a/core/block_dragger.js +++ b/core/block_dragger.js @@ -27,6 +27,7 @@ goog.require('Blockly.utils.Coordinate'); goog.require('Blockly.utils.dom'); goog.requireType('Blockly.BlockSvg'); +goog.requireType('Blockly.IDragTarget'); goog.requireType('Blockly.WorkspaceSvg'); @@ -62,13 +63,11 @@ Blockly.BlockDragger = function(block, workspace) { new Blockly.InsertionMarkerManager(this.draggingBlock_); /** - * Which delete area the mouse pointer is over, if any. - * One of {@link Blockly.DELETE_AREA_TRASH}, - * {@link Blockly.DELETE_AREA_TOOLBOX}, or {@link Blockly.DELETE_AREA_NONE}. - * @type {?number} - * @protected + * Which drag area the mouse pointer is over, if any. + * @type {?Blockly.IDragTarget} + * @private */ - this.deleteArea_ = null; + this.dragTarget_ = null; /** * Whether the block would be deleted if dropped immediately. @@ -112,7 +111,7 @@ Blockly.BlockDragger.prototype.dispose = function() { * on this block and its descendants. Moving an icon moves the bubble that * extends from it if that bubble is open. * @param {!Blockly.BlockSvg} block The root block that is being dragged. - * @return {!Array.} The list of all icons and their locations. + * @return {!Array} The list of all icons and their locations. * @private */ Blockly.BlockDragger.initIconData_ = function(block) { @@ -233,8 +232,15 @@ Blockly.BlockDragger.prototype.drag = function(e, currentDragDeltaXY) { this.draggingBlock_.moveDuringDrag(newLoc); this.dragIcons_(delta); - this.deleteArea_ = this.workspace_.isDeleteArea(e); - this.draggedConnectionManager_.update(delta, this.deleteArea_); + var oldDragTarget = this.dragTarget_; + this.dragTarget_ = this.workspace_.getDragTarget(e); + if (this.dragTarget_ !== oldDragTarget) { + oldDragTarget && oldDragTarget.onDragExit(); + this.dragTarget_ && this.dragTarget_.onDragEnter(); + } + + this.draggedConnectionManager_.update(delta, this.dragTarget_); + this.wouldDeleteBlock_ = this.draggedConnectionManager_.wouldDeleteBlock(); this.updateCursorDuringBlockDrag_(); }; @@ -260,8 +266,16 @@ Blockly.BlockDragger.prototype.endDrag = function(e, currentDragDeltaXY) { var newLoc = Blockly.utils.Coordinate.sum(this.startXY_, delta); this.draggingBlock_.moveOffDragSurface(newLoc); - var deleted = this.maybeDeleteBlock_(); - if (!deleted) { + if (this.dragTarget_) { + this.dragTarget_.onBlockDrop(this.draggingBlock_); + } + + if (this.wouldDeleteBlock_) { + // Fire a move event, so we know where to go back to for an undo. + this.fireMoveEvent_(); + this.draggingBlock_.dispose(false, true); + Blockly.draggingConnections = []; + } else { // Moving the block is expensive, so only do it if the block is not deleted. this.updateBlockAfterMove_(delta); } @@ -334,49 +348,13 @@ Blockly.BlockDragger.prototype.fireMoveEvent_ = function() { Blockly.Events.fire(event); }; -/** - * Shut the trash can and, if necessary, delete the dragging block. - * Should be called at the end of a block drag. - * @return {boolean} Whether the block was deleted. - * @protected - */ -Blockly.BlockDragger.prototype.maybeDeleteBlock_ = function() { - var trashcan = this.workspace_.trashcan; - - if (this.wouldDeleteBlock_) { - if (trashcan) { - setTimeout(trashcan.closeLid.bind(trashcan), 100); - } - // Fire a move event, so we know where to go back to for an undo. - this.fireMoveEvent_(); - this.draggingBlock_.dispose(false, true); - Blockly.draggingConnections = []; - } else if (trashcan) { - // Make sure the trash can lid is closed. - trashcan.closeLid(); - } - return this.wouldDeleteBlock_; -}; - /** * Update the cursor (and possibly the trash can lid) to reflect whether the * dragging block would be deleted if released immediately. * @protected */ Blockly.BlockDragger.prototype.updateCursorDuringBlockDrag_ = function() { - this.wouldDeleteBlock_ = this.draggedConnectionManager_.wouldDeleteBlock(); - var trashcan = this.workspace_.trashcan; - if (this.wouldDeleteBlock_) { - this.draggingBlock_.setDeleteStyle(true); - if (this.deleteArea_ == Blockly.DELETE_AREA_TRASH && trashcan) { - trashcan.setLidOpen(true); - } - } else { - this.draggingBlock_.setDeleteStyle(false); - if (trashcan) { - trashcan.setLidOpen(false); - } - } + this.draggingBlock_.setDeleteStyle(this.wouldDeleteBlock_); }; /** @@ -422,7 +400,7 @@ Blockly.BlockDragger.prototype.dragIcons_ = function(dxy) { /** * Get a list of the insertion markers that currently exist. Drags have 0, 1, * or 2 insertion markers. - * @return {!Array.} A possibly empty list of insertion + * @return {!Array} A possibly empty list of insertion * marker blocks. * @public */ diff --git a/core/block_svg.js b/core/block_svg.js index eadc785fa..fc4611a67 100644 --- a/core/block_svg.js +++ b/core/block_svg.js @@ -27,6 +27,9 @@ goog.require('Blockly.Events'); goog.require('Blockly.Events.BlockMove'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.Selected'); +goog.require('Blockly.IASTNodeLocationSvg'); +goog.require('Blockly.IBoundedElement'); +goog.require('Blockly.ICopyable'); goog.require('Blockly.Msg'); goog.require('Blockly.RenderedConnection'); goog.require('Blockly.TabNavigateCursor'); @@ -39,6 +42,7 @@ goog.require('Blockly.utils.deprecation'); goog.require('Blockly.utils.dom'); goog.require('Blockly.utils.object'); goog.require('Blockly.utils.Rect'); +goog.require('Blockly.utils.Svg'); goog.require('Blockly.utils.userAgent'); goog.require('Blockly.Xml'); @@ -46,9 +50,6 @@ goog.requireType('Blockly.blockRendering.Debug'); goog.requireType('Blockly.Comment'); goog.requireType('Blockly.Connection'); goog.requireType('Blockly.Field'); -goog.requireType('Blockly.IASTNodeLocationSvg'); -goog.requireType('Blockly.IBoundedElement'); -goog.requireType('Blockly.ICopyable'); goog.requireType('Blockly.Input'); goog.requireType('Blockly.Mutator'); goog.requireType('Blockly.Theme'); @@ -156,7 +157,7 @@ Blockly.BlockSvg.prototype.width = 0; /** * Map from IDs for warnings text to PIDs of functions to apply them. * Used to be able to maintain multiple warnings. - * @type {Object.} + * @type {Object} * @private */ Blockly.BlockSvg.prototype.warningTextDb_ = null; @@ -199,7 +200,7 @@ Blockly.BlockSvg.prototype.compose; /** * An optional method for defining custom block context menu items. - * @type {?function(!Array.)} + * @type {?function(!Array)} */ Blockly.BlockSvg.prototype.customContextMenu; @@ -339,33 +340,33 @@ Blockly.BlockSvg.prototype.unselect = function() { /** * Block's mutator icon (if any). - * @type {Blockly.Mutator} + * @type {?Blockly.Mutator} */ Blockly.BlockSvg.prototype.mutator = null; /** * Block's comment icon (if any). - * @type {Blockly.Comment} + * @type {?Blockly.Comment} * @deprecated August 2019. Use getCommentIcon instead. */ Blockly.BlockSvg.prototype.comment = null; /** * Block's comment icon (if any). - * @type {Blockly.Comment} + * @type {?Blockly.Comment} * @private */ Blockly.BlockSvg.prototype.commentIcon_ = null; /** * Block's warning icon (if any). - * @type {Blockly.Warning} + * @type {?Blockly.Warning} */ Blockly.BlockSvg.prototype.warning = null; /** * Returns a list of mutator, comment, and warning icons. - * @return {!Array} List of icons. + * @return {!Array} List of icons. */ Blockly.BlockSvg.prototype.getIcons = function() { var icons = []; @@ -383,7 +384,7 @@ Blockly.BlockSvg.prototype.getIcons = function() { /** * Set parent of this block to be a new block or null. - * @param {Blockly.Block} newParent New parent block. + * @param {?Blockly.Block} newParent New parent block. * @override */ Blockly.BlockSvg.prototype.setParent = function(newParent) { @@ -747,7 +748,7 @@ Blockly.BlockSvg.prototype.showHelp = function() { /** * Generate the context menu for this block. * @protected - * @return {Array.} Context menu options + * @return {?Array} Context menu options or null if no menu. */ Blockly.BlockSvg.prototype.generateContextMenu = function() { if (this.workspace.options.readOnly || !this.contextMenu) { @@ -1008,7 +1009,7 @@ Blockly.BlockSvg.prototype.updateDisabled = function() { /** * Get the comment icon attached to this block, or null if the block has no * comment. - * @return {Blockly.Comment} The comment icon attached to this block, or null. + * @return {?Blockly.Comment} The comment icon attached to this block, or null. */ Blockly.BlockSvg.prototype.getCommentIcon = function() { return this.commentIcon_; @@ -1137,7 +1138,7 @@ Blockly.BlockSvg.prototype.setWarningText = function(text, opt_id) { /** * Give this block a mutator dialog. - * @param {Blockly.Mutator} mutator A mutator dialog instance or null to remove. + * @param {?Blockly.Mutator} mutator A mutator dialog instance or null to remove. */ Blockly.BlockSvg.prototype.setMutator = function(mutator) { if (this.mutator && this.mutator !== mutator) { @@ -1233,7 +1234,7 @@ Blockly.BlockSvg.prototype.setColour = function(colour) { /** * Set the style and colour values of a block. - * @param {string} blockStyleName Name of the block style + * @param {string} blockStyleName Name of the block style. * @throws {Error} if the block style does not exist. */ Blockly.BlockSvg.prototype.setStyle = function(blockStyleName) { @@ -1278,7 +1279,7 @@ Blockly.BlockSvg.prototype.bringToFront = function() { /** * Set whether this block can chain onto the bottom of another block. * @param {boolean} newBoolean True if there can be a previous statement. - * @param {(string|Array.|null)=} opt_check Statement type or + * @param {(string|Array|null)=} opt_check Statement type or * list of statement types. Null/undefined if any type could be connected. */ Blockly.BlockSvg.prototype.setPreviousStatement = function(newBoolean, @@ -1295,7 +1296,7 @@ Blockly.BlockSvg.prototype.setPreviousStatement = function(newBoolean, /** * Set whether another block can chain onto the bottom of this block. * @param {boolean} newBoolean True if there can be a next statement. - * @param {(string|Array.|null)=} opt_check Statement type or + * @param {(string|Array|null)=} opt_check Statement type or * list of statement types. Null/undefined if any type could be connected. */ Blockly.BlockSvg.prototype.setNextStatement = function(newBoolean, opt_check) { @@ -1311,7 +1312,7 @@ Blockly.BlockSvg.prototype.setNextStatement = function(newBoolean, opt_check) { /** * Set whether this block returns a value. * @param {boolean} newBoolean True if there is an output. - * @param {(string|Array.|null)=} opt_check Returned type or list + * @param {(string|Array|null)=} opt_check Returned type or list * of returned types. Null or undefined if any type could be returned * (e.g. variable get). */ @@ -1444,7 +1445,7 @@ Blockly.BlockSvg.prototype.setConnectionTracking = function(track) { * @param {boolean} all If true, return all connections even hidden ones. * Otherwise, for a non-rendered block return an empty list, and for a * collapsed block don't return inputs connections. - * @return {!Array.} Array of connections. + * @return {!Array} Array of connections. * @package */ Blockly.BlockSvg.prototype.getConnections_ = function(all) { @@ -1472,7 +1473,7 @@ Blockly.BlockSvg.prototype.getConnections_ = function(all) { /** * Walks down a stack of blocks and finds the last next connection on the stack. - * @return {Blockly.RenderedConnection} The last next connection on the stack, + * @return {?Blockly.RenderedConnection} The last next connection on the stack, * or null. * @package * @override @@ -1488,7 +1489,7 @@ Blockly.BlockSvg.prototype.lastConnectionInStack = function() { * Used to match connections between a block and its insertion marker. * @param {!Blockly.Block} otherBlock The other block to match against. * @param {!Blockly.Connection} conn The other connection to match. - * @return {Blockly.RenderedConnection} The matching connection on this block, + * @return {?Blockly.RenderedConnection} The matching connection on this block, * or null. * @package * @override @@ -1602,7 +1603,7 @@ Blockly.BlockSvg.prototype.positionNearConnection = function(sourceConnection, /** * Return the parent block or null if this block is at the top level. - * @return {Blockly.BlockSvg} The block that holds the current block. + * @return {?Blockly.BlockSvg} The block (if any) that holds the current block. * @override */ Blockly.BlockSvg.prototype.getParent = function() { @@ -1708,9 +1709,9 @@ Blockly.BlockSvg.prototype.updateConnectionLocations_ = function() { }; /** - * Add the cursor svg to this block's svg group. - * @param {SVGElement} cursorSvg The svg root of the cursor to be added to the - * block svg group. + * Add the cursor SVG to this block's SVG group. + * @param {SVGElement} cursorSvg The SVG root of the cursor to be added to the + * block SVG group. * @package */ Blockly.BlockSvg.prototype.setCursorSvg = function(cursorSvg) { @@ -1718,9 +1719,9 @@ Blockly.BlockSvg.prototype.setCursorSvg = function(cursorSvg) { }; /** - * Add the marker svg to this block's svg group. - * @param {SVGElement} markerSvg The svg root of the marker to be added to the - * block svg group. + * Add the marker SVG to this block's SVG group. + * @param {SVGElement} markerSvg The SVG root of the marker to be added to the + * block SVG group. * @package */ Blockly.BlockSvg.prototype.setMarkerSvg = function(markerSvg) { diff --git a/core/blockly.js b/core/blockly.js index 8c3cf6b8c..e889cb840 100644 --- a/core/blockly.js +++ b/core/blockly.js @@ -17,9 +17,9 @@ goog.provide('Blockly'); goog.require('Blockly.browserEvents'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); goog.require('Blockly.connectionTypes'); +goog.require('Blockly.constants'); +goog.require('Blockly.DropDownDiv'); goog.require('Blockly.Events'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.BlockCreate'); @@ -83,7 +83,7 @@ Blockly.selected = null; /** * All of the connections on blocks that are currently being dragged. - * @type {!Array.} + * @type {!Array} * @package */ Blockly.draggingConnections = []; @@ -216,7 +216,12 @@ Blockly.deleteBlock = function(selected) { if (!selected.workspace.isFlyout) { Blockly.Events.setGroup(true); Blockly.hideChaff(); - selected.dispose(/* heal */ true, true); + if (selected.outputConnection) { + // Do not attempt to heal rows (https://github.com/google/blockly/issues/4832) + selected.dispose(false, true); + } else { + selected.dispose(/* heal */ true, true); + } Blockly.Events.setGroup(false); } }; @@ -294,27 +299,20 @@ Blockly.onContextMenu_ = function(e) { /** * Close tooltips, context menus, dropdown selections, etc. - * @param {boolean=} opt_allowToolbox If true, don't close the toolbox. + * @param {boolean=} opt_onlyClosePopups Whether only popups should be closed. */ -Blockly.hideChaff = function(opt_allowToolbox) { +Blockly.hideChaff = function(opt_onlyClosePopups) { Blockly.Tooltip.hide(); Blockly.WidgetDiv.hide(); Blockly.DropDownDiv.hideWithoutAnimation(); - if (!opt_allowToolbox) { - var workspace = Blockly.getMainWorkspace(); - // For now the trashcan flyout always autocloses because it overlays the - // trashcan UI (no trashcan to click to close it). - if (workspace.trashcan && - workspace.trashcan.flyout) { - workspace.trashcan.closeFlyout(); - } - var toolbox = workspace.getToolbox(); - if (toolbox && - toolbox.getFlyout() && - toolbox.getFlyout().autoClose) { - toolbox.clearSelection(); - } - } + + var onlyClosePopups = !!opt_onlyClosePopups; + var workspace = Blockly.getMainWorkspace(); + var autoHideables = workspace.getComponentManager().getComponents( + Blockly.ComponentManager.Capability.AUTOHIDEABLE, true); + autoHideables.forEach(function(autoHideable) { + autoHideable.autoHide(onlyClosePopups); + }); }; /** @@ -380,7 +378,7 @@ Blockly.jsonInitFactory_ = function(jsonDef) { /** * Define blocks from an array of JSON block definitions, as might be generated * by the Blockly Developer Tools. - * @param {!Array.} jsonArray An array of JSON block definitions. + * @param {!Array} jsonArray An array of JSON block definitions. */ Blockly.defineBlocksWithJsonArray = function(jsonArray) { for (var i = 0; i < jsonArray.length; i++) { @@ -475,7 +473,7 @@ Blockly.checkBlockColourConstants = function() { * Checks for a constant in the Blockly namespace, verifying it is undefined or * has the old/original value. Prints a warning if this is not true. * @param {string} msgName The Msg constant identifier. - * @param {Array.} blocklyNamePath The name parts of the tested + * @param {!Array} blocklyNamePath The name parts of the tested * constant. * @param {number|undefined} expectedValue The expected value of the constant. * @private diff --git a/core/blocks.js b/core/blocks.js index c39f81c0c..5f0d96b21 100644 --- a/core/blocks.js +++ b/core/blocks.js @@ -18,6 +18,6 @@ goog.provide('Blockly.Blocks'); /** * A mapping of block type names to block prototype objects. - * @type {!Object.} + * @type {!Object} */ Blockly.Blocks = Object.create(null); diff --git a/core/browser_events.js b/core/browser_events.js index 98bf661d7..3a251637b 100644 --- a/core/browser_events.js +++ b/core/browser_events.js @@ -13,13 +13,14 @@ goog.provide('Blockly.browserEvents'); goog.require('Blockly.Touch'); +goog.require('Blockly.utils.global'); /** * Blockly opaque event data used to unbind events when using * `Blockly.browserEvents.bind` and * `Blockly.browserEvents.conditionalBind`. - * @typedef {!Array.} + * @typedef {!Array} */ Blockly.browserEvents.Data; @@ -30,7 +31,7 @@ Blockly.browserEvents.Data; * mousedown or mousemove, which may be part of a drag or click). * @param {!EventTarget} node Node upon which to listen. * @param {string} name Event name to listen to (e.g. 'mousedown'). - * @param {Object} thisObject The value of 'this' in the function. + * @param {?Object} thisObject The value of 'this' in the function. * @param {!Function} func Function to call when event is triggered. * @param {boolean=} opt_noCaptureIdentifier True if triggering on this event * should not block execution of other event handlers on this touch or @@ -105,7 +106,7 @@ Blockly.browserEvents.conditionalBind = function( * mouseover for tooltips). * @param {!EventTarget} node Node upon which to listen. * @param {string} name Event name to listen to (e.g. 'mousedown'). - * @param {Object} thisObject The value of 'this' in the function. + * @param {?Object} thisObject The value of 'this' in the function. * @param {!Function} func Function to call when event is triggered. * @return {!Blockly.browserEvents.Data} Opaque data that can be passed to * unbindEvent_. diff --git a/core/bubble.js b/core/bubble.js index c65dba459..161b2fb29 100644 --- a/core/bubble.js +++ b/core/bubble.js @@ -13,6 +13,7 @@ goog.provide('Blockly.Bubble'); goog.require('Blockly.browserEvents'); +goog.require('Blockly.IBubble'); goog.require('Blockly.Scrollbar'); goog.require('Blockly.Touch'); goog.require('Blockly.utils'); @@ -27,7 +28,6 @@ goog.require('Blockly.Workspace'); goog.requireType('Blockly.BlockDragSurfaceSvg'); goog.requireType('Blockly.BlockSvg'); -goog.requireType('Blockly.IBubble'); goog.requireType('Blockly.MetricsManager'); goog.requireType('Blockly.WorkspaceSvg'); @@ -37,7 +37,7 @@ goog.requireType('Blockly.WorkspaceSvg'); * @param {!Blockly.WorkspaceSvg} workspace The workspace on which to draw the * bubble. * @param {!Element} content SVG content for the bubble. - * @param {Element} shape SVG element to avoid eclipsing. + * @param {!Element} shape SVG element to avoid eclipsing. * @param {!Blockly.utils.Coordinate} anchorXY Absolute position of bubble's * anchor point. * @param {?number} bubbleWidth Width of bubble, or null if not resizable. diff --git a/core/bubble_dragger.js b/core/bubble_dragger.js index 2f75276dd..38c339158 100644 --- a/core/bubble_dragger.js +++ b/core/bubble_dragger.js @@ -51,13 +51,11 @@ Blockly.BubbleDragger = function(bubble, workspace) { this.workspace_ = workspace; /** - * Which delete area the mouse pointer is over, if any. - * One of {@link Blockly.DELETE_AREA_TRASH}, - * {@link Blockly.DELETE_AREA_TOOLBOX}, or {@link Blockly.DELETE_AREA_NONE}. - * @type {?number} + * Which drag target the mouse pointer is over, if any. + * @type {?Blockly.IDragTarget} * @private */ - this.deleteArea_ = null; + this.dragTarget_ = null; /** * Whether the bubble would be deleted if dropped immediately. @@ -136,33 +134,41 @@ Blockly.BubbleDragger.prototype.dragBubble = function(e, currentDragDeltaXY) { this.draggingBubble_.moveDuringDrag(this.dragSurface_, newLoc); - if (this.draggingBubble_.isDeletable()) { - this.deleteArea_ = this.workspace_.isDeleteArea(e); - this.updateCursorDuringBubbleDrag_(); + var oldDragTarget = this.dragTarget_; + this.dragTarget_ = this.workspace_.getDragTarget(e); + if (this.dragTarget_ !== oldDragTarget) { + oldDragTarget && oldDragTarget.onDragExit(); + this.dragTarget_ && this.dragTarget_.onDragEnter(); } + this.wouldDeleteBubble_ = this.shouldDelete_(this.dragTarget_); + + this.updateCursorDuringBubbleDrag_(); }; /** - * Shut the trash can and, if necessary, delete the dragging bubble. - * Should be called at the end of a bubble drag. - * @return {boolean} Whether the bubble was deleted. + * Whether ending the drag would delete the bubble. + * @param {?Blockly.IDragTarget} dragTarget The drag target that the bubblee is + * currently over. + * @return {boolean} Whether dropping the bubble immediately would delete the + * block. * @private */ -Blockly.BubbleDragger.prototype.maybeDeleteBubble_ = function() { - var trashcan = this.workspace_.trashcan; +Blockly.BubbleDragger.prototype.shouldDelete_ = function(dragTarget) { + var couldDeleteBubble = this.draggingBubble_.isDeletable(); - if (this.wouldDeleteBubble_) { - if (trashcan) { - setTimeout(trashcan.closeLid.bind(trashcan), 100); + if (couldDeleteBubble && dragTarget) { + // TODO(#4881) use hasCapability instead of getComponents + var deleteAreas = this.workspace_.getComponentManager().getComponents( + Blockly.ComponentManager.Capability.DELETE_AREA, false); + var isDeleteArea = deleteAreas.some(function(deleteArea) { + return dragTarget === deleteArea; + }); + if (isDeleteArea) { + return (/** @type {!Blockly.IDeleteArea} */ (dragTarget)) + .wouldDeleteBubble(this.draggingBubble_); } - // Fire a move event, so we know where to go back to for an undo. - this.fireMoveEvent_(); - this.draggingBubble_.dispose(false, true); - } else if (trashcan) { - // Make sure the trash can lid is closed. - trashcan.closeLid(); } - return this.wouldDeleteBubble_; + return false; }; /** @@ -171,18 +177,10 @@ Blockly.BubbleDragger.prototype.maybeDeleteBubble_ = function() { * @private */ Blockly.BubbleDragger.prototype.updateCursorDuringBubbleDrag_ = function() { - this.wouldDeleteBubble_ = this.deleteArea_ != Blockly.DELETE_AREA_NONE; - var trashcan = this.workspace_.trashcan; if (this.wouldDeleteBubble_) { this.draggingBubble_.setDeleteStyle(true); - if (this.deleteArea_ == Blockly.DELETE_AREA_TRASH && trashcan) { - trashcan.setLidOpen(true); - } } else { this.draggingBubble_.setDeleteStyle(false); - if (trashcan) { - trashcan.setLidOpen(false); - } } }; @@ -200,12 +198,18 @@ Blockly.BubbleDragger.prototype.endBubbleDrag = function( var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY); var newLoc = Blockly.utils.Coordinate.sum(this.startXY_, delta); - // Move the bubble to its final location. this.draggingBubble_.moveTo(newLoc.x, newLoc.y); - var deleted = this.maybeDeleteBubble_(); - if (!deleted) { + if (this.dragTarget_) { + this.dragTarget_.onBubbleDrop(this.draggingBubble_); + } + + if (this.wouldDeleteBubble_) { + // Fire a move event, so we know where to go back to for an undo. + this.fireMoveEvent_(); + this.draggingBubble_.dispose(false, true); + } else { // Put everything back onto the bubble canvas. if (this.dragSurface_) { this.dragSurface_.clearAndHide(this.workspace_.getBubbleCanvas()); diff --git a/core/component_manager.js b/core/component_manager.js new file mode 100644 index 000000000..e5b7c4192 --- /dev/null +++ b/core/component_manager.js @@ -0,0 +1,222 @@ +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Manager for all items registered with the workspace. + * @author kozbial@google.com (Monica Kozbial) + */ + +'use strict'; + +goog.provide('Blockly.ComponentManager'); + +goog.requireType('Blockly.IAutoHideable'); +goog.requireType('Blockly.IComponent'); +goog.requireType('Blockly.IDeleteArea'); +goog.requireType('Blockly.IDragTarget'); +goog.requireType('Blockly.IPositionable'); + + +/** + * Manager for all items registered with the workspace. + * @constructor + */ +Blockly.ComponentManager = function() { + /** + * A map of the components registered with the workspace, mapped to id. + * @type {!Object} + * @private + */ + this.componentData_ = Object.create(null); + + /** + * A map of capabilities to component IDs. + * @type {!Object>} + * @private + */ + this.capabilityToComponentIds_ = Object.create(null); +}; + +/** + * An object storing component information. + * @typedef {{ + * id: string, + * component: !Blockly.IComponent, + * capabilities: ( + * !Array>), + * weight: number + * }} + */ +Blockly.ComponentManager.ComponentDatum; + +/** + * Adds a component. + * @param {!Blockly.ComponentManager.ComponentDatum} componentInfo The data for + * the component to register. + * @param {boolean=} opt_allowOverrides True to prevent an error when overriding + * an already registered item. + * @template T + */ +Blockly.ComponentManager.prototype.addComponent = function( + componentInfo, opt_allowOverrides) { + // Don't throw an error if opt_allowOverrides is true. + if (!opt_allowOverrides && this.componentData_[componentInfo.id]) { + throw Error( + 'Plugin "' + componentInfo.id + '" with capabilities "' + + this.componentData_[componentInfo.id].capabilities + + '" already added.'); + } + this.componentData_[componentInfo.id] = componentInfo; + for (var i = 0, type; (type = componentInfo.capabilities[i]); i++) { + var typeKey = String(type).toLowerCase(); + if (this.capabilityToComponentIds_[typeKey] === undefined) { + this.capabilityToComponentIds_[typeKey] = [componentInfo.id]; + } else { + this.capabilityToComponentIds_[typeKey].push(componentInfo.id); + } + } +}; + +/** + * Adds a capability to a existing registered component. + * @param {string} id The ID of the component to add the capability to. + * @param {string|!Blockly.ComponentManager.Capability + * } capability The capability to add. + */ +Blockly.ComponentManager.prototype.addCapability = function(id, capability) { + capability = String(capability).toLowerCase(); + if (!this.getComponent(id)) { + throw Error('Cannot add capability, "' + capability + '". Plugin "' + + id + '" has not been added to the ComponentManager'); + } + if (this.hasCapability(id, capability)) { + console.warn('Plugin "' + id + 'already has capability "' + + capability + '"'); + return; + } + this.componentData_[id].capabilities.push(capability); + this.capabilityToComponentIds_[capability].push(id); +}; + +/** + * Removes a capability from an existing registered component. + * @param {string} id The ID of the component to remove the capability from. + * @param {string|!Blockly.ComponentManager.Capability + * } capability The capability to remove. + */ +Blockly.ComponentManager.prototype.removeCapability = function(id, capability) { + capability = String(capability).toLowerCase(); + if (!this.getComponent(id)) { + throw Error('Cannot remove capability, "' + capability + '". Plugin "' + + id + '" has not been added to the ComponentManager'); + } + if (!this.hasCapability(id, capability)) { + console.warn('Plugin "' + id + 'doesn\'t have capability "' + + capability + '" to remove'); + return; + } + this.componentData_[id].capabilities.splice( + this.componentData_[id].capabilities.indexOf(capability), 1); + this.capabilityToComponentIds_[capability].splice( + this.capabilityToComponentIds_[capability].indexOf(id), 1); +}; + +/** + * Returns whether the component with this id has the specified capability. + * @param {string} id The ID of the component to check. + * @param {string|!Blockly.ComponentManager.Capability + * } capability The capability to check for. + * @return {boolean} Whether the component has the capability. + */ +Blockly.ComponentManager.prototype.hasCapability = function(id, capability) { + capability = String(capability).toLowerCase(); + return this.componentData_[id].capabilities.indexOf(capability) !== -1; +}; + +/** + * Gets the component with the given ID and the given type. + * @param {string} id The ID of the component to get. + * @return {!Blockly.IComponent|undefined} The component with the given name + * or undefined if not found. + */ +Blockly.ComponentManager.prototype.getComponent = function(id) { + return this.componentData_[id] && this.componentData_[id].component; +}; + +/** + * Gets all the components of the specified type. + * @param {!Blockly.ComponentManager.Capability} capability The capability of the + * component. + * @param {boolean} sorted Whether to return list ordered by weights. + * @return {!Array} The components that match the specified capability. + * @template T + */ +Blockly.ComponentManager.prototype.getComponents = function(capability, sorted) { + var typeKey = String(capability).toLowerCase(); + var componentIds = this.capabilityToComponentIds_[typeKey]; + if (!componentIds) { + return []; + } + var components = []; + if (sorted) { + var componentDataList = []; + var componentData = this.componentData_; + componentIds.forEach(function(id) { + componentDataList.push(componentData[id]); + }); + componentDataList.sort(function(a, b) { + return a.weight - b.weight; + }); + componentDataList.forEach(function(ComponentDatum) { + components.push(ComponentDatum.component); + }); + } else { + var componentData = this.componentData_; + componentIds.forEach(function(id) { + components.push(componentData[id].component); + }); + } + return components; +}; + +/** + * A name with the capability of the element stored in the generic. + * @param {string} name The name of the component capability. + * @constructor + * @template T + */ +Blockly.ComponentManager.Capability = function(name) { + /** + * @type {string} + * @private + */ + this.name_ = name; +}; + +/** + * Returns the name of the capability. + * @return {string} The name. + * @override + */ +Blockly.ComponentManager.Capability.prototype.toString = function() { + return this.name_; +}; + +/** @type {!Blockly.ComponentManager.Capability} */ +Blockly.ComponentManager.Capability.POSITIONABLE = + new Blockly.ComponentManager.Capability('positionable'); + +/** @type {!Blockly.ComponentManager.Capability} */ +Blockly.ComponentManager.Capability.DRAG_TARGET = + new Blockly.ComponentManager.Capability('drag_target'); + +/** @type {!Blockly.ComponentManager.Capability} */ +Blockly.ComponentManager.Capability.DELETE_AREA = + new Blockly.ComponentManager.Capability('delete_area'); + +/** @type {!Blockly.ComponentManager.Capability} */ +Blockly.ComponentManager.Capability.AUTOHIDEABLE = + new Blockly.ComponentManager.Capability('autohideable'); diff --git a/core/connection.js b/core/connection.js index e5a632a32..c9415dd05 100644 --- a/core/connection.js +++ b/core/connection.js @@ -18,11 +18,11 @@ goog.require('Blockly.constants'); goog.require('Blockly.Events'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.BlockMove'); +goog.require('Blockly.IASTNodeLocationWithBlock'); goog.require('Blockly.utils.deprecation'); goog.require('Blockly.Xml'); goog.requireType('Blockly.Block'); -goog.requireType('Blockly.IASTNodeLocationWithBlock'); goog.requireType('Blockly.IConnectionChecker'); goog.requireType('Blockly.Input'); @@ -134,7 +134,7 @@ Blockly.Connection.prototype.connect_ = function(childConnection) { // Attempt to reattach the orphan at the end of the newly inserted // block. Since this block may be a row, walk down to the end // or to the first (and only) shadow block. - var connection = Blockly.Connection.lastConnectionInRow( + var connection = Blockly.Connection.getConnectionForOrphanedOutput( childBlock, orphanBlock); if (connection) { orphanBlock.outputConnection.connect(connection); @@ -372,30 +372,31 @@ Blockly.Connection.connectReciprocally_ = function(first, second) { }; /** - * Does the given block have one and only one connection point that will accept - * an orphaned block? + * Returns the single connection on the block that will accept the orphaned + * block, if one can be found. If the block has multiple compatible connections + * (even if they are filled) this returns null. If the block has no compatible + * connections, this returns null. * @param {!Blockly.Block} block The superior block. * @param {!Blockly.Block} orphanBlock The inferior block. - * @return {Blockly.Connection} The suitable connection point on 'block', + * @return {?Blockly.Connection} The suitable connection point on 'block', * or null. * @private */ -Blockly.Connection.singleConnection_ = function(block, orphanBlock) { - var connection = null; +Blockly.Connection.getSingleConnection_ = function(block, orphanBlock) { + var foundConnection = null; var output = orphanBlock.outputConnection; - for (var i = 0; i < block.inputList.length; i++) { - var thisConnection = block.inputList[i].connection; - var typeChecker = output.getConnectionChecker(); - if (thisConnection && - thisConnection.type == Blockly.connectionTypes.INPUT_VALUE && - typeChecker.canConnect(output, thisConnection, false)) { - if (connection) { + var typeChecker = output.getConnectionChecker(); + + for (var i = 0, input; (input = block.inputList[i]); i++) { + var connection = input.connection; + if (connection && typeChecker.canConnect(output, connection, false)) { + if (foundConnection) { return null; // More than one connection. } - connection = thisConnection; + foundConnection = connection; } } - return connection; + return foundConnection; }; /** @@ -406,22 +407,23 @@ Blockly.Connection.singleConnection_ = function(block, orphanBlock) { * Terminates early for shadow blocks. * @param {!Blockly.Block} startBlock The block on which to start the search. * @param {!Blockly.Block} orphanBlock The block that is looking for a home. - * @return {Blockly.Connection} The suitable connection point on the chain + * @return {?Blockly.Connection} The suitable connection point on the chain * of blocks, or null. * @package */ -Blockly.Connection.lastConnectionInRow = function(startBlock, orphanBlock) { - var newBlock = startBlock; - var connection; - while ((connection = Blockly.Connection.singleConnection_( - /** @type {!Blockly.Block} */ (newBlock), orphanBlock))) { - newBlock = connection.targetBlock(); - if (!newBlock || newBlock.isShadow()) { - return connection; - } - } - return null; -}; +Blockly.Connection.getConnectionForOrphanedOutput = + function(startBlock, orphanBlock) { + var newBlock = startBlock; + var connection; + while ((connection = Blockly.Connection.getSingleConnection_( + /** @type {!Blockly.Block} */ (newBlock), orphanBlock))) { + newBlock = connection.targetBlock(); + if (!newBlock || newBlock.isShadow()) { + return connection; + } + } + return null; + }; /** * Disconnect this connection. @@ -491,8 +493,7 @@ Blockly.Connection.prototype.respawnShadow_ = function() { var parentBlock = this.getSourceBlock(); var shadow = this.getShadowDom(); if (parentBlock.workspace && shadow) { - var blockShadow = - Blockly.Xml.domToBlock(shadow, parentBlock.workspace); + var blockShadow = Blockly.Xml.domToBlock(shadow, parentBlock.workspace); if (blockShadow.outputConnection) { this.connect(blockShadow.outputConnection); } else if (blockShadow.previousConnection) { @@ -505,7 +506,7 @@ Blockly.Connection.prototype.respawnShadow_ = function() { /** * Returns the block that this connection connects to. - * @return {Blockly.Block} The connected block or null if none is connected. + * @return {?Blockly.Block} The connected block or null if none is connected. */ Blockly.Connection.prototype.targetBlock = function() { if (this.isConnected()) { @@ -567,7 +568,7 @@ Blockly.Connection.prototype.onCheckChanged_ = function() { /** * Change a connection's compatibility. - * @param {?(string|!Array.)} check Compatible value type or list of + * @param {?(string|!Array)} check Compatible value type or list of * value types. Null if all types are compatible. * @return {!Blockly.Connection} The connection being modified * (to allow chaining). @@ -588,7 +589,7 @@ Blockly.Connection.prototype.setCheck = function(check) { /** * Get a connection's compatibility. - * @return {Array} List of compatible value types. + * @return {?Array} List of compatible value types. * Null if all types are compatible. * @public */ @@ -598,7 +599,7 @@ Blockly.Connection.prototype.getCheck = function() { /** * Changes the connection's shadow block. - * @param {Element} shadow DOM representation of a block or null. + * @param {?Element} shadow DOM representation of a block or null. */ Blockly.Connection.prototype.setShadowDom = function(shadow) { this.shadowDom_ = shadow; @@ -613,8 +614,8 @@ Blockly.Connection.prototype.setShadowDom = function(shadow) { }; /** - * Returns the xml representation of the connection's shadow block. - * @return {Element} Shadow DOM representation of a block or null. + * Returns the XML representation of the connection's shadow block. + * @return {?Element} Shadow DOM representation of a block or null. */ Blockly.Connection.prototype.getShadowDom = function() { return this.shadowDom_; @@ -629,7 +630,7 @@ Blockly.Connection.prototype.getShadowDom = function() { * {@link Blockly.RenderedConnection} overrides this behavior with a list * computed from the rendered positioning. * @param {number} _maxLimit The maximum radius to another connection. - * @return {!Array.} List of connections. + * @return {!Array} List of connections. * @package */ Blockly.Connection.prototype.neighbours = function(_maxLimit) { @@ -638,17 +639,16 @@ Blockly.Connection.prototype.neighbours = function(_maxLimit) { /** * Get the parent input of a connection. - * @return {Blockly.Input} The input that the connection belongs to or null if + * @return {?Blockly.Input} The input that the connection belongs to or null if * no parent exists. * @package */ Blockly.Connection.prototype.getParentInput = function() { var parentInput = null; - var block = this.sourceBlock_; - var inputs = block.inputList; - for (var idx = 0; idx < block.inputList.length; idx++) { - if (inputs[idx].connection === this) { - parentInput = inputs[idx]; + var inputs = this.sourceBlock_.inputList; + for (var i = 0; i < inputs.length; i++) { + if (inputs[i].connection === this) { + parentInput = inputs[i]; break; } } @@ -661,11 +661,12 @@ Blockly.Connection.prototype.getParentInput = function() { * @return {string} The description. */ Blockly.Connection.prototype.toString = function() { - var msg; var block = this.sourceBlock_; if (!block) { return 'Orphan Connection'; - } else if (block.outputConnection == this) { + } + var msg; + if (block.outputConnection == this) { msg = 'Output Connection of '; } else if (block.previousConnection == this) { msg = 'Previous Connection of '; diff --git a/core/connection_db.js b/core/connection_db.js index b670ff2f2..4b2615725 100644 --- a/core/connection_db.js +++ b/core/connection_db.js @@ -35,7 +35,7 @@ goog.requireType('Blockly.utils.Coordinate'); Blockly.ConnectionDB = function(checker) { /** * Array of connections sorted by y position in workspace units. - * @type {!Array.} + * @type {!Array} * @private */ this.connections_ = []; @@ -84,21 +84,21 @@ Blockly.ConnectionDB.prototype.findIndexOfConnection_ = function(conn, yPos) { yPos = conn.y; // Walk forward and back on the y axis looking for the connection. - var pointerMin = bestGuess; - var pointerMax = bestGuess; - while (pointerMin >= 0 && this.connections_[pointerMin].y == yPos) { - if (this.connections_[pointerMin] == conn) { - return pointerMin; + var pointer = bestGuess; + while (pointer >= 0 && this.connections_[pointer].y == yPos) { + if (this.connections_[pointer] == conn) { + return pointer; } - pointerMin--; + pointer--; } - while (pointerMax < this.connections_.length && - this.connections_[pointerMax].y == yPos) { - if (this.connections_[pointerMax] == conn) { - return pointerMax; + pointer = bestGuess; + while (pointer < this.connections_.length && + this.connections_[pointer].y == yPos) { + if (this.connections_[pointer] == conn) { + return pointer; } - pointerMax++; + pointer++; } return -1; }; @@ -150,7 +150,7 @@ Blockly.ConnectionDB.prototype.removeConnection = function(connection, yPos) { * @param {!Blockly.RenderedConnection} connection The connection whose * neighbours should be returned. * @param {number} maxRadius The maximum radius to another connection. - * @return {!Array.} List of connections. + * @return {!Array} List of connections. */ Blockly.ConnectionDB.prototype.getNeighbours = function(connection, maxRadius) { var db = this.connections_; @@ -286,7 +286,7 @@ Blockly.ConnectionDB.prototype.searchForClosest = function(conn, maxRadius, * Initialize a set of connection DBs for a workspace. * @param {!Blockly.IConnectionChecker} checker The workspace's * connection checker, used to decide if connections are valid during a drag. - * @return {!Array.} Array of databases. + * @return {!Array} Array of databases. */ Blockly.ConnectionDB.init = function(checker) { // Create four databases, one for each connection type. diff --git a/core/constants.js b/core/constants.js index bf3c675ae..1d19fb8d5 100644 --- a/core/constants.js +++ b/core/constants.js @@ -161,26 +161,6 @@ Blockly.OPPOSITE_TYPE[Blockly.connectionTypes.NEXT_STATEMENT] = Blockly.OPPOSITE_TYPE[Blockly.connectionTypes.PREVIOUS_STATEMENT] = Blockly.connectionTypes.NEXT_STATEMENT; -/** - * ENUM representing that an event is not in any delete areas. - * Null for backwards compatibility reasons. - * @const - */ -Blockly.DELETE_AREA_NONE = null; - -/** - * ENUM representing that an event is in the delete area of the trash can. - * @const - */ -Blockly.DELETE_AREA_TRASH = 1; - -/** - * ENUM representing that an event is in the delete area of the toolbox or - * flyout. - * @const - */ -Blockly.DELETE_AREA_TOOLBOX = 2; - /** * String for use in the "custom" attribute of a category in toolbox XML. * This string indicates that the category should be dynamically populated with @@ -221,13 +201,13 @@ Blockly.RENAME_VARIABLE_ID = 'RENAME_VARIABLE_ID'; Blockly.DELETE_VARIABLE_ID = 'DELETE_VARIABLE_ID'; /** - * The language-neutral id given to the collapsed input. + * The language-neutral ID given to the collapsed input. * @const {string} */ Blockly.constants.COLLAPSED_INPUT_NAME = '_TEMP_COLLAPSED_INPUT'; /** - * The language-neutral id given to the collapsed field. + * The language-neutral ID given to the collapsed field. * @const {string} */ Blockly.constants.COLLAPSED_FIELD_NAME = '_TEMP_COLLAPSED_FIELD'; diff --git a/core/contextmenu.js b/core/contextmenu.js index d663d03c5..e070207b7 100644 --- a/core/contextmenu.js +++ b/core/contextmenu.js @@ -54,7 +54,7 @@ Blockly.ContextMenu.menu_ = null; /** * Construct the menu based on the list of options and show the menu. * @param {!Event} e Mouse event. - * @param {!Array.} options Array of menu options. + * @param {!Array} options Array of menu options. * @param {boolean} rtl True if RTL, false if LTR. */ Blockly.ContextMenu.show = function(e, options, rtl) { @@ -75,7 +75,7 @@ Blockly.ContextMenu.show = function(e, options, rtl) { /** * Create the context menu object and populate it with the given options. - * @param {!Array.} options Array of menu options. + * @param {!Array} options Array of menu options. * @param {boolean} rtl True if RTL, false if LTR. * @return {!Blockly.Menu} The menu that will be shown on right click. * @private diff --git a/core/contextmenu_items.js b/core/contextmenu_items.js index 4dc62dcd3..b4adeb2f7 100644 --- a/core/contextmenu_items.js +++ b/core/contextmenu_items.js @@ -183,7 +183,7 @@ Blockly.ContextMenuItems.registerExpand = function() { /** * Adds a block and its children to a list of deletable blocks. * @param {!Blockly.BlockSvg} block to delete. - * @param {!Array.} deleteList list of blocks that can be deleted. This will be + * @param {!Array} deleteList list of blocks that can be deleted. This will be * modifed in place with the given block and its descendants. * @private */ @@ -191,7 +191,7 @@ Blockly.ContextMenuItems.addDeletableBlocks_ = function(block, deleteList) { if (block.isDeletable()) { Array.prototype.push.apply(deleteList, block.getDescendants(false)); } else { - var children = /** @type !Array. */ (block.getChildren(false)); + var children = /** @type !Array */ (block.getChildren(false)); for (var i = 0; i < children.length; i++) { Blockly.ContextMenuItems.addDeletableBlocks_(children[i], deleteList); } @@ -201,7 +201,7 @@ Blockly.ContextMenuItems.addDeletableBlocks_ = function(block, deleteList) { /** * Constructs a list of blocks that can be deleted in the given workspace. * @param {!Blockly.WorkspaceSvg} workspace to delete all blocks from. - * @return {!Array.} list of blocks to delete. + * @return {!Array} list of blocks to delete. * @private */ Blockly.ContextMenuItems.getDeletableBlocks_ = function(workspace) { @@ -214,8 +214,8 @@ Blockly.ContextMenuItems.getDeletableBlocks_ = function(workspace) { }; /** Deletes the given blocks. Used to delete all blocks in the workspace. - * @param {!Array.} deleteList list of blocks to delete. - * @param {string} eventGroup event group id with which all delete events should be associated. + * @param {!Array} deleteList list of blocks to delete. + * @param {string} eventGroup event group ID with which all delete events should be associated. * @private */ Blockly.ContextMenuItems.deleteNext_ = function(deleteList, eventGroup) { @@ -479,7 +479,9 @@ Blockly.ContextMenuItems.registerDelete = function() { }, callback: function(/** @type {!Blockly.ContextMenuRegistry.Scope} */ scope) { Blockly.Events.setGroup(true); - scope.block.dispose(true, true); + if (scope.block) { + Blockly.deleteBlock(scope.block); + } Blockly.Events.setGroup(false); }, scopeType: Blockly.ContextMenuRegistry.ScopeType.BLOCK, diff --git a/core/contextmenu_registry.js b/core/contextmenu_registry.js index f3f3b2205..38cf08d3c 100644 --- a/core/contextmenu_registry.js +++ b/core/contextmenu_registry.js @@ -31,11 +31,11 @@ Blockly.ContextMenuRegistry = function() { Blockly.ContextMenuRegistry.registry = this; /** - * Registry of all registered RegistryItems, keyed by id. - * @type {!Object} + * Registry of all registered RegistryItems, keyed by ID. + * @type {!Object} * @private */ - this.registry_ = {}; + this.registry_ = Object.create(null); }; /** @@ -93,37 +93,33 @@ Blockly.ContextMenuRegistry.registry = null; /** * Registers a RegistryItem. * @param {!Blockly.ContextMenuRegistry.RegistryItem} item Context menu item to register. - * @throws {Error} if an item with the given id already exists. + * @throws {Error} if an item with the given ID already exists. */ Blockly.ContextMenuRegistry.prototype.register = function(item) { if (this.registry_[item.id]) { - throw Error('Menu item with id "' + item.id + '" is already registered.'); + throw Error('Menu item with ID "' + item.id + '" is already registered.'); } this.registry_[item.id] = item; }; /** - * Unregisters a RegistryItem with the given id. - * @param {string} id The id of the RegistryItem to remove. - * @throws {Error} if an item with the given id does not exist. + * Unregisters a RegistryItem with the given ID. + * @param {string} id The ID of the RegistryItem to remove. + * @throws {Error} if an item with the given ID does not exist. */ Blockly.ContextMenuRegistry.prototype.unregister = function(id) { - if (this.registry_[id]) { - delete this.registry_[id]; - } else { - throw new Error('Menu item with id "' + id + '" not found.'); + if (!this.registry_[id]) { + throw new Error('Menu item with ID "' + id + '" not found.'); } + delete this.registry_[id]; }; /** - * @param {string} id The id of the RegistryItem to get. - * @returns {?Blockly.ContextMenuRegistry.RegistryItem} RegistryItem or null if not found + * @param {string} id The ID of the RegistryItem to get. + * @return {?Blockly.ContextMenuRegistry.RegistryItem} RegistryItem or null if not found */ Blockly.ContextMenuRegistry.prototype.getItem = function(id) { - if (this.registry_[id]) { - return this.registry_[id]; - } - return null; + return this.registry_[id] || null; }; /** @@ -133,7 +129,7 @@ Blockly.ContextMenuRegistry.prototype.getItem = function(id) { * shown (e.g. on a block or on a workspace) * @param {!Blockly.ContextMenuRegistry.Scope} scope Current scope of context menu * (i.e., the exact workspace or block being clicked on) - * @returns {!Array.} the list of ContextMenuOptions + * @return {!Array} the list of ContextMenuOptions */ Blockly.ContextMenuRegistry.prototype.getContextMenuOptions = function(scopeType, scope) { var menuOptions = []; diff --git a/core/css.js b/core/css.js index c359af567..9f6037d7b 100644 --- a/core/css.js +++ b/core/css.js @@ -28,7 +28,7 @@ Blockly.Css.injected_ = false; * Add some CSS to the blob that will be injected later. Allows optional * components such as fields and the toolbox to store separate CSS. * The provided array of CSS will be destroyed by this function. - * @param {!Array.} cssArray Array of CSS strings. + * @param {!Array} cssArray Array of CSS strings. */ Blockly.Css.register = function(cssArray) { if (Blockly.Css.injected_) { @@ -88,13 +88,13 @@ Blockly.Css.CONTENT = [ '.blocklyWidgetDiv {', 'display: none;', 'position: absolute;', - 'z-index: 99999;', /* big value for bootstrap3 compatibility */ + 'z-index: 99999;', /* big value for bootstrap3 compatibility */ '}', '.injectionDiv {', 'height: 100%;', 'position: relative;', - 'overflow: hidden;', /* So blocks in drag surface disappear at edges */ + 'overflow: hidden;', /* So blocks in drag surface disappear at edges */ 'touch-action: none;', '}', @@ -125,7 +125,7 @@ Blockly.Css.CONTENT = [ 'right: 0;', 'bottom: 0;', 'overflow: visible !important;', - 'z-index: 50;', /* Display below toolbox, but above everything else. */ + 'z-index: 50;', /* Display below toolbox, but above everything else. */ '}', '.blocklyBlockCanvas.blocklyCanvasTransitioning,', @@ -143,7 +143,7 @@ Blockly.Css.CONTENT = [ 'opacity: .9;', 'padding: 2px;', 'position: absolute;', - 'z-index: 100000;', /* big value for bootstrap3 compatibility */ + 'z-index: 100000;', /* big value for bootstrap3 compatibility */ '}', '.blocklyDropDownDiv {', @@ -165,7 +165,7 @@ Blockly.Css.CONTENT = [ '}', '.blocklyDropDownContent {', - 'max-height: 300px;', // @todo: spec for maximum height. + 'max-height: 300px;', // @todo: spec for maximum height. 'overflow: auto;', 'overflow-x: hidden;', 'position: relative;', @@ -498,11 +498,11 @@ Blockly.Css.CONTENT = [ '}', '.blocklyDropDownDiv .blocklyMenu {', - 'background: inherit;', /* Compatibility with gapi, reset from goog-menu */ - 'border: inherit;', /* Compatibility with gapi, reset from goog-menu */ + 'background: inherit;', /* Compatibility with gapi, reset from goog-menu */ + 'border: inherit;', /* Compatibility with gapi, reset from goog-menu */ 'font: normal 13px "Helvetica Neue", Helvetica, sans-serif;', 'outline: none;', - 'position: relative;', /* Compatibility with gapi, reset from goog-menu */ + 'position: relative;', /* Compatibility with gapi, reset from goog-menu */ 'z-index: 20000;', /* Arbitrary, but some apps depend on it... */ '}', @@ -541,7 +541,7 @@ Blockly.Css.CONTENT = [ 'background: url(<<>>/sprites.png) no-repeat -48px -16px;', 'float: left;', 'margin-left: -24px;', - 'position: static;', /* Scroll with the menu. */ + 'position: static;', /* Scroll with the menu. */ '}', '.blocklyMenuItemRtl .blocklyMenuItemCheckbox {', diff --git a/core/delete_area.js b/core/delete_area.js new file mode 100644 index 000000000..92edf36f5 --- /dev/null +++ b/core/delete_area.js @@ -0,0 +1,53 @@ +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview The abstract class for a component that can delete a block or + * bubble that is dropped on top of it. + * @author kozbial@google.com (Monica Kozbial) + */ + +'use strict'; + +goog.provide('Blockly.DeleteArea'); + +goog.require('Blockly.DragTarget'); +goog.require('Blockly.IDeleteArea'); + + +/** + * Abstract class for a component that can delete a block or bubble that is + * dropped on top of it. + * @extends {Blockly.DragTarget} + * @implements {Blockly.IDeleteArea} + * @constructor + */ +Blockly.DeleteArea = function() { + Blockly.DeleteArea.superClass_.constructor.call(this); +}; +Blockly.utils.object.inherits(Blockly.DeleteArea, Blockly.DragTarget); + +/** + * Returns whether the provided block would be deleted if dropped on this area. + * @param {!Blockly.BlockSvg} _block The block. + * @param {boolean} couldConnect Whether the block could could connect to + * another. + * @return {boolean} Whether the block provided would be deleted if dropped on + * this area. + */ +Blockly.DeleteArea.prototype.wouldDeleteBlock = function(_block, couldConnect) { + return !couldConnect; +}; + +/** + * Returns whether the provided bubble would be deleted if dropped on this area. + * @param {!Blockly.IBubble} _bubble The bubble. + * @return {boolean} Whether the bubble provided would be deleted if dropped on + * this area. + */ +Blockly.DeleteArea.prototype.wouldDeleteBubble = function(_bubble) { + return true; +}; diff --git a/core/drag_target.js b/core/drag_target.js new file mode 100644 index 000000000..7a905fa0d --- /dev/null +++ b/core/drag_target.js @@ -0,0 +1,70 @@ +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview The abstract class for a component with custom behaviour when a + * block or bubble is dragged over or dropped on top of it. + * @author kozbial@google.com (Monica Kozbial) + */ + +'use strict'; + +goog.provide('Blockly.DragTarget'); + +goog.require('Blockly.IDragTarget'); + +goog.requireType('Blockly.BlockSvg'); +goog.requireType('Blockly.IBubble'); +goog.requireType('Blockly.utils.Rect'); + + +/** + * Abstract class for a component with custom behaviour when a block or bubble + * is dragged over or dropped on top of it. + * @implements {Blockly.IDragTarget} + * @constructor + */ +Blockly.DragTarget = function() {}; + +/** + * Returns the bounding rectangle of the drag target area in pixel units + * relative to the Blockly injection div. + * @return {?Blockly.utils.Rect} The component's bounding box. Null if drag + * target area should be ignored. + */ +Blockly.DragTarget.prototype.getClientRect; + +/** + * Handles when a cursor with a block or bubble enters this drag target. + */ +Blockly.DragTarget.prototype.onDragEnter = function() { + // no-op +}; + +/** + * Handles when a cursor with a block or bubble exits this drag target. + */ +Blockly.DragTarget.prototype.onDragExit = function() { + // no-op +}; + +/** + * Handles when a block is dropped on this component. Should not handle delete + * here. + * @param {!Blockly.BlockSvg} _block The block. + */ +Blockly.DragTarget.prototype.onBlockDrop = function(_block) { + // no-op +}; + +/** + * Handles when a bubble is dropped on this component. Should not handle delete + * here. + * @param {!Blockly.IBubble} _bubble The bubble. + */ +Blockly.DragTarget.prototype.onBubbleDrop = function(_bubble) { + // no-op +}; diff --git a/core/dropdowndiv.js b/core/dropdowndiv.js index d7d383cbc..68698371e 100644 --- a/core/dropdowndiv.js +++ b/core/dropdowndiv.js @@ -493,7 +493,7 @@ Blockly.DropDownDiv.getPositionBelowMetrics_ = function( return { initialX: xCoords.divX, initialY : primaryY, - finalX: xCoords.divX, // X position remains constant during animation. + finalX: xCoords.divX, // X position remains constant during animation. finalY: finalY, arrowX: xCoords.arrowX, arrowY: arrowY, @@ -525,12 +525,12 @@ Blockly.DropDownDiv.getPositionAboveMetrics_ = function( var arrowY = divSize.height - (Blockly.DropDownDiv.BORDER_SIZE * 2) - (Blockly.DropDownDiv.ARROW_SIZE / 2); var finalY = secondaryY - divSize.height - Blockly.DropDownDiv.PADDING_Y; - var initialY = secondaryY - divSize.height; // No padding on Y + var initialY = secondaryY - divSize.height; // No padding on Y. return { initialX: xCoords.divX, initialY : initialY, - finalX: xCoords.divX, // X position remains constant during animation. + finalX: xCoords.divX, // X position remains constant during animation. finalY: finalY, arrowX: xCoords.arrowX, arrowY: arrowY, @@ -560,8 +560,8 @@ Blockly.DropDownDiv.getPositionTopOfPageMetrics_ = function( return { initialX: xCoords.divX, initialY : 0, - finalX: xCoords.divX, // X position remains constant during animation. - finalY: 0, // Y position remains constant during animation. + finalX: xCoords.divX, // X position remains constant during animation. + finalY: 0, // Y position remains constant during animation. arrowAtTop: null, arrowX: null, arrowY: null, diff --git a/core/events/block_events.js b/core/events/block_events.js index df7e077f6..8be1dae30 100644 --- a/core/events/block_events.js +++ b/core/events/block_events.js @@ -20,9 +20,9 @@ goog.provide('Blockly.Events.Create'); // Deprecated. goog.provide('Blockly.Events.Delete'); // Deprecated. goog.provide('Blockly.Events.Move'); // Deprecated. +goog.require('Blockly.connectionTypes'); goog.require('Blockly.Events'); goog.require('Blockly.Events.Abstract'); -goog.require('Blockly.connectionTypes'); goog.require('Blockly.registry'); goog.require('Blockly.utils.Coordinate'); goog.require('Blockly.utils.object'); @@ -44,7 +44,7 @@ Blockly.Events.BlockBase = function(opt_block) { this.isBlank = typeof opt_block == 'undefined'; /** - * The block id for the block this event pertains to + * The block ID for the block this event pertains to * @type {string} */ this.blockId = this.isBlank ? '' : opt_block.id; @@ -332,7 +332,7 @@ Blockly.utils.object.inherits(Blockly.Events.Delete, Blockly.Events.BlockBase); /** * Class for a block deletion event. - * @param {Blockly.Block} block The deleted block. Null for a blank event. + * @param {?Blockly.Block} block The deleted block. Null for a blank event. * @extends {Blockly.Events.BlockBase} * @constructor */ @@ -420,7 +420,7 @@ Blockly.utils.object.inherits(Blockly.Events.Move, Blockly.Events.BlockBase); /** * Class for a block move event. Created before the move. - * @param {Blockly.Block} block The moved block. Null for a blank event. + * @param {?Blockly.Block} block The moved block. Null for a blank event. * @extends {Blockly.Events.BlockBase} * @constructor */ diff --git a/core/events/events.js b/core/events/events.js index 56c1b370d..982e84577 100644 --- a/core/events/events.js +++ b/core/events/events.js @@ -266,9 +266,9 @@ Blockly.Events.fireNow_ = function() { /** * Filter the queued events and merge duplicates. - * @param {!Array.} queueIn Array of events. + * @param {!Array} queueIn Array of events. * @param {boolean} forward True if forward (redo), false if backward (undo). - * @return {!Array.} Array of filtered events. + * @return {!Array} Array of filtered events. */ Blockly.Events.filter = function(queueIn, forward) { var queue = queueIn.slice(); // Shallow copy of queue. @@ -281,7 +281,7 @@ Blockly.Events.filter = function(queueIn, forward) { // Merge duplicates. for (var i = 0, event; (event = queue[i]); i++) { if (!event.isNull()) { - // Treat all ui events as the same type in hash table. + // Treat all UI events as the same type in hash table. var eventType = event.isUiEvent ? Blockly.Events.UI : event.type; var key = [eventType, event.blockId, event.workspaceId].join(' '); @@ -305,6 +305,12 @@ Blockly.Events.filter = function(queueIn, forward) { event.name == lastEvent.name) { // Merge change events. lastEvent.newValue = event.newValue; + } else if (event.type == Blockly.Events.VIEWPORT_CHANGE) { + // Merge viewport change events. + lastEvent.viewTop = event.viewTop; + lastEvent.viewLeft = event.viewLeft; + lastEvent.scale = event.scale; + lastEvent.oldScale = event.oldScale; } else if (event.type == Blockly.Events.CLICK && lastEvent.type == Blockly.Events.BUBBLE_OPEN) { // Drop click events caused by opening/closing bubbles. @@ -390,7 +396,7 @@ Blockly.Events.setGroup = function(state) { /** * Compute a list of the IDs of the specified block and all its descendants. * @param {!Blockly.Block} block The root block. - * @return {!Array.} List of block IDs. + * @return {!Array} List of block IDs. * @package */ Blockly.Events.getDescendantIds = function(block) { diff --git a/core/events/events_abstract.js b/core/events/events_abstract.js index 83e892086..719f6d937 100644 --- a/core/events/events_abstract.js +++ b/core/events/events_abstract.js @@ -52,7 +52,7 @@ Blockly.Events.Abstract = function() { }; /** - * Whether or not the event is a ui event. + * Whether or not the event is a UI event. * @type {boolean} */ Blockly.Events.Abstract.prototype.isUiEvent = false; diff --git a/core/events/events_block_drag.js b/core/events/events_block_drag.js index 202a9240d..9d256822a 100644 --- a/core/events/events_block_drag.js +++ b/core/events/events_block_drag.js @@ -26,7 +26,7 @@ goog.requireType('Blockly.Block'); * dragged. Undefined for a blank event. * @param {boolean=} opt_isStart Whether this is the start of a block drag. * Undefined for a blank event. - * @param {!Array.=} opt_blocks The blocks affected by this + * @param {!Array=} opt_blocks The blocks affected by this * drag. Undefined for a blank event. * @extends {Blockly.Events.UiBase} * @constructor @@ -44,7 +44,7 @@ Blockly.Events.BlockDrag = function(opt_block, opt_isStart, opt_blocks) { /** * The blocks affected by this drag event. - * @type {!Array.|undefined} + * @type {!Array|undefined} */ this.blocks = opt_blocks; }; diff --git a/core/events/events_selected.js b/core/events/events_selected.js index e1d71d32a..cfb7c6573 100644 --- a/core/events/events_selected.js +++ b/core/events/events_selected.js @@ -20,9 +20,9 @@ goog.require('Blockly.utils.object'); /** * Class for a selected event. - * @param {?string=} opt_oldElementId The id of the previously selected + * @param {?string=} opt_oldElementId The ID of the previously selected * element. Null if no element last selected. Undefined for a blank event. - * @param {?string=} opt_newElementId The id of the selected element. Null if no + * @param {?string=} opt_newElementId The ID of the selected element. Null if no * element currently selected (deselect). Undefined for a blank event. * @param {string=} opt_workspaceId The workspace identifier for this event. * Null if no element previously selected. Undefined for a blank event. diff --git a/core/extensions.js b/core/extensions.js index 267d172e7..0a2c146ad 100644 --- a/core/extensions.js +++ b/core/extensions.js @@ -28,7 +28,7 @@ goog.requireType('Blockly.Block'); * The set of all registered extensions, keyed by extension name/id. * @private */ -Blockly.Extensions.ALL_ = {}; +Blockly.Extensions.ALL_ = Object.create(null); /** * Registers a new extension function. Extensions are functions that help @@ -78,7 +78,7 @@ Blockly.Extensions.registerMixin = function(name, mixinObj) { * @param {!Object} mixinObj The values to mix in. * @param {(function())=} opt_helperFn An optional function to apply after * mixing in the object. - * @param {!Array.=} opt_blockList A list of blocks to appear in the + * @param {!Array=} opt_blockList A list of blocks to appear in the * flyout of the mutator dialog. * @throws {Error} if the mutation is invalid or can't be applied to the block. */ @@ -157,7 +157,7 @@ Blockly.Extensions.apply = function(name, block, isMutator) { Blockly.Extensions.checkBlockHasMutatorProperties_(errorPrefix, block); } else { if (!Blockly.Extensions.mutatorPropertiesMatch_( - /** @type {!Array.} */ (mutatorProperties), block)) { + /** @type {!Array} */ (mutatorProperties), block)) { throw Error('Error when applying extension "' + name + '": ' + 'mutation properties changed when applying a non-mutator extension.'); } @@ -227,10 +227,9 @@ Blockly.Extensions.checkMutatorDialog_ = function(object, errorPrefix) { return true; } else if (!hasCompose && !hasDecompose) { return false; - } else { - throw Error(errorPrefix + - 'Must have both or neither of "compose" and "decompose"'); } + throw Error(errorPrefix + + 'Must have both or neither of "compose" and "decompose"'); }; /** @@ -257,7 +256,7 @@ Blockly.Extensions.checkBlockHasMutatorProperties_ = function(errorPrefix, /** * Get a list of values of mutator properties on the given block. * @param {!Blockly.Block} block The block to inspect. - * @return {!Array.} A list with all of the defined properties, which + * @return {!Array} A list with all of the defined properties, which * should be functions, but may be anything other than undefined. * @private */ @@ -284,7 +283,7 @@ Blockly.Extensions.getMutatorProperties_ = function(block) { * Check that the current mutator properties match a list of old mutator * properties. This should be called after applying a non-mutator extension, * to verify that the extension didn't change properties it shouldn't. - * @param {!Array.} oldProperties The old values to compare to. + * @param {!Array} oldProperties The old values to compare to. * @param {!Blockly.Block} block The block to inspect for new values. * @return {boolean} True if the property lists match. * @private @@ -317,7 +316,7 @@ Blockly.Extensions.mutatorPropertiesMatch_ = function(oldProperties, block) { * reported as warnings in the console, and are never fatal. * @param {string} dropdownName The name of the field whose value is the key * to the lookup table. - * @param {!Object.} lookupTable The table of field values to + * @param {!Object} lookupTable The table of field values to * tooltip text. * @return {!Function} The extension function. */ @@ -377,7 +376,7 @@ Blockly.Extensions.buildTooltipForDropdown = function(dropdownName, * Emits console warnings when they are not. * @param {!Blockly.Block} block The block containing the dropdown * @param {string} dropdownName The name of the dropdown - * @param {!Object.} lookupTable The string lookup table + * @param {!Object} lookupTable The string lookup table * @private */ Blockly.Extensions.checkDropdownOptionsInTable_ = function(block, dropdownName, diff --git a/core/field.js b/core/field.js index c0ec9db80..9d52bacbb 100644 --- a/core/field.js +++ b/core/field.js @@ -15,11 +15,17 @@ goog.provide('Blockly.Field'); goog.require('Blockly.browserEvents'); +goog.require('Blockly.DropDownDiv'); goog.require('Blockly.Events'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.BlockChange'); /** @suppress {extraRequire} */ goog.require('Blockly.Gesture'); +goog.require('Blockly.IASTNodeLocationSvg'); +goog.require('Blockly.IASTNodeLocationWithBlock'); +goog.require('Blockly.IKeyboardAccessible'); +goog.require('Blockly.IRegistrable'); +goog.require('Blockly.MarkerManager'); goog.require('Blockly.Tooltip'); goog.require('Blockly.utils'); goog.require('Blockly.utils.dom'); @@ -28,15 +34,12 @@ goog.require('Blockly.utils.Size'); goog.require('Blockly.utils.style'); goog.require('Blockly.utils.Svg'); goog.require('Blockly.utils.userAgent'); +goog.require('Blockly.WidgetDiv'); goog.requireType('Blockly.Block'); goog.requireType('Blockly.blockRendering.ConstantProvider'); goog.requireType('Blockly.BlockSvg'); -goog.requireType('Blockly.IASTNodeLocationSvg'); -goog.requireType('Blockly.IASTNodeLocationWithBlock'); -goog.requireType('Blockly.IKeyboardAccessible'); goog.requireType('Blockly.Input'); -goog.requireType('Blockly.IRegistrable'); goog.requireType('Blockly.ShortcutRegistry'); goog.requireType('Blockly.utils.Coordinate'); goog.requireType('Blockly.WorkspaceSvg'); @@ -533,7 +536,7 @@ Blockly.Field.prototype.setValidator = function(handler) { /** * Gets the validation function for editable fields, or null if not set. - * @return {Function} Validation function, or null. + * @return {?Function} Validation function, or null. */ Blockly.Field.prototype.getValidator = function() { return this.validator_; @@ -946,7 +949,7 @@ Blockly.Field.prototype.setTooltip = function(newTip) { /** * Returns the tooltip text for this field. - * @returns {string} The tooltip text for this field. + * @return {string} The tooltip text for this field. */ Blockly.Field.prototype.getTooltip = function() { var clickTarget = this.getClickTarget_(); @@ -1041,8 +1044,8 @@ Blockly.Field.prototype.onShortcut = function(_shortcut) { }; /** - * Add the cursor svg to this fields svg group. - * @param {SVGElement} cursorSvg The svg root of the cursor to be added to the + * Add the cursor SVG to this fields SVG group. + * @param {SVGElement} cursorSvg The SVG root of the cursor to be added to the * field group. * @package */ @@ -1057,8 +1060,8 @@ Blockly.Field.prototype.setCursorSvg = function(cursorSvg) { }; /** - * Add the marker svg to this fields svg group. - * @param {SVGElement} markerSvg The svg root of the marker to be added to the + * Add the marker SVG to this fields SVG group. + * @param {SVGElement} markerSvg The SVG root of the marker to be added to the * field group. * @package */ diff --git a/core/field_angle.js b/core/field_angle.js index a78f0008b..5cadd6e48 100644 --- a/core/field_angle.js +++ b/core/field_angle.js @@ -18,10 +18,12 @@ goog.require('Blockly.DropDownDiv'); goog.require('Blockly.fieldRegistry'); goog.require('Blockly.FieldTextInput'); goog.require('Blockly.utils.dom'); +goog.require('Blockly.utils.KeyCodes'); goog.require('Blockly.utils.math'); goog.require('Blockly.utils.object'); goog.require('Blockly.utils.Svg'); goog.require('Blockly.utils.userAgent'); +goog.require('Blockly.WidgetDiv'); /** @@ -345,7 +347,7 @@ Blockly.FieldAngle.prototype.dropdownCreate_ = function() { }; /** - * Disposes of events and dom-references belonging to the angle editor. + * Disposes of events and DOM-references belonging to the angle editor. * @private */ Blockly.FieldAngle.prototype.dropdownDispose_ = function() { diff --git a/core/field_colour.js b/core/field_colour.js index cec789887..09082f4d8 100644 --- a/core/field_colour.js +++ b/core/field_colour.js @@ -130,14 +130,14 @@ Blockly.FieldColour.prototype.isDirty_ = false; /** * Array of colours used by this field. If null, use the global list. - * @type {Array.} + * @type {Array} * @private */ Blockly.FieldColour.prototype.colours_ = null; /** * Array of colour tooltips used by this field. If null, use the global list. - * @type {Array.} + * @type {Array} * @private */ Blockly.FieldColour.prototype.titles_ = null; @@ -243,7 +243,7 @@ Blockly.FieldColour.prototype.getText = function() { * An array of colour strings for the palette. * Copied from goog.ui.ColorPicker.SIMPLE_GRID_COLORS * All colour pickers use this unless overridden with setColours. - * @type {!Array.} + * @type {!Array} */ Blockly.FieldColour.COLOURS = [ // grays @@ -279,7 +279,7 @@ Blockly.FieldColour.prototype.DEFAULT_VALUE = Blockly.FieldColour.COLOURS[0]; * An array of tooltip strings for the palette. If not the same length as * COLOURS, the colour's hex code will be used for any missing titles. * All colour pickers use this unless overridden with setColours. - * @type {!Array.} + * @type {!Array} */ Blockly.FieldColour.TITLES = []; @@ -291,9 +291,9 @@ Blockly.FieldColour.COLUMNS = 7; /** * Set a custom colour grid for this field. - * @param {Array.} colours Array of colours for this block, + * @param {Array} colours Array of colours for this block, * or null to use default (Blockly.FieldColour.COLOURS). - * @param {Array.=} opt_titles Optional array of colour tooltips, + * @param {Array=} opt_titles Optional array of colour tooltips, * or null to use default (Blockly.FieldColour.TITLES). * @return {!Blockly.FieldColour} Returns itself (for method chaining). */ @@ -473,7 +473,7 @@ Blockly.FieldColour.prototype.onMouseLeave_ = function() { /** * Returns the currently highlighted item (if any). - * @return {HTMLElement} Highlighted item (null if none). + * @return {?HTMLElement} Highlighted item (null if none). * @private */ Blockly.FieldColour.prototype.getHighlighted_ = function() { @@ -572,7 +572,7 @@ Blockly.FieldColour.prototype.dropdownCreate_ = function() { }; /** - * Disposes of events and dom-references belonging to the colour editor. + * Disposes of events and DOM-references belonging to the colour editor. * @private */ Blockly.FieldColour.prototype.dropdownDispose_ = function() { diff --git a/core/field_dropdown.js b/core/field_dropdown.js index 17ecc6292..89f6bb1e1 100644 --- a/core/field_dropdown.js +++ b/core/field_dropdown.js @@ -14,6 +14,7 @@ goog.provide('Blockly.FieldDropdown'); +goog.require('Blockly.DropDownDiv'); goog.require('Blockly.Field'); goog.require('Blockly.fieldRegistry'); goog.require('Blockly.Menu'); @@ -30,7 +31,7 @@ goog.require('Blockly.utils.userAgent'); /** * Class for an editable dropdown field. - * @param {(!Array.|!Function)} menuGenerator A non-empty array of + * @param {(!Array|!Function)} menuGenerator A non-empty array of * options for a dropdown list, or a function which generates these options. * @param {Function=} opt_validator A function that is called to validate * changes to the field's value. Takes in a language-neutral dropdown @@ -51,15 +52,15 @@ Blockly.FieldDropdown = function(menuGenerator, opt_validator, opt_config) { /** * An array of options for a dropdown list, * or a function which generates these options. - * @type {(!Array.| - * !function(this:Blockly.FieldDropdown): !Array.)} + * @type {(!Array| + * !function(this:Blockly.FieldDropdown): !Array)} * @protected */ this.menuGenerator_ = menuGenerator; /** * A cache of the most recently generated options. - * @type {Array.>} + * @type {Array>} * @private */ this.generatedOptions_ = null; @@ -336,8 +337,8 @@ Blockly.FieldDropdown.prototype.dropdownCreate_ = function() { var options = this.getOptions(false); this.selectedMenuItem_ = null; for (var i = 0; i < options.length; i++) { - var content = options[i][0]; // Human-readable text or image. - var value = options[i][1]; // Language-neutral value. + var content = options[i][0]; // Human-readable text or image. + var value = options[i][1]; // Language-neutral value. if (typeof content == 'object') { // An image, not text. var image = new Image(content['width'], content['height']); @@ -361,7 +362,7 @@ Blockly.FieldDropdown.prototype.dropdownCreate_ = function() { }; /** - * Disposes of events and dom-references belonging to the dropdown editor. + * Disposes of events and DOM-references belonging to the dropdown editor. * @private */ Blockly.FieldDropdown.prototype.dropdownDispose_ = function() { @@ -448,11 +449,11 @@ Blockly.FieldDropdown.prototype.trimOptions_ = function() { /** * Use the calculated prefix and suffix lengths to trim all of the options in * the given array. - * @param {!Array.} options Array of option tuples: + * @param {!Array} options Array of option tuples: * (human-readable text or image, language-neutral name). * @param {number} prefixLength The length of the common prefix. * @param {number} suffixLength The length of the common suffix - * @return {!Array.} A new array with all of the option text trimmed. + * @return {!Array} A new array with all of the option text trimmed. */ Blockly.FieldDropdown.applyTrim_ = function(options, prefixLength, suffixLength) { @@ -479,7 +480,7 @@ Blockly.FieldDropdown.prototype.isOptionListDynamic = function() { * Return a list of the options for this dropdown. * @param {boolean=} opt_useCache For dynamic options, whether or not to use the * cached options or to re-generate them. - * @return {!Array.} A non-empty array of option tuples: + * @return {!Array} A non-empty array of option tuples: * (human-readable text or image, language-neutral name). * @throws {TypeError} If generated options are incorrectly structured. */ @@ -491,7 +492,7 @@ Blockly.FieldDropdown.prototype.getOptions = function(opt_useCache) { } return this.generatedOptions_; } - return /** @type {!Array.>} */ (this.menuGenerator_); + return /** @type {!Array>} */ (this.menuGenerator_); }; /** diff --git a/core/field_label.js b/core/field_label.js index 6f35b0c84..c332dde23 100644 --- a/core/field_label.js +++ b/core/field_label.js @@ -109,8 +109,8 @@ Blockly.FieldLabel.prototype.doClassValidation_ = function(opt_newValue) { }; /** - * Set the css class applied to the field's textElement_. - * @param {?string} cssClass The new css class name, or null to remove. + * Set the CSS class applied to the field's textElement_. + * @param {?string} cssClass The new CSS class name, or null to remove. */ Blockly.FieldLabel.prototype.setClass = function(cssClass) { if (this.textElement_) { diff --git a/core/field_multilineinput.js b/core/field_multilineinput.js index b0e782a66..c6260e4fd 100644 --- a/core/field_multilineinput.js +++ b/core/field_multilineinput.js @@ -15,6 +15,8 @@ goog.provide('Blockly.FieldMultilineInput'); goog.require('Blockly.Css'); +goog.require('Blockly.Field'); +goog.require('Blockly.fieldRegistry'); goog.require('Blockly.FieldTextInput'); goog.require('Blockly.utils'); goog.require('Blockly.utils.aria'); @@ -23,6 +25,7 @@ goog.require('Blockly.utils.KeyCodes'); goog.require('Blockly.utils.object'); goog.require('Blockly.utils.Svg'); goog.require('Blockly.utils.userAgent'); +goog.require('Blockly.WidgetDiv'); /** @@ -97,8 +100,8 @@ Blockly.FieldMultilineInput.fromJson = function(options) { * @package */ Blockly.FieldMultilineInput.prototype.toXml = function(fieldElement) { - // Replace '\n' characters with html-escaped equivalent ' '. This is - // needed so the plain-text representation of the xml produced by + // Replace '\n' characters with HTML-escaped equivalent ' '. This is + // needed so the plain-text representation of the XML produced by // `Blockly.Xml.domToText` will appear on a single line (this is a limitation // of the plain-text format). fieldElement.textContent = this.getValue().replace(/\n/g, ' '); diff --git a/core/field_number.js b/core/field_number.js index c5c3287a0..2cfa2ca23 100644 --- a/core/field_number.js +++ b/core/field_number.js @@ -222,17 +222,14 @@ Blockly.FieldNumber.prototype.setPrecision = function(precision) { * @private */ Blockly.FieldNumber.prototype.setPrecisionInternal_ = function(precision) { - if (precision == null) { - // Number(precision) would also be 0, but set explicitly to be clear. - this.precision_ = 0; - } else { - precision = Number(precision); - if (!isNaN(precision)) { - this.precision_ = precision; - } + this.precision_ = Number(precision) || 0; + var precisionString = String(this.precision_); + if (precisionString.indexOf('e') != -1) { + // String() is fast. But it turns .0000001 into '1e-7'. + // Use the much slower toLocaleString to access all the digits. + precisionString = + this.precision_.toLocaleString('en-US', {maximumFractionDigits: 20}); } - - var precisionString = this.precision_.toLocaleString("en-US", {maximumFractionDigits: 20}); var decimalIndex = precisionString.indexOf('.'); if (decimalIndex == -1) { // If the precision is 0 (float) allow any number of decimals, diff --git a/core/field_registry.js b/core/field_registry.js index cf30979c8..7f431ff7d 100644 --- a/core/field_registry.js +++ b/core/field_registry.js @@ -49,7 +49,7 @@ Blockly.fieldRegistry.unregister = function(type) { * Blockly.fieldRegistry.register. * @param {!Object} options A JSON object with a type and options specific * to the field type. - * @return {Blockly.Field} The new field instance or null if a field wasn't + * @return {?Blockly.Field} The new field instance or null if a field wasn't * found with the given type name * @package */ diff --git a/core/field_textinput.js b/core/field_textinput.js index 4d8a8f04d..bd97f5fcb 100644 --- a/core/field_textinput.js +++ b/core/field_textinput.js @@ -13,6 +13,7 @@ goog.provide('Blockly.FieldTextInput'); goog.require('Blockly.browserEvents'); +goog.require('Blockly.DropDownDiv'); goog.require('Blockly.Events'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.BlockChange'); @@ -26,6 +27,7 @@ goog.require('Blockly.utils.dom'); goog.require('Blockly.utils.KeyCodes'); goog.require('Blockly.utils.object'); goog.require('Blockly.utils.userAgent'); +goog.require('Blockly.WidgetDiv'); goog.requireType('Blockly.BlockSvg'); goog.requireType('Blockly.WorkspaceSvg'); @@ -387,7 +389,7 @@ Blockly.FieldTextInput.prototype.widgetCreate_ = function() { /** * Closes the editor, saves the results, and disposes of any events or - * dom-references belonging to the editor. + * DOM-references belonging to the editor. * @protected */ Blockly.FieldTextInput.prototype.widgetDispose_ = function() { @@ -488,8 +490,8 @@ Blockly.FieldTextInput.prototype.onHtmlInputChange_ = function(_e) { }; /** - * Set the html input value and the field's internal value. The difference - * between this and ``setValue`` is that this also updates the html input + * Set the HTML input value and the field's internal value. The difference + * between this and ``setValue`` is that this also updates the HTML input * value whilst editing. * @param {*} newValue New value. * @protected @@ -536,28 +538,28 @@ Blockly.FieldTextInput.prototype.isTabNavigable = function() { /** * Use the `getText_` developer hook to override the field's text representation. - * When we're currently editing, return the current html value instead. + * When we're currently editing, return the current HTML value instead. * Otherwise, return null which tells the field to use the default behaviour * (which is a string cast of the field's value). - * @return {?string} The html value if we're editing, otherwise null. + * @return {?string} The HTML value if we're editing, otherwise null. * @protected * @override */ Blockly.FieldTextInput.prototype.getText_ = function() { if (this.isBeingEdited_ && this.htmlInput_) { - // We are currently editing, return the html input value instead. + // We are currently editing, return the HTML input value instead. return this.htmlInput_.value; } return null; }; /** - * Transform the provided value into a text to show in the html input. - * Override this method if the field's html input representation is different + * Transform the provided value into a text to show in the HTML input. + * Override this method if the field's HTML input representation is different * than the field's value. This should be coupled with an override of * `getValueFromEditorText_`. * @param {*} value The value stored in this field. - * @return {string} The text to show on the html input. + * @return {string} The text to show on the HTML input. * @protected */ Blockly.FieldTextInput.prototype.getEditorText_ = function(value) { @@ -565,12 +567,12 @@ Blockly.FieldTextInput.prototype.getEditorText_ = function(value) { }; /** - * Transform the text received from the html input into a value to store + * Transform the text received from the HTML input into a value to store * in this field. - * Override this method if the field's html input representation is different + * Override this method if the field's HTML input representation is different * than the field's value. This should be coupled with an override of * `getEditorText_`. - * @param {string} text Text received from the html input. + * @param {string} text Text received from the HTML input. * @return {*} The value to store. * @protected */ diff --git a/core/field_variable.js b/core/field_variable.js index dcb73e237..efdf08bfa 100644 --- a/core/field_variable.js +++ b/core/field_variable.js @@ -39,7 +39,7 @@ goog.requireType('Blockly.MenuItem'); * @param {Function=} opt_validator A function that is called to validate * changes to the field's value. Takes in a variable ID & returns a * validated variable ID, or null to abort the change. - * @param {Array.=} opt_variableTypes A list of the types of variables + * @param {Array=} opt_variableTypes A list of the types of variables * to include in the dropdown. * @param {string=} opt_defaultType The type of variable to create if this * field's value is not explicitly set. Defaults to ''. @@ -58,8 +58,8 @@ Blockly.FieldVariable = function(varName, opt_validator, opt_variableTypes, /** * An array of options for a dropdown list, * or a function which generates these options. - * @type {(!Array.| - * !function(this:Blockly.FieldDropdown): !Array.)} + * @type {(!Array| + * !function(this:Blockly.FieldDropdown): !Array)} * @protected */ this.menuGenerator_ = Blockly.FieldVariable.dropdownCreate; @@ -129,7 +129,7 @@ Blockly.FieldVariable.prototype.configure_ = function(config) { */ Blockly.FieldVariable.prototype.initModel = function() { if (this.variable_) { - return; // Initialization already happened. + return; // Initialization already happened. } var variable = Blockly.Variables.getOrCreateVariablePackage( this.sourceBlock_.workspace, null, @@ -225,7 +225,7 @@ Blockly.FieldVariable.prototype.getText = function() { * Get the variable model for the selected variable. * Not guaranteed to be in the variable map on the workspace (e.g. if accessed * after the variable has been deleted). - * @return {Blockly.VariableModel} The selected variable, or null if none was + * @return {?Blockly.VariableModel} The selected variable, or null if none was * selected. * @package */ @@ -238,7 +238,7 @@ Blockly.FieldVariable.prototype.getVariable = function() { * Returns null if the variable is not set, because validators should not * run on the initial setValue call, because the field won't be attached to * a block and workspace at that point. - * @return {Function} Validation function, or null. + * @return {?Function} Validation function, or null. */ Blockly.FieldVariable.prototype.getValidator = function() { // Validators shouldn't operate on the initial setValue call. @@ -251,9 +251,9 @@ Blockly.FieldVariable.prototype.getValidator = function() { }; /** - * Ensure that the id belongs to a valid variable of an allowed type. - * @param {*=} opt_newValue The id of the new variable to set. - * @return {?string} The validated id, or null if invalid. + * Ensure that the ID belongs to a valid variable of an allowed type. + * @param {*=} opt_newValue The ID of the new variable to set. + * @return {?string} The validated ID, or null if invalid. * @protected */ Blockly.FieldVariable.prototype.doClassValidation_ = function(opt_newValue) { @@ -300,7 +300,7 @@ Blockly.FieldVariable.prototype.doValueUpdate_ = function(newId) { Blockly.FieldVariable.prototype.typeIsAllowed_ = function(type) { var typeList = this.getVariableTypes_(); if (!typeList) { - return true; // If it's null, all types are valid. + return true; // If it's null, all types are valid. } for (var i = 0; i < typeList.length; i++) { if (type == typeList[i]) { @@ -312,7 +312,7 @@ Blockly.FieldVariable.prototype.typeIsAllowed_ = function(type) { /** * Return a list of variable types to include in the dropdown. - * @return {!Array.} Array of variable types. + * @return {!Array} Array of variable types. * @throws {Error} if variableTypes is an empty array. * @private */ @@ -338,7 +338,7 @@ Blockly.FieldVariable.prototype.getVariableTypes_ = function() { /** * Parse the optional arguments representing the allowed variable types and the * default variable type. - * @param {Array.=} opt_variableTypes A list of the types of variables + * @param {Array=} opt_variableTypes A list of the types of variables * to include in the dropdown. If null or undefined, variables of all types * will be displayed in the dropdown. * @param {string=} opt_defaultType The type of the variable to create if this @@ -388,7 +388,7 @@ Blockly.FieldVariable.prototype.refreshVariableName = function() { /** * Return a sorted list of variable names for variable dropdown menus. * Include a special option at the end for creating a new variable name. - * @return {!Array.} Array of variable names/id tuples. + * @return {!Array} Array of variable names/id tuples. * @this {Blockly.FieldVariable} */ Blockly.FieldVariable.dropdownCreate = function() { diff --git a/core/flyout_base.js b/core/flyout_base.js index 971ca8914..06ceecbbb 100644 --- a/core/flyout_base.js +++ b/core/flyout_base.js @@ -16,6 +16,7 @@ goog.require('Blockly.Block'); /** @suppress {extraRequire} */ goog.require('Blockly.blockRendering'); goog.require('Blockly.browserEvents'); +goog.require('Blockly.DeleteArea'); goog.require('Blockly.Events'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.BlockCreate'); @@ -24,6 +25,7 @@ goog.require('Blockly.Events.VarCreate'); goog.require('Blockly.FlyoutMetricsManager'); /** @suppress {extraRequire} */ goog.require('Blockly.Gesture'); +goog.require('Blockly.IFlyout'); goog.require('Blockly.ScrollbarPair'); goog.require('Blockly.Tooltip'); /** @suppress {extraRequire} */ @@ -39,8 +41,6 @@ goog.require('Blockly.Xml'); goog.requireType('Blockly.BlockSvg'); goog.requireType('Blockly.FlyoutButton'); -goog.requireType('Blockly.IDeleteArea'); -goog.requireType('Blockly.IFlyout'); goog.requireType('Blockly.Options'); goog.requireType('Blockly.utils.Rect'); @@ -51,10 +51,11 @@ goog.requireType('Blockly.utils.Rect'); * workspace. * @constructor * @abstract - * @implements {Blockly.IDeleteArea} * @implements {Blockly.IFlyout} + * @extends {Blockly.DeleteArea} */ Blockly.Flyout = function(workspaceOptions) { + Blockly.Flyout.superClass_.constructor.call(this); workspaceOptions.setMetrics = this.setMetrics_.bind(this); /** @@ -91,7 +92,7 @@ Blockly.Flyout = function(workspaceOptions) { /** * Opaque data that can be passed to Blockly.unbindEvent_. - * @type {!Array.} + * @type {!Array} * @private */ this.eventWrappers_ = []; @@ -99,28 +100,28 @@ Blockly.Flyout = function(workspaceOptions) { /** * List of background mats that lurk behind each block to catch clicks * landing in the blocks' lakes and bays. - * @type {!Array.} + * @type {!Array} * @private */ this.mats_ = []; /** * List of visible buttons. - * @type {!Array.} + * @type {!Array} * @protected */ this.buttons_ = []; /** * List of event listeners. - * @type {!Array.} + * @type {!Array} * @private */ this.listeners_ = []; /** * List of blocks that should always be disabled. - * @type {!Array.} + * @type {!Array} * @private */ this.permanentlyDisabled_ = []; @@ -140,6 +141,7 @@ Blockly.Flyout = function(workspaceOptions) { */ this.targetWorkspace = null; }; +Blockly.utils.object.inherits(Blockly.Flyout, Blockly.DeleteArea); /** * Does the flyout automatically close when a block is created? @@ -232,8 +234,8 @@ Blockly.Flyout.prototype.dragAngleRange_ = 70; /** * Creates the flyout's DOM. Only needs to be called once. The flyout can - * either exist as its own svg element or be a g element nested inside a - * separate svg element. + * either exist as its own SVG element or be a g element nested inside a + * separate SVG element. * @param {string| * !Blockly.utils.Svg| * !Blockly.utils.Svg} tagName The type of tag to @@ -300,6 +302,16 @@ Blockly.Flyout.prototype.init = function(targetWorkspace) { this.workspace_.setVariableMap(this.targetWorkspace.getVariableMap()); this.workspace_.createPotentialVariableMap(); + + targetWorkspace.getComponentManager().addComponent({ + id: 'flyout' + this.workspace_.id, + component: this, + weight: 1, + capabilities: [ + Blockly.ComponentManager.Capability.DELETE_AREA, + Blockly.ComponentManager.Capability.DRAG_TARGET + ] + }); }; /** @@ -380,6 +392,11 @@ Blockly.Flyout.prototype.setVisible = function(visible) { this.isVisible_ = visible; if (visibilityChanged) { + if (!this.autoClose) { + // Auto-close flyouts are ignored as drag targets, so only non auto-close + // flyouts need to have their drag target updated. + this.workspace_.recordDragTargets(); + } this.updateDisplay_(); } }; @@ -498,7 +515,7 @@ Blockly.Flyout.prototype.show = function(flyoutDef) { // Parse the Array, Node or NodeList into a a list of flyout items. var parsedContent = Blockly.utils.toolbox.convertFlyoutDefToJsonArray(flyoutDef); var flyoutInfo = - /** @type {{contents:!Array., gaps:!Array.}} */ ( + /** @type {{contents:!Array, gaps:!Array}} */ ( this.createFlyoutInfo_(parsedContent)); this.layout_(flyoutInfo.contents, flyoutInfo.gaps); @@ -537,7 +554,7 @@ Blockly.Flyout.prototype.show = function(flyoutDef) { * the flyout. * @param {!Blockly.utils.toolbox.FlyoutItemInfoArray} parsedContent The array * of objects to show in the flyout. - * @return {{contents:Array., gaps:Array.}} The list of contents + * @return {{contents:Array, gaps:Array}} The list of contents * and gaps needed to lay out the flyout. * @private */ @@ -594,7 +611,7 @@ Blockly.Flyout.prototype.createFlyoutInfo_ = function(parsedContent) { /** * Gets the flyout definition for the dynamic category. * @param {string} categoryName The name of the dynamic category. - * @return {!Array.} The array of flyout items. + * @return {!Array} The array of flyout items. * @private */ Blockly.Flyout.prototype.getDynamicCategoryContents_ = function(categoryName) { @@ -684,7 +701,7 @@ Blockly.Flyout.prototype.getBlockXml_ = function(blockInfo) { * Add the necessary gap in the flyout for a separator. * @param {!Blockly.utils.toolbox.SeparatorInfo} sepInfo The object holding * information about a separator. - * @param {!Array.} gaps The list gaps between items in the flyout. + * @param {!Array} gaps The list gaps between items in the flyout. * @param {number} defaultGap The default gap between the button and next element. * @private */ @@ -1018,8 +1035,9 @@ Blockly.Flyout.prototype.placeNewBlock_ = function(oldBlock) { }; /** - * Return the deletion rectangle for this flyout in viewport coordinates. - * @return {Blockly.utils.Rect} Rectangle in which to delete. + * Returns the bounding rectangle of the drag target area in pixel units + * relative to viewport. + * @return {Blockly.utils.Rect} The component's bounding box. */ Blockly.Flyout.prototype.getClientRect; @@ -1051,8 +1069,8 @@ Blockly.Flyout.prototype.setMetrics_; /** * Lay out the blocks in the flyout. - * @param {!Array.} contents The blocks and buttons to lay out. - * @param {!Array.} gaps The visible gaps between blocks. + * @param {!Array} contents The blocks and buttons to lay out. + * @param {!Array} gaps The visible gaps between blocks. * @protected */ Blockly.Flyout.prototype.layout_; diff --git a/core/flyout_button.js b/core/flyout_button.js index cf996f46d..643790d9f 100644 --- a/core/flyout_button.js +++ b/core/flyout_button.js @@ -17,6 +17,7 @@ goog.require('Blockly.Css'); goog.require('Blockly.utils'); goog.require('Blockly.utils.Coordinate'); goog.require('Blockly.utils.dom'); +goog.require('Blockly.utils.style'); goog.require('Blockly.utils.Svg'); goog.requireType('Blockly.utils.toolbox'); diff --git a/core/flyout_horizontal.js b/core/flyout_horizontal.js index 07d9803db..9ef631834 100644 --- a/core/flyout_horizontal.js +++ b/core/flyout_horizontal.js @@ -16,6 +16,7 @@ goog.provide('Blockly.HorizontalFlyout'); goog.require('Blockly.Block'); /** @suppress {extraRequire} */ goog.require('Blockly.constants'); +goog.require('Blockly.DropDownDiv'); goog.require('Blockly.Flyout'); goog.require('Blockly.registry'); goog.require('Blockly.Scrollbar'); @@ -230,8 +231,8 @@ Blockly.HorizontalFlyout.prototype.wheel_ = function(e) { /** * Lay out the blocks in the flyout. - * @param {!Array.} contents The blocks and buttons to lay out. - * @param {!Array.} gaps The visible gaps between blocks. + * @param {!Array} contents The blocks and buttons to lay out. + * @param {!Array} gaps The visible gaps between blocks. * @protected */ Blockly.HorizontalFlyout.prototype.layout_ = function(contents, gaps) { @@ -303,11 +304,15 @@ Blockly.HorizontalFlyout.prototype.isDragTowardWorkspace = function( }; /** - * Return the deletion rectangle for this flyout in viewport coordinates. - * @return {Blockly.utils.Rect} Rectangle in which to delete. + * Returns the bounding rectangle of the drag target area in pixel units + * relative to viewport. + * @return {?Blockly.utils.Rect} The component's bounding box. Null if drag + * target area should be ignored. */ Blockly.HorizontalFlyout.prototype.getClientRect = function() { - if (!this.svgGroup_) { + if (!this.svgGroup_ || this.autoClose || this.isVisible()) { + // The bounding rectangle won't compute correctly if the flyout is closed + // and auto-close flyouts aren't valid drag targets (or delete areas). return null; } diff --git a/core/flyout_vertical.js b/core/flyout_vertical.js index 66f754107..ca60d5718 100644 --- a/core/flyout_vertical.js +++ b/core/flyout_vertical.js @@ -16,6 +16,7 @@ goog.provide('Blockly.VerticalFlyout'); goog.require('Blockly.Block'); /** @suppress {extraRequire} */ goog.require('Blockly.constants'); +goog.require('Blockly.DropDownDiv'); goog.require('Blockly.Flyout'); goog.require('Blockly.registry'); goog.require('Blockly.Scrollbar'); @@ -221,8 +222,8 @@ Blockly.VerticalFlyout.prototype.wheel_ = function(e) { /** * Lay out the blocks in the flyout. - * @param {!Array.} contents The blocks and buttons to lay out. - * @param {!Array.} gaps The visible gaps between blocks. + * @param {!Array} contents The blocks and buttons to lay out. + * @param {!Array} gaps The visible gaps between blocks. * @protected */ Blockly.VerticalFlyout.prototype.layout_ = function(contents, gaps) { @@ -286,11 +287,15 @@ Blockly.VerticalFlyout.prototype.isDragTowardWorkspace = function( }; /** - * Return the deletion rectangle for this flyout in viewport coordinates. - * @return {Blockly.utils.Rect} Rectangle in which to delete. + * Returns the bounding rectangle of the drag target area in pixel units + * relative to viewport. + * @return {?Blockly.utils.Rect} The component's bounding box. Null if drag + * target area should be ignored. */ Blockly.VerticalFlyout.prototype.getClientRect = function() { - if (!this.svgGroup_) { + if (!this.svgGroup_ || this.autoClose || this.isVisible()) { + // The bounding rectangle won't compute correctly if the flyout is closed + // and auto-close flyouts aren't valid drag targets (or delete areas). return null; } diff --git a/core/generator.js b/core/generator.js index 77943cf7a..781cd7263 100644 --- a/core/generator.js +++ b/core/generator.js @@ -16,6 +16,7 @@ goog.provide('Blockly.Generator'); goog.require('Blockly.Block'); /** @suppress {extraRequire} */ goog.require('Blockly.constants'); +goog.require('Blockly.utils.deprecation'); goog.requireType('Blockly.Names'); goog.requireType('Blockly.Workspace'); @@ -32,11 +33,6 @@ Blockly.Generator = function(name) { new RegExp(this.FUNCTION_NAME_PLACEHOLDER_, 'g'); }; -/** - * Category to separate generated function names from variables and procedures. - */ -Blockly.Generator.NAME_TYPE = 'generated_function'; - /** * Arbitrary code to inject into locations that risk causing infinite loops. * Any instances of '%1' will be replaced by the block ID that failed. @@ -77,7 +73,7 @@ Blockly.Generator.prototype.COMMENT_WRAP = 60; /** * List of outer-inner pairings that do NOT require parentheses. - * @type {!Array.>} + * @type {!Array>} */ Blockly.Generator.prototype.ORDER_OVERRIDES = []; @@ -92,7 +88,7 @@ Blockly.Generator.prototype.isInitialized = null; /** * Generate code for all blocks in the workspace to the specified language. - * @param {Blockly.Workspace} workspace Workspace to generate code from. + * @param {!Blockly.Workspace=} workspace Workspace to generate code from. * @return {string} Generated code. */ Blockly.Generator.prototype.workspaceToCode = function(workspace) { @@ -223,9 +219,8 @@ Blockly.Generator.prototype.blockToCode = function(block, opt_thisOnly) { } else if (code === null) { // Block has handled code generation itself. return ''; - } else { - throw SyntaxError('Invalid code generated: ' + code); } + throw SyntaxError('Invalid code generated: ' + code); }; /** @@ -388,7 +383,7 @@ Blockly.Generator.prototype.FUNCTION_NAME_PLACEHOLDER_ = '{leCUI8hutHZI4480Dc}'; /** * A dictionary of definitions to be printed before the code. - * @type {Object} + * @type {!Object|undefined} * @protected */ Blockly.Generator.prototype.definitions_; @@ -396,38 +391,67 @@ Blockly.Generator.prototype.definitions_; /** * A dictionary mapping desired function names in definitions_ to actual * function names (to avoid collisions with user functions). - * @type {Object} + * @type {!Object|undefined} * @protected */ Blockly.Generator.prototype.functionNames_; /** - * A database of variable names. - * @type {Blockly.Names} + * A database of variable and procedure names. + * @type {!Blockly.Names|undefined} * @protected */ -Blockly.Generator.prototype.variableDB_; +Blockly.Generator.prototype.nameDB_; + +Object.defineProperty(Blockly.Generator.prototype, 'variableDB_', { + /** + * Getter. + * @deprecated 'variableDB_' was renamed to 'nameDB_' (May 2021). + * @this {Blockly.Generator} + * @return {!Blockly.Names|undefined} Name database. + */ + get: function() { + Blockly.utils.deprecation.warn( + 'variableDB_', 'May 2021', 'May 2026', 'nameDB_'); + return this.nameDB_; + }, + /** + * Setter. + * @deprecated 'variableDB_' was renamed to 'nameDB_' (May 2021). + * @this {Blockly.Generator} + * @param {!Blockly.Names|undefined} nameDb New name database. + */ + set: function(nameDb) { + Blockly.utils.deprecation.warn( + 'variableDB_', 'May 2021', 'May 2026', 'nameDB_'); + this.nameDB_ = nameDb; + } +}); /** - * Define a function to be included in the generated code. + * Define a developer-defined function (not a user-defined procedure) to be + * included in the generated code. Used for creating private helper functions. * The first time this is called with a given desiredName, the code is * saved and an actual name is generated. Subsequent calls with the * same desiredName have no effect but have the same return value. * * It is up to the caller to make sure the same desiredName is not - * used for different code values. + * used for different helper functions (e.g. use "colourRandom" and + * "listRandom", not "random"). There is no danger of colliding with reserved + * words, or user-defined variable or procedure names. * * The code gets output when Blockly.Generator.finish() is called. * - * @param {string} desiredName The desired name of the function (e.g., isPrime). - * @param {!Array.} code A list of statements. Use ' ' for indents. + * @param {string} desiredName The desired name of the function + * (e.g. mathIsPrime). + * @param {!Array} code A list of statements. Use ' ' for indents. * @return {string} The actual name of the new function. This may differ * from desiredName if the former has already been taken by the user. * @protected */ Blockly.Generator.prototype.provideFunction_ = function(desiredName, code) { if (!this.definitions_[desiredName]) { - var functionName = this.variableDB_.getDistinctName(desiredName, + var functionName = this.nameDB_.getDistinctName(desiredName, Blockly.PROCEDURE_CATEGORY_NAME); this.functionNames_[desiredName] = functionName; var codeText = code.join('\n').replace( @@ -455,6 +479,12 @@ Blockly.Generator.prototype.provideFunction_ = function(desiredName, code) { */ Blockly.Generator.prototype.init = function(_workspace) { // Optionally override + // Create a dictionary of definitions to be printed before the code. + this.definitions_ = Object.create(null); + // Create a dictionary mapping desired developer-defined function names in + // definitions_ to actual function names (to avoid collisions with + // user-defined procedures). + this.functionNames_ = Object.create(null); }; /** @@ -477,13 +507,16 @@ Blockly.Generator.prototype.scrub_ = function(_block, code, _opt_thisOnly) { /** * Hook for code to run at end of code generation. - * Subclasses may override this, e.g. to prepend the generated code with the - * variable definitions. + * Subclasses may override this, e.g. to prepend the generated code with import + * statements or variable definitions. * @param {string} code Generated code. * @return {string} Completed code. */ Blockly.Generator.prototype.finish = function(code) { // Optionally override + // Clean up temporary data. + delete this.definitions_; + delete this.functionNames_; return code; }; diff --git a/core/gesture.js b/core/gesture.js index 741b0cd74..55378930b 100644 --- a/core/gesture.js +++ b/core/gesture.js @@ -27,6 +27,7 @@ goog.require('Blockly.Tooltip'); goog.require('Blockly.Touch'); goog.require('Blockly.utils'); goog.require('Blockly.utils.Coordinate'); +goog.require('Blockly.Workspace'); goog.require('Blockly.WorkspaceDragger'); goog.requireType('Blockly.BlockSvg'); @@ -957,7 +958,7 @@ Blockly.Gesture.prototype.hasStarted = function() { /** * Get a list of the insertion markers that currently exist. Block drags have * 0, 1, or 2 insertion markers. - * @return {!Array.} A possibly empty list of insertion + * @return {!Array} A possibly empty list of insertion * marker blocks. * @package */ diff --git a/core/grid.js b/core/grid.js index e1b9c5d88..56171ef50 100644 --- a/core/grid.js +++ b/core/grid.js @@ -108,7 +108,7 @@ Blockly.Grid.prototype.getSpacing = function() { }; /** - * Get the id of the pattern element, which should be randomized to avoid + * Get the ID of the pattern element, which should be randomized to avoid * conflicts with other Blockly instances on the page. * @return {string} The pattern ID. * @package diff --git a/core/icon.js b/core/icon.js index 5e32a53a6..c5f3477cd 100644 --- a/core/icon.js +++ b/core/icon.js @@ -56,14 +56,14 @@ Blockly.Icon.prototype.SIZE = 17; /** * Bubble UI (if visible). - * @type {Blockly.Bubble} + * @type {?Blockly.Bubble} * @protected */ Blockly.Icon.prototype.bubble_ = null; /** * Absolute coordinate of icon's center. - * @type {Blockly.utils.Coordinate} + * @type {?Blockly.utils.Coordinate} * @protected */ Blockly.Icon.prototype.iconXY_ = null; @@ -177,7 +177,7 @@ Blockly.Icon.prototype.computeIconLocation = function() { /** * Returns the center of the block's icon relative to the surface. - * @return {Blockly.utils.Coordinate} Object with x and y properties in + * @return {?Blockly.utils.Coordinate} Object with x and y properties in * workspace coordinates. */ Blockly.Icon.prototype.getIconLocation = function() { diff --git a/core/inject.js b/core/inject.js index 418b004a1..d8dede3e7 100644 --- a/core/inject.js +++ b/core/inject.js @@ -25,12 +25,15 @@ goog.require('Blockly.Tooltip'); goog.require('Blockly.utils'); goog.require('Blockly.utils.aria'); goog.require('Blockly.utils.dom'); +goog.require('Blockly.utils.math'); goog.require('Blockly.utils.Svg'); goog.require('Blockly.utils.userAgent'); +goog.require('Blockly.Workspace'); goog.require('Blockly.WorkspaceDragSurfaceSvg'); goog.require('Blockly.WorkspaceSvg'); +goog.require('Blockly.WidgetDiv'); -goog.requireType('Blockly.Workspace'); +goog.requireType('Blockly.BlockSvg'); /** @@ -164,7 +167,7 @@ Blockly.createMainWorkspace_ = function(svg, options, blockDragSurface, mainWorkspace.getTheme().getClassName()); if (!wsOptions.hasCategories && wsOptions.languageTree) { - // Add flyout as an that is a sibling of the workspace svg. + // Add flyout as an that is a sibling of the workspace SVG. var flyout = mainWorkspace.addFlyout(Blockly.utils.Svg.SVG); Blockly.utils.dom.insertAfter(flyout, svg); } @@ -232,8 +235,7 @@ Blockly.bumpTopObjectsIntoBounds_ = function(workspace) { var scrollMetricsInWsCoords = metricsManager.getScrollMetrics(true); var topBlocks = workspace.getTopBoundedElements(); for (var i = 0, block; (block = topBlocks[i]); i++) { - Blockly.bumpObjectIntoBounds_( - workspace, scrollMetricsInWsCoords, block); + Blockly.bumpObjectIntoBounds_(workspace, scrollMetricsInWsCoords, block); } }; @@ -246,7 +248,7 @@ Blockly.bumpTopObjectsIntoBounds_ = function(workspace) { Blockly.bumpIntoBoundsHandler_ = function(workspace) { return function(e) { var metricsManager = workspace.getMetricsManager(); - if (!metricsManager.hasFixedEdges || workspace.isDragging()) { + if (!metricsManager.hasFixedEdges() || workspace.isDragging()) { return; } @@ -376,12 +378,11 @@ Blockly.init_ = function(mainWorkspace) { } } - var verticalSpacing = Blockly.Scrollbar.scrollbarThickness; if (options.hasTrashcan) { - verticalSpacing = mainWorkspace.trashcan.init(verticalSpacing); + mainWorkspace.trashcan.init(); } if (options.zoomOptions && options.zoomOptions.controls) { - mainWorkspace.zoomControls_.init(verticalSpacing); + mainWorkspace.zoomControls_.init(); } if (options.moveOptions && options.moveOptions.scrollbars) { diff --git a/core/input.js b/core/input.js index d898ce351..57189c278 100644 --- a/core/input.js +++ b/core/input.js @@ -50,7 +50,7 @@ Blockly.Input = function(type, name, block, connection) { this.sourceBlock_ = block; /** @type {Blockly.Connection} */ this.connection = connection; - /** @type {!Array.} */ + /** @type {!Array} */ this.fieldRow = []; }; @@ -69,7 +69,7 @@ Blockly.Input.prototype.visible_ = true; /** * Get the source block for this input. - * @return {Blockly.Block} The source block, or null if there is none. + * @return {?Blockly.Block} The source block, or null if there is none. */ Blockly.Input.prototype.getSourceBlock = function() { return this.sourceBlock_; @@ -168,9 +168,8 @@ Blockly.Input.prototype.removeField = function(name, opt_quiet) { } if (opt_quiet) { return false; - } else { - throw Error('Field "' + name + '" not found.'); } + throw Error('Field "' + name + '" not found.'); }; /** @@ -185,7 +184,7 @@ Blockly.Input.prototype.isVisible = function() { * Sets whether this input is visible or not. * Should only be used to collapse/uncollapse a block. * @param {boolean} visible True if visible. - * @return {!Array.} List of blocks to render. + * @return {!Array} List of blocks to render. * @package */ Blockly.Input.prototype.setVisible = function(visible) { @@ -230,7 +229,7 @@ Blockly.Input.prototype.markDirty = function() { /** * Change a connection's compatibility. - * @param {string|Array.|null} check Compatible value type or + * @param {string|Array|null} check Compatible value type or * list of value types. Null if all types are compatible. * @return {!Blockly.Input} The input being modified (to allow chaining). */ @@ -259,8 +258,8 @@ Blockly.Input.prototype.setAlign = function(align) { /** * Changes the connection's shadow block. - * @param {Element} shadow DOM representation of a block or null. - * @return {Blockly.Input} The input being modified (to allow chaining). + * @param {?Element} shadow DOM representation of a block or null. + * @return {!Blockly.Input} The input being modified (to allow chaining). */ Blockly.Input.prototype.setShadowDom = function(shadow) { if (!this.connection) { @@ -271,8 +270,8 @@ Blockly.Input.prototype.setShadowDom = function(shadow) { }; /** - * Returns the xml representation of the connection's shadow block. - * @return {Element} Shadow DOM representation of a block or null. + * Returns the XML representation of the connection's shadow block. + * @return {?Element} Shadow DOM representation of a block or null. */ Blockly.Input.prototype.getShadowDom = function() { if (!this.connection) { diff --git a/core/insertion_marker_manager.js b/core/insertion_marker_manager.js index dc69e44df..1a7988c24 100644 --- a/core/insertion_marker_manager.js +++ b/core/insertion_marker_manager.js @@ -131,7 +131,7 @@ Blockly.InsertionMarkerManager = function(block) { * other blocks. This includes all open connections on the top block, as well * as the last connection on the block stack. * Does not change during a drag. - * @type {!Array.} + * @type {!Array} * @private */ this.availableConnections_ = this.initAvailableConnections_(); @@ -148,6 +148,17 @@ Blockly.InsertionMarkerManager.PREVIEW_TYPE = { REPLACEMENT_FADE: 2, }; +/** + * An error message to throw if the block created by createMarkerBlock_ is + * missing any components. + * @type {string} + * @const + */ +Blockly.InsertionMarkerManager.DUPLICATE_BLOCK_ERROR = 'The insertion marker ' + + 'manager tried to create a marker but the result is missing %1. If ' + + 'you are using a mutator, make sure your domToMutation method is ' + + 'properly defined.'; + /** * Sever all links from this object. * @package @@ -229,14 +240,15 @@ Blockly.InsertionMarkerManager.prototype.applyConnections = function() { * Update connections based on the most recent move location. * @param {!Blockly.utils.Coordinate} dxy Position relative to drag start, * in workspace units. - * @param {?number} deleteArea One of {@link Blockly.DELETE_AREA_TRASH}, - * {@link Blockly.DELETE_AREA_TOOLBOX}, or {@link Blockly.DELETE_AREA_NONE}. + * @param {?Blockly.IDragTarget} dragTarget The drag target that the block is + * currently over. * @package */ -Blockly.InsertionMarkerManager.prototype.update = function(dxy, deleteArea) { +Blockly.InsertionMarkerManager.prototype.update = function(dxy, dragTarget) { var candidate = this.getCandidate_(dxy); - this.wouldDeleteBlock_ = this.shouldDelete_(candidate, deleteArea); + this.wouldDeleteBlock_ = this.shouldDelete_(candidate, dragTarget); + var shouldUpdate = this.wouldDeleteBlock_ || this.shouldUpdatePreviews_(candidate, dxy); @@ -279,9 +291,17 @@ Blockly.InsertionMarkerManager.prototype.createMarkerBlock_ = function(sourceBlo continue; // Ignore the collapsed input. } var resultInput = result.inputList[i]; + if (!resultInput) { + throw new Error(Blockly.InsertionMarkerManager.DUPLICATE_BLOCK_ERROR + .replace('%1', 'an input')); + } for (var j = 0; j < sourceInput.fieldRow.length; j++) { var sourceField = sourceInput.fieldRow[j]; var resultField = resultInput.fieldRow[j]; + if (!resultField) { + throw new Error(Blockly.InsertionMarkerManager.DUPLICATE_BLOCK_ERROR + .replace('%1', 'a field')); + } resultField.setValue(sourceField.getValue()); } } @@ -303,7 +323,7 @@ Blockly.InsertionMarkerManager.prototype.createMarkerBlock_ = function(sourceBlo * only be called once, at the beginning of a drag. * If the stack has more than one block, this function will populate * lastOnStack_ and create the corresponding insertion marker. - * @return {!Array.} A list of available + * @return {!Array} A list of available * connections. * @private */ @@ -365,7 +385,7 @@ Blockly.InsertionMarkerManager.prototype.shouldUpdatePreviews_ = function( } else { console.error('Only one of localConnection_ and closestConnection_ was set.'); } - } else { // No connection found. + } else { // No connection found. // Only need to update if we were showing a preview before. return !!(this.localConnection_ && this.closestConnection_); } @@ -426,23 +446,32 @@ Blockly.InsertionMarkerManager.prototype.getStartRadius_ = function() { /** * Whether ending the drag would delete the block. * @param {!Object} candidate An object containing a local connection, a closest - * connection, and a radius. - * @param {?number} deleteArea One of {@link Blockly.DELETE_AREA_TRASH}, - * {@link Blockly.DELETE_AREA_TOOLBOX}, or {@link Blockly.DELETE_AREA_NONE}. - * @return {boolean} True if dropping the block immediately would replace - * delete the block. False otherwise. + * connection, and a radius. + * @param {?Blockly.IDragTarget} dragTarget The drag target that the block is + * currently over. + * @return {boolean} Whether dropping the block immediately would delete the + * block. * @private */ -Blockly.InsertionMarkerManager.prototype.shouldDelete_ = function(candidate, - deleteArea) { - // Prefer connecting over dropping into the trash can, but prefer dragging to - // the toolbox over connecting to other blocks. - var wouldConnect = candidate && !!candidate.closest && - deleteArea != Blockly.DELETE_AREA_TOOLBOX; - var wouldDelete = !!deleteArea && !this.topBlock_.getParent() && - this.topBlock_.isDeletable(); +Blockly.InsertionMarkerManager.prototype.shouldDelete_ = function( + candidate, dragTarget) { + var couldDeleteBlock = + !this.topBlock_.getParent() && this.topBlock_.isDeletable(); - return wouldDelete && !wouldConnect; + if (couldDeleteBlock && dragTarget) { + // TODO(#4881) use hasCapability instead of getComponents + var deleteAreas = this.workspace_.getComponentManager().getComponents( + Blockly.ComponentManager.Capability.DELETE_AREA, false); + var isDeleteArea = deleteAreas.some(function(deleteArea) { + return dragTarget === deleteArea; + }); + if (isDeleteArea) { + return ( + /** @type {!Blockly.IDeleteArea} */ (dragTarget)) + .wouldDeleteBlock(this.topBlock_, candidate && !!candidate.closest); + } + } + return false; }; /** @@ -694,7 +723,7 @@ Blockly.InsertionMarkerManager.prototype.hideReplacementFade_ = function() { /** * Get a list of the insertion markers that currently exist. Drags have 0, 1, * or 2 insertion markers. - * @return {!Array.} A possibly empty list of insertion + * @return {!Array} A possibly empty list of insertion * marker blocks. * @package */ diff --git a/core/interfaces/i_accessibility.js b/core/interfaces/i_accessibility.js index 5fb3304bd..30d724959 100644 --- a/core/interfaces/i_accessibility.js +++ b/core/interfaces/i_accessibility.js @@ -34,16 +34,16 @@ Blockly.IASTNodeLocation = function() {}; Blockly.IASTNodeLocationSvg = function() {}; /** - * Add the marker svg to this node's svg group. - * @param {SVGElement} markerSvg The svg root of the marker to be added to the - * svg group. + * Add the marker SVG to this node's SVG group. + * @param {SVGElement} markerSvg The SVG root of the marker to be added to the + * SVG group. */ Blockly.IASTNodeLocationSvg.prototype.setMarkerSvg; /** - * Add the cursor svg to this node's svg group. - * @param {SVGElement} cursorSvg The svg root of the cursor to be added to the - * svg group. + * Add the cursor SVG to this node's SVG group. + * @param {SVGElement} cursorSvg The SVG root of the cursor to be added to the + * SVG group. */ Blockly.IASTNodeLocationSvg.prototype.setCursorSvg; diff --git a/core/interfaces/i_autohideable.js b/core/interfaces/i_autohideable.js new file mode 100644 index 000000000..542919286 --- /dev/null +++ b/core/interfaces/i_autohideable.js @@ -0,0 +1,33 @@ +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview The interface for a component that is automatically hidden + * when Blockly.hideChaff is called. + * @author kozbial@google.com (Monica Kozbial) + */ + +'use strict'; + +goog.provide('Blockly.IAutoHideable'); + + +goog.require('Blockly.IComponent'); + + +/** + * Interface for a component that can be automatically hidden. + * @extends {Blockly.IComponent} + * @interface + */ +Blockly.IAutoHideable = function() {}; + +/** + * Hides the component. Called in Blockly.hideChaff. + * @param {boolean} onlyClosePopups Whether only popups should be closed. + * Flyouts should not be closed if this is true. + */ +Blockly.IAutoHideable.prototype.autoHide; diff --git a/core/interfaces/i_bubble.js b/core/interfaces/i_bubble.js index aad591aee..e9e2671cc 100644 --- a/core/interfaces/i_bubble.js +++ b/core/interfaces/i_bubble.js @@ -13,9 +13,10 @@ goog.provide('Blockly.IBubble'); +goog.require('Blockly.IContextMenu'); +goog.require('Blockly.IDeletable'); + goog.requireType('Blockly.BlockDragSurfaceSvg'); -goog.requireType('Blockly.IContextMenu'); -goog.requireType('Blockly.IDeletable'); goog.requireType('Blockly.utils.Coordinate'); diff --git a/core/interfaces/i_component.js b/core/interfaces/i_component.js new file mode 100644 index 000000000..093f5b64c --- /dev/null +++ b/core/interfaces/i_component.js @@ -0,0 +1,24 @@ +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Interface for a workspace component that can be registered with + * the ComponentManager. + * @author kozbial@google.com (Monica Kozbial) + */ + +'use strict'; + +goog.provide('Blockly.IComponent'); + + +/** + * The interface for a workspace component that can be registered with the + * ComponentManager. + * @interface + */ +Blockly.IComponent = function() {}; + diff --git a/core/interfaces/i_delete_area.js b/core/interfaces/i_delete_area.js new file mode 100644 index 000000000..e3bbb3d7c --- /dev/null +++ b/core/interfaces/i_delete_area.js @@ -0,0 +1,44 @@ +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview The interface for a component that can delete a block or bubble + * that is dropped on top of it. + * @author kozbial@google.com (Monica Kozbial) + */ + +'use strict'; + +goog.provide('Blockly.IDeleteArea'); + +goog.require('Blockly.IDragTarget'); + + +/** + * Interface for a component that can delete a block or bubble that is dropped + * on top of it. + * @extends {Blockly.IDragTarget} + * @interface + */ +Blockly.IDeleteArea = function() {}; + +/** + * Returns whether the provided block would be deleted if dropped on this area. + * @param {!Blockly.BlockSvg} block The block. + * @param {boolean} couldConnect Whether the block could could connect to + * another. + * @return {boolean} Whether the block provided would be deleted if dropped on + * this area. + */ +Blockly.IDeleteArea.prototype.wouldDeleteBlock; + +/** + * Returns whether the provided bubble would be deleted if dropped on this area. + * @param {!Blockly.IBubble} bubble The bubble. + * @return {boolean} Whether the bubble provided would be deleted if dropped on + * this area. + */ +Blockly.IDeleteArea.prototype.wouldDeleteBubble; diff --git a/core/interfaces/i_deletearea.js b/core/interfaces/i_deletearea.js deleted file mode 100644 index f406a0152..000000000 --- a/core/interfaces/i_deletearea.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview The interface for a component that can delete a block that is - * dropped on top of it. - * @author aschmiedt@google.com (Abby Schmiedt) - */ - -'use strict'; - -goog.provide('Blockly.IDeleteArea'); - -goog.requireType('Blockly.utils.Rect'); - - -/** - * Interface for a component that can delete a block that is dropped on top of it. - * @interface - */ -Blockly.IDeleteArea = function() {}; - -/** - * Return the deletion rectangle. - * @return {Blockly.utils.Rect} Rectangle in which to delete. - */ -Blockly.IDeleteArea.prototype.getClientRect; diff --git a/core/interfaces/i_drag_target.js b/core/interfaces/i_drag_target.js new file mode 100644 index 000000000..fa7c2c286 --- /dev/null +++ b/core/interfaces/i_drag_target.js @@ -0,0 +1,60 @@ +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview The interface for a component that has a handler for when a + * block is dropped on top of it. + * @author kozbial@google.com (Monica Kozbial) + */ + +'use strict'; + +goog.provide('Blockly.IDragTarget'); + +goog.require('Blockly.IComponent'); + +goog.requireType('Blockly.BlockSvg'); +goog.requireType('Blockly.IBubble'); +goog.requireType('Blockly.utils.Rect'); + +/** + * Interface for a component with custom behaviour when a block or bubble is + * dragged over or dropped on top of it. + * @extends {Blockly.IComponent} + * @interface + */ +Blockly.IDragTarget = function() {}; + +/** + * Returns the bounding rectangle of the drag target area in pixel units + * relative to viewport. + * @return {Blockly.utils.Rect} The component's bounding box. + */ +Blockly.IDragTarget.prototype.getClientRect; + +/** + * Handles when a cursor with a block or bubble enters this drag target. + */ +Blockly.IDragTarget.prototype.onDragEnter; + +/** + * Handles when a cursor with a block or bubble exits this drag target. + */ +Blockly.IDragTarget.prototype.onDragExit; + +/** + * Handles when a block is dropped on this component. Should not handle delete + * here. + * @param {!Blockly.BlockSvg} block The block. + */ +Blockly.IDragTarget.prototype.onBlockDrop; + +/** + * Handles when a bubble is dropped on this component. Should not handle delete + * here. + * @param {!Blockly.IBubble} bubble The bubble. + */ +Blockly.IDragTarget.prototype.onBubbleDrop; diff --git a/core/interfaces/i_metrics_manager.js b/core/interfaces/i_metrics_manager.js index 967ad60b1..916f14d5d 100644 --- a/core/interfaces/i_metrics_manager.js +++ b/core/interfaces/i_metrics_manager.js @@ -69,17 +69,17 @@ Blockly.IMetricsManager.prototype.getFlyoutMetrics; Blockly.IMetricsManager.prototype.getToolboxMetrics; /** - * Gets the width and height of the workspace's parent svg element in pixel + * Gets the width and height of the workspace's parent SVG element in pixel * coordinates. This area includes the toolbox and the visible workspace area. * @return {!Blockly.utils.Size} The width and height of the workspace's parent - * svg element. + * SVG element. * @public */ Blockly.IMetricsManager.prototype.getSvgMetrics; /** * Gets the absolute left and absolute top in pixel coordinates. - * This is where the visible workspace starts in relation to the svg container. + * This is where the visible workspace starts in relation to the SVG container. * @return {!Blockly.MetricsManager.AbsoluteMetrics} The absolute metrics for * the workspace. * @public diff --git a/core/interfaces/i_plugin.js b/core/interfaces/i_plugin.js deleted file mode 100644 index 4fc9b8c51..000000000 --- a/core/interfaces/i_plugin.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Interface for a plugin. - * @author kozbial@google.com (Monica Kozbial) - */ - -'use strict'; - -goog.provide('Blockly.IPlugin'); - - -/** - * The interface for a workspace plugin. - * @interface - */ -Blockly.IPlugin = function() {}; - diff --git a/core/interfaces/i_positionable.js b/core/interfaces/i_positionable.js index 5e08e0beb..64679bcc9 100644 --- a/core/interfaces/i_positionable.js +++ b/core/interfaces/i_positionable.js @@ -5,7 +5,7 @@ */ /** - * @fileoverview The interface for a positionable ui element. + * @fileoverview The interface for a positionable UI element. * @author kozbial@google.com (Monica Kozbial) */ @@ -13,12 +13,12 @@ goog.provide('Blockly.IPositionable'); -goog.require('Blockly.IPlugin'); +goog.require('Blockly.IComponent'); /** * Interface for a component that is positioned on top of the workspace. - * @extends {Blockly.IPlugin} + * @extends {Blockly.IComponent} * @interface */ Blockly.IPositionable = function() {}; @@ -34,6 +34,6 @@ Blockly.IPositionable.prototype.position; /** * Returns the bounding rectangle of the UI element in pixel units relative to * the Blockly injection div. - * @return {!Blockly.utils.Rect} The plugin’s bounding box. + * @return {!Blockly.utils.Rect} The UI elements’s bounding box. */ Blockly.IPositionable.prototype.getBoundingRectangle; diff --git a/core/interfaces/i_toolbox_item.js b/core/interfaces/i_toolbox_item.js index b6e302d50..afd6191f7 100644 --- a/core/interfaces/i_toolbox_item.js +++ b/core/interfaces/i_toolbox_item.js @@ -26,7 +26,7 @@ Blockly.IToolboxItem = function() {}; /** * Initializes the toolbox item. - * This includes creating the dom and updating the state of any items based + * This includes creating the DOM and updating the state of any items based * on the info object. * @return {void} * @public @@ -42,7 +42,7 @@ Blockly.IToolboxItem.prototype.getDiv; /** * Gets a unique identifier for this toolbox item. - * @return {string} The id for the toolbox item. + * @return {string} The ID for the toolbox item. * @public */ Blockly.IToolboxItem.prototype.getId; @@ -114,10 +114,10 @@ Blockly.ISelectableToolboxItem.prototype.getContents; Blockly.ISelectableToolboxItem.prototype.setSelected; /** - * Gets the html element that is clickable. - * The parent toolbox element receives clicks. The parent toolbox will add an id to this element so - * it can pass the onClick event to the correct toolboxItem. - * @return {!Element} The html element that receives clicks. + * Gets the HTML element that is clickable. + * The parent toolbox element receives clicks. The parent toolbox will add an ID + * to this element so it can pass the onClick event to the correct toolboxItem. + * @return {!Element} The HTML element that receives clicks. * @public */ Blockly.ISelectableToolboxItem.prototype.getClickTarget; diff --git a/core/interfaces/i_workspace_plugin.js b/core/interfaces/i_workspace_plugin.js deleted file mode 100644 index dea62c122..000000000 --- a/core/interfaces/i_workspace_plugin.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Interface for plugins that can be registered on the workspace. - * @author kozbial@google.com (Monica Kozbial) - */ - -'use strict'; - -goog.provide('Blockly.IWorkspacePlugin'); - -/** - * Base interface for a plugin that can be registered on the workspace. - * @interface - */ -Blockly.IWorkspacePlugin = function() {}; diff --git a/core/marker_manager.js b/core/marker_manager.js index 05988a757..82c149052 100644 --- a/core/marker_manager.js +++ b/core/marker_manager.js @@ -27,14 +27,14 @@ goog.requireType('Blockly.WorkspaceSvg'); Blockly.MarkerManager = function(workspace){ /** * The cursor. - * @type {Blockly.Cursor} + * @type {?Blockly.Cursor} * @private */ this.cursor_ = null; /** - * The cursor's svg element. - * @type {SVGElement} + * The cursor's SVG element. + * @type {?SVGElement} * @private */ this.cursorSvg_ = null; @@ -44,7 +44,7 @@ Blockly.MarkerManager = function(workspace){ * @type {!Object} * @private */ - this.markers_ = {}; + this.markers_ = Object.create(null); /** * The workspace this marker manager is associated with. @@ -78,7 +78,7 @@ Blockly.MarkerManager.prototype.registerMarker = function(id, marker) { /** * Unregister the marker by removing it from the map of markers. - * @param {string} id The id of the marker to unregister. + * @param {string} id The ID of the marker to unregister. */ Blockly.MarkerManager.prototype.unregisterMarker = function(id) { var marker = this.markers_[id]; @@ -86,27 +86,27 @@ Blockly.MarkerManager.prototype.unregisterMarker = function(id) { marker.dispose(); delete this.markers_[id]; } else { - throw Error('Marker with id ' + id + ' does not exist. Can only unregister' + - 'markers that exist.'); + throw Error('Marker with ID ' + id + ' does not exist. ' + + 'Can only unregister markers that exist.'); } }; /** * Get the cursor for the workspace. - * @return {Blockly.Cursor} The cursor for this workspace. + * @return {?Blockly.Cursor} The cursor for this workspace. */ Blockly.MarkerManager.prototype.getCursor = function() { return this.cursor_; }; /** - * Get a single marker that corresponds to the given id. + * Get a single marker that corresponds to the given ID. * @param {string} id A unique identifier for the marker. - * @return {Blockly.Marker} The marker that corresponds to the given id, or null - * if none exists. + * @return {?Blockly.Marker} The marker that corresponds to the given ID, + * or null if none exists. */ Blockly.MarkerManager.prototype.getMarker = function(id) { - return this.markers_[id]; + return this.markers_[id] || null; }; /** @@ -127,9 +127,9 @@ Blockly.MarkerManager.prototype.setCursor = function(cursor) { }; /** - * Add the cursor svg to this workspace svg group. - * @param {SVGElement} cursorSvg The svg root of the cursor to be added to the - * workspace svg group. + * Add the cursor SVG to this workspace SVG group. + * @param {?SVGElement} cursorSvg The SVG root of the cursor to be added to the + * workspace SVG group. * @package */ Blockly.MarkerManager.prototype.setCursorSvg = function(cursorSvg) { @@ -143,9 +143,9 @@ Blockly.MarkerManager.prototype.setCursorSvg = function(cursorSvg) { }; /** - * Add the marker svg to this workspaces svg group. - * @param {SVGElement} markerSvg The svg root of the marker to be added to the - * workspace svg group. + * Add the marker SVG to this workspaces SVG group. + * @param {?SVGElement} markerSvg The SVG root of the marker to be added to the + * workspace SVG group. * @package */ Blockly.MarkerManager.prototype.setMarkerSvg = function(markerSvg) { @@ -164,7 +164,7 @@ Blockly.MarkerManager.prototype.setMarkerSvg = function(markerSvg) { }; /** - * Redraw the attached cursor svg if needed. + * Redraw the attached cursor SVG if needed. * @package */ Blockly.MarkerManager.prototype.updateMarkers = function() { diff --git a/core/menu.js b/core/menu.js index f4b52bd98..97f47248a 100644 --- a/core/menu.js +++ b/core/menu.js @@ -32,7 +32,7 @@ Blockly.Menu = function() { * Array of menu items. * (Nulls are never in the array, but typing the array as nullable prevents * the compiler from objecting to .indexOf(null)) - * @type {!Array.} + * @type {!Array} * @private */ this.menuItems_ = []; @@ -49,7 +49,7 @@ Blockly.Menu = function() { /** * This is the element that we will listen to the real focus events on. * A value of null means no menu item is highlighted. - * @type {Blockly.MenuItem} + * @type {?Blockly.MenuItem} * @private */ this.highlightedItem_ = null; @@ -91,7 +91,7 @@ Blockly.Menu = function() { /** * The menu's root DOM element. - * @type {Element} + * @type {?Element} * @private */ this.element_ = null; @@ -149,7 +149,7 @@ Blockly.Menu.prototype.render = function(container) { /** * Gets the menu's element. - * @return {Element} The DOM element. + * @return {?Element} The DOM element. * @package */ Blockly.Menu.prototype.getElement = function() { @@ -255,7 +255,7 @@ Blockly.Menu.prototype.getMenuItem_ = function(elem) { /** * Highlights the given menu item, or clears highlighting if null. - * @param {Blockly.MenuItem} item Item to highlight, or null. + * @param {?Blockly.MenuItem} item Item to highlight, or null. * @package */ Blockly.Menu.prototype.setHighlighted = function(item) { @@ -382,7 +382,7 @@ Blockly.Menu.prototype.handleClick_ = function(e) { /** * Handles mouse enter events. Focus the element. - * @param {Event} _e Mouse event to handle. + * @param {!Event} _e Mouse event to handle. * @private */ Blockly.Menu.prototype.handleMouseEnter_ = function(_e) { @@ -391,7 +391,7 @@ Blockly.Menu.prototype.handleMouseEnter_ = function(_e) { /** * Handles mouse leave events. Blur and clear highlight. - * @param {Event} _e Mouse event to handle. + * @param {!Event} _e Mouse event to handle. * @private */ Blockly.Menu.prototype.handleMouseLeave_ = function(_e) { diff --git a/core/menuitem.js b/core/menuitem.js index 8ff6cfc85..91e156742 100644 --- a/core/menuitem.js +++ b/core/menuitem.js @@ -91,7 +91,7 @@ Blockly.MenuItem = function(content, opt_value) { /** * Bound function to call when this menu item is clicked. - * @type {Function} + * @type {?Function} * @private */ this.actionHandler_ = null; @@ -153,7 +153,7 @@ Blockly.MenuItem.prototype.dispose = function() { /** * Gets the menu item's element. - * @return {Element} The DOM element. + * @return {?Element} The DOM element. * @package */ Blockly.MenuItem.prototype.getElement = function() { diff --git a/core/metrics_manager.js b/core/metrics_manager.js index 5c420ae37..841114d14 100644 --- a/core/metrics_manager.js +++ b/core/metrics_manager.js @@ -52,7 +52,7 @@ Blockly.MetricsManager = function(workspace) { Blockly.MetricsManager.ToolboxMetrics; /** - * Describes where the viewport starts in relation to the workspace svg. + * Describes where the viewport starts in relation to the workspace SVG. * @typedef {{ * left: number, * top: number @@ -84,7 +84,7 @@ Blockly.MetricsManager.ContainerRegion; Blockly.MetricsManager.FixedEdges; /** - * Common metrics used for ui elements. + * Common metrics used for UI elements. * @typedef {{ * viewMetrics: !Blockly.MetricsManager.ContainerRegion, * absoluteMetrics: !Blockly.MetricsManager.AbsoluteMetrics, @@ -151,10 +151,10 @@ Blockly.MetricsManager.prototype.getToolboxMetrics = function() { }; /** - * Gets the width and height of the workspace's parent svg element in pixel + * Gets the width and height of the workspace's parent SVG element in pixel * coordinates. This area includes the toolbox and the visible workspace area. * @return {!Blockly.utils.Size} The width and height of the workspace's parent - * svg element. + * SVG element. * @public */ Blockly.MetricsManager.prototype.getSvgMetrics = function() { @@ -163,7 +163,7 @@ Blockly.MetricsManager.prototype.getSvgMetrics = function() { /** * Gets the absolute left and absolute top in pixel coordinates. - * This is where the visible workspace starts in relation to the svg container. + * This is where the visible workspace starts in relation to the SVG container. * @return {!Blockly.MetricsManager.AbsoluteMetrics} The absolute metrics for * the workspace. * @public @@ -356,7 +356,7 @@ Blockly.MetricsManager.prototype.getPaddedContent_ = function( * content metrics if they have been previously computed. Passing in null * may cause the content metrics to be computed again, if it is needed. * @return {!Blockly.MetricsManager.ContainerRegion} The metrics for the scroll - * container + * container. */ Blockly.MetricsManager.prototype.getScrollMetrics = function( opt_getWorkspaceCoordinates, opt_viewMetrics, opt_contentMetrics) { @@ -365,7 +365,7 @@ Blockly.MetricsManager.prototype.getScrollMetrics = function( var contentMetrics = opt_contentMetrics || this.getContentMetrics(); var fixedEdges = this.getComputedFixedEdges_(viewMetrics); - // Add padding around content + // Add padding around content. var paddedContent = this.getPaddedContent_(viewMetrics, contentMetrics); // Use combination of fixed bounds and padded content to make scroll area. @@ -387,8 +387,8 @@ Blockly.MetricsManager.prototype.getScrollMetrics = function( }; /** - * Returns common metrics used by ui elements. - * @return {!Blockly.MetricsManager.UiMetrics} The ui metrics. + * Returns common metrics used by UI elements. + * @return {!Blockly.MetricsManager.UiMetrics} The UI metrics. */ Blockly.MetricsManager.prototype.getUiMetrics = function() { return { @@ -502,7 +502,7 @@ Blockly.utils.object.inherits( /** * Gets the bounding box of the blocks on the flyout's workspace. * This is in workspace coordinates. - * @returns {!SVGRect|{height: number, y: number, width: number, x: number}} The + * @return {!SVGRect|{height: number, y: number, width: number, x: number}} The * bounding box of the blocks on the workspace. * @private */ diff --git a/core/mutator.js b/core/mutator.js index 2a10991cd..1bd6d0988 100644 --- a/core/mutator.js +++ b/core/mutator.js @@ -20,6 +20,7 @@ goog.require('Blockly.Events.BlockChange'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.BubbleOpen'); goog.require('Blockly.Icon'); +goog.require('Blockly.Options'); goog.require('Blockly.utils'); goog.require('Blockly.utils.dom'); goog.require('Blockly.utils.object'); @@ -39,7 +40,7 @@ goog.requireType('Blockly.Workspace'); /** * Class for a mutator dialog. - * @param {!Array.} quarkNames List of names of sub-blocks for flyout. + * @param {!Array} quarkNames List of names of sub-blocks for flyout. * @extends {Blockly.Icon} * @constructor */ @@ -49,6 +50,13 @@ Blockly.Mutator = function(quarkNames) { }; Blockly.utils.object.inherits(Blockly.Mutator, Blockly.Icon); +/** + * Workspace in the mutator's bubble. + * @type {?Blockly.WorkspaceSvg} + * @private + */ +Blockly.Mutator.prototype.workspace_ = null; + /** * Width of workspace. * @private @@ -63,7 +71,7 @@ Blockly.Mutator.prototype.workspaceHeight_ = 0; /** * Set the block this mutator is associated with. - * @param {Blockly.BlockSvg} block The block associated with this mutator. + * @param {!Blockly.BlockSvg} block The block associated with this mutator. * @package */ Blockly.Mutator.prototype.setBlock = function(block) { @@ -72,8 +80,8 @@ Blockly.Mutator.prototype.setBlock = function(block) { /** * Returns the workspace inside this mutator icon's bubble. - * @return {Blockly.WorkspaceSvg} The workspace inside this mutator icon's - * bubble. + * @return {?Blockly.WorkspaceSvg} The workspace inside this mutator icon's + * bubble or null if the mutator isn't open. * @package */ Blockly.Mutator.prototype.getWorkspace = function() { @@ -188,9 +196,9 @@ Blockly.Mutator.prototype.createEditor_ = function() { this.workspace_.addChangeListener(Blockly.Events.disableOrphans); // Mutator flyouts go inside the mutator workspace's rather than in - // a top level svg. Instead of handling scale themselves, mutators + // a top level SVG. Instead of handling scale themselves, mutators // inherit scale from the parent workspace. - // To fix this, scale needs to be applied at a different level in the dom. + // To fix this, scale needs to be applied at a different level in the DOM. var flyoutSvg = hasFlyout ? this.workspace_.addFlyout(Blockly.utils.Svg.G) : null; var background = this.workspace_.createDom('blocklyMutatorBackground'); @@ -279,7 +287,7 @@ Blockly.Mutator.prototype.resizeBubble_ = function() { */ Blockly.Mutator.prototype.onBubbleMove_ = function() { if (this.workspace_) { - this.workspace_.recordDeleteAreas(); + this.workspace_.recordDragTargets(); } }; @@ -465,16 +473,14 @@ Blockly.Mutator.prototype.updateBlockStyle = function() { if (ws && ws.getAllBlocks(false)) { var workspaceBlocks = ws.getAllBlocks(false); - for (var i = 0; i < workspaceBlocks.length; i++) { - var block = workspaceBlocks[i]; + for (var i = 0, block; (block = workspaceBlocks[i]); i++) { block.setStyle(block.getStyleName()); } var flyout = ws.getFlyout(); if (flyout) { var flyoutBlocks = flyout.workspace_.getAllBlocks(false); - for (var i = 0; i < flyoutBlocks.length; i++) { - var block = flyoutBlocks[i]; + for (var i = 0, block; (block = flyoutBlocks[i]); i++) { block.setStyle(block.getStyleName()); } } @@ -510,7 +516,7 @@ Blockly.Mutator.reconnect = function(connectionChild, block, inputName) { * Get the parent workspace of a workspace that is inside a mutator, taking into * account whether it is a flyout. * @param {Blockly.Workspace} workspace The workspace that is inside a mutator. - * @return {Blockly.Workspace} The mutator's parent workspace or null. + * @return {?Blockly.Workspace} The mutator's parent workspace or null. * @public */ Blockly.Mutator.findParentWs = function(workspace) { diff --git a/core/names.js b/core/names.js index 648b849c2..3abd27f9e 100644 --- a/core/names.js +++ b/core/names.js @@ -5,7 +5,7 @@ */ /** - * @fileoverview Utility functions for handling variables and procedure names. + * @fileoverview Utility functions for handling variable and procedure names. * @author fraser@google.com (Neil Fraser) */ 'use strict'; @@ -20,11 +20,11 @@ goog.requireType('Blockly.VariableMap'); /** - * Class for a database of entity names (variables, functions, etc). + * Class for a database of entity names (variables, procedures, etc). * @param {string} reservedWords A comma-separated string of words that are * illegal for use as names in a language (e.g. 'new,if,this,...'). * @param {string=} opt_variablePrefix Some languages need a '$' or a namespace - * before all variable names. + * before all variable names (but not procedure names). * @constructor */ Blockly.Names = function(reservedWords, opt_variablePrefix) { @@ -52,9 +52,9 @@ Blockly.Names.DEVELOPER_VARIABLE_TYPE = 'DEVELOPER_VARIABLE'; * When JavaScript (or most other languages) is generated, variable 'foo' and * procedure 'foo' would collide. However, Blockly has no such problems since * variable get 'foo' and procedure call 'foo' are unambiguous. - * Therefore, Blockly keeps a separate type name to disambiguate. - * getName('foo', 'variable') -> 'foo' - * getName('foo', 'procedure') -> 'foo2' + * Therefore, Blockly keeps a separate realm name to disambiguate. + * getName('foo', 'VARIABLE') -> 'foo' + * getName('foo', 'PROCEDURE') -> 'foo2' */ /** @@ -76,7 +76,7 @@ Blockly.Names.prototype.setVariableMap = function(map) { /** * Get the name for a user-defined variable, based on its ID. - * This should only be used for variables of type + * This should only be used for variables of realm * Blockly.VARIABLE_CATEGORY_NAME. * @param {string} id The ID to look up in the variable map. * @return {?string} The name of the referenced variable, or null if there was @@ -85,60 +85,101 @@ Blockly.Names.prototype.setVariableMap = function(map) { */ Blockly.Names.prototype.getNameForUserVariable_ = function(id) { if (!this.variableMap_) { - console.log('Deprecated call to Blockly.Names.prototype.getName without ' + + console.warn('Deprecated call to Blockly.Names.prototype.getName without ' + 'defining a variable map. To fix, add the following code in your ' + 'generator\'s init() function:\n' + - 'Blockly.YourGeneratorName.variableDB_.setVariableMap(' + + 'Blockly.YourGeneratorName.nameDB_.setVariableMap(' + 'workspace.getVariableMap());'); return null; } var variable = this.variableMap_.getVariableById(id); if (variable) { return variable.name; - } else { - return null; + } + return null; +}; + +/** + * Generate names for user variables, but only ones that are being used. + * @param {!Blockly.Workspace} workspace Workspace to generate variables from. + */ +Blockly.Names.prototype.populateVariables = function(workspace) { + var variables = Blockly.Variables.allUsedVarModels(workspace); + for (var i = 0; i < variables.length; i++) { + this.getName(variables[i].getId(), Blockly.VARIABLE_CATEGORY_NAME); + } +}; + +/** + * Generate names for procedures. + * @param {!Blockly.Workspace} workspace Workspace to generate procedures from. + */ +Blockly.Names.prototype.populateProcedures = function(workspace) { + var procedures = Blockly.Procedures.allProcedures(workspace); + // Flatten the return vs no-return procedure lists. + procedures = procedures[0].concat(procedures[1]); + for (var i = 0; i < procedures.length; i++) { + this.getName(procedures[i][0], Blockly.PROCEDURE_CATEGORY_NAME); } }; /** * Convert a Blockly entity name to a legal exportable entity name. - * @param {string} name The Blockly entity name (no constraints). - * @param {string} type The type of entity in Blockly - * ('VARIABLE', 'PROCEDURE', 'BUILTIN', etc...). + * @param {string} nameOrId The Blockly entity name (no constraints) or + * variable ID. + * @param {string} realm The realm of entity in Blockly + * ('VARIABLE', 'PROCEDURE', 'DEVELOPER_VARIABLE', etc...). * @return {string} An entity name that is legal in the exported language. */ -Blockly.Names.prototype.getName = function(name, type) { - if (type == Blockly.VARIABLE_CATEGORY_NAME) { - var varName = this.getNameForUserVariable_(name); +Blockly.Names.prototype.getName = function(nameOrId, realm) { + var name = nameOrId; + if (realm == Blockly.VARIABLE_CATEGORY_NAME) { + var varName = this.getNameForUserVariable_(nameOrId); if (varName) { + // Successful ID lookup. name = varName; } } - var normalized = name.toLowerCase() + '_' + type; + var normalizedName = name.toLowerCase(); - var isVarType = type == Blockly.VARIABLE_CATEGORY_NAME || - type == Blockly.Names.DEVELOPER_VARIABLE_TYPE; + var isVar = realm == Blockly.VARIABLE_CATEGORY_NAME || + realm == Blockly.Names.DEVELOPER_VARIABLE_TYPE; - var prefix = isVarType ? this.variablePrefix_ : ''; - if (normalized in this.db_) { - return prefix + this.db_[normalized]; + var prefix = isVar ? this.variablePrefix_ : ''; + if (!(realm in this.db_)) { + this.db_[realm] = Object.create(null); } - var safeName = this.getDistinctName(name, type); - this.db_[normalized] = safeName.substr(prefix.length); + var realmDb = this.db_[realm]; + if (normalizedName in realmDb) { + return prefix + realmDb[normalizedName]; + } + var safeName = this.getDistinctName(name, realm); + realmDb[normalizedName] = safeName.substr(prefix.length); return safeName; }; +/** + * Return a list of all known user-created names in a specified realm. + * @param {string} realm The realm of entity in Blockly + * ('VARIABLE', 'PROCEDURE', 'DEVELOPER_VARIABLE', etc...). + * @return {!Array} A list of Blockly entity names (no constraints). + */ +Blockly.Names.prototype.getUserNames = function(realm) { + var realmDb = this.db_[realm] || {}; + return Object.keys(realmDb); +}; + /** * Convert a Blockly entity name to a legal exportable entity name. * Ensure that this is a new name not overlapping any previously defined name. * Also check against list of reserved words for the current language and * ensure name doesn't collide. * @param {string} name The Blockly entity name (no constraints). - * @param {string} type The type of entity in Blockly - * ('VARIABLE', 'PROCEDURE', 'BUILTIN', etc...). + * @param {string} realm The realm of entity in Blockly + * ('VARIABLE', 'PROCEDURE', 'DEVELOPER_VARIABLE', etc...). * @return {string} An entity name that is legal in the exported language. */ -Blockly.Names.prototype.getDistinctName = function(name, type) { +Blockly.Names.prototype.getDistinctName = function(name, realm) { var safeName = this.safeName_(name); var i = ''; while (this.dbReverse_[safeName + i] || @@ -148,16 +189,16 @@ Blockly.Names.prototype.getDistinctName = function(name, type) { } safeName += i; this.dbReverse_[safeName] = true; - var isVarType = type == Blockly.VARIABLE_CATEGORY_NAME || - type == Blockly.Names.DEVELOPER_VARIABLE_TYPE; - var prefix = isVarType ? this.variablePrefix_ : ''; + var isVar = realm == Blockly.VARIABLE_CATEGORY_NAME || + realm == Blockly.Names.DEVELOPER_VARIABLE_TYPE; + var prefix = isVar ? this.variablePrefix_ : ''; return prefix + safeName; }; /** * Given a proposed entity name, generate a name that conforms to the * [_A-Za-z][_A-Za-z0-9]* format that most languages consider legal for - * variables. + * variable and function names. * @param {string} name Potentially illegal entity name. * @return {string} Safe entity name. * @private @@ -186,5 +227,6 @@ Blockly.Names.prototype.safeName_ = function(name) { * @return {boolean} True if names are the same. */ Blockly.Names.equals = function(name1, name2) { + // name1.localeCompare(name2) is slower. return name1.toLowerCase() == name2.toLowerCase(); }; diff --git a/core/options.js b/core/options.js index f8e1ee4cc..58c4e378a 100644 --- a/core/options.js +++ b/core/options.js @@ -123,7 +123,7 @@ Blockly.Options = function(options) { this.readOnly = readOnly; /** @type {number} */ this.maxBlocks = options['maxBlocks'] || Infinity; - /** @type {?Object.} */ + /** @type {?Object} */ this.maxInstances = options['maxInstances']; /** @type {string} */ this.pathToMedia = pathToMedia; @@ -175,7 +175,7 @@ Blockly.Options = function(options) { /** * Map of plugin type to name of registered plugin or plugin class. - * @type {!Object.} + * @type {!Object} */ this.plugins = plugins; }; @@ -275,7 +275,7 @@ Blockly.Options.parseMoveOptions_ = function(options, hasCategories) { } else { moveOptions.scrollbars = !!move['scrollbars'] || !!options['scrollbars']; } - + if (!moveOptions.scrollbars || move['wheel'] === undefined) { // Defaults to true if single-direction scroll is enabled. moveOptions.wheel = typeof moveOptions.scrollbars == 'object'; diff --git a/core/plugin_manager.js b/core/plugin_manager.js deleted file mode 100644 index 5e62092bd..000000000 --- a/core/plugin_manager.js +++ /dev/null @@ -1,137 +0,0 @@ -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Manager for all items registered with the workspace. - * @author kozbial@google.com (Monica Kozbial) - */ - -'use strict'; - -goog.provide('Blockly.PluginManager'); - - -/** - * Manager for all items registered with the workspace. - * @constructor - */ -Blockly.PluginManager = function() { - /** - * A map of the plugins registered with the workspace, mapped to id. - * @type {!Object} - * @private - */ - this.pluginData_ = {}; - - /** - * A map of types to plugin ids. - * @type {!Object>} - * @private - */ - this.typeToPluginIds_ = {}; -}; - -/** - * An object storing plugin information. - * @typedef {{ - * id: string, - * plugin: !Blockly.IPlugin, - * types: !Array>, - * weight: number - * }} - */ -Blockly.PluginManager.PluginDatum; - -/** - * Adds a plugin. - * @param {!Blockly.PluginManager.PluginDatum} pluginDataObject The plugin. - * @template T - */ -Blockly.PluginManager.prototype.addPlugin = function(pluginDataObject) { - this.pluginData_[pluginDataObject.id] = pluginDataObject; - for (var i = 0, type; (type = pluginDataObject.types[i]); i++) { - var typeKey = String(type).toLowerCase(); - if (this.typeToPluginIds_[typeKey] === undefined) { - this.typeToPluginIds_[typeKey] = [pluginDataObject.id]; - } else { - this.typeToPluginIds_[typeKey].push(pluginDataObject.id); - } - } -}; - -/** - * Gets the plugin with the given id and the given type. - * @param {string} id The id of the plugin to get. - * @return {!Blockly.IPlugin|undefined} The plugin with the given name - * or undefined if not found. - */ -Blockly.PluginManager.prototype.getPlugin = function(id) { - return this.pluginData_[id] && this.pluginData_[id].plugin; -}; - -/** - * Gets all the plugins of the specified type. - * @param {!Blockly.PluginManager.Type} type The type of the plugin. - * @param {boolean} sorted Whether to return list ordered by weights. - * @return {!Array} The plugins that match the - * specified type. - * @template T - */ -Blockly.PluginManager.prototype.getPlugins = function(type, sorted) { - var typeKey = String(type).toLowerCase(); - var pluginIds = this.typeToPluginIds_[typeKey]; - if (!pluginIds) { - return []; - } - var plugins = []; - if (sorted) { - var pluginDataList = []; - var pluginData = this.pluginData_; - pluginIds.forEach(function(id) { - pluginDataList.push(pluginData[id]); - }); - pluginDataList.sort(function(a, b) { - return a.weight - b.weight; - }); - pluginDataList.forEach(function(pluginDatum) { - plugins.push(pluginDatum.plugin); - }); - } else { - var pluginData = this.pluginData_; - pluginIds.forEach(function(id) { - plugins.push(pluginData[id].plugin); - }); - } - return plugins; -}; - -/** - * A name with the type of the element stored in the generic. - * @param {string} name The name of the plugin type. - * @constructor - * @template T - */ -Blockly.PluginManager.Type = function(name) { - /** - * @type {string} - * @private - */ - this.name_ = name; -}; - -/** - * Returns the name of the type. - * @return {string} The name. - * @override - */ -Blockly.PluginManager.Type.prototype.toString = function() { - return this.name_; -}; - -/** @type {!Blockly.PluginManager.Type} */ -Blockly.PluginManager.Type.POSITIONABLE = - new Blockly.PluginManager.Type('positionable'); - diff --git a/core/positionable_helpers.js b/core/positionable_helpers.js new file mode 100644 index 000000000..3dc52e50c --- /dev/null +++ b/core/positionable_helpers.js @@ -0,0 +1,180 @@ +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Utility functions for positioning UI elements. + * @author kozbial@google.com (Monica Kozbial) + */ +'use strict'; + +goog.provide('Blockly.uiPosition'); + +goog.require('Blockly.Scrollbar'); +goog.require('Blockly.utils.Rect'); +goog.require('Blockly.utils.toolbox'); + +goog.requireType('Blockly.MetricsManager'); +goog.requireType('Blockly.WorkspaceSvg'); + + +/** + * Enum for vertical positioning. + * @enum {number} + * @package + */ +Blockly.uiPosition.verticalPosition = { + TOP: 0, + BOTTOM: 1 +}; + +/** + * Enum for horizontal positioning. + * @enum {number} + * @package + */ +Blockly.uiPosition.horizontalPosition = { + LEFT: 0, + RIGHT: 1 +}; + +/** + * An object defining a horizontal and vertical positioning. + * @typedef {{ + * horizontal: !Blockly.uiPosition.horizontalPosition, + * vertical: !Blockly.uiPosition.verticalPosition + * }} + * @package + */ +Blockly.uiPosition.Position; + +/** + * Enum for bump rules to use for dealing with collisions. + * @enum {number} + * @package + */ +Blockly.uiPosition.bumpDirection = { + UP: 0, + DOWN: 1 +}; + +/** + * Returns a rectangle representing reasonable position for where to place a UI + * element of the specified size given the restraints and locations of the + * scrollbars. This method does not take into account any already placed UI + * elements. + * @param {!Blockly.uiPosition.Position} position The starting + * horizontal and vertical position. + * @param {!Blockly.utils.Size} size the size of the UI element to get a start + * position for. + * @param {number} horizontalPadding The horizontal padding to use. + * @param {number} verticalPadding The vertical padding to use. + * @param {!Blockly.MetricsManager.UiMetrics} metrics The workspace UI metrics. + * @param {!Blockly.WorkspaceSvg} workspace The workspace. + * @return {!Blockly.utils.Rect} The suggested start position. + * @package + */ +Blockly.uiPosition.getStartPositionRect = function( + position, size, horizontalPadding, + verticalPadding, metrics, workspace) { + // Horizontal positioning. + var left = 0; + var hasVerticalScrollbar = + workspace.scrollbar && workspace.scrollbar.canScrollVertically(); + if (position.horizontal === + Blockly.uiPosition.horizontalPosition.LEFT) { + left = metrics.absoluteMetrics.left + horizontalPadding; + if (hasVerticalScrollbar && workspace.RTL) { + left += Blockly.Scrollbar.scrollbarThickness; + } + } else { // position.horizontal == horizontalPosition.RIGHT + left = metrics.absoluteMetrics.left + metrics.viewMetrics.width - + size.width - horizontalPadding; + if (hasVerticalScrollbar && !workspace.RTL) { + left -= Blockly.Scrollbar.scrollbarThickness; + } + } + // Vertical positioning. + var top = 0; + if (position.vertical === + Blockly.uiPosition.verticalPosition.TOP) { + top = metrics.absoluteMetrics.top + verticalPadding; + } else { // position.vertical == verticalPosition.BOTTOM + top = metrics.absoluteMetrics.top + metrics.viewMetrics.height - + size.height - verticalPadding; + if (workspace.scrollbar && workspace.scrollbar.canScrollHorizontally()) { + // The scrollbars are always positioned on the bottom if they exist. + top -= Blockly.Scrollbar.scrollbarThickness; + } + } + return new Blockly.utils.Rect( + top, top + size.height, left, left + size.width); +}; + +/** + * Returns a corner position that is on the opposite side of the workspace from + * the toolbox. + * If in horizontal orientation, defaults to the bottom corner. If in vertical + * orientation, defaults to the right corner. + * @param {!Blockly.WorkspaceSvg} workspace The workspace. + * @param {!Blockly.MetricsManager.UiMetrics} metrics The workspace metrics. + * @return {!Blockly.uiPosition.Position} The suggested corner position. + * @package + */ +Blockly.uiPosition.getCornerOppositeToolbox = function(workspace, metrics) { + var leftCorner = + metrics.toolboxMetrics.position !== Blockly.utils.toolbox.Position.LEFT && + (!workspace.horizontalLayout || workspace.RTL); + var topCorner = + metrics.toolboxMetrics.position === Blockly.utils.toolbox.Position.BOTTOM; + var horizontalPosition = leftCorner ? + Blockly.uiPosition.horizontalPosition.LEFT : + Blockly.uiPosition.horizontalPosition.RIGHT; + var verticalPosition = topCorner ? + Blockly.uiPosition.verticalPosition.TOP : + Blockly.uiPosition.verticalPosition.BOTTOM; + return { + horizontal: horizontalPosition, + vertical: verticalPosition + }; +}; + +/** + * Returns a position Rect based on a starting position that is bumped + * so that it doesn't intersect with any of the provided savedPositions. This + * method does not check that the bumped position is still within bounds. + * @param {!Blockly.utils.Rect} startRect The starting position to use. + * @param {number} margin The margin to use between elements when bumping. + * @param {!Blockly.uiPosition.bumpDirection} bumpDirection The direction + * to bump if there is a collision with an existing UI element. + * @param {!Array} savedPositions List of rectangles that + * represent the positions of UI elements already placed. + * @return {!Blockly.utils.Rect} The suggested position rectangle. + * @package + */ +Blockly.uiPosition.bumpPositionRect = function( + startRect, margin, bumpDirection, savedPositions) { + var top = startRect.top; + var left = startRect.left; + var width = startRect.right - startRect.left; + var height = startRect.bottom - startRect.top; + + // Check for collision and bump if needed. + var boundingRect = startRect; + for (var i = 0, otherEl; (otherEl = savedPositions[i]); i++) { + if (boundingRect.intersects(otherEl)) { + if (bumpDirection === Blockly.uiPosition.bumpDirection.UP) { + top = otherEl.top - height - margin; + } else { // bumpDirection == bumpDirection.DOWN + top = otherEl.bottom + margin; + } + // Recheck other savedPositions + boundingRect = new Blockly.utils.Rect( + top, top + height, left, left + width); + i = -1; + } + } + return boundingRect; +}; diff --git a/core/procedures.js b/core/procedures.js index c720db195..984ef03fa 100644 --- a/core/procedures.js +++ b/core/procedures.js @@ -60,7 +60,7 @@ Blockly.Procedures.ProcedureBlock; /** * Find all user-created procedure definitions in a workspace. * @param {!Blockly.Workspace} root Root workspace. - * @return {!Array.>} Pair of arrays, the + * @return {!Array>} Pair of arrays, the * first contains procedures without return variables, the second with. * Each procedure is defined by a three-element list of name, parameter * list, and return value boolean. @@ -87,7 +87,7 @@ Blockly.Procedures.allProcedures = function(root) { * @private */ Blockly.Procedures.procTupleComparator_ = function(ta, tb) { - return ta[0].toLowerCase().localeCompare(tb[0].toLowerCase()); + return ta[0].localeCompare(tb[0], undefined, {sensitivity: 'base'}); }; /** @@ -188,7 +188,7 @@ Blockly.Procedures.rename = function(name) { /** * Construct the blocks required by the flyout for the procedure category. * @param {!Blockly.Workspace} workspace The workspace containing procedures. - * @return {!Array.} Array of XML block elements. + * @return {!Array} Array of XML block elements. */ Blockly.Procedures.flyoutCategory = function(workspace) { var xmlList = []; @@ -337,7 +337,7 @@ Blockly.Procedures.mutatorChangeListener_ = function(e) { * Find all the callers of a named procedure. * @param {string} name Name of procedure. * @param {!Blockly.Workspace} workspace The workspace to find callers in. - * @return {!Array.} Array of caller blocks. + * @return {!Array} Array of caller blocks. */ Blockly.Procedures.getCallers = function(name, workspace) { var callers = []; @@ -391,18 +391,20 @@ Blockly.Procedures.mutateCallers = function(defBlock) { * Find the definition block for the named procedure. * @param {string} name Name of procedure. * @param {!Blockly.Workspace} workspace The workspace to search. - * @return {Blockly.Block} The procedure definition block, or null not found. + * @return {?Blockly.Block} The procedure definition block, or null not found. */ Blockly.Procedures.getDefinition = function(name, workspace) { - // Assume that a procedure definition is a top block. - var blocks = workspace.getTopBlocks(false); + // Do not assume procedure is a top block. Some languages allow nested + // procedures. Also do not assume it is one of the built-in blocks. Only + // rely on getProcedureDef. + var blocks = workspace.getAllBlocks(false); for (var i = 0; i < blocks.length; i++) { if (blocks[i].getProcedureDef) { var procedureBlock = /** @type {!Blockly.Procedures.ProcedureBlock} */ ( blocks[i]); var tuple = procedureBlock.getProcedureDef(); if (tuple && Blockly.Names.equals(tuple[0], name)) { - return blocks[i]; + return blocks[i]; // Can't use procedureBlock var due to type check. } } } diff --git a/core/registry.js b/core/registry.js index a2126cc27..2959cf73e 100644 --- a/core/registry.js +++ b/core/registry.js @@ -34,7 +34,7 @@ goog.requireType('Blockly.ToolboxItem'); * * @type {Object>} */ -Blockly.registry.typeMap_ = {}; +Blockly.registry.typeMap_ = Object.create(null); /** * The string used to register the default class for a type of plugin. @@ -142,7 +142,7 @@ Blockly.registry.register = function( var typeRegistry = Blockly.registry.typeMap_[type]; // If the type registry has not been created, create it. if (!typeRegistry) { - typeRegistry = Blockly.registry.typeMap_[type] = {}; + typeRegistry = Blockly.registry.typeMap_[type] = Object.create(null); } // Validate that the given class has all the required properties. @@ -265,7 +265,7 @@ Blockly.registry.getClass = function(type, name, opt_throwIfMissing) { * @param {string} name The plugin's name. (Ex. logic_category) * @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we * are unable to find the object. - * @returns {T} The object with the given name and type or null if none exists. + * @return {?T} The object with the given name and type or null if none exists. * @template T */ Blockly.registry.getObject = function(type, name, opt_throwIfMissing) { diff --git a/core/rendered_connection.js b/core/rendered_connection.js index 246414625..a9b9c8d33 100644 --- a/core/rendered_connection.js +++ b/core/rendered_connection.js @@ -119,7 +119,7 @@ Blockly.RenderedConnection.prototype.getSourceBlock = function() { /** * Returns the block that this connection connects to. - * @return {Blockly.BlockSvg} The connected block or null if none is connected. + * @return {?Blockly.BlockSvg} The connected block or null if none is connected. * @override */ Blockly.RenderedConnection.prototype.targetBlock = function() { @@ -386,7 +386,7 @@ Blockly.RenderedConnection.prototype.stopTrackingAll = function() { /** * Start tracking this connection, as well as all down-stream connections on * any block attached to this connection. This happens when a block is expanded. - * @return {!Array.} List of blocks to render. + * @return {!Array} List of blocks to render. */ Blockly.RenderedConnection.prototype.startTrackingAll = function() { this.setTracking(true); @@ -509,7 +509,7 @@ Blockly.RenderedConnection.prototype.respawnShadow_ = function() { * Type checking does not apply, since this function is used for bumping. * @param {number} maxLimit The maximum radius to another connection, in * workspace units. - * @return {!Array.} List of connections. + * @return {!Array} List of connections. * @package */ Blockly.RenderedConnection.prototype.neighbours = function(maxLimit) { diff --git a/core/renderers/common/constants.js b/core/renderers/common/constants.js index 6ff75a777..a21ef85aa 100644 --- a/core/renderers/common/constants.js +++ b/core/renderers/common/constants.js @@ -261,14 +261,14 @@ Blockly.blockRendering.ConstantProvider = function() { * to be the height of the text based on the font used. * @type {number} */ - this.FIELD_TEXT_HEIGHT = -1; // Dynamically set + this.FIELD_TEXT_HEIGHT = -1; // Dynamically set. /** * Text baseline. This constant is dynamically set in ``setFontConstants_`` * to be the baseline of the text based on the font used. * @type {number} */ - this.FIELD_TEXT_BASELINE = -1; // Dynamically set + this.FIELD_TEXT_BASELINE = -1; // Dynamically set. /** * A field's border rect corner radius. @@ -587,10 +587,10 @@ Blockly.blockRendering.ConstantProvider.prototype.setTheme = function( /** * The block styles map. - * @type {Object.} + * @type {Object} * @package */ - this.blockStyles = {}; + this.blockStyles = Object.create(null); var blockStyles = theme.blockStyles; for (var key in blockStyles) { @@ -855,7 +855,7 @@ Blockly.blockRendering.ConstantProvider.prototype.makePuzzleTab = function() { var halfHeight = height / 2; var control1Y = halfHeight + overlap; var control2Y = halfHeight + 0.5; - var control3Y = overlap; // 2.5 + var control3Y = overlap; // 2.5 var endPoint1 = Blockly.utils.svgPaths.point(-width, forward * halfHeight); var endPoint2 = Blockly.utils.svgPaths.point(width, forward * halfHeight); @@ -1181,7 +1181,7 @@ Blockly.blockRendering.ConstantProvider.prototype.injectCSS_ = function( /** * Get any renderer specific CSS to inject when the renderer is initialized. * @param {string} selector CSS selector to use. - * @return {!Array.} Array of CSS strings. + * @return {!Array} Array of CSS strings. * @protected */ Blockly.blockRendering.ConstantProvider.prototype.getCSS_ = function(selector) { diff --git a/core/renderers/common/debugger.js b/core/renderers/common/debugger.js index 36b02bbdf..0e99fc613 100644 --- a/core/renderers/common/debugger.js +++ b/core/renderers/common/debugger.js @@ -38,7 +38,7 @@ goog.requireType('Blockly.RenderedConnection'); Blockly.blockRendering.Debug = function(constants) { /** * An array of SVG elements that have been created by this object. - * @type {Array.} + * @type {Array} * @private */ this.debugElements_ = []; @@ -62,7 +62,7 @@ Blockly.blockRendering.Debug = function(constants) { /** * Configuration object containing booleans to enable and disable debug * rendering of specific rendering components. - * @type {!Object.} + * @type {!Object} */ Blockly.blockRendering.Debug.config = { rowSpacers: true, @@ -420,7 +420,7 @@ Blockly.blockRendering.Debug.prototype.drawDebug = function(block, info) { /** * Show a debug filter to highlight that a block has been rendered. - * @param {!SVGElement} svgPath The block's svg path. + * @param {!SVGElement} svgPath The block's SVG path. * @package */ Blockly.blockRendering.Debug.prototype.drawRender = function(svgPath) { diff --git a/core/renderers/common/drawer.js b/core/renderers/common/drawer.js index d82e48a93..f91b97d7a 100644 --- a/core/renderers/common/drawer.js +++ b/core/renderers/common/drawer.js @@ -227,7 +227,7 @@ Blockly.blockRendering.Drawer.prototype.drawRightSideRow_ = function(row) { /** * Add steps for the bottom edge of a block, possibly including a notch - * for the next connection + * for the next connection. * @protected */ Blockly.blockRendering.Drawer.prototype.drawBottom_ = function() { @@ -449,7 +449,7 @@ Blockly.blockRendering.Drawer.prototype.positionNextConnection_ = function() { if (bottomRow.connection) { var connInfo = bottomRow.connection; - var x = connInfo.xPos; // Already contains info about startX + var x = connInfo.xPos; // Already contains info about startX. var connX = (this.info_.RTL ? -x : x); connInfo.connectionModel.setOffsetInBlock(connX, bottomRow.baseline); } diff --git a/core/renderers/common/i_path_object.js b/core/renderers/common/i_path_object.js index 708175168..6a7dfc2b7 100644 --- a/core/renderers/common/i_path_object.js +++ b/core/renderers/common/i_path_object.js @@ -47,14 +47,14 @@ Blockly.blockRendering.IPathObject.prototype.constants; Blockly.blockRendering.IPathObject.prototype.style; /** - * Holds the cursors svg element when the cursor is attached to the block. + * Holds the cursors SVG element when the cursor is attached to the block. * This is null if there is no cursor on the block. * @type {SVGElement} */ Blockly.blockRendering.IPathObject.prototype.cursorSvg; /** - * Holds the markers svg element when the marker is attached to the block. + * Holds the markers SVG element when the marker is attached to the block. * This is null if there is no marker on the block. * @type {SVGElement} */ @@ -89,17 +89,17 @@ Blockly.blockRendering.IPathObject.prototype.setStyle; Blockly.blockRendering.IPathObject.prototype.flipRTL; /** - * Add the cursor svg to this block's svg group. - * @param {SVGElement} cursorSvg The svg root of the cursor to be added to the - * block svg group. + * Add the cursor SVG to this block's SVG group. + * @param {SVGElement} cursorSvg The SVG root of the cursor to be added to the + * block SVG group. * @package */ Blockly.blockRendering.IPathObject.prototype.setCursorSvg; /** - * Add the marker svg to this block's svg group. - * @param {SVGElement} markerSvg The svg root of the marker to be added to the - * block svg group. + * Add the marker SVG to this block's SVG group. + * @param {SVGElement} markerSvg The SVG root of the marker to be added to the + * block SVG group. * @package */ Blockly.blockRendering.IPathObject.prototype.setMarkerSvg; diff --git a/core/renderers/common/info.js b/core/renderers/common/info.js index 919814b46..f3eac053a 100644 --- a/core/renderers/common/info.js +++ b/core/renderers/common/info.js @@ -14,10 +14,12 @@ goog.provide('Blockly.blockRendering.RenderInfo'); goog.require('Blockly.blockRendering.BottomRow'); goog.require('Blockly.blockRendering.ExternalValueInput'); +goog.require('Blockly.blockRendering.Field'); goog.require('Blockly.blockRendering.Hat'); goog.require('Blockly.blockRendering.InlineInput'); goog.require('Blockly.blockRendering.InputRow'); goog.require('Blockly.blockRendering.InRowSpacer'); +goog.require('Blockly.blockRendering.JaggedEdge'); goog.require('Blockly.blockRendering.Measurable'); goog.require('Blockly.blockRendering.NextConnection'); goog.require('Blockly.blockRendering.OutputConnection'); @@ -133,19 +135,19 @@ Blockly.blockRendering.RenderInfo = function(renderer, block) { /** * An array of Row objects containing sizing information. - * @type {!Array.} + * @type {!Array} */ this.rows = []; /** * An array of input rows on the block. - * @type {!Array.} + * @type {!Array} */ this.inputRows = []; /** * An array of measurable objects containing hidden icons. - * @type {!Array.} + * @type {!Array} */ this.hiddenIcons = []; @@ -208,14 +210,12 @@ Blockly.blockRendering.RenderInfo.prototype.createRows_ = function() { // Icons always go on the first row, before anything else. var icons = this.block_.getIcons(); - if (icons.length) { - for (var i = 0, icon; (icon = icons[i]); i++) { - var iconInfo = new Blockly.blockRendering.Icon(this.constants_, icon); - if (this.isCollapsed && icon.collapseHidden) { - this.hiddenIcons.push(iconInfo); - } else { - activeRow.elements.push(iconInfo); - } + for (var i = 0, icon; (icon = icons[i]); i++) { + var iconInfo = new Blockly.blockRendering.Icon(this.constants_, icon); + if (this.isCollapsed && icon.collapseHidden) { + this.hiddenIcons.push(iconInfo); + } else { + activeRow.elements.push(iconInfo); } } @@ -262,17 +262,12 @@ Blockly.blockRendering.RenderInfo.prototype.createRows_ = function() { Blockly.blockRendering.RenderInfo.prototype.populateTopRow_ = function() { var hasPrevious = !!this.block_.previousConnection; var hasHat = (this.block_.hat ? - this.block_.hat === 'cap' : this.constants_.ADD_START_HATS) && - !this.outputConnection && !hasPrevious; - var leftSquareCorner = this.topRow.hasLeftSquareCorner(this.block_); + this.block_.hat === 'cap' : this.constants_.ADD_START_HATS) && + !this.outputConnection && !hasPrevious; - if (leftSquareCorner) { - this.topRow.elements.push( - new Blockly.blockRendering.SquareCorner(this.constants_)); - } else { - this.topRow.elements.push( - new Blockly.blockRendering.RoundCorner(this.constants_)); - } + var cornerClass = this.topRow.hasLeftSquareCorner(this.block_) ? + Blockly.blockRendering.SquareCorner : Blockly.blockRendering.RoundCorner; + this.topRow.elements.push(new cornerClass(this.constants_)); if (hasHat) { var hat = new Blockly.blockRendering.Hat(this.constants_); @@ -299,15 +294,9 @@ Blockly.blockRendering.RenderInfo.prototype.populateTopRow_ = function() { this.topRow.minHeight = this.constants_.TOP_ROW_MIN_HEIGHT; } - var rightSquareCorner = this.topRow.hasRightSquareCorner(this.block_); - - if (rightSquareCorner) { - this.topRow.elements.push( - new Blockly.blockRendering.SquareCorner(this.constants_, 'right')); - } else { - this.topRow.elements.push( - new Blockly.blockRendering.RoundCorner(this.constants_, 'right')); - } + cornerClass = this.topRow.hasRightSquareCorner(this.block_) ? + Blockly.blockRendering.SquareCorner : Blockly.blockRendering.RoundCorner; + this.topRow.elements.push(new cornerClass(this.constants_, 'right')); }; /** diff --git a/core/renderers/common/path_object.js b/core/renderers/common/path_object.js index f2c3f319e..e81b8e0e2 100644 --- a/core/renderers/common/path_object.js +++ b/core/renderers/common/path_object.js @@ -97,9 +97,9 @@ Blockly.blockRendering.PathObject.prototype.flipRTL = function() { }; /** - * Add the cursor svg to this block's svg group. - * @param {SVGElement} cursorSvg The svg root of the cursor to be added to the - * block svg group. + * Add the cursor SVG to this block's SVG group. + * @param {SVGElement} cursorSvg The SVG root of the cursor to be added to the + * block SVG group. * @package */ Blockly.blockRendering.PathObject.prototype.setCursorSvg = function(cursorSvg) { @@ -113,9 +113,9 @@ Blockly.blockRendering.PathObject.prototype.setCursorSvg = function(cursorSvg) { }; /** - * Add the marker svg to this block's svg group. - * @param {SVGElement} markerSvg The svg root of the marker to be added to the - * block svg group. + * Add the marker SVG to this block's SVG group. + * @param {SVGElement} markerSvg The SVG root of the marker to be added to the + * block SVG group. * @package */ Blockly.blockRendering.PathObject.prototype.setMarkerSvg = function(markerSvg) { diff --git a/core/renderers/common/renderer.js b/core/renderers/common/renderer.js index af575403f..4d7c6ca17 100644 --- a/core/renderers/common/renderer.js +++ b/core/renderers/common/renderer.js @@ -248,19 +248,13 @@ Blockly.blockRendering.Renderer.prototype.orphanCanConnectAtEnd = function(topBlock, orphanBlock, localType) { var orphanConnection = null; var lastConnection = null; - if (localType == - Blockly.connectionTypes - .OUTPUT_VALUE) { // We are replacing an output. + if (localType == Blockly.connectionTypes.OUTPUT_VALUE) { orphanConnection = orphanBlock.outputConnection; - // TODO: I don't think this function necessarily has the correct logic, - // but for now it is being kept for behavioral backwards-compat. - lastConnection = Blockly.Connection - .lastConnectionInRow( + lastConnection = + Blockly.Connection.getConnectionForOrphanedOutput( /** @type {!Blockly.Block} **/ (topBlock), orphanBlock); - } else { // We are replacing a previous. + } else { orphanConnection = orphanBlock.previousConnection; - // TODO: This lives on the block while lastConnectionInRow lives on - // on the connection. Something is fishy. lastConnection = topBlock.lastConnectionInStack(); } diff --git a/core/renderers/geras/drawer.js b/core/renderers/geras/drawer.js index 25870f9cb..360d123ce 100644 --- a/core/renderers/geras/drawer.js +++ b/core/renderers/geras/drawer.js @@ -197,7 +197,7 @@ Blockly.geras.Drawer.prototype.positionNextConnection_ = function() { if (bottomRow.connection) { var connInfo = bottomRow.connection; - var x = connInfo.xPos; // Already contains info about startX + var x = connInfo.xPos; // Already contains info about startX. var connX = (this.info_.RTL ? -x : x) + (this.constants_.DARK_PATH_OFFSET / 2); connInfo.connectionModel.setOffsetInBlock( diff --git a/core/renderers/measurables/rows.js b/core/renderers/measurables/rows.js index 0c458b605..b300e96ed 100644 --- a/core/renderers/measurables/rows.js +++ b/core/renderers/measurables/rows.js @@ -47,7 +47,7 @@ Blockly.blockRendering.Row = function(constants) { /** * An array of elements contained in this row. * @package - * @type {!Array.} + * @type {!Array} */ this.elements = []; diff --git a/core/renderers/zelos/constants.js b/core/renderers/zelos/constants.js index 5c629d99e..bb039250a 100644 --- a/core/renderers/zelos/constants.js +++ b/core/renderers/zelos/constants.js @@ -214,23 +214,23 @@ Blockly.zelos.ConstantProvider = function() { * @package */ this.SHAPE_IN_SHAPE_PADDING = { - 1: { // Outer shape: hexagon. - 0: 5 * this.GRID_UNIT, // Field in hexagon. - 1: 2 * this.GRID_UNIT, // Hexagon in hexagon. - 2: 5 * this.GRID_UNIT, // Round in hexagon. - 3: 5 * this.GRID_UNIT // Square in hexagon. + 1: { // Outer shape: hexagon. + 0: 5 * this.GRID_UNIT, // Field in hexagon. + 1: 2 * this.GRID_UNIT, // Hexagon in hexagon. + 2: 5 * this.GRID_UNIT, // Round in hexagon. + 3: 5 * this.GRID_UNIT // Square in hexagon. }, - 2: { // Outer shape: round. - 0: 3 * this.GRID_UNIT, // Field in round. - 1: 3 * this.GRID_UNIT, // Hexagon in round. - 2: 1 * this.GRID_UNIT, // Round in round. - 3: 2 * this.GRID_UNIT // Square in round. + 2: { // Outer shape: round. + 0: 3 * this.GRID_UNIT, // Field in round. + 1: 3 * this.GRID_UNIT, // Hexagon in round. + 2: 1 * this.GRID_UNIT, // Round in round. + 3: 2 * this.GRID_UNIT // Square in round. }, - 3: { // Outer shape: square. - 0: 2 * this.GRID_UNIT, // Field in square. - 1: 2 * this.GRID_UNIT, // Hexagon in square. - 2: 2 * this.GRID_UNIT, // Round in square. - 3: 2 * this.GRID_UNIT // Square in square. + 3: { // Outer shape: square. + 0: 2 * this.GRID_UNIT, // Field in square. + 1: 2 * this.GRID_UNIT, // Hexagon in square. + 2: 2 * this.GRID_UNIT, // Round in square. + 3: 2 * this.GRID_UNIT // Square in square. } }; diff --git a/core/renderers/zelos/path_object.js b/core/renderers/zelos/path_object.js index 391cd26fc..9a406e90b 100644 --- a/core/renderers/zelos/path_object.js +++ b/core/renderers/zelos/path_object.js @@ -45,24 +45,24 @@ Blockly.zelos.PathObject = function(root, style, constants) { /** * The selected path of the block. - * @type {SVGElement} + * @type {?SVGElement} * @private */ this.svgPathSelected_ = null; /** * The outline paths on the block. - * @type {!Object.} + * @type {!Object} * @private */ - this.outlines_ = {}; + this.outlines_ = Object.create(null); /** * A set used to determine which outlines were used during a draw pass. The * set is initialized with a reference to all the outlines in * `this.outlines_`. Every time we use an outline during the draw pass, the * reference is removed from this set. - * @type {Object.} + * @type {Object} * @private */ this.remainingOutlines_ = null; @@ -98,8 +98,7 @@ Blockly.zelos.PathObject.prototype.applyColour = function(block) { } // Apply colour to outlines. - for (var i = 0, keys = Object.keys(this.outlines_), - key; (key = keys[i]); i++) { + for (var key in this.outlines_) { this.outlines_[key].setAttribute('fill', this.style.colourTertiary); } }; @@ -110,8 +109,7 @@ Blockly.zelos.PathObject.prototype.applyColour = function(block) { Blockly.zelos.PathObject.prototype.flipRTL = function() { Blockly.zelos.PathObject.superClass_.flipRTL.call(this); // Mirror each input outline path. - for (var i = 0, keys = Object.keys(this.outlines_), - key; (key = keys[i]); i++) { + for (var key in this.outlines_) { this.outlines_[key].setAttribute('transform', 'scale(-1 1)'); } }; @@ -175,9 +173,8 @@ Blockly.zelos.PathObject.prototype.updateShapeForInputHighlight = function( * @package */ Blockly.zelos.PathObject.prototype.beginDrawing = function() { - this.remainingOutlines_ = {}; - for (var i = 0, keys = Object.keys(this.outlines_), - key; (key = keys[i]); i++) { + this.remainingOutlines_ = Object.create(null); + for (var key in this.outlines_) { // The value set here isn't used anywhere, we are just using the // object as a Set data structure. this.remainingOutlines_[key] = 1; @@ -192,8 +189,7 @@ Blockly.zelos.PathObject.prototype.endDrawing = function() { // Go through all remaining outlines that were not used this draw pass, and // remove them. if (this.remainingOutlines_) { - for (var i = 0, keys = Object.keys(this.remainingOutlines_), - key; (key = keys[i]); i++) { + for (var key in this.remainingOutlines_) { this.removeOutlinePath_(key); } } diff --git a/core/requires.js b/core/requires.js index f08286ec4..009ab3f9c 100644 --- a/core/requires.js +++ b/core/requires.js @@ -82,8 +82,6 @@ goog.require('Blockly.zelos.Renderer'); // Blockly Themes. // Classic is the default theme. goog.require('Blockly.Themes.Classic'); -goog.require('Blockly.Themes.Dark'); goog.require('Blockly.Themes.Deuteranopia'); goog.require('Blockly.Themes.HighContrast'); goog.require('Blockly.Themes.Tritanopia'); -// goog.require('Blockly.Themes.Modern'); diff --git a/core/scrollbar.js b/core/scrollbar.js index 341d1fdfd..aab3852f2 100644 --- a/core/scrollbar.js +++ b/core/scrollbar.js @@ -58,7 +58,7 @@ Blockly.ScrollbarPair = function( this.hScroll = new Blockly.Scrollbar( workspace, true, isPair, opt_class, opt_margin); } - if (addVertical ) { + if (addVertical) { this.vScroll = new Blockly.Scrollbar( workspace, false, isPair, opt_class, opt_margin); } @@ -496,32 +496,24 @@ Blockly.Scrollbar.DEFAULT_SCROLLBAR_MARGIN = 0.5; /** - * @param {Blockly.utils.Metrics} first An object containing computed + * @param {!Blockly.utils.Metrics} first An object containing computed * measurements of a workspace. - * @param {?Blockly.utils.Metrics} second Another object containing computed + * @param {!Blockly.utils.Metrics} second Another object containing computed * measurements of a workspace. * @return {boolean} Whether the two sets of metrics are equivalent. * @private */ Blockly.Scrollbar.metricsAreEquivalent_ = function(first, second) { - if (!(first && second)) { - return false; - } - - if (first.viewWidth != second.viewWidth || - first.viewHeight != second.viewHeight || - first.viewLeft != second.viewLeft || - first.viewTop != second.viewTop || - first.absoluteTop != second.absoluteTop || - first.absoluteLeft != second.absoluteLeft || - first.scrollWidth != second.scrollWidth || - first.scrollHeight != second.scrollHeight || - first.scrollLeft != second.scrollLeft || - first.scrollTop != second.scrollTop) { - return false; - } - - return true; + return (first.viewWidth == second.viewWidth && + first.viewHeight == second.viewHeight && + first.viewLeft == second.viewLeft && + first.viewTop == second.viewTop && + first.absoluteTop == second.absoluteTop && + first.absoluteLeft == second.absoluteLeft && + first.scrollWidth == second.scrollWidth && + first.scrollHeight == second.scrollHeight && + first.scrollLeft == second.scrollLeft && + first.scrollTop == second.scrollTop); }; /** @@ -649,8 +641,8 @@ Blockly.Scrollbar.prototype.resize = function(opt_metrics) { } } - if (Blockly.Scrollbar.metricsAreEquivalent_(hostMetrics, - this.oldHostMetrics_)) { + if (this.oldHostMetrics_ && Blockly.Scrollbar.metricsAreEquivalent_( + hostMetrics, this.oldHostMetrics_)) { return; } @@ -671,7 +663,7 @@ Blockly.Scrollbar.prototype.resize = function(opt_metrics) { * hostMetrics with cached old host metrics. * @param {!Blockly.utils.Metrics} hostMetrics A data structure describing all * the required dimensions, possibly fetched from the host object. - * @return {boolean} Whether a resizeView is necesssary. + * @return {boolean} Whether a resizeView is necessary. * @private */ Blockly.Scrollbar.prototype.requiresViewResize_ = function(hostMetrics) { @@ -723,8 +715,8 @@ Blockly.Scrollbar.prototype.resizeViewHorizontal = function(hostMetrics) { Blockly.Scrollbar.scrollbarThickness - this.margin_; this.setPosition(xCoordinate, yCoordinate); - // If the view has been resized, a content resize will also be necessary. The - // reverse is not true. + // If the view has been resized, a content resize will also be necessary. + // The reverse is not true. this.resizeContentHorizontal(hostMetrics); }; diff --git a/core/shortcut_registry.js b/core/shortcut_registry.js index 90a8af7f3..14684e1b8 100644 --- a/core/shortcut_registry.js +++ b/core/shortcut_registry.js @@ -165,11 +165,10 @@ Blockly.ShortcutRegistry.prototype.removeKeyMapping = function( delete this.keyMap_[keyCode]; } return true; - } else if (!opt_quiet) { - console.warn( - 'No keyboard shortcut with name "' + shortcutName + + } + if (!opt_quiet) { + console.warn('No keyboard shortcut with name "' + shortcutName + '" registered with key code "' + keyCode + '"'); - return false; } return false; }; @@ -320,7 +319,7 @@ Blockly.ShortcutRegistry.prototype.checkModifiers_ = function( /** * Creates the serialized key code that will be used in the key map. * @param {number} keyCode Number code representing the key. - * @param {?Array.} modifiers List of modifier key codes to be used with + * @param {?Array} modifiers List of modifier key codes to be used with * the key. All valid modifiers can be found in the * Blockly.ShortcutRegistry.modifierKeys. * @return {string} The serialized key code for the given modifiers and key. diff --git a/core/theme.js b/core/theme.js index 3fcdb5c25..182710f16 100644 --- a/core/theme.js +++ b/core/theme.js @@ -19,9 +19,9 @@ goog.require('Blockly.utils.object'); /** * Class for a theme. * @param {string} name Theme name. - * @param {!Object.=} opt_blockStyles A map + * @param {!Object=} opt_blockStyles A map * from style names (strings) to objects with style attributes for blocks. - * @param {!Object.=} opt_categoryStyles A + * @param {!Object=} opt_categoryStyles A * map from style names (strings) to objects with style attributes for * categories. * @param {!Blockly.Theme.ComponentStyle=} opt_componentStyles A map of Blockly @@ -39,14 +39,14 @@ Blockly.Theme = function(name, opt_blockStyles, opt_categoryStyles, /** * The block styles map. - * @type {!Object.} + * @type {!Object} * @package */ this.blockStyles = opt_blockStyles || Object.create(null); /** * The category styles map. - * @type {!Object.} + * @type {!Object} * @package */ this.categoryStyles = opt_categoryStyles || Object.create(null); diff --git a/core/theme/dark.js b/core/theme/dark.js deleted file mode 100644 index 398497660..000000000 --- a/core/theme/dark.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Dark theme. - * @author samelh@google.com (Sam El-Husseini) - */ -'use strict'; - -goog.provide('Blockly.Themes.Dark'); - -goog.require('Blockly.Theme'); - -Blockly.Themes.Dark = Blockly.Theme.defineTheme('dark', { - 'base': Blockly.Themes.Classic, - 'componentStyles': { - 'workspaceBackgroundColour': '#1e1e1e', - 'toolboxBackgroundColour': 'blackBackground', - 'toolboxForegroundColour': '#fff', - 'flyoutBackgroundColour': '#252526', - 'flyoutForegroundColour': '#ccc', - 'flyoutOpacity': 1, - 'scrollbarColour': '#797979', - 'insertionMarkerColour': '#fff', - 'insertionMarkerOpacity': 0.3, - 'scrollbarOpacity': 0.4, - 'cursorColour': '#d0d0d0', - 'blackBackground': '#333' - } -}); diff --git a/core/theme/highcontrast.js b/core/theme/highcontrast.js index bd1084354..b38077474 100644 --- a/core/theme/highcontrast.js +++ b/core/theme/highcontrast.js @@ -113,7 +113,7 @@ Blockly.Themes.HighContrast.setComponentStyle('selectedGlowSize', 1); Blockly.Themes.HighContrast.setComponentStyle('replacementGlowColour', '#000000'); Blockly.Themes.HighContrast.setFontStyle({ - 'family': null, // Use default font-family - 'weight': null, // Use default font-weight + 'family': null, // Use default font-family. + 'weight': null, // Use default font-weight. 'size': 16 }); diff --git a/core/theme/modern.js b/core/theme/modern.js deleted file mode 100644 index 2ed8a6845..000000000 --- a/core/theme/modern.js +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Modern theme. - * Same colours as classic, but single coloured border. - */ -'use strict'; - -goog.provide('Blockly.Themes.Modern'); - -goog.require('Blockly.Theme'); - - -// Temporary holding object. -Blockly.Themes.Modern = {}; - -Blockly.Themes.Modern.defaultBlockStyles = { - "colour_blocks": { - "colourPrimary": "#a5745b", - "colourSecondary": "#dbc7bd", - "colourTertiary": "#845d49" - }, - "list_blocks": { - "colourPrimary": "#745ba5", - "colourSecondary": "#c7bddb", - "colourTertiary": "#5d4984" - }, - "logic_blocks": { - "colourPrimary": "#5b80a5", - "colourSecondary": "#bdccdb", - "colourTertiary": "#496684" - }, - "loop_blocks": { - "colourPrimary": "#5ba55b", - "colourSecondary": "#bddbbd", - "colourTertiary": "#498449" - }, - "math_blocks": { - "colourPrimary": "#5b67a5", - "colourSecondary": "#bdc2db", - "colourTertiary": "#495284" - }, - "procedure_blocks": { - "colourPrimary": "#995ba5", - "colourSecondary": "#d6bddb", - "colourTertiary": "#7a4984" - }, - "text_blocks": { - "colourPrimary": "#5ba58c", - "colourSecondary": "#bddbd1", - "colourTertiary": "#498470" - }, - "variable_blocks": { - "colourPrimary": "#a55b99", - "colourSecondary": "#dbbdd6", - "colourTertiary": "#84497a" - }, - "variable_dynamic_blocks": { - "colourPrimary": "#a55b99", - "colourSecondary": "#dbbdd6", - "colourTertiary": "#84497a" - }, - "hat_blocks": { - "colourPrimary": "#a55b99", - "colourSecondary": "#dbbdd6", - "colourTertiary": "#84497a", - "hat": "cap" - } -}; - -Blockly.Themes.Modern.categoryStyles = { - "colour_category": { - "colour": "#a5745b" - }, - "list_category": { - "colour": "#745ba5" - }, - "logic_category": { - "colour": "#5b80a5" - }, - "loop_category": { - "colour": "#5ba55b" - }, - "math_category": { - "colour": "#5b67a5" - }, - "procedure_category": { - "colour": "#995ba5" - }, - "text_category": { - "colour": "#5ba58c" - }, - "variable_category": { - "colour": "#a55b99" - }, - "variable_dynamic_category": { - "colour": "#a55b99" - } -}; - -// This style is still being fleshed out and may change. -Blockly.Themes.Modern = - new Blockly.Theme('modern', Blockly.Themes.Modern.defaultBlockStyles, - Blockly.Themes.Modern.categoryStyles); diff --git a/core/theme/tritanopia.js b/core/theme/tritanopia.js index 544e10600..aa53cb0f9 100644 --- a/core/theme/tritanopia.js +++ b/core/theme/tritanopia.js @@ -6,7 +6,7 @@ /** * @fileoverview Tritanopia theme. - * A color palette for people that have tritanopia (the inability to perceive + * A colour palette for people that have tritanopia (the inability to perceive * blue light). */ 'use strict'; diff --git a/core/theme_manager.js b/core/theme_manager.js index 64cb1cae4..6c461a2e7 100644 --- a/core/theme_manager.js +++ b/core/theme_manager.js @@ -45,14 +45,14 @@ Blockly.ThemeManager = function(workspace, theme) { /** * A list of workspaces that are subscribed to this theme. - * @type {!Array.} + * @type {!Array} * @private */ this.subscribedWorkspaces_ = []; /** * A map of subscribed UI components, keyed by component name. - * @type {!Object.>} + * @type {!Object>} * @private */ this.componentDB_ = Object.create(null); diff --git a/core/toolbox/category.js b/core/toolbox/category.js index 04d80df2b..daab5832b 100644 --- a/core/toolbox/category.js +++ b/core/toolbox/category.js @@ -12,6 +12,7 @@ goog.provide('Blockly.ToolboxCategory'); +goog.require('Blockly.ISelectableToolboxItem'); goog.require('Blockly.registry'); goog.require('Blockly.ToolboxItem'); goog.require('Blockly.utils'); @@ -125,7 +126,7 @@ Blockly.ToolboxCategory = function(categoryDef, toolbox, opt_parent) { Blockly.utils.object.inherits(Blockly.ToolboxCategory, Blockly.ToolboxItem); /** - * All the css class names that are used to create a category. + * All the CSS class names that are used to create a category. * @typedef {{ * container:(string|undefined), * row:(string|undefined), @@ -215,7 +216,7 @@ Blockly.ToolboxCategory.prototype.init = function() { }; /** - * Creates the dom for the category. + * Creates the DOM for the category. * @return {!Element} The parent element for the category. * @protected */ @@ -305,7 +306,7 @@ Blockly.ToolboxCategory.prototype.createIconDom_ = function() { /** * Creates the span that holds the category label. - * This should have an id for accessibility purposes. + * This should have an ID for accessibility purposes. * @param {string} name The name of the category. * @return {!Element} The span that holds the category label. * @protected @@ -389,10 +390,10 @@ Blockly.ToolboxCategory.prototype.getColourfromStyle_ = function(styleName) { }; /** - * Gets the html element that is clickable. - * The parent toolbox element receives clicks. The parent toolbox will add an id to this element so - * it can pass the onClick event to the correct toolboxItem. - * @return {!Element} The html element that receives clicks. + * Gets the HTML element that is clickable. + * The parent toolbox element receives clicks. The parent toolbox will add an ID + * to this element so it can pass the onClick event to the correct toolboxItem. + * @return {!Element} The HTML element that receives clicks. * @public */ Blockly.ToolboxCategory.prototype.getClickTarget = function() { diff --git a/core/toolbox/collapsible_category.js b/core/toolbox/collapsible_category.js index f7693a97f..979931848 100644 --- a/core/toolbox/collapsible_category.js +++ b/core/toolbox/collapsible_category.js @@ -12,6 +12,7 @@ goog.provide('Blockly.CollapsibleToolboxCategory'); +goog.require('Blockly.ICollapsibleToolboxItem'); goog.require('Blockly.registry'); goog.require('Blockly.ToolboxCategory'); goog.require('Blockly.ToolboxItem'); @@ -21,7 +22,6 @@ goog.require('Blockly.utils.dom'); goog.require('Blockly.utils.object'); goog.require('Blockly.utils.toolbox'); -goog.requireType('Blockly.ICollapsibleToolboxItem'); goog.requireType('Blockly.IToolbox'); goog.requireType('Blockly.IToolboxItem'); @@ -66,7 +66,7 @@ Blockly.CollapsibleToolboxCategory = function(categoryDef, toolbox, opt_parent) Blockly.utils.object.inherits(Blockly.CollapsibleToolboxCategory, Blockly.ToolboxCategory); /** - * All the css class names that are used to create a collapsible + * All the CSS class names that are used to create a collapsible * category. This is all the properties from the regular category plus contents. * @typedef {{ * container:?string, @@ -186,7 +186,7 @@ Blockly.CollapsibleToolboxCategory.prototype.createIconDom_ = function() { }; /** - * Create the dom for all subcategories. + * Create the DOM for all subcategories. * @param {!Array} subcategories The subcategories. * @return {!Element} The div holding all the subcategories. * @protected diff --git a/core/toolbox/separator.js b/core/toolbox/separator.js index 2c51cd4a0..63ded4a6b 100644 --- a/core/toolbox/separator.js +++ b/core/toolbox/separator.js @@ -13,12 +13,12 @@ goog.provide('Blockly.ToolboxSeparator'); +goog.require('Blockly.IToolboxItem'); goog.require('Blockly.registry'); goog.require('Blockly.ToolboxItem'); goog.require('Blockly.utils.dom'); goog.requireType('Blockly.IToolbox'); -goog.requireType('Blockly.IToolboxItem'); goog.requireType('Blockly.utils.toolbox'); @@ -37,7 +37,7 @@ Blockly.ToolboxSeparator = function(separatorDef, toolbox) { Blockly.ToolboxSeparator.superClass_.constructor.call( this, separatorDef, toolbox); /** - * All the css class names that are used to create a separator. + * All the CSS class names that are used to create a separator. * @type {!Blockly.ToolboxSeparator.CssConfig} * @protected */ @@ -51,7 +51,7 @@ Blockly.ToolboxSeparator = function(separatorDef, toolbox) { Blockly.utils.object.inherits(Blockly.ToolboxSeparator, Blockly.ToolboxItem); /** - * All the css class names that are used to create a separator. + * All the CSS class names that are used to create a separator. * @typedef {{ * container:(string|undefined) * }} @@ -72,7 +72,7 @@ Blockly.ToolboxSeparator.prototype.init = function() { }; /** - * Creates the dom for a separator. + * Creates the DOM for a separator. * @return {!Element} The parent element for the separator. * @protected */ diff --git a/core/toolbox/toolbox.js b/core/toolbox/toolbox.js index fce49de23..64a1a51db 100644 --- a/core/toolbox/toolbox.js +++ b/core/toolbox/toolbox.js @@ -17,9 +17,15 @@ goog.require('Blockly.CollapsibleToolboxCategory'); /** @suppress {extraRequire} */ goog.require('Blockly.constants'); goog.require('Blockly.Css'); +goog.require('Blockly.DeleteArea'); goog.require('Blockly.Events'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.ToolboxItemSelect'); +goog.require('Blockly.IAutoHideable'); +goog.require('Blockly.IKeyboardAccessible'); +goog.require('Blockly.IStyleable'); +goog.require('Blockly.IToolbox'); +goog.require('Blockly.Options'); goog.require('Blockly.registry'); goog.require('Blockly.Touch'); goog.require('Blockly.utils'); @@ -29,12 +35,8 @@ goog.require('Blockly.utils.Rect'); goog.require('Blockly.utils.toolbox'); goog.requireType('Blockly.ICollapsibleToolboxItem'); -goog.requireType('Blockly.IDeleteArea'); goog.requireType('Blockly.IFlyout'); -goog.requireType('Blockly.IKeyboardAccessible'); goog.requireType('Blockly.ISelectableToolboxItem'); -goog.requireType('Blockly.IStyleable'); -goog.requireType('Blockly.IToolbox'); goog.requireType('Blockly.IToolboxItem'); goog.requireType('Blockly.ShortcutRegistry'); goog.requireType('Blockly.WorkspaceSvg'); @@ -46,12 +48,14 @@ goog.requireType('Blockly.WorkspaceSvg'); * @param {!Blockly.WorkspaceSvg} workspace The workspace in which to create new * blocks. * @constructor + * @implements {Blockly.IAutoHideable} * @implements {Blockly.IKeyboardAccessible} - * @implements {Blockly.IDeleteArea} * @implements {Blockly.IStyleable} * @implements {Blockly.IToolbox} + * @extends {Blockly.DeleteArea} */ Blockly.Toolbox = function(workspace) { + Blockly.Toolbox.superClass_.constructor.call(this); /** * The workspace this toolbox is on. * @type {!Blockly.WorkspaceSvg} @@ -122,10 +126,10 @@ Blockly.Toolbox = function(workspace) { /** * A map from toolbox item IDs to toolbox items. - * @type {!Object} + * @type {!Object} * @protected */ - this.contentMap_ = {}; + this.contentMap_ = Object.create(null); /** * Position of the toolbox and flyout relative to the workspace. @@ -156,6 +160,7 @@ Blockly.Toolbox = function(workspace) { */ this.boundEvents_ = []; }; +Blockly.utils.object.inherits(Blockly.Toolbox, Blockly.DeleteArea); /** * Handles the given keyboard shortcut. @@ -186,12 +191,22 @@ Blockly.Toolbox.prototype.init = function() { themeManager.subscribe(this.HtmlDiv, 'toolboxBackgroundColour', 'background-color'); themeManager.subscribe(this.HtmlDiv, 'toolboxForegroundColour', 'color'); + this.workspace_.getComponentManager().addComponent({ + id: 'toolbox', + component: this, + weight: 1, + capabilities: [ + Blockly.ComponentManager.Capability.AUTOHIDEABLE, + Blockly.ComponentManager.Capability.DELETE_AREA, + Blockly.ComponentManager.Capability.DRAG_TARGET + ] + }); }; /** - * Creates the dom for the toolbox. + * Creates the DOM for the toolbox. * @param {!Blockly.WorkspaceSvg} workspace The workspace this toolbox is on. - * @return {!Element} The html container for the toolbox. + * @return {!Element} The HTML container for the toolbox. * @protected */ Blockly.Toolbox.prototype.createDom_ = function(workspace) { @@ -212,7 +227,7 @@ Blockly.Toolbox.prototype.createDom_ = function(workspace) { /** * Creates the container div for the toolbox. - * @return {!Element} The html container for the toolbox. + * @return {!Element} The HTML container for the toolbox. * @protected */ Blockly.Toolbox.prototype.createContainer_ = function() { @@ -226,7 +241,7 @@ Blockly.Toolbox.prototype.createContainer_ = function() { /** * Creates the container for all the contents in the toolbox. - * @return {!Element} The html container for the toolbox contents. + * @return {!Element} The HTML container for the toolbox contents. * @protected */ Blockly.Toolbox.prototype.createContentsContainer_ = function() { @@ -240,8 +255,8 @@ Blockly.Toolbox.prototype.createContentsContainer_ = function() { /** * Adds event listeners to the toolbox container div. - * @param {!Element} container The html container for the toolbox. - * @param {!Element} contentsContainer The html container for the contents + * @param {!Element} container The HTML container for the toolbox. + * @param {!Element} contentsContainer The HTML container for the contents * of the toolbox. * @protected */ @@ -381,7 +396,7 @@ Blockly.Toolbox.prototype.render = function(toolboxDef) { } } this.contents_ = []; - this.contentMap_ = {}; + this.contentMap_ = Object.create(null); this.renderContents_(toolboxDef['contents']); this.position(); }; @@ -394,7 +409,7 @@ Blockly.Toolbox.prototype.render = function(toolboxDef) { */ Blockly.Toolbox.prototype.renderContents_ = function(toolboxDef) { // This is for performance reasons. By using document fragment we only have to - // add to the dom once. + // add to the DOM once. var fragment = document.createDocumentFragment(); for (var i = 0, toolboxItemDef; (toolboxItemDef = toolboxDef[i]); i++) { this.createToolboxItem_(toolboxItemDef, fragment); @@ -414,7 +429,7 @@ Blockly.Toolbox.prototype.createToolboxItem_ = function(toolboxItemDef, fragment var registryName = toolboxItemDef['kind']; // Categories that are collapsible are created using a class registered under - // a diffferent name. + // a different name. if (registryName.toUpperCase() == 'CATEGORY' && Blockly.utils.toolbox.isCategoryCollapsible( /** @type {!Blockly.utils.toolbox.CategoryInfo} */(toolboxItemDef))) { @@ -431,7 +446,7 @@ Blockly.Toolbox.prototype.createToolboxItem_ = function(toolboxItemDef, fragment if (toolboxItemDom) { fragment.appendChild(toolboxItemDom); } - // Adds the id to the html element that can receive a click. + // Adds the ID to the HTML element that can receive a click. // This is used in onClick_ to find the toolboxItem that was clicked. if (toolboxItem.getClickTarget) { toolboxItem.getClickTarget().setAttribute('id', toolboxItem.getId()); @@ -484,9 +499,10 @@ Blockly.Toolbox.prototype.removeStyle = function(style) { }; /** - * Return the deletion rectangle for this toolbox. - * @return {?Blockly.utils.Rect} Rectangle in which to delete. - * @public + * Returns the bounding rectangle of the drag target area in pixel units + * relative to viewport. + * @return {?Blockly.utils.Rect} The component's bounding box. Null if drag + * target area should be ignored. */ Blockly.Toolbox.prototype.getClientRect = function() { if (!this.HtmlDiv) { @@ -518,14 +534,27 @@ Blockly.Toolbox.prototype.getClientRect = function() { }; /** - * Gets the toolbox item with the given id. - * @param {string} id The id of the toolbox item. - * @return {?Blockly.IToolboxItem} The toolbox item with the given id, or null if - * no item exists. + * Returns whether the provided block would be deleted if dropped on this area. + * @param {!Blockly.BlockSvg} _block The block. + * @param {boolean} _couldConnect Whether the block could could connect to + * another. + * @return {boolean} Whether the block provided would be deleted if dropped on + * this area. + */ +Blockly.Toolbox.prototype.wouldDeleteBlock = function(_block, _couldConnect) { + // Prefer dragging to the toolbox over connecting to other blocks. + return true; +}; + +/** + * Gets the toolbox item with the given ID. + * @param {string} id The ID of the toolbox item. + * @return {?Blockly.IToolboxItem} The toolbox item with the given ID, or null + * if no item exists. * @public */ Blockly.Toolbox.prototype.getToolboxItemById = function(id) { - return this.contentMap_[id]; + return this.contentMap_[id] || null; }; /** @@ -695,6 +724,17 @@ Blockly.Toolbox.prototype.setVisible = function(isVisible) { this.HtmlDiv.style.display = isVisible ? 'block' : 'none'; }; +/** + * Hides the component. Called in Blockly.hideChaff. + * @param {boolean} onlyClosePopups Whether only popups should be closed. + * Flyouts should not be closed if this is true. + */ +Blockly.Toolbox.prototype.autoHide = function(onlyClosePopups) { + if (!onlyClosePopups && this.flyout_ && this.flyout_.autoClose) { + this.clearSelection(); + } +}; + /** * Sets the given item as selected. * No-op if the item is not selectable. diff --git a/core/toolbox/toolbox_item.js b/core/toolbox/toolbox_item.js index e7c807667..febc0a068 100644 --- a/core/toolbox/toolbox_item.js +++ b/core/toolbox/toolbox_item.js @@ -12,9 +12,10 @@ goog.provide('Blockly.ToolboxItem'); +goog.require('Blockly.IToolboxItem'); + goog.requireType('Blockly.ICollapsibleToolboxItem'); goog.requireType('Blockly.IToolbox'); -goog.requireType('Blockly.IToolboxItem'); goog.requireType('Blockly.utils.toolbox'); goog.requireType('Blockly.WorkspaceSvg'); @@ -76,7 +77,7 @@ Blockly.ToolboxItem = function(toolboxItemDef, toolbox, opt_parent) { /** * Initializes the toolbox item. - * This includes creating the dom and updating the state of any items based + * This includes creating the DOM and updating the state of any items based * on the info object. * @public */ @@ -95,7 +96,7 @@ Blockly.ToolboxItem.prototype.getDiv = function() { /** * Gets a unique identifier for this toolbox item. - * @return {string} The id for the toolbox item. + * @return {string} The ID for the toolbox item. * @public */ Blockly.ToolboxItem.prototype.getId = function() { diff --git a/core/tooltip.js b/core/tooltip.js index 95b45ab16..12819e13f 100644 --- a/core/tooltip.js +++ b/core/tooltip.js @@ -124,7 +124,7 @@ Blockly.Tooltip.DIV = null; /** * Returns the tooltip text for the given element. * @param {?Object} object The object to get the tooltip text of. - * @returns {string} The tooltip text of the element. + * @return {string} The tooltip text of the element. */ Blockly.Tooltip.getTooltipOfObject = function(object) { var obj = Blockly.Tooltip.getTargetObject_(object); @@ -146,7 +146,7 @@ Blockly.Tooltip.getTooltipOfObject = function(object) { * tooltip. Could be the object itself. * @param {?Object} obj The object are trying to find the target tooltip * object of. - * @returns {?{tooltip}} The target tooltip object. + * @return {?{tooltip}} The target tooltip object. * @private */ Blockly.Tooltip.getTargetObject_ = function(obj) { diff --git a/core/touch.js b/core/touch.js index 62bbddf19..b6668c398 100644 --- a/core/touch.js +++ b/core/touch.js @@ -175,7 +175,7 @@ Blockly.Touch.getTouchIdentifierFromEvent = function(e) { Blockly.Touch.checkTouchIdentifier = function(e) { var identifier = Blockly.Touch.getTouchIdentifierFromEvent(e); - // if (Blockly.touchIdentifier_ )is insufficient because Android touch + // if (Blockly.touchIdentifier_) is insufficient because Android touch // identifiers may be zero. if (Blockly.Touch.touchIdentifier_ !== undefined && Blockly.Touch.touchIdentifier_ !== null) { @@ -236,7 +236,7 @@ Blockly.Touch.isTouchEvent = function(e) { * point. * @param {!Event} e A mouse event or a touch event with one or more changed * touches. - * @return {!Array.} An array of mouse or touch events. Each touch + * @return {!Array} An array of mouse or touch events. Each touch * event will have exactly one changed touch. */ Blockly.Touch.splitEventByTouches = function(e) { diff --git a/core/touch_gesture.js b/core/touch_gesture.js index 7423ff269..169d80062 100644 --- a/core/touch_gesture.js +++ b/core/touch_gesture.js @@ -314,7 +314,7 @@ Blockly.TouchGesture.prototype.handleTouchEnd = function(e) { /** * Helper function returning the current touch point coordinate. * @param {!Event} e A touch or pointer event. - * @return {Blockly.utils.Coordinate} The current touch point coordinate + * @return {?Blockly.utils.Coordinate} The current touch point coordinate * @package */ Blockly.TouchGesture.prototype.getTouchPoint = function(e) { diff --git a/core/trashcan.js b/core/trashcan.js index 5eba6453f..7781a79bd 100644 --- a/core/trashcan.js +++ b/core/trashcan.js @@ -15,21 +15,22 @@ goog.provide('Blockly.Trashcan'); goog.require('Blockly.browserEvents'); /** @suppress {extraRequire} */ goog.require('Blockly.constants'); +goog.require('Blockly.DeleteArea'); goog.require('Blockly.Events'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.TrashcanOpen'); +goog.require('Blockly.IAutoHideable'); goog.require('Blockly.IPositionable'); +goog.require('Blockly.Options'); goog.require('Blockly.registry'); -goog.require('Blockly.Scrollbar'); +goog.require('Blockly.uiPosition'); goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.math'); goog.require('Blockly.utils.Rect'); goog.require('Blockly.utils.Svg'); goog.require('Blockly.utils.toolbox'); goog.require('Blockly.Xml'); goog.requireType('Blockly.Events.Abstract'); -goog.requireType('Blockly.IDeleteArea'); goog.requireType('Blockly.IFlyout'); goog.requireType('Blockly.WorkspaceSvg'); @@ -38,10 +39,12 @@ goog.requireType('Blockly.WorkspaceSvg'); * Class for a trash can. * @param {!Blockly.WorkspaceSvg} workspace The workspace to sit in. * @constructor - * @implements {Blockly.IDeleteArea} + * @implements {Blockly.IAutoHideable} * @implements {Blockly.IPositionable} + * @extends {Blockly.DeleteArea} */ Blockly.Trashcan = function(workspace) { + Blockly.Trashcan.superClass_.constructor.call(this); /** * The workspace the trashcan sits in. * @type {!Blockly.WorkspaceSvg} @@ -51,7 +54,7 @@ Blockly.Trashcan = function(workspace) { /** * A list of XML (stored as strings) representing blocks in the trashcan. - * @type {!Array.} + * @type {!Array} * @private */ this.contents_ = []; @@ -100,6 +103,7 @@ Blockly.Trashcan = function(workspace) { } this.workspace_.addChangeListener(this.onDelete_.bind(this)); }; +Blockly.utils.object.inherits(Blockly.Trashcan, Blockly.DeleteArea); /** * Width of both the trash can and lid images. @@ -123,18 +127,18 @@ Blockly.Trashcan.prototype.BODY_HEIGHT_ = 44; Blockly.Trashcan.prototype.LID_HEIGHT_ = 16; /** - * Distance between trashcan and bottom edge of workspace. + * Distance between trashcan and bottom or top edge of workspace. * @const {number} * @private */ -Blockly.Trashcan.prototype.MARGIN_BOTTOM_ = 20; +Blockly.Trashcan.prototype.MARGIN_VERTICAL_ = 20; /** - * Distance between trashcan and right edge of workspace. + * Distance between trashcan and right or left edge of workspace. * @const {number} * @private */ -Blockly.Trashcan.prototype.MARGIN_SIDE_ = 20; +Blockly.Trashcan.prototype.MARGIN_HORIZONTAL_ = 20; /** * Extent of hotspot on all sides beyond the size of the image. @@ -257,6 +261,13 @@ Blockly.Trashcan.prototype.left_ = 0; */ Blockly.Trashcan.prototype.top_ = 0; +/** + * Whether this has been initialized. + * @type {boolean} + * @private + */ +Blockly.Trashcan.prototype.initialized_ = false; + /** * Create the trash can elements. * @return {!SVGElement} The trash can's SVG group. @@ -341,23 +352,28 @@ Blockly.Trashcan.prototype.createDom = function() { }; /** - * Initialize the trash can. - * @param {number} verticalSpacing Vertical distance from workspace edge to the - * same edge of the trashcan. - * @return {number} Vertical distance from workspace edge to the opposite - * edge of the trashcan. + * Initializes the trash can. */ -Blockly.Trashcan.prototype.init = function(verticalSpacing) { +Blockly.Trashcan.prototype.init = function() { if (this.workspace_.options.maxTrashcanContents > 0) { Blockly.utils.dom.insertAfter( this.flyout.createDom(Blockly.utils.Svg.SVG), this.workspace_.getParentSvg()); this.flyout.init(this.workspace_); } - - this.verticalSpacing_ = this.MARGIN_BOTTOM_ + verticalSpacing; + this.workspace_.getComponentManager().addComponent({ + id: 'trashcan', + component: this, + weight: 1, + capabilities: [ + Blockly.ComponentManager.Capability.AUTOHIDEABLE, + Blockly.ComponentManager.Capability.DELETE_AREA, + Blockly.ComponentManager.Capability.DRAG_TARGET, + Blockly.ComponentManager.Capability.POSITIONABLE + ] + }); + this.initialized_ = true; this.setLidOpen(false); - return this.verticalSpacing_ + this.BODY_HEIGHT_ + this.LID_HEIGHT_; }; /** @@ -399,11 +415,7 @@ Blockly.Trashcan.prototype.openFlyout = function() { if (this.contentsIsOpen()) { return; } - - var xml = []; - for (var i = 0, text; (text = this.contents_[i]); i++) { - xml[i] = Blockly.Xml.textToDom(text); - } + var xml = this.contents_.map(Blockly.Xml.textToDom); this.flyout.show(xml); this.fireUiEvent_(true); }; @@ -415,11 +427,23 @@ Blockly.Trashcan.prototype.closeFlyout = function() { if (!this.contentsIsOpen()) { return; } - this.flyout.hide(); this.fireUiEvent_(false); }; +/** + * Hides the component. Called in Blockly.hideChaff. + * @param {boolean} onlyClosePopups Whether only popups should be closed. + * Flyouts should not be closed if this is true. + */ +Blockly.Trashcan.prototype.autoHide = function(onlyClosePopups) { + // For now the trashcan flyout always autocloses because it overlays the + // trashcan UI (no trashcan to click to close it). + if (!onlyClosePopups && this.flyout) { + this.closeFlyout(); + } +}; + /** * Empties the trashcan's contents. If the contents-flyout is currently open * it will be closed. @@ -443,47 +467,28 @@ Blockly.Trashcan.prototype.emptyContents = function() { */ Blockly.Trashcan.prototype.position = function(metrics, savedPositions) { // Not yet initialized. - if (!this.verticalSpacing_) { + if (!this.initialized_) { return; } - if (metrics.toolboxMetrics.position == Blockly.utils.toolbox.Position.LEFT || - (this.workspace_.horizontalLayout && !this.workspace_.RTL)) { - // Right corner placement. - this.left_ = metrics.viewMetrics.width + metrics.absoluteMetrics.left - - this.WIDTH_ - this.MARGIN_SIDE_ - Blockly.Scrollbar.scrollbarThickness; - } else { - // Left corner placement. - this.left_ = this.MARGIN_SIDE_ + Blockly.Scrollbar.scrollbarThickness; - } + + var cornerPosition = + Blockly.uiPosition.getCornerOppositeToolbox(this.workspace_, metrics); var height = this.BODY_HEIGHT_ + this.LID_HEIGHT_; - // Upper corner placement - var minTop = this.top_ = metrics.absoluteMetrics.top + this.verticalSpacing_; - // Bottom corner placement - var maxTop = metrics.absoluteMetrics.top + metrics.viewMetrics.height - - height - this.verticalSpacing_; - var placeBottom = - metrics.toolboxMetrics.position !== Blockly.utils.toolbox.Position.BOTTOM; - this.top_ = placeBottom ? maxTop : minTop; + var startRect = Blockly.uiPosition.getStartPositionRect( + cornerPosition, new Blockly.utils.Size(this.WIDTH_, height), + this.MARGIN_HORIZONTAL_, this.MARGIN_VERTICAL_, metrics, this.workspace_); - // Check for collision and bump if needed. - var boundingRect = this.getBoundingRectangle(); - for (var i = 0, otherEl; (otherEl = savedPositions[i]); i++) { - if (boundingRect.intersects(otherEl)) { - if (placeBottom) { - // Bump up - this.top_ = otherEl.top - height - this.MARGIN_BOTTOM_; - } else { - this.top_ = otherEl.bottom + this.MARGIN_BOTTOM_; - } - // Recheck other savedPositions - boundingRect = this.getBoundingRectangle(); - i = -1; - } - } - // Clamp top value within valid range. - this.top_ = Blockly.utils.math.clamp(minTop, this.top_, maxTop); + var verticalPosition = cornerPosition.vertical; + var bumpDirection = + verticalPosition === Blockly.uiPosition.verticalPosition.TOP ? + Blockly.uiPosition.bumpDirection.DOWN : + Blockly.uiPosition.bumpDirection.UP; + var positionRect = Blockly.uiPosition.bumpPositionRect( + startRect, this.MARGIN_VERTICAL_, bumpDirection, savedPositions); + this.top_ = positionRect.top; + this.left_ = positionRect.left; this.svgGroup_.setAttribute('transform', 'translate(' + this.left_ + ',' + this.top_ + ')'); }; @@ -491,7 +496,7 @@ Blockly.Trashcan.prototype.position = function(metrics, savedPositions) { /** * Returns the bounding rectangle of the UI element in pixel units relative to * the Blockly injection div. - * @return {!Blockly.utils.Rect} The plugin’s bounding box. + * @return {!Blockly.utils.Rect} The UI elements’s bounding box. */ Blockly.Trashcan.prototype.getBoundingRectangle = function() { var bottom = this.top_ + this.BODY_HEIGHT_ + this.LID_HEIGHT_; @@ -500,8 +505,10 @@ Blockly.Trashcan.prototype.getBoundingRectangle = function() { }; /** - * Return the deletion rectangle for this trash can. - * @return {Blockly.utils.Rect} Rectangle in which to delete. + * Returns the bounding rectangle of the drag target area in pixel units + * relative to viewport. + * @return {?Blockly.utils.Rect} The component's bounding box. Null if drag + * target area should be ignored. */ Blockly.Trashcan.prototype.getClientRect = function() { if (!this.svgGroup_) { @@ -517,6 +524,51 @@ Blockly.Trashcan.prototype.getClientRect = function() { return new Blockly.utils.Rect(top, bottom, left, right); }; +/** + * Handles when a cursor with a block or bubble enters this drag target. + * @override + */ +Blockly.Trashcan.prototype.onDragEnter = function() { + this.setLidOpen(true); +}; + +/** + * Handles when a cursor with a block or bubble exits this drag target. + * @override + */ +Blockly.Trashcan.prototype.onDragExit = function() { + this.setLidOpen(false); +}; + + +/** + * Handles when a block is dropped on this component. Should not handle delete + * here. + * @param {!Blockly.BlockSvg} _block The block. + * @override + */ +Blockly.Trashcan.prototype.onBlockDrop = function(_block) { + this.onDrop_(); +}; + +/** + * Handles when a bubble is dropped on this component. Should not handle delete + * here. + * @param {!Blockly.IBubble} _bubble The bubble. + * @override + */ +Blockly.Trashcan.prototype.onBubbleDrop = function(_bubble) { + this.onDrop_(); +}; + +/** + * Handles when a block or bubble is dropped on this component. + * @private + */ +Blockly.Trashcan.prototype.onDrop_ = function() { + setTimeout(this.closeLid.bind(this), 100); +}; + /** * Flip the lid open or shut. * @param {boolean} state True if open. @@ -604,7 +656,7 @@ Blockly.Trashcan.prototype.click = function() { }; /** - * Fires a ui event for trashcan flyout open or close. + * Fires a UI event for trashcan flyout open or close. * @param {boolean} trashcanOpen Whether the flyout is opening. * @private */ diff --git a/core/utils.js b/core/utils.js index b6141b3c8..171e83422 100644 --- a/core/utils.js +++ b/core/utils.js @@ -164,7 +164,7 @@ Blockly.utils.isRightButton = function(e) { * The origin (0,0) is the top-left corner of the Blockly SVG. * @param {!Event} e Mouse event. * @param {!Element} svg SVG element. - * @param {SVGMatrix} matrix Inverted screen CTM to use. + * @param {?SVGMatrix} matrix Inverted screen CTM to use. * @return {!SVGPoint} Object with .x and .y properties. */ Blockly.utils.mouseToSvg = function(e, svg, matrix) { @@ -213,7 +213,7 @@ Blockly.utils.getScrollDeltaPixels = function(e) { * (e.g., '%%'). * @param {string} message Text which might contain string table references and * interpolation tokens. - * @return {!Array.} Array of strings and numbers. + * @return {!Array} Array of strings and numbers. */ Blockly.utils.tokenizeInterpolation = function(message) { return Blockly.utils.tokenizeInterpolation_(message, true); @@ -270,7 +270,7 @@ Blockly.utils.checkMessageReferences = function(message) { * interpolation tokens. * @param {boolean} parseInterpolationTokens Option to parse numeric * interpolation tokens (%1, %2, ...) when true. - * @return {!Array.} Array of strings and numbers. + * @return {!Array} Array of strings and numbers. * @private */ Blockly.utils.tokenizeInterpolation_ = function(message, @@ -583,10 +583,10 @@ Blockly.utils.getBlockTypeCounts = function(block, opt_stripFollowing) { /** * Converts screen coordinates to workspace coordinates. - * @param {Blockly.WorkspaceSvg} ws The workspace to find the coordinates on. - * @param {Blockly.utils.Coordinate} screenCoordinates The screen coordinates to + * @param {!Blockly.WorkspaceSvg} ws The workspace to find the coordinates on. + * @param {!Blockly.utils.Coordinate} screenCoordinates The screen coordinates to * be converted to workspace coordinates - * @return {Blockly.utils.Coordinate} The workspace coordinates. + * @return {!Blockly.utils.Coordinate} The workspace coordinates. * @package */ Blockly.utils.screenToWsCoordinates = function(ws, screenCoordinates) { diff --git a/core/utils/aria.js b/core/utils/aria.js index f455b9928..4cacc1ff7 100644 --- a/core/utils/aria.js +++ b/core/utils/aria.js @@ -12,6 +12,10 @@ */ 'use strict'; +/** + * @name Blockly.utils.aria + * @namespace + */ goog.provide('Blockly.utils.aria'); @@ -155,7 +159,7 @@ Blockly.utils.aria.setRole = function(element, roleName) { * @param {!Blockly.utils.aria.State} stateName State attribute being set. * Automatically adds prefix 'aria-' to the state name if the attribute is * not an extra attribute. - * @param {string|boolean|number|!Array.} value Value + * @param {string|boolean|number|!Array} value Value * for the state attribute. */ Blockly.utils.aria.setState = function(element, stateName, value) { diff --git a/core/utils/colour.js b/core/utils/colour.js index ded55d5e9..b64b81eb5 100644 --- a/core/utils/colour.js +++ b/core/utils/colour.js @@ -79,7 +79,7 @@ Blockly.utils.colour.rgbToHex = function(r, g, b) { * Converts a colour to RGB. * @param {string} colour String representing colour in any * colour format ('#ff0000', 'red', '0xff000', etc). - * @return {!Array.} RGB representation of the colour. + * @return {!Array} RGB representation of the colour. */ Blockly.utils.colour.hexToRgb = function(colour) { var hex = Blockly.utils.colour.parse(colour); diff --git a/core/utils/coordinate.js b/core/utils/coordinate.js index be17d00a1..da196acea 100644 --- a/core/utils/coordinate.js +++ b/core/utils/coordinate.js @@ -42,8 +42,8 @@ Blockly.utils.Coordinate = function(x, y) { /** * Compares coordinates for equality. - * @param {Blockly.utils.Coordinate} a A Coordinate. - * @param {Blockly.utils.Coordinate} b A Coordinate. + * @param {?Blockly.utils.Coordinate} a A Coordinate. + * @param {?Blockly.utils.Coordinate} b A Coordinate. * @return {boolean} True iff the coordinates are equal, or if both are null. */ Blockly.utils.Coordinate.equals = function(a, b) { diff --git a/core/utils/deprecation.js b/core/utils/deprecation.js index ca9c19ab4..4c948f22b 100644 --- a/core/utils/deprecation.js +++ b/core/utils/deprecation.js @@ -7,25 +7,31 @@ /** * @fileoverview Helper function for warning developers about deprecations. * This method is not specific to Blockly. - * @author fenichel@google.com (Rachel Fenichel); + * @author fenichel@google.com (Rachel Fenichel) */ 'use strict'; +/** + * @name Blockly.utils.deprecation + * @namespace + */ goog.provide('Blockly.utils.deprecation'); + /** - * Warn developers that a function is deprecated. - * @param {string} functionName The name of the function. - * @param {string} deprecationDate The date when the function was deprecated. + * Warn developers that a function or property is deprecated. + * @param {string} name The name of the function or property. + * @param {string} deprecationDate The date of deprecation. * Prefer 'month yyyy' or 'quarter yyyy' format. - * @param {string} deletionDate The date when the function will be deleted, in - * the same format as the deprecation date. - * @param {string=} opt_use The name of a function to use instead, if any. + * @param {string} deletionDate The date of deletion, in the same format as the + * deprecation date. + * @param {string=} opt_use The name of a function or property to use instead, + * if any. * @package */ Blockly.utils.deprecation.warn = function( - functionName, deprecationDate, deletionDate, opt_use) { - var msg = functionName + ' was deprecated on ' + deprecationDate + + name, deprecationDate, deletionDate, opt_use) { + var msg = name + ' was deprecated on ' + deprecationDate + ' and will be deleted on ' + deletionDate + '.'; if (opt_use) { msg += '\nUse ' + opt_use + ' instead.'; diff --git a/core/utils/dom.js b/core/utils/dom.js index 3762297fa..392f0094d 100644 --- a/core/utils/dom.js +++ b/core/utils/dom.js @@ -175,8 +175,8 @@ Blockly.utils.dom.hasClass = function(element, className) { /** * Removes a node from its parent. No-op if not attached to a parent. - * @param {Node} node The node to remove. - * @return {Node} The node removed if removed; else, null. + * @param {?Node} node The node to remove. + * @return {?Node} The node removed if removed; else, null. */ // Copied from Closure goog.dom.removeNode Blockly.utils.dom.removeNode = function(node) { @@ -232,7 +232,7 @@ Blockly.utils.dom.setCssTransform = function(element, transform) { Blockly.utils.dom.startTextWidthCache = function() { Blockly.utils.dom.cacheReference_++; if (!Blockly.utils.dom.cacheWidths_) { - Blockly.utils.dom.cacheWidths_ = {}; + Blockly.utils.dom.cacheWidths_ = Object.create(null); } }; diff --git a/core/utils/idgenerator.js b/core/utils/idgenerator.js index e17c51f31..347b71d02 100644 --- a/core/utils/idgenerator.js +++ b/core/utils/idgenerator.js @@ -12,6 +12,10 @@ */ 'use strict'; +/** + * @name Blockly.utils.IdGenerator + * @namespace + */ goog.provide('Blockly.utils.IdGenerator'); diff --git a/core/utils/keycodes.js b/core/utils/keycodes.js index 2129dadf1..a5be94cb8 100644 --- a/core/utils/keycodes.js +++ b/core/utils/keycodes.js @@ -12,6 +12,10 @@ */ 'use strict'; +/** + * @name Blockly.utils.KeyCodes + * @namespace + */ goog.provide('Blockly.utils.KeyCodes'); diff --git a/core/utils/metrics.js b/core/utils/metrics.js index dda790f4f..226ef0734 100644 --- a/core/utils/metrics.js +++ b/core/utils/metrics.js @@ -10,6 +10,10 @@ */ 'use strict'; +/** + * @name Blockly.utils.Metrics + * @namespace + */ goog.provide('Blockly.utils.Metrics'); diff --git a/core/utils/object.js b/core/utils/object.js index e382b9ee5..37837ee3e 100644 --- a/core/utils/object.js +++ b/core/utils/object.js @@ -10,6 +10,10 @@ */ 'use strict'; +/** + * @name Blockly.utils.object + * @namespace + */ goog.provide('Blockly.utils.object'); @@ -62,9 +66,7 @@ Blockly.utils.object.deepMerge = function(target, source) { */ Blockly.utils.object.values = function(obj) { if (Object.values) { - /* eslint-disable es5/no-es6-methods */ return Object.values(obj); - /* eslint-enable es5/no-es6-methods */ } // Fallback for IE. return Object.keys(obj).map(function(e) { diff --git a/core/utils/rect.js b/core/utils/rect.js index fcea05623..128ec4eae 100644 --- a/core/utils/rect.js +++ b/core/utils/rect.js @@ -56,7 +56,7 @@ Blockly.utils.Rect.prototype.contains = function(x, y) { /** * Tests whether this rectangle intersects the provided rectangle. * Assumes that the coordinate system increases going down and left. - * @param {Blockly.utils.Rect} other The other rectangle to check for + * @param {!Blockly.utils.Rect} other The other rectangle to check for * intersection with. * @return {boolean} Whether this rectangle intersects the provided rectangle. */ diff --git a/core/utils/size.js b/core/utils/size.js index 66c9d0be1..2ffa91ac1 100644 --- a/core/utils/size.js +++ b/core/utils/size.js @@ -42,8 +42,8 @@ Blockly.utils.Size = function(width, height) { /** * Compares sizes for equality. - * @param {Blockly.utils.Size} a A Size. - * @param {Blockly.utils.Size} b A Size. + * @param {?Blockly.utils.Size} a A Size. + * @param {?Blockly.utils.Size} b A Size. * @return {boolean} True iff the sizes have equal widths and equal * heights, or if both are null. */ diff --git a/core/utils/string.js b/core/utils/string.js index 2d1b8e6e1..880401a4c 100644 --- a/core/utils/string.js +++ b/core/utils/string.js @@ -32,7 +32,7 @@ Blockly.utils.string.startsWith = function(str, prefix) { /** * Given an array of strings, return the length of the shortest one. - * @param {!Array.} array Array of strings. + * @param {!Array} array Array of strings. * @return {number} Length of shortest string. */ Blockly.utils.string.shortestStringLength = function(array) { @@ -47,7 +47,7 @@ Blockly.utils.string.shortestStringLength = function(array) { /** * Given an array of strings, return the length of the common prefix. * Words may not be split. Any space after a word is included in the length. - * @param {!Array.} array Array of strings. + * @param {!Array} array Array of strings. * @param {number=} opt_shortest Length of shortest string. * @return {number} Length of common prefix. */ @@ -82,7 +82,7 @@ Blockly.utils.string.commonWordPrefix = function(array, opt_shortest) { /** * Given an array of strings, return the length of the common suffix. * Words may not be split. Any space after a word is included in the length. - * @param {!Array.} array Array of strings. + * @param {!Array} array Array of strings. * @param {number=} opt_shortest Length of shortest string. * @return {number} Length of common suffix. */ @@ -180,8 +180,8 @@ Blockly.utils.string.wrapLine_ = function(text, limit) { /** * Compute a score for how good the wrapping is. - * @param {!Array.} words Array of each word. - * @param {!Array.} wordBreaks Array of line breaks. + * @param {!Array} words Array of each word. + * @param {!Array} wordBreaks Array of line breaks. * @param {number} limit Width to wrap each line. * @return {number} Larger the better. * @private @@ -232,10 +232,10 @@ Blockly.utils.string.wrapScore_ = function(words, wordBreaks, limit) { /** * Mutate the array of line break locations until an optimal solution is found. * No line breaks are added or deleted, they are simply moved around. - * @param {!Array.} words Array of each word. - * @param {!Array.} wordBreaks Array of line breaks. + * @param {!Array} words Array of each word. + * @param {!Array} wordBreaks Array of line breaks. * @param {number} limit Width to wrap each line. - * @return {!Array.} New array of optimal line breaks. + * @return {!Array} New array of optimal line breaks. * @private */ Blockly.utils.string.wrapMutate_ = function(words, wordBreaks, limit) { @@ -266,8 +266,8 @@ Blockly.utils.string.wrapMutate_ = function(words, wordBreaks, limit) { /** * Reassemble the array of words into text, with the specified line breaks. - * @param {!Array.} words Array of each word. - * @param {!Array.} wordBreaks Array of line breaks. + * @param {!Array} words Array of each word. + * @param {!Array} wordBreaks Array of line breaks. * @return {string} Plain text. * @private */ diff --git a/core/utils/style.js b/core/utils/style.js index d236e5ab2..1c169453d 100644 --- a/core/utils/style.js +++ b/core/utils/style.js @@ -75,7 +75,7 @@ Blockly.utils.style.getSizeWithDisplay_ = function(element) { * Copied from Closure's goog.style.getStyle_ * * @param {!Element} element Element to get style of. - * @param {string} style Property to get (must be camelCase, not css-style.). + * @param {string} style Property to get (must be camelCase, not CSS-style). * @return {string} Style value. * @private */ diff --git a/core/utils/svg_paths.js b/core/utils/svg_paths.js index d2066599a..e123dca28 100644 --- a/core/utils/svg_paths.js +++ b/core/utils/svg_paths.js @@ -38,7 +38,7 @@ Blockly.utils.svgPaths.point = function(x, y) { * These coordinates are unitless and hence in the user coordinate system. * @param {string} command The command to use. * Should be one of: c, C, s, S, q, Q. - * @param {!Array.} points An array containing all of the points to pass to the + * @param {!Array} points An array containing all of the points to pass to the * curve command, in order. The points are represented as strings of the * format ' x, y '. * @return {string} A string defining one or more Bezier curves. See the MDN @@ -96,7 +96,7 @@ Blockly.utils.svgPaths.lineTo = function(dx, dy) { * equivalent to a series of 'l' commands. * These coordinates are unitless and hence in the user coordinate system. * See developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths#Line_commands - * @param {!Array.} points An array containing all of the points to + * @param {!Array} points An array containing all of the points to * draw lines to, in order. The points are represented as strings of the * format ' dx,dy '. * @return {string} A string of the format ' l (dx,dy)+ ' diff --git a/core/utils/toolbox.js b/core/utils/toolbox.js index adaba33f1..c4a1375bb 100644 --- a/core/utils/toolbox.js +++ b/core/utils/toolbox.js @@ -10,6 +10,10 @@ */ 'use strict'; +/** + * @name Blockly.utils.toolbox + * @namespace + */ goog.provide('Blockly.utils.toolbox'); /** @suppress {extraRequire} */ @@ -209,7 +213,7 @@ Blockly.utils.toolbox.convertToolboxDefToJson = function(toolboxDef) { /** * Validates the toolbox JSON fields have been set correctly. - * @param {Blockly.utils.toolbox.ToolboxInfo} toolboxJson Object holding + * @param {!Blockly.utils.toolbox.ToolboxInfo} toolboxJson Object holding * information for creating a toolbox. * @throws {Error} if the toolbox is not the correct format. * @private @@ -341,7 +345,7 @@ Blockly.utils.toolbox.xmlToJsonArray_ = function(toolboxDef) { var tagName = child.tagName.toUpperCase(); obj['kind'] = tagName; - // Store the xml for a block + // Store the XML for a block. if (tagName == 'BLOCK') { obj['blockxml'] = child; } else if (child.childNodes && child.childNodes.length > 0) { @@ -349,7 +353,7 @@ Blockly.utils.toolbox.xmlToJsonArray_ = function(toolboxDef) { obj['contents'] = Blockly.utils.toolbox.xmlToJsonArray_(child); } - // Add xml attributes to object + // Add XML attributes to object Blockly.utils.toolbox.addAttributes_(child, obj); arr.push(obj); } diff --git a/core/utils/useragent.js b/core/utils/useragent.js index 453fa01d2..0df8467ed 100644 --- a/core/utils/useragent.js +++ b/core/utils/useragent.js @@ -20,6 +20,7 @@ goog.provide('Blockly.utils.userAgent'); goog.require('Blockly.utils.global'); + /** @const {boolean} */ Blockly.utils.userAgent.IE; diff --git a/core/utils/xml.js b/core/utils/xml.js index 4bd3f7dfa..26f7bfc47 100644 --- a/core/utils/xml.js +++ b/core/utils/xml.js @@ -18,6 +18,7 @@ */ goog.provide('Blockly.utils.xml'); + /** * Namespace for Blockly's XML. */ diff --git a/core/variable_map.js b/core/variable_map.js index 9c559b92e..34fa926ec 100644 --- a/core/variable_map.js +++ b/core/variable_map.js @@ -38,7 +38,7 @@ Blockly.VariableMap = function(workspace) { * A map from variable type to list of variable names. The lists contain all * of the named variables in the workspace, including variables * that are not currently in use. - * @type {!Object.>} + * @type {!Object>} * @private */ this.variableMap_ = Object.create(null); @@ -102,7 +102,7 @@ Blockly.VariableMap.prototype.renameVariableById = function(id, newName) { * The new name must not conflict with any existing variable names. * @param {!Blockly.VariableModel} variable Variable to rename. * @param {string} newName New variable name. - * @param {!Array.} blocks The list of all blocks in the + * @param {!Array} blocks The list of all blocks in the * workspace. * @private */ @@ -125,7 +125,7 @@ Blockly.VariableMap.prototype.renameVariableAndUses_ = function(variable, * @param {string} newName New variable name. * @param {!Blockly.VariableModel} conflictVar The variable that was already * using newName. - * @param {!Array.} blocks The list of all blocks in the + * @param {!Array} blocks The list of all blocks in the * workspace. * @private */ @@ -264,7 +264,7 @@ Blockly.VariableMap.prototype.deleteVariableById = function(id) { * Deletes a variable and all of its uses from this workspace without asking the * user for confirmation. * @param {!Blockly.VariableModel} variable Variable to delete. - * @param {!Array.} uses An array of uses of the variable. + * @param {!Array} uses An array of uses of the variable. * @package */ Blockly.VariableMap.prototype.deleteVariableInternal = function(variable, @@ -293,7 +293,7 @@ Blockly.VariableMap.prototype.deleteVariableInternal = function(variable, * @param {string} name The name to check for. * @param {?string=} opt_type The type of the variable. If not provided it * defaults to the empty string, which is a specific type. - * @return {Blockly.VariableModel} The variable with the given name, or null if + * @return {?Blockly.VariableModel} The variable with the given name, or null if * it was not found. */ Blockly.VariableMap.prototype.getVariable = function(name, opt_type) { @@ -310,14 +310,13 @@ Blockly.VariableMap.prototype.getVariable = function(name, opt_type) { }; /** - * Find the variable by the given ID and return it. Return null if it is not - * found. + * Find the variable by the given ID and return it. Return null if not found. * @param {string} id The ID to check for. - * @return {Blockly.VariableModel} The variable with the given ID. + * @return {?Blockly.VariableModel} The variable with the given ID. */ Blockly.VariableMap.prototype.getVariableById = function(id) { var keys = Object.keys(this.variableMap_); - for (var i = 0; i < keys.length; i++ ) { + for (var i = 0; i < keys.length; i++) { var key = keys[i]; for (var j = 0, variable; (variable = this.variableMap_[key][j]); j++) { if (variable.getId() == id) { @@ -332,7 +331,7 @@ Blockly.VariableMap.prototype.getVariableById = function(id) { * Get a list containing all of the variables of a specified type. If type is * null, return list of variables with empty string type. * @param {?string} type Type of the variables to find. - * @return {!Array.} The sought after variables of the + * @return {!Array} The sought after variables of the * passed in type. An empty array if none are found. */ Blockly.VariableMap.prototype.getVariablesOfType = function(type) { @@ -350,7 +349,7 @@ Blockly.VariableMap.prototype.getVariablesOfType = function(type) { * @param {?Blockly.Workspace} ws The workspace used to look for potential * variables. This can be different than the workspace stored on this object * if the passed in ws is a flyout workspace. - * @return {!Array.} List of variable types. + * @return {!Array} List of variable types. * @package */ Blockly.VariableMap.prototype.getVariableTypes = function(ws) { @@ -375,7 +374,7 @@ Blockly.VariableMap.prototype.getVariableTypes = function(ws) { /** * Return all variables of all types. - * @return {!Array.} List of variable models. + * @return {!Array} List of variable models. */ Blockly.VariableMap.prototype.getAllVariables = function() { var all_variables = []; @@ -387,7 +386,7 @@ Blockly.VariableMap.prototype.getAllVariables = function() { /** * Returns all of the variable names of all types. - * @return {!Array.} All of the variable names of all types. + * @return {!Array} All of the variable names of all types. */ Blockly.VariableMap.prototype.getAllVariableNames = function() { var allNames = []; @@ -403,7 +402,7 @@ Blockly.VariableMap.prototype.getAllVariableNames = function() { /** * Find all the uses of a named variable. * @param {string} id ID of the variable to find. - * @return {!Array.} Array of block usages. + * @return {!Array} Array of block usages. */ Blockly.VariableMap.prototype.getVariableUsesById = function(id) { var uses = []; diff --git a/core/variable_model.js b/core/variable_model.js index d1e477a3b..bc097da8a 100644 --- a/core/variable_model.js +++ b/core/variable_model.js @@ -24,8 +24,8 @@ goog.requireType('Blockly.Workspace'); * Class for a variable model. * Holds information for the variable including name, ID, and type. * @param {!Blockly.Workspace} workspace The variable's workspace. - * @param {string} name The name of the variable. This must be unique across - * variables and procedures. + * @param {string} name The name of the variable. This is the user-visible name + * (e.g. 'my var' or '私の変数'), not the generated name. * @param {string=} opt_type The type of the variable like 'int' or 'string'. * Does not need to be unique. Field_variable can filter variables based on * their type. This will default to '' which is a specific type. @@ -42,8 +42,7 @@ Blockly.VariableModel = function(workspace, name, opt_type, opt_id) { this.workspace = workspace; /** - * The name of the variable, typically defined by the user. It must be - * unique across all names used for procedures and variables. It may be + * The name of the variable, typically defined by the user. It may be * changed by the user. * @type {string} */ @@ -59,7 +58,7 @@ Blockly.VariableModel = function(workspace, name, opt_type, opt_id) { this.type = opt_type || ''; /** - * A unique id for the variable. This should be defined at creation and + * A unique ID for the variable. This should be defined at creation and * not change, even if the name changes. In most cases this should be a * UUID. * @type {string} @@ -87,13 +86,5 @@ Blockly.VariableModel.prototype.getId = function() { * @package */ Blockly.VariableModel.compareByName = function(var1, var2) { - var name1 = var1.name.toLowerCase(); - var name2 = var2.name.toLowerCase(); - if (name1 < name2) { - return -1; - } else if (name1 == name2) { - return 0; - } else { - return 1; - } + return var1.name.localeCompare(var2.name, undefined, {sensitivity: 'base'}); }; diff --git a/core/variables.js b/core/variables.js index 5d4cb9a6e..1c091898e 100644 --- a/core/variables.js +++ b/core/variables.js @@ -41,7 +41,7 @@ Blockly.Variables.NAME_TYPE = Blockly.VARIABLE_CATEGORY_NAME; * To get a list of all variables on a workspace, including unused variables, * call Workspace.getAllVariables. * @param {!Blockly.Workspace} ws The workspace to search for variables. - * @return {!Array.} Array of variable models. + * @return {!Array} Array of variable models. */ Blockly.Variables.allUsedVarModels = function(ws) { var blocks = ws.getAllBlocks(false); @@ -81,7 +81,7 @@ Blockly.Variables.ALL_DEVELOPER_VARS_WARNINGS_BY_BLOCK_TYPE_ = {}; * your block and return a list of variable names. * For use by generators. * @param {!Blockly.Workspace} workspace The workspace to search. - * @return {!Array.} A list of non-duplicated variable names. + * @return {!Array} A list of non-duplicated variable names. */ Blockly.Variables.allDeveloperVariables = function(workspace) { var blocks = workspace.getAllBlocks(false); @@ -116,7 +116,7 @@ Blockly.Variables.allDeveloperVariables = function(workspace) { * Construct the elements (blocks and button) required by the flyout for the * variable category. * @param {!Blockly.Workspace} workspace The workspace containing variables. - * @return {!Array.} Array of XML elements. + * @return {!Array} Array of XML elements. */ Blockly.Variables.flyoutCategory = function(workspace) { var xmlList = []; @@ -138,7 +138,7 @@ Blockly.Variables.flyoutCategory = function(workspace) { /** * Construct the blocks required by the flyout for the variable category. * @param {!Blockly.Workspace} workspace The workspace containing variables. - * @return {!Array.} Array of XML block elements. + * @return {!Array} Array of XML block elements. */ Blockly.Variables.flyoutCategoryBlocks = function(workspace) { var variableModelList = workspace.getVariablesOfType(''); @@ -207,7 +207,7 @@ Blockly.Variables.generateUniqueName = function(workspace) { * will try to generate single letter names in the range a -> z (skip l). It * will start with the character passed to startChar. * @param {string} startChar The character to start the search at. - * @param {!Array.} usedNames A list of all of the used names. + * @param {!Array} usedNames A list of all of the used names. * @return {string} A unique name that is not present in the usedNames array. */ Blockly.Variables.generateUniqueNameFromOptions = function(startChar, usedNames) { @@ -322,13 +322,12 @@ Blockly.Variables.createVariable = * collision. * @param {!Blockly.Workspace} workspace The workspace on which to rename the * variable. - * @param {Blockly.VariableModel} variable Variable to rename. + * @param {!Blockly.VariableModel} variable Variable to rename. * @param {function(?string=)=} opt_callback A callback. It will * be passed an acceptable new variable name, or null if change is to be * aborted (cancel button), or undefined if an existing variable was chosen. */ -Blockly.Variables.renameVariable = function(workspace, variable, - opt_callback) { +Blockly.Variables.renameVariable = function(workspace, variable, opt_callback) { // This function needs to be named so it can be called recursively. var promptAndCheckWithAlert = function(defaultName) { var promptText = @@ -393,7 +392,7 @@ Blockly.Variables.promptName = function(promptText, defaultText, callback) { * @param {string} type The type to exclude from the search. * @param {!Blockly.Workspace} workspace The workspace to search for the * variable. - * @return {Blockly.VariableModel} The variable with the given name and a + * @return {?Blockly.VariableModel} The variable with the given name and a * different type, or null if none was found. * @private */ @@ -414,7 +413,7 @@ Blockly.Variables.nameUsedWithOtherType_ = function(name, type, workspace) { * @param {string} name The name to search for. * @param {!Blockly.Workspace} workspace The workspace to search for the * variable. - * @return {Blockly.VariableModel} The variable with the given name, + * @return {?Blockly.VariableModel} The variable with the given name, * or null if none was found. */ Blockly.Variables.nameUsedWithAnyType = function(name, workspace) { @@ -433,7 +432,7 @@ Blockly.Variables.nameUsedWithAnyType = function(name, workspace) { * Generate DOM objects representing a variable field. * @param {!Blockly.VariableModel} variableModel The variable model to * represent. - * @return {Element} The generated DOM. + * @return {?Element} The generated DOM. * @public */ Blockly.Variables.generateVariableFieldDom = function(variableModel) { @@ -483,7 +482,7 @@ Blockly.Variables.getOrCreateVariablePackage = function(workspace, id, opt_name, * Only used if lookup by ID fails. * @param {string=} opt_type The type to use to look up the variable. * Only used if lookup by ID fails. - * @return {Blockly.VariableModel} The variable corresponding to the given ID + * @return {?Blockly.VariableModel} The variable corresponding to the given ID * or name + type combination, or null if not found. * @public */ @@ -551,9 +550,9 @@ Blockly.Variables.createVariable_ = function(workspace, id, opt_name, * workspace after adding a new block, using the given list of variables that * were in the workspace before the new block was added. * @param {!Blockly.Workspace} workspace The workspace to inspect. - * @param {!Array.} originalVariables The array of + * @param {!Array} originalVariables The array of * variables that existed in the workspace before adding the new block. - * @return {!Array.} The new array of variables that + * @return {!Array} The new array of variables that * were freshly added to the workspace after creating the new block, * or [] if no new variables were added to the workspace. * @package diff --git a/core/variables_dynamic.js b/core/variables_dynamic.js index f761e5273..630064eeb 100644 --- a/core/variables_dynamic.js +++ b/core/variables_dynamic.js @@ -38,7 +38,7 @@ Blockly.VariablesDynamic.onCreateVariableButtonClick_Colour = function(button) { * Construct the elements (blocks and button) required by the flyout for the * variable category. * @param {!Blockly.Workspace} workspace The workspace containing variables. - * @return {!Array.} Array of XML elements. + * @return {!Array} Array of XML elements. */ Blockly.VariablesDynamic.flyoutCategory = function(workspace) { var xmlList = []; @@ -71,7 +71,7 @@ Blockly.VariablesDynamic.flyoutCategory = function(workspace) { /** * Construct the blocks required by the flyout for the variable category. * @param {!Blockly.Workspace} workspace The workspace containing variables. - * @return {!Array.} Array of XML block elements. + * @return {!Array} Array of XML block elements. */ Blockly.VariablesDynamic.flyoutCategoryBlocks = function(workspace) { var variableModelList = workspace.getAllVariables(); diff --git a/core/warning.js b/core/warning.js index e60ceccda..9bbd9c91b 100644 --- a/core/warning.js +++ b/core/warning.js @@ -36,7 +36,7 @@ Blockly.Warning = function(block) { Blockly.Warning.superClass_.constructor.call(this, block); this.createIcon(); // The text_ object can contain multiple warnings. - this.text_ = {}; + this.text_ = Object.create(null); }; Blockly.utils.object.inherits(Blockly.Warning, Blockly.Icon); diff --git a/core/widgetdiv.js b/core/widgetdiv.js index 608048aa9..316e78b61 100644 --- a/core/widgetdiv.js +++ b/core/widgetdiv.js @@ -190,8 +190,8 @@ Blockly.WidgetDiv.positionWithAnchor = function(viewportBBox, anchorBBox, * current viewport, in window coordinates. * @param {!Blockly.utils.Rect} anchorBBox The bounding rectangle of the anchor, * in window coordinates. - * @param {Blockly.utils.Size} widgetSize The dimensions of the widget inside the - * widget div. + * @param {!Blockly.utils.Size} widgetSize The dimensions of the widget inside + * the widget div. * @param {boolean} rtl Whether the Blockly workspace is in RTL mode. * @return {number} A valid x-coordinate for the top left corner of the widget * div, in window coordinates. @@ -222,8 +222,8 @@ Blockly.WidgetDiv.calculateX_ = function(viewportBBox, anchorBBox, widgetSize, * current viewport, in window coordinates. * @param {!Blockly.utils.Rect} anchorBBox The bounding rectangle of the anchor, * in window coordinates. - * @param {Blockly.utils.Size} widgetSize The dimensions of the widget inside the - * widget div. + * @param {!Blockly.utils.Size} widgetSize The dimensions of the widget inside + * the widget div. * @return {number} A valid y-coordinate for the top left corner of the widget * div, in window coordinates. * @private diff --git a/core/workspace.js b/core/workspace.js index 820c966dc..9a1dd8cbb 100644 --- a/core/workspace.js +++ b/core/workspace.js @@ -15,6 +15,7 @@ goog.provide('Blockly.Workspace'); /** @suppress {extraRequire} */ goog.require('Blockly.ConnectionChecker'); goog.require('Blockly.Events'); +goog.require('Blockly.IASTNodeLocation'); goog.require('Blockly.Options'); goog.require('Blockly.registry'); goog.require('Blockly.utils'); @@ -24,7 +25,6 @@ goog.require('Blockly.VariableMap'); goog.requireType('Blockly.Block'); goog.requireType('Blockly.ConnectionDB'); goog.requireType('Blockly.Events.Abstract'); -goog.requireType('Blockly.IASTNodeLocation'); goog.requireType('Blockly.IConnectionChecker'); goog.requireType('Blockly.utils.toolbox'); goog.requireType('Blockly.VariableModel'); @@ -60,12 +60,12 @@ Blockly.Workspace = function(opt_options) { this.connectionChecker = new connectionCheckerClass(this); /** - * @type {!Array.} + * @type {!Array} * @private */ this.topBlocks_ = []; /** - * @type {!Array.} + * @type {!Array} * @private */ this.topComments_ = []; @@ -75,17 +75,17 @@ Blockly.Workspace = function(opt_options) { */ this.commentDB_ = Object.create(null); /** - * @type {!Array.} + * @type {!Array} * @private */ this.listeners_ = []; /** - * @type {!Array.} + * @type {!Array} * @protected */ this.undoStack_ = []; /** - * @type {!Array.} + * @type {!Array} * @protected */ this.redoStack_ = []; @@ -116,7 +116,7 @@ Blockly.Workspace = function(opt_options) { * A FieldVariable must always refer to a Blockly.VariableModel. We reconcile * these by tracking "potential" variables in the flyout. These variables * become real when references to them are dragged into the main workspace. - * @type {Blockly.VariableMap} + * @type {?Blockly.VariableMap} * @private */ this.potentialVariableMap_ = null; @@ -144,7 +144,7 @@ Blockly.Workspace.prototype.MAX_UNDO = 1024; /** * Set of databases for rapid lookup of connection locations. - * @type {Array.} + * @type {Array} */ Blockly.Workspace.prototype.connectionDBList = null; @@ -208,7 +208,7 @@ Blockly.Workspace.prototype.removeTopBlock = function(block) { * Finds the top-level blocks and returns them. Blocks are optionally sorted * by position; top to bottom (with slight LTR or RTL bias). * @param {boolean} ordered Sort the list if true. - * @return {!Array.} The top-level block objects. + * @return {!Array} The top-level block objects. */ Blockly.Workspace.prototype.getTopBlocks = function(ordered) { // Copy the topBlocks_ list. @@ -252,7 +252,7 @@ Blockly.Workspace.prototype.removeTypedBlock = function(block) { * optionally sorted by position; top to bottom (with slight LTR or RTL bias). * @param {string} type The type of block to search for. * @param {boolean} ordered Sort the list if true. - * @return {!Array.} The blocks of the given type. + * @return {!Array} The blocks of the given type. */ Blockly.Workspace.prototype.getBlocksByType = function(type, ordered) { if (!this.typedBlocksDB_[type]) { @@ -306,7 +306,7 @@ Blockly.Workspace.prototype.removeTopComment = function(comment) { * Finds the top-level comments and returns them. Comments are optionally * sorted by position; top to bottom (with slight LTR or RTL bias). * @param {boolean} ordered Sort the list if true. - * @return {!Array.} The top-level comment objects. + * @return {!Array} The top-level comment objects. * @package */ Blockly.Workspace.prototype.getTopComments = function(ordered) { @@ -327,7 +327,7 @@ Blockly.Workspace.prototype.getTopComments = function(ordered) { * Find all blocks in workspace. Blocks are optionally sorted * by position; top to bottom (with slight LTR or RTL bias). * @param {boolean} ordered Sort the list if true. - * @return {!Array.} Array of blocks. + * @return {!Array} Array of blocks. */ Blockly.Workspace.prototype.getAllBlocks = function(ordered) { if (ordered) { @@ -411,7 +411,7 @@ Blockly.Workspace.prototype.createVariable = function(name, opt_type, opt_id) { /** * Find all the uses of the given variable, which is identified by ID. * @param {string} id ID of the variable to find. - * @return {!Array.} Array of block usages. + * @return {!Array} Array of block usages. */ Blockly.Workspace.prototype.getVariableUsesById = function(id) { return this.variableMap_.getVariableUsesById(id); @@ -427,12 +427,11 @@ Blockly.Workspace.prototype.deleteVariableById = function(id) { }; /** - * Find the variable by the given name and return it. Return null if it is not - * found. + * Find the variable by the given name and return it. Return null if not found. * @param {string} name The name to check for. * @param {string=} opt_type The type of the variable. If not provided it * defaults to the empty string, which is a specific type. - * @return {Blockly.VariableModel} The variable with the given name. + * @return {?Blockly.VariableModel} The variable with the given name. */ // TODO (#1559): Possibly delete this function after resolving #1559. Blockly.Workspace.prototype.getVariable = function(name, opt_type) { @@ -440,10 +439,9 @@ Blockly.Workspace.prototype.getVariable = function(name, opt_type) { }; /** - * Find the variable by the given ID and return it. Return null if it is not - * found. + * Find the variable by the given ID and return it. Return null if not found. * @param {string} id The ID to check for. - * @return {Blockly.VariableModel} The variable with the given ID. + * @return {?Blockly.VariableModel} The variable with the given ID. */ Blockly.Workspace.prototype.getVariableById = function(id) { return this.variableMap_.getVariableById(id); @@ -453,7 +451,7 @@ Blockly.Workspace.prototype.getVariableById = function(id) { * Find the variable with the specified type. If type is null, return list of * variables with empty string type. * @param {?string} type Type of the variables to find. - * @return {!Array.} The sought after variables of the + * @return {!Array} The sought after variables of the * passed in type. An empty array if none are found. */ Blockly.Workspace.prototype.getVariablesOfType = function(type) { @@ -462,7 +460,7 @@ Blockly.Workspace.prototype.getVariablesOfType = function(type) { /** * Return all variable types. - * @return {!Array.} List of variable types. + * @return {!Array} List of variable types. * @package */ Blockly.Workspace.prototype.getVariableTypes = function() { @@ -471,7 +469,7 @@ Blockly.Workspace.prototype.getVariableTypes = function() { /** * Return all variables of all types. - * @return {!Array.} List of variable models. + * @return {!Array} List of variable models. */ Blockly.Workspace.prototype.getAllVariables = function() { return this.variableMap_.getAllVariables(); @@ -479,7 +477,7 @@ Blockly.Workspace.prototype.getAllVariables = function() { /** * Returns all variable names of all types. - * @return {!Array.} List of all variable names of all types. + * @return {!Array} List of all variable names of all types. */ Blockly.Workspace.prototype.getAllVariableNames = function() { return this.variableMap_.getAllVariableNames(); @@ -577,7 +575,7 @@ Blockly.Workspace.prototype.hasBlockLimits = function() { /** * Gets the undo stack for workplace. - * @return {!Array.} undo stack + * @return {!Array} undo stack * @package */ Blockly.Workspace.prototype.getUndoStack = function() { @@ -586,7 +584,7 @@ Blockly.Workspace.prototype.getUndoStack = function() { /** * Gets the redo stack for workplace. - * @return {!Array.} redo stack + * @return {!Array} redo stack * @package */ Blockly.Workspace.prototype.getRedoStack = function() { @@ -650,7 +648,7 @@ Blockly.Workspace.prototype.addChangeListener = function(func) { /** * Stop listening for this workspace's changes. - * @param {Function} func Function to stop calling. + * @param {!Function} func Function to stop calling. */ Blockly.Workspace.prototype.removeChangeListener = function(func) { Blockly.utils.arrayRemove(this.listeners_, func); @@ -676,7 +674,7 @@ Blockly.Workspace.prototype.fireChangeListener = function(event) { /** * Find the block on this workspace with the specified ID. * @param {string} id ID of block to find. - * @return {Blockly.Block} The sought after block, or null if not found. + * @return {?Blockly.Block} The sought after block, or null if not found. */ Blockly.Workspace.prototype.getBlockById = function(id) { return this.blockDB_[id] || null; @@ -704,7 +702,7 @@ Blockly.Workspace.prototype.removeBlockById = function(id) { /** * Find the comment on this workspace with the specified ID. * @param {string} id ID of comment to find. - * @return {Blockly.WorkspaceComment} The sought after comment, or null if not + * @return {?Blockly.WorkspaceComment} The sought after comment, or null if not * found. * @package */ @@ -733,7 +731,7 @@ Blockly.Workspace.prototype.allInputsFilled = function( /** * Return the variable map that contains "potential" variables. * These exist in the flyout but not in the workspace. - * @return {Blockly.VariableMap} The potential variable map. + * @return {?Blockly.VariableMap} The potential variable map. * @package */ Blockly.Workspace.prototype.getPotentialVariableMap = function() { @@ -765,6 +763,7 @@ Blockly.Workspace.prototype.setVariableMap = function(variableMap) { this.variableMap_ = variableMap; }; + /** * Database of all workspaces. * @private @@ -774,7 +773,7 @@ Blockly.Workspace.WorkspaceDB_ = Object.create(null); /** * Find the workspace with the specified ID. * @param {string} id ID of workspace to find. - * @return {Blockly.Workspace} The sought after workspace or null if not found. + * @return {?Blockly.Workspace} The sought after workspace or null if not found. */ Blockly.Workspace.getById = function(id) { return Blockly.Workspace.WorkspaceDB_[id] || null; @@ -782,7 +781,7 @@ Blockly.Workspace.getById = function(id) { /** * Find all workspaces. - * @return {!Array.} Array of workspaces. + * @return {!Array} Array of workspaces. */ Blockly.Workspace.getAll = function() { var workspaces = []; diff --git a/core/workspace_audio.js b/core/workspace_audio.js index 81fcfda73..954b8f892 100644 --- a/core/workspace_audio.js +++ b/core/workspace_audio.js @@ -63,7 +63,7 @@ Blockly.WorkspaceAudio.prototype.dispose = function() { /** * Load an audio file. Cache it, ready for instantaneous playing. - * @param {!Array.} filenames List of file types in decreasing order of + * @param {!Array} filenames List of file types in decreasing order of * preference (i.e. increasing size). E.g. ['media/go.mp3', 'media/go.wav'] * Filenames include path from Blockly's root. File extensions matter. * @param {string} name Name of sound. diff --git a/core/workspace_svg.js b/core/workspace_svg.js index 14a508e31..941ece363 100644 --- a/core/workspace_svg.js +++ b/core/workspace_svg.js @@ -29,13 +29,14 @@ goog.require('Blockly.Events.ThemeChange'); goog.require('Blockly.Events.ViewportChange'); goog.require('Blockly.Gesture'); goog.require('Blockly.Grid'); +goog.require('Blockly.IASTNodeLocationSvg'); goog.require('Blockly.MarkerManager'); /** @suppress {extraRequire} */ goog.require('Blockly.MetricsManager'); /** @suppress {extraRequire} */ goog.require('Blockly.Msg'); goog.require('Blockly.Options'); -goog.require('Blockly.PluginManager'); +goog.require('Blockly.ComponentManager'); goog.require('Blockly.registry'); goog.require('Blockly.ThemeManager'); goog.require('Blockly.Themes.Classic'); @@ -59,8 +60,8 @@ goog.requireType('Blockly.BlockDragSurfaceSvg'); goog.requireType('Blockly.blockRendering.Renderer'); goog.requireType('Blockly.Cursor'); goog.requireType('Blockly.FlyoutButton'); -goog.requireType('Blockly.IASTNodeLocationSvg'); goog.requireType('Blockly.IBoundedElement'); +goog.requireType('Blockly.IDragTarget'); goog.requireType('Blockly.IFlyout'); goog.requireType('Blockly.IMetricsManager'); goog.requireType('Blockly.IToolbox'); @@ -114,10 +115,10 @@ Blockly.WorkspaceSvg = function( options.setMetrics || Blockly.WorkspaceSvg.setTopLevelWorkspaceMetrics_; /** - * @type {!Blockly.PluginManager} + * @type {!Blockly.ComponentManager} * @private */ - this.pluginManager_ = new Blockly.PluginManager(); + this.componentManager_ = new Blockly.ComponentManager(); this.connectionDBList = Blockly.ConnectionDB.init(this.connectionChecker); @@ -135,7 +136,7 @@ Blockly.WorkspaceSvg = function( /** * List of currently highlighted blocks. Block highlighting is often used to * visually mark blocks currently being executed. - * @type {!Array.} + * @type {!Array} * @private */ this.highlightedBlocks_ = []; @@ -166,18 +167,18 @@ Blockly.WorkspaceSvg = function( /** * Map from function names to callbacks, for deciding what to do when a custom * toolbox category is opened. - * @type {!Object.>} + * @type {!Object>} * @private */ - this.toolboxCategoryCallbacks_ = {}; + this.toolboxCategoryCallbacks_ = Object.create(null); /** * Map from function names to callbacks, for deciding what to do when a button * is clicked. - * @type {!Object.} + * @type {!Object} * @private */ - this.flyoutButtonCallbacks_ = {}; + this.flyoutButtonCallbacks_ = Object.create(null); if (Blockly.Variables && Blockly.Variables.flyoutCategory) { this.registerToolboxCategoryCallback(Blockly.VARIABLE_CATEGORY_NAME, @@ -227,11 +228,22 @@ Blockly.WorkspaceSvg = function( /** * The list of top-level bounded elements on the workspace. - * @type {!Array.} + * @type {!Array} * @private */ this.topBoundedElements_ = []; + /** + * The recorded drag targets. + * @type {!Array< + * { + * component: !Blockly.IDragTarget, + * clientRect: !Blockly.utils.Rect, + * }>} + * @private + */ + this.dragTargetAreas_ = []; + /** * The cached size of the parent svg element. * Used to compute svg metrics. @@ -487,7 +499,7 @@ Blockly.WorkspaceSvg.prototype.lastRecordedPageScroll_ = null; /** * Developers may define this function to add custom menu options to the * workspace's context menu or edit the workspace-created set of menu options. - * @param {!Array.} options List of menu options to add to. + * @param {!Array} options List of menu options to add to. * @param {!Event} e The right-click event that triggered the context menu. */ Blockly.WorkspaceSvg.prototype.configureContextMenu; @@ -502,7 +514,7 @@ Blockly.WorkspaceSvg.prototype.targetWorkspace = null; /** * Inverted screen CTM, for use in mouseToSvg. - * @type {SVGMatrix} + * @type {?SVGMatrix} * @private */ Blockly.WorkspaceSvg.prototype.inverseScreenCTM_ = null; @@ -516,7 +528,7 @@ Blockly.WorkspaceSvg.prototype.inverseScreenCTMDirty_ = true; /** * Get the marker manager for this workspace. - * @return {Blockly.MarkerManager} The marker manager. + * @return {!Blockly.MarkerManager} The marker manager. */ Blockly.WorkspaceSvg.prototype.getMarkerManager = function() { return this.markerManager_; @@ -541,19 +553,19 @@ Blockly.WorkspaceSvg.prototype.setMetricsManager = function(metricsManager) { this.getMetrics = this.metricsManager_.getMetrics.bind(this.metricsManager_); }; -/* - * Gets the plugin manager for this workspace. - * @return {!Blockly.PluginManager} The plugin manager. +/** + * Gets the component manager for this workspace. + * @return {!Blockly.ComponentManager} The component manager. * @public */ -Blockly.WorkspaceSvg.prototype.getPluginManager = function() { - return this.pluginManager_; +Blockly.WorkspaceSvg.prototype.getComponentManager = function() { + return this.componentManager_; }; /** - * Add the cursor svg to this workspaces svg group. - * @param {SVGElement} cursorSvg The svg root of the cursor to be added to the - * workspace svg group. + * Add the cursor SVG to this workspaces SVG group. + * @param {SVGElement} cursorSvg The SVG root of the cursor to be added to the + * workspace SVG group. * @package */ Blockly.WorkspaceSvg.prototype.setCursorSvg = function(cursorSvg) { @@ -561,9 +573,9 @@ Blockly.WorkspaceSvg.prototype.setCursorSvg = function(cursorSvg) { }; /** - * Add the marker svg to this workspaces svg group. - * @param {SVGElement} markerSvg The svg root of the marker to be added to the - * workspace svg group. + * Add the marker SVG to this workspaces SVG group. + * @param {SVGElement} markerSvg The SVG root of the marker to be added to the + * workspace SVG group. * @package */ Blockly.WorkspaceSvg.prototype.setMarkerSvg = function(markerSvg) { @@ -571,10 +583,10 @@ Blockly.WorkspaceSvg.prototype.setMarkerSvg = function(markerSvg) { }; /** - * Get the marker with the given id. - * @param {string} id The id of the marker. - * @return {Blockly.Marker} The marker with the given id or null if no marker - * with the given id exists. + * Get the marker with the given ID. + * @param {string} id The ID of the marker. + * @return {?Blockly.Marker} The marker with the given ID or null if no marker + * with the given ID exists. * @package */ Blockly.WorkspaceSvg.prototype.getMarker = function(id) { @@ -586,7 +598,7 @@ Blockly.WorkspaceSvg.prototype.getMarker = function(id) { /** * The cursor for this workspace. - * @return {Blockly.Cursor} The cursor for the workspace. + * @return {?Blockly.Cursor} The cursor for the workspace. */ Blockly.WorkspaceSvg.prototype.getCursor = function() { if (this.markerManager_) { @@ -597,7 +609,8 @@ Blockly.WorkspaceSvg.prototype.getCursor = function() { /** * Get the block renderer attached to this workspace. - * @return {!Blockly.blockRendering.Renderer} The renderer attached to this workspace. + * @return {!Blockly.blockRendering.Renderer} The renderer attached to this + * workspace. */ Blockly.WorkspaceSvg.prototype.getRenderer = function() { return this.renderer_; @@ -644,7 +657,7 @@ Blockly.WorkspaceSvg.prototype.refreshTheme = function() { // Update all blocks in workspace that have a style name. this.updateBlockStyles_(this.getAllBlocks(false).filter( function(block) { - return block.getStyleName() !== undefined; + return !!block.getStyleName(); } )); @@ -666,7 +679,7 @@ Blockly.WorkspaceSvg.prototype.refreshTheme = function() { /** * Updates all the blocks with new style. - * @param {!Array.} blocks List of blocks to update the style + * @param {!Array} blocks List of blocks to update the style * on. * @private */ @@ -684,7 +697,7 @@ Blockly.WorkspaceSvg.prototype.updateBlockStyles_ = function(blocks) { /** * Getter for the inverted screen CTM. - * @return {SVGMatrix} The matrix to use in mouseToSvg + * @return {?SVGMatrix} The matrix to use in mouseToSvg */ Blockly.WorkspaceSvg.prototype.getInverseScreenCTM = function() { // Defer getting the screen CTM until we actually need it, this should @@ -749,9 +762,9 @@ Blockly.WorkspaceSvg.prototype.getSvgXY = function(element) { }; /** - * Gets the size of the workspace's parent svg element. + * Gets the size of the workspace's parent SVG element. * @return {!Blockly.utils.Size} The cached width and height of the workspace's - * parent svg element. + * parent SVG element. * @package */ Blockly.WorkspaceSvg.prototype.getCachedParentSvgSize = function() { @@ -797,8 +810,8 @@ Blockly.WorkspaceSvg.prototype.getInjectionDiv = function() { }; /** - * Get the svg block canvas for the workspace. - * @return {SVGElement} The svg group for the workspace. + * Get the SVG block canvas for the workspace. + * @return {?SVGElement} The SVG group for the workspace. * @package */ Blockly.WorkspaceSvg.prototype.getBlockCanvas = function() { @@ -878,7 +891,7 @@ Blockly.WorkspaceSvg.prototype.createDom = function(opt_backgroundClass) { if (this.grid_) { this.grid_.update(this.scale); } - this.recordDeleteAreas(); + this.recordDragTargets(); var CursorClass = Blockly.registry.getClassFromOptions( Blockly.registry.Type.CURSOR, this.options); @@ -977,7 +990,7 @@ Blockly.WorkspaceSvg.prototype.dispose = function() { /** * Obtain a newly created block. * - * This block's svg must still be initialized + * This block's SVG must still be initialized * ([initSvg]{@link Blockly.BlockSvg#initSvg}) and it must be rendered * ([render]{@link Blockly.BlockSvg#render}) before the block will be visible. * @param {!string} prototypeName Name of the language object containing @@ -1003,12 +1016,6 @@ Blockly.WorkspaceSvg.prototype.addTrashcan = function() { this.trashcan = new Blockly.Trashcan(this); var svgTrashcan = this.trashcan.createDom(); this.svgGroup_.insertBefore(svgTrashcan, this.svgBlockCanvas_); - this.pluginManager_.addPlugin({ - id: 'trashcan', - plugin: this.trashcan, - weight: 1, - types: [Blockly.PluginManager.Type.POSITIONABLE] - }); }; /** @@ -1023,12 +1030,6 @@ Blockly.WorkspaceSvg.prototype.addZoomControls = function() { this.zoomControls_ = new Blockly.ZoomControls(this); var svgZoomControls = this.zoomControls_.createDom(); this.svgGroup_.appendChild(svgZoomControls); - this.pluginManager_.addPlugin({ - id: 'zoomControls', - plugin: this.zoomControls_, - weight: 2, - types: [Blockly.PluginManager.Type.POSITIONABLE] - }); }; /** @@ -1078,7 +1079,7 @@ Blockly.WorkspaceSvg.prototype.addFlyout = function(tagName) { * owned by either the toolbox or the workspace, depending on toolbox * configuration. It will be null if there is no flyout. * @param {boolean=} opt_own Whether to only return the workspace's own flyout. - * @return {Blockly.IFlyout} The flyout on this workspace. + * @return {?Blockly.IFlyout} The flyout on this workspace. * @package */ Blockly.WorkspaceSvg.prototype.getFlyout = function(opt_own) { @@ -1093,7 +1094,7 @@ Blockly.WorkspaceSvg.prototype.getFlyout = function(opt_own) { /** * Getter for the toolbox associated with this workspace, if one exists. - * @return {Blockly.IToolbox} The toolbox on this workspace. + * @return {?Blockly.IToolbox} The toolbox on this workspace. * @package */ Blockly.WorkspaceSvg.prototype.getToolbox = function() { @@ -1107,7 +1108,7 @@ Blockly.WorkspaceSvg.prototype.getToolbox = function() { */ Blockly.WorkspaceSvg.prototype.updateScreenCalculations_ = function() { this.updateInverseScreenCTM(); - this.recordDeleteAreas(); + this.recordDragTargets(); }; /** @@ -1141,8 +1142,8 @@ Blockly.WorkspaceSvg.prototype.resize = function() { this.flyout_.position(); } - var positionables = this.pluginManager_.getPlugins( - Blockly.PluginManager.Type.POSITIONABLE, true); + var positionables = this.componentManager_.getComponents( + Blockly.ComponentManager.Capability.POSITIONABLE, true); var metrics = this.getMetricsManager().getUiMetrics(); var savedPositions = []; for (var i = 0, positionable; (positionable = positionables[i]); i++) { @@ -1181,10 +1182,10 @@ Blockly.WorkspaceSvg.prototype.getCanvas = function() { }; /** - * Caches the width and height of the workspace's parent svg element for use + * Caches the width and height of the workspace's parent SVG element for use * with getSvgMetrics. - * @param {?number} width The width of the parent svg element. - * @param {?number} height The height of the parent svg element + * @param {?number} width The width of the parent SVG element. + * @param {?number} height The height of the parent SVG element * @package */ Blockly.WorkspaceSvg.prototype.setCachedParentSvgSize = function(width, height) { @@ -1343,7 +1344,7 @@ Blockly.WorkspaceSvg.prototype.setupDragSurface = function() { /** * Gets the drag surface blocks are moved to when a drag is started. - * @return {Blockly.BlockDragSurfaceSvg} This workspace's block drag surface, + * @return {?Blockly.BlockDragSurfaceSvg} This workspace's block drag surface, * if one is in use. * @package */ @@ -1629,38 +1630,50 @@ Blockly.WorkspaceSvg.prototype.createVariable = function(name, /** * Make a list of all the delete areas for this workspace. + * @deprecated Use workspace.recordDragTargets. (2021 June) */ Blockly.WorkspaceSvg.prototype.recordDeleteAreas = function() { - if (this.trashcan && this.svgGroup_.parentNode) { - this.deleteAreaTrash_ = this.trashcan.getClientRect(); - } else { - this.deleteAreaTrash_ = null; - } - if (this.flyout_) { - this.deleteAreaToolbox_ = this.flyout_.getClientRect(); - } else if (this.toolbox_ && typeof this.toolbox_.getClientRect == 'function') { - this.deleteAreaToolbox_ = this.toolbox_.getClientRect(); - } else { - this.deleteAreaToolbox_ = null; - } + Blockly.utils.deprecation.warn( + 'WorkspaceSvg.prototype.recordDeleteAreas', + 'June 2021', + 'June 2022', + 'WorkspaceSvg.prototype.recordDragTargets'); + this.recordDragTargets(); }; /** - * Is the mouse event over a delete area (toolbox or non-closing flyout)? - * @param {!Event} e Mouse move event. - * @return {?number} Null if not over a delete area, or an enum representing - * which delete area the event is over. + * Make a list of all the delete areas for this workspace. */ -Blockly.WorkspaceSvg.prototype.isDeleteArea = function(e) { - if (this.deleteAreaTrash_ && - this.deleteAreaTrash_.contains(e.clientX, e.clientY)) { - return Blockly.DELETE_AREA_TRASH; +Blockly.WorkspaceSvg.prototype.recordDragTargets = function() { + var dragTargets = this.componentManager_.getComponents( + Blockly.ComponentManager.Capability.DRAG_TARGET, true); + + this.dragTargetAreas_ = []; + for (var i = 0, targetArea; (targetArea = dragTargets[i]); i++) { + var rect = targetArea.getClientRect(); + if (rect) { + this.dragTargetAreas_.push({ + component: targetArea, + clientRect: rect, + }); + } } - if (this.deleteAreaToolbox_ && - this.deleteAreaToolbox_.contains(e.clientX, e.clientY)) { - return Blockly.DELETE_AREA_TOOLBOX; +}; + + +/** + * Returns the drag target the mouse event is over. + * @param {!Event} e Mouse move event. + * @return {?Blockly.IDragTarget} Null if not over a drag target, or the drag + * target the event is over. + */ +Blockly.WorkspaceSvg.prototype.getDragTarget = function(e) { + for (var i = 0, targetArea; (targetArea = this.dragTargetAreas_[i]); i++) { + if (targetArea.clientRect.contains(e.clientX, e.clientY)) { + return targetArea.component; + } } - return Blockly.DELETE_AREA_NONE; + return null; }; /** @@ -1799,7 +1812,7 @@ Blockly.WorkspaceSvg.prototype.onMouseWheel_ = function(e) { // This is needed as for some browser/system combinations which do not // set deltaX. x = this.scrollX - scrollDelta.y; - y = this.scrollY; // Don't scroll vertically + y = this.scrollY; // Don't scroll vertically. } this.scroll(x, y); } @@ -2212,7 +2225,7 @@ Blockly.WorkspaceSvg.prototype.setScale = function(newScale) { if (this.flyout_) { // No toolbox, resize flyout. this.flyout_.reflow(); - this.recordDeleteAreas(); + this.recordDragTargets(); } if (this.grid_) { this.grid_.update(this.scale); @@ -2225,8 +2238,8 @@ Blockly.WorkspaceSvg.prototype.setScale = function(newScale) { this.scrollX -= metrics.absoluteLeft; this.scrollY -= metrics.absoluteTop; - // // The scroll values and the view values are additive inverses of - // // each other, so when we subtract from one we have to add to the other. + // The scroll values and the view values are additive inverses of + // each other, so when we subtract from one we have to add to the other. metrics.viewLeft += metrics.absoluteLeft; metrics.viewTop += metrics.absoluteTop; @@ -2262,7 +2275,7 @@ Blockly.WorkspaceSvg.prototype.getScale = function() { * @package */ Blockly.WorkspaceSvg.prototype.scroll = function(x, y) { - Blockly.hideChaff(/* opt_allowToolbox */ true); + Blockly.hideChaff(/* opt_onlyClosePopups */ true); // Keep scrolling within the bounds of the content. var metrics = this.getMetrics(); @@ -2327,7 +2340,7 @@ Blockly.WorkspaceSvg.setTopLevelWorkspaceMetrics_ = function(xyRatio) { /** * Find the block on this workspace with the specified ID. * @param {string} id ID of block to find. - * @return {Blockly.BlockSvg} The sought after block, or null if not found. + * @return {?Blockly.BlockSvg} The sought after block, or null if not found. * @override */ Blockly.WorkspaceSvg.prototype.getBlockById = function(id) { @@ -2339,7 +2352,7 @@ Blockly.WorkspaceSvg.prototype.getBlockById = function(id) { * Finds the top-level blocks and returns them. Blocks are optionally sorted * by position; top to bottom (with slight LTR or RTL bias). * @param {boolean} ordered Sort the list if true. - * @return {!Array.} The top-level block objects. + * @return {!Array} The top-level block objects. * @override */ Blockly.WorkspaceSvg.prototype.getTopBlocks = function(ordered) { @@ -2402,7 +2415,7 @@ Blockly.WorkspaceSvg.prototype.removeTopBoundedElement = function(element) { /** * Finds the top-level bounded elements and returns them. - * @return {!Array.} The top-level bounded elements. + * @return {!Array} The top-level bounded elements. */ Blockly.WorkspaceSvg.prototype.getTopBoundedElements = function() { return [].concat(this.topBoundedElements_); @@ -2477,7 +2490,7 @@ Blockly.WorkspaceSvg.prototype.removeButtonCallback = function(key) { * custom toolbox categories in this workspace. See the variable and procedure * categories as an example. * @param {string} key The name to use to look up this function. - * @param {function(!Blockly.Workspace):!Array.} func The function to + * @param {function(!Blockly.Workspace):!Array} func The function to * call when the given toolbox category is opened. */ Blockly.WorkspaceSvg.prototype.registerToolboxCategoryCallback = function(key, @@ -2492,7 +2505,7 @@ Blockly.WorkspaceSvg.prototype.registerToolboxCategoryCallback = function(key, * Get the callback function associated with a given key, for populating * custom toolbox categories in this workspace. * @param {string} key The name to use to look up the function. - * @return {?function(!Blockly.Workspace):!Array.} The function + * @return {?function(!Blockly.Workspace):!Array} The function * corresponding to the given key for this workspace, or null if no function * is registered. */ @@ -2512,7 +2525,7 @@ Blockly.WorkspaceSvg.prototype.removeToolboxCategoryCallback = function(key) { * Look up the gesture that is tracking this touch stream on this workspace. * May create a new gesture. * @param {!Event} e Mouse event or touch event. - * @return {Blockly.TouchGesture} The gesture that is tracking this touch + * @return {?Blockly.TouchGesture} The gesture that is tracking this touch * stream, or null if no valid gesture exists. * @package */ @@ -2570,7 +2583,7 @@ Blockly.WorkspaceSvg.prototype.getAudioManager = function() { /** * Get the grid object for this workspace, or null if there is none. - * @return {Blockly.Grid} The grid object for this workspace. + * @return {?Blockly.Grid} The grid object for this workspace. * @package */ Blockly.WorkspaceSvg.prototype.getGrid = function() { diff --git a/core/xml.js b/core/xml.js index e8c6940cf..4140d6528 100644 --- a/core/xml.js +++ b/core/xml.js @@ -59,7 +59,7 @@ Blockly.Xml.workspaceToDom = function(workspace, opt_noId) { /** * Encode a list of variables as XML. - * @param {!Array.} variableList List of all variable + * @param {!Array} variableList List of all variable * models. * @return {!Element} Tree of XML elements. */ @@ -109,7 +109,7 @@ Blockly.Xml.blockToDomWithXY = function(block, opt_noId) { /** * Encode a field as XML. * @param {!Blockly.Field} field The field to encode. - * @return {Element} XML element, or null if the field did not need to be + * @return {?Element} XML element, or null if the field did not need to be * serialized. * @private */ @@ -166,7 +166,7 @@ Blockly.Xml.blockToDom = function(block, opt_noId) { element.setAttribute('type', block.type); if (!opt_noId) { // It's important to use setAttribute here otherwise IE11 won't serialize - // the block's id when domToText is called. + // the block's ID when domToText is called. element.setAttribute('id', block.id); } if (block.mutationToDom) { @@ -375,7 +375,7 @@ Blockly.Xml.textToDom = function(text) { * create blocks on the workspace. * @param {!Element} xml XML DOM. * @param {!Blockly.Workspace} workspace The workspace. - * @return {Array.} An array containing new block ids. + * @return {!Array} An array containing new block IDs. */ Blockly.Xml.clearWorkspaceAndLoadFromXml = function(xml, workspace) { workspace.setResizesEnabled(false); @@ -389,7 +389,7 @@ Blockly.Xml.clearWorkspaceAndLoadFromXml = function(xml, workspace) { * Decode an XML DOM and create blocks on the workspace. * @param {!Element} xml XML DOM. * @param {!Blockly.Workspace} workspace The workspace. - * @return {!Array.} An array containing new block IDs. + * @return {!Array} An array containing new block IDs. * @suppress {strictModuleDepCheck} Suppress module check while workspace * comments are not bundled in. */ @@ -489,7 +489,7 @@ Blockly.Xml.domToWorkspace = function(xml, workspace) { * blocks immediately below prior blocks, aligned by their starting edge. * @param {!Element} xml The XML DOM. * @param {!Blockly.Workspace} workspace The workspace to add to. - * @return {Array.} An array containing new block IDs. + * @return {!Array} An array containing new block IDs. */ Blockly.Xml.appendDomToWorkspace = function(xml, workspace) { var bbox; // Bounding box of the current blocks. @@ -637,10 +637,10 @@ Blockly.Xml.domToVariables = function(xmlVariables, workspace) { Blockly.Xml.childNodeTagMap; /** - * Creates a mapping of childNodes for each supported xml tag for the provided + * Creates a mapping of childNodes for each supported XML tag for the provided * xmlBlock. Logs a warning for any encountered unsupported tags. * @param {!Element} xmlBlock XML block element. - * @return {Blockly.Xml.childNodeTagMap} The childNode map from nodeName to + * @return {!Blockly.Xml.childNodeTagMap} The childNode map from nodeName to * node. */ Blockly.Xml.mapSupportedXmlTags_ = function(xmlBlock) { @@ -691,7 +691,7 @@ Blockly.Xml.mapSupportedXmlTags_ = function(xmlBlock) { /** * Applies mutation tag child nodes to the given block. - * @param {Array} xmlChildren Child nodes. + * @param {!Array} xmlChildren Child nodes. * @param {!Blockly.Block} block The block to apply the child nodes on. * @return {boolean} True if mutation may have added some elements that need * initialization (requiring initSvg call). @@ -714,7 +714,7 @@ Blockly.Xml.applyMutationTagNodes_ = function(xmlChildren, block) { /** * Applies comment tag child nodes to the given block. - * @param {Array} xmlChildren Child nodes. + * @param {!Array} xmlChildren Child nodes. * @param {!Blockly.Block} block The block to apply the child nodes on. * @private */ @@ -741,7 +741,7 @@ Blockly.Xml.applyCommentTagNodes_ = function(xmlChildren, block) { /** * Applies data tag child nodes to the given block. - * @param {Array} xmlChildren Child nodes. + * @param {!Array} xmlChildren Child nodes. * @param {!Blockly.Block} block The block to apply the child nodes on. * @private */ @@ -753,7 +753,7 @@ Blockly.Xml.applyDataTagNodes_ = function(xmlChildren, block) { /** * Applies field tag child nodes to the given block. - * @param {Array} xmlChildren Child nodes. + * @param {!Array} xmlChildren Child nodes. * @param {!Blockly.Block} block The block to apply the child nodes on. * @private */ @@ -765,8 +765,8 @@ Blockly.Xml.applyFieldTagNodes_ = function(xmlChildren, block) { }; /** - * Finds any enclosed blocks or shadows within this xml node. - * @param {!Element} xmlNode The xml node to extract child block info from. + * Finds any enclosed blocks or shadows within this XML node. + * @param {!Element} xmlNode The XML node to extract child block info from. * @return {{childBlockElement: ?Element, childShadowElement: ?Element}} Any * found child block. * @private @@ -787,7 +787,7 @@ Blockly.Xml.findChildBlocks_ = function(xmlNode) { /** * Applies input child nodes (value or statement) to the given block. - * @param {Array} xmlChildren Child nodes. + * @param {!Array} xmlChildren Child nodes. * @param {!Blockly.Workspace} workspace The workspace containing the given * block. * @param {!Blockly.Block} block The block to apply the child nodes on. @@ -821,7 +821,7 @@ Blockly.Xml.applyInputTagNodes_ = function(xmlChildren, workspace, block, /** * Applies next child nodes to the given block. - * @param {Array} xmlChildren Child nodes. + * @param {!Array} xmlChildren Child nodes. * @param {!Blockly.Workspace} workspace The workspace containing the given * block. * @param {!Blockly.Block} block The block to apply the child nodes on. diff --git a/core/zoom_controls.js b/core/zoom_controls.js index f089c9e6d..530a24142 100644 --- a/core/zoom_controls.js +++ b/core/zoom_controls.js @@ -19,13 +19,12 @@ goog.require('Blockly.Css'); goog.require('Blockly.Events'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.Click'); -goog.require('Blockly.Scrollbar'); +goog.require('Blockly.IPositionable'); goog.require('Blockly.Touch'); +goog.require('Blockly.uiPosition'); goog.require('Blockly.utils.dom'); goog.require('Blockly.utils.Rect'); goog.require('Blockly.utils.Svg'); -goog.require('Blockly.utils.toolbox'); -goog.require('Blockly.IPositionable'); goog.requireType('Blockly.WorkspaceSvg'); @@ -67,14 +66,6 @@ Blockly.ZoomControls = function(workspace) { */ this.onZoomOutWrapper_ = null; - /** - * The starting vertical distance between the workspace edge and the control. - * The value is initialized during `init`. - * @type {?number} - * @private - */ - this.verticalSpacing_ = null; - /** * The zoom in svg element. * @type {SVGGElement} @@ -100,30 +91,49 @@ Blockly.ZoomControls = function(workspace) { /** * Width of the zoom controls. * @type {number} + * @const * @private */ Blockly.ZoomControls.prototype.WIDTH_ = 32; /** - * Height of the zoom controls. + * Height of each zoom control. * @type {number} + * @const * @private */ -Blockly.ZoomControls.prototype.HEIGHT_ = 110; +Blockly.ZoomControls.prototype.HEIGHT_ = 32; /** - * Distance between zoom controls and bottom edge of workspace. + * Small spacing used between the zoom in and out control, in pixels. * @type {number} + * @const * @private */ -Blockly.ZoomControls.prototype.MARGIN_BOTTOM_ = 20; +Blockly.ZoomControls.prototype.SMALL_SPACING_ = 2; /** - * Distance between zoom controls and right edge of workspace. + * Large spacing used between the zoom in and reset control, in pixels. + * @type {number} + * @const + * @private + */ +Blockly.ZoomControls.prototype.LARGE_SPACING_ = 11; + +/** + * Distance between zoom controls and bottom or top edge of workspace. + * @type {number} + * @const + * @private + */ +Blockly.ZoomControls.prototype.MARGIN_VERTICAL_ = 20; + +/** + * Distance between zoom controls and right or left edge of workspace. * @type {number} * @private */ -Blockly.ZoomControls.prototype.MARGIN_SIDE_ = 20; +Blockly.ZoomControls.prototype.MARGIN_HORIZONTAL_ = 20; /** * The SVG group containing the zoom controls. @@ -146,6 +156,12 @@ Blockly.ZoomControls.prototype.left_ = 0; */ Blockly.ZoomControls.prototype.top_ = 0; +/** + * Whether this has been initialized. + * @type {boolean} + * @private + */ +Blockly.ZoomControls.prototype.initialized_ = false; /** * Create the zoom controls. @@ -170,19 +186,20 @@ Blockly.ZoomControls.prototype.createDom = function() { }; /** - * Initialize the zoom controls. - * @param {number} verticalSpacing Vertical distances from workspace edge to the - * same edge of the controls. - * @return {number} Vertical distance from workspace edge to the opposite - * edge of the controls. + * Initializes the zoom controls. */ -Blockly.ZoomControls.prototype.init = function(verticalSpacing) { - this.verticalSpacing_ = this.MARGIN_BOTTOM_ + verticalSpacing; - return this.verticalSpacing_ + this.HEIGHT_; +Blockly.ZoomControls.prototype.init = function() { + this.workspace_.getComponentManager().addComponent({ + id: 'zoomControls', + component: this, + weight: 2, + capabilities: [Blockly.ComponentManager.Capability.POSITIONABLE] + }); + this.initialized_ = true; }; /** - * Dispose of this zoom controls. + * Disposes of this zoom controls. * Unlink from all DOM elements to prevent memory leaks. */ Blockly.ZoomControls.prototype.dispose = function() { @@ -203,10 +220,14 @@ Blockly.ZoomControls.prototype.dispose = function() { /** * Returns the bounding rectangle of the UI element in pixel units relative to * the Blockly injection div. - * @return {!Blockly.utils.Rect} The plugin’s bounding box. + * @return {!Blockly.utils.Rect} The UI elements’s bounding box. */ Blockly.ZoomControls.prototype.getBoundingRectangle = function() { - var bottom = this.top_ + this.HEIGHT_; + var height = this.SMALL_SPACING_ + 2 * this.HEIGHT_; + if (this.zoomResetGroup_) { + height += this.LARGE_SPACING_ + this.HEIGHT_; + } + var bottom = this.top_ + height; var right = this.left_ + this.WIDTH_; return new Blockly.utils.Rect(this.top_, bottom, this.left_, right); }; @@ -222,55 +243,52 @@ Blockly.ZoomControls.prototype.getBoundingRectangle = function() { */ Blockly.ZoomControls.prototype.position = function(metrics, savedPositions) { // Not yet initialized. - if (!this.verticalSpacing_) { + if (!this.initialized_) { return; } - if (metrics.toolboxMetrics.position == Blockly.utils.toolbox.Position.LEFT || - (this.workspace_.horizontalLayout && !this.workspace_.RTL)) { - // Right corner placement. - this.left_ = metrics.viewMetrics.width + metrics.absoluteMetrics.left - - this.WIDTH_ - this.MARGIN_SIDE_ - Blockly.Scrollbar.scrollbarThickness; - } else { - // Left corner placement. - this.left_ = this.MARGIN_SIDE_ + Blockly.Scrollbar.scrollbarThickness; - } - // Upper corner placement - var minTop = this.top_ = metrics.absoluteMetrics.top + this.verticalSpacing_; - // Bottom corner placement - var maxTop = metrics.absoluteMetrics.top + metrics.viewMetrics.height - - this.HEIGHT_ - this.verticalSpacing_; - var placeBottom = - metrics.toolboxMetrics.position !== Blockly.utils.toolbox.Position.BOTTOM; - this.top_ = placeBottom ? maxTop : minTop; - if (placeBottom) { - this.zoomInGroup_.setAttribute('transform', 'translate(0, 43)'); - this.zoomOutGroup_.setAttribute('transform', 'translate(0, 77)'); - } else { - this.zoomInGroup_.setAttribute('transform', 'translate(0, 34)'); + var cornerPosition = + Blockly.uiPosition.getCornerOppositeToolbox(this.workspace_, metrics); + var height = this.SMALL_SPACING_ + 2 * this.HEIGHT_; + if (this.zoomResetGroup_) { + height += this.LARGE_SPACING_ + this.HEIGHT_; + } + var startRect = Blockly.uiPosition.getStartPositionRect( + cornerPosition, new Blockly.utils.Size(this.WIDTH_, height), + this.MARGIN_HORIZONTAL_, this.MARGIN_VERTICAL_, metrics, + this.workspace_); + + var verticalPosition = cornerPosition.vertical; + var bumpDirection = + verticalPosition === Blockly.uiPosition.verticalPosition.TOP ? + Blockly.uiPosition.bumpDirection.DOWN : + Blockly.uiPosition.bumpDirection.UP; + var positionRect = Blockly.uiPosition.bumpPositionRect( + startRect, this.MARGIN_VERTICAL_, bumpDirection, savedPositions); + + if (verticalPosition === Blockly.uiPosition.verticalPosition.TOP) { + var zoomInTranslateY = this.SMALL_SPACING_ + this.HEIGHT_; + this.zoomInGroup_.setAttribute('transform', + 'translate(0, ' + zoomInTranslateY + ')'); if (this.zoomResetGroup_) { - this.zoomResetGroup_.setAttribute('transform', 'translate(0, 77)'); + var zoomResetTranslateY = + zoomInTranslateY + this.LARGE_SPACING_ + this.HEIGHT_; + this.zoomResetGroup_.setAttribute('transform', + 'translate(0, ' + zoomResetTranslateY + ')'); } + } else { + var zoomInTranslateY = this.zoomResetGroup_ ? + this.LARGE_SPACING_ + this.HEIGHT_ : 0; + this.zoomInGroup_.setAttribute('transform', + 'translate(0, ' + zoomInTranslateY + ')'); + var zoomOutTranslateY = + zoomInTranslateY + this.SMALL_SPACING_ + this.HEIGHT_; + this.zoomOutGroup_.setAttribute('transform', + 'translate(0, ' + zoomOutTranslateY + ')'); } - // Check for collision and bump if needed. - var boundingRect = this.getBoundingRectangle(); - for (var i = 0, otherEl; (otherEl = savedPositions[i]); i++) { - if (boundingRect.intersects(otherEl)) { - if (placeBottom) { - // Bump up - this.top_ = otherEl.top - this.HEIGHT_ - this.MARGIN_BOTTOM_; - } else { - this.top_ = otherEl.bottom + this.MARGIN_BOTTOM_; - } - // Recheck other savedPositions - boundingRect = this.getBoundingRectangle(); - i = -1; - } - } - // Clamp top value within valid range. - this.top_ = Blockly.utils.math.clamp(minTop, this.top_, maxTop); - + this.top_ = positionRect.top; + this.left_ = positionRect.left; this.svgGroup_.setAttribute('transform', 'translate(' + this.left_ + ',' + this.top_ + ')'); }; @@ -474,7 +492,7 @@ Blockly.ZoomControls.prototype.resetZoom_ = function(e) { }; /** - * Fires a zoom control ui event. + * Fires a zoom control UI event. * @private */ Blockly.ZoomControls.prototype.fireZoomEvent_ = function() { diff --git a/demos/blockfactory/app_controller.js b/demos/blockfactory/app_controller.js index 60fb0bb1e..58b70b88d 100644 --- a/demos/blockfactory/app_controller.js +++ b/demos/blockfactory/app_controller.js @@ -432,7 +432,7 @@ AppController.prototype.assignExporterChangeListeners = function() { /** * If given checkbox is checked, enable the given elements. Otherwise, disable. * @param {boolean} enabled True if enabled, false otherwise. - * @param {!Array.} idArray Array of element IDs to enable when + * @param {!Array} idArray Array of element IDs to enable when * checkbox is checked. */ AppController.prototype.ifCheckedEnable = function(enabled, idArray) { diff --git a/demos/blockfactory/block_definition_extractor.js b/demos/blockfactory/block_definition_extractor.js index 10d9d0f7b..0a9687f4b 100644 --- a/demos/blockfactory/block_definition_extractor.js +++ b/demos/blockfactory/block_definition_extractor.js @@ -49,7 +49,7 @@ BlockDefinitionExtractor.buildBlockFactoryWorkspace = function(block) { * inner text. * * @param {string} name New element tag name. - * @param {!Object.=} opt_attrs Optional list of attributes. + * @param {!Object=} opt_attrs Optional list of attributes. * @param {string=} opt_text Optional inner text. * @return {!Element} The newly created element. * @private @@ -112,7 +112,7 @@ BlockDefinitionExtractor.buildTypeConstraintBlockForConnection_ = } else if (connection.check_.length === 1) { typeBlock = BlockDefinitionExtractor.buildBlockForType_( connection.check_[0]); - } else if (connection.check_.length > 1 ) { + } else if (connection.check_.length > 1) { typeBlock = BlockDefinitionExtractor.typeGroup_(connection.check_); } } else { @@ -323,7 +323,7 @@ BlockDefinitionExtractor.input_ = function(input, align) { /** * Constructs a sequence elements representing the field definition. - * @param {Array.} fieldRow A list of fields in a Blockly.Input. + * @param {Array} fieldRow A list of fields in a Blockly.Input. * @return {Element} The fist element of the sequence * (and the root of the constructed DOM). * @private @@ -600,7 +600,7 @@ BlockDefinitionExtractor.buildFieldImage_ = /** * Creates a element a group of allowed connection constraint types. * - * @param {Array.} types List of type names in this group. + * @param {Array} types List of type names in this group. * @return {Element} The element representing the group, with child * types attached. * @private @@ -707,7 +707,7 @@ BlockDefinitionExtractor.typeOther_ = function(type) { }; /** - * Creates a block Element for the color_hue block, with the given hue. + * Creates a block Element for the colour_hue block, with the given hue. * @param hue {number} The hue value, from 0 to 360. * @return {Element} The Element representing a colour_hue block * with the given hue. diff --git a/demos/blockfactory/block_exporter_controller.js b/demos/blockfactory/block_exporter_controller.js index 525a2fefc..b195bf374 100644 --- a/demos/blockfactory/block_exporter_controller.js +++ b/demos/blockfactory/block_exporter_controller.js @@ -253,7 +253,7 @@ BlockExporterController.prototype.selectUsedBlocks = function() { /** * Set the array that holds the block types used in workspace factory. - * @param {!Array.} usedBlockTypes Block types used in + * @param {!Array} usedBlockTypes Block types used in */ BlockExporterController.prototype.setUsedBlockTypes = function(usedBlockTypes) { diff --git a/demos/blockfactory/block_exporter_tools.js b/demos/blockfactory/block_exporter_tools.js index 3446312df..1af4ace60 100644 --- a/demos/blockfactory/block_exporter_tools.js +++ b/demos/blockfactory/block_exporter_tools.js @@ -170,7 +170,7 @@ BlockExporterTools.prototype.generateCategoryFromBlockLib = }; /** - * Generate selector dom from block library storage. For each block in the + * Generate selector DOM from block library storage. For each block in the * library, it has a block option, which consists of a checkbox, a label, * and a fixed size preview workspace. * @param {!BlockLibraryStorage} blockLibStorage Block Library Storage object. diff --git a/demos/blockfactory/block_exporter_view.js b/demos/blockfactory/block_exporter_view.js index f505438a7..50d4262bc 100644 --- a/demos/blockfactory/block_exporter_view.js +++ b/demos/blockfactory/block_exporter_view.js @@ -70,7 +70,7 @@ BlockExporterView.prototype.deselectAllBlocks = function() { /** * Given an array of selected blocks, selects these blocks in the view, marking * the checkboxes accordingly. - * @param {Array.} blockTypes Array of block types to select. + * @param {Array} blockTypes Array of block types to select. */ BlockExporterView.prototype.setSelectedBlockTypes = function(blockTypes) { for (var i = 0, blockType; blockType = blockTypes[i]; i++) { @@ -80,7 +80,7 @@ BlockExporterView.prototype.setSelectedBlockTypes = function(blockTypes) { /** * Returns array of selected blocks. - * @return {!Array.} Array of all selected block types. + * @return {!Array} Array of all selected block types. */ BlockExporterView.prototype.getSelectedBlockTypes = function() { var selectedTypes = []; diff --git a/demos/blockfactory/block_library_controller.js b/demos/blockfactory/block_library_controller.js index 25156e9ce..c4ab6ac68 100644 --- a/demos/blockfactory/block_library_controller.js +++ b/demos/blockfactory/block_library_controller.js @@ -212,7 +212,7 @@ BlockLibraryController.prototype.hasEmptyBlockLibrary = function() { /** * Get all block types stored in block library. - * @return {!Array.} Array of block types. + * @return {!Array} Array of block types. */ BlockLibraryController.prototype.getStoredBlockTypes = function() { return this.storage.getBlockTypes(); diff --git a/demos/blockfactory/block_library_storage.js b/demos/blockfactory/block_library_storage.js index b0df067fa..38a822cb2 100644 --- a/demos/blockfactory/block_library_storage.js +++ b/demos/blockfactory/block_library_storage.js @@ -100,7 +100,7 @@ BlockLibraryStorage.prototype.getBlockXml = function(blockType) { /** * Returns map of each block type to its corresponding XML stored in current * block library (this.blocks). - * @param {!Array.} blockTypes Types of blocks. + * @param {!Array} blockTypes Types of blocks. * @return {!Object} Map of block type to corresponding XML. */ BlockLibraryStorage.prototype.getBlockXmlMap = function(blockTypes) { @@ -115,7 +115,7 @@ BlockLibraryStorage.prototype.getBlockXmlMap = function(blockTypes) { /** * Returns array of all block types stored in current block library. - * @return {!Array.} Array of block types stored in library. + * @return {!Array} Array of block types stored in library. */ BlockLibraryStorage.prototype.getBlockTypes = function() { return Object.keys(this.blocks); @@ -134,7 +134,7 @@ BlockLibraryStorage.prototype.isEmpty = function() { /** * Returns array of all block types stored in current block library. - * @return {!Array.} Map of block type to corresponding XML text. + * @return {!Array} Map of block type to corresponding XML text. */ BlockLibraryStorage.prototype.getBlockXmlTextMap = function() { return this.blocks; diff --git a/demos/blockfactory/block_option.js b/demos/blockfactory/block_option.js index a67b81f9e..d72326220 100644 --- a/demos/blockfactory/block_option.js +++ b/demos/blockfactory/block_option.js @@ -46,9 +46,9 @@ var BlockOption = function(blockSelector, blockType, previewBlockXml) { }; /** - * Creates the dom for a single block option. Includes checkbox, label, and div + * Creates the DOM for a single block option. Includes checkbox, label, and div * in which to inject the preview block. - * @return {!Element} Root node of the selector dom which consists of a + * @return {!Element} Root node of the selector DOM which consists of a * checkbox, a label, and a fixed size preview workspace per block. */ BlockOption.prototype.createDom = function() { diff --git a/demos/blockfactory/factory.css b/demos/blockfactory/factory.css index c0bd9b2b9..73a1c1e3c 100644 --- a/demos/blockfactory/factory.css +++ b/demos/blockfactory/factory.css @@ -526,12 +526,12 @@ td.taboff:hover { text-decoration: none; } -/* Change color of dropdown links on hover. */ +/* Change colour of dropdown links on hover. */ .dropdown-content a:hover, .dropdown-content label:hover { background-color: #EEE; } -/* Change color of dropdown links on selected. */ +/* Change colour of dropdown links on selected. */ .dropdown-content-selected { background-color: #DDD; } diff --git a/demos/blockfactory/factory_utils.js b/demos/blockfactory/factory_utils.js index 9044257dd..93ca8ba97 100644 --- a/demos/blockfactory/factory_utils.js +++ b/demos/blockfactory/factory_utils.js @@ -97,7 +97,7 @@ FactoryUtils.getGeneratorStub = function(block, generatorLanguage) { // Subclass of Blockly.FieldDropdown, must test first. code.push(makeVar('variable', name) + " = Blockly." + language + - ".variableDB_.getName(block.getFieldValue('" + name + + ".nameDB_.getName(block.getFieldValue('" + name + "'), Blockly.Variables.NAME_TYPE);"); } else if (field instanceof Blockly.FieldAngle) { // Subclass of Blockly.FieldTextInput, must test first. @@ -377,7 +377,7 @@ FactoryUtils.connectionLineJs_ = function(functionName, typeName, workspace) { /** * Returns field strings and any config. * @param {!Blockly.Block} block Input block. - * @return {!Array.} Field strings. + * @return {!Array} Field strings. * @private */ FactoryUtils.getFieldsJs_ = function(block) { @@ -484,7 +484,7 @@ FactoryUtils.getFieldsJs_ = function(block) { /** * Returns field strings and any config. * @param {!Blockly.Block} block Input block. - * @return {!Array.} Array of static text and field configs. + * @return {!Array} Array of static text and field configs. * @private */ FactoryUtils.getFieldsJson_ = function(block) { @@ -614,7 +614,7 @@ FactoryUtils.getOptTypesFrom = function(block, name) { * Fetch the type(s) defined in the given input. * @param {!Blockly.Block} block Block with input. * @param {string} name Name of the input. - * @return {!Array.} List of types. + * @return {!Array} List of types. * @private */ FactoryUtils.getTypesFrom_ = function(block, name) { @@ -745,7 +745,7 @@ FactoryUtils.getBlockTypeFromJsDefinition = function(blockDef) { /** * Generates a category containing blocks of the specified block types. - * @param {!Array.} blocks Blocks to include in the category. + * @param {!Array} blocks Blocks to include in the category. * @param {string} categoryName Name to use for the generated category. * @return {!Element} Category XML containing the given block types. */ @@ -771,7 +771,7 @@ FactoryUtils.generateCategoryXml = function(blocks, categoryName) { * Parses a string containing JavaScript block definition(s) to create an array * in which each element is a single block definition. * @param {string} blockDefsString JavaScript block definition(s). - * @return {!Array.} Array of block definitions. + * @return {!Array} Array of block definitions. */ FactoryUtils.parseJsBlockDefinitions = function(blockDefsString) { var blockDefArray = []; @@ -797,7 +797,7 @@ FactoryUtils.parseJsBlockDefinitions = function(blockDefsString) { * JSON objects. * @param {string} blockDefsString String containing JSON block * definition(s). - * @return {!Array.} Array of block definitions. + * @return {!Array} Array of block definitions. */ FactoryUtils.parseJsonBlockDefinitions = function(blockDefsString) { var blockDefArray = []; @@ -827,7 +827,7 @@ FactoryUtils.parseJsonBlockDefinitions = function(blockDefsString) { * Define blocks from imported block definitions. * @param {string} blockDefsString Block definition(s). * @param {string} format Block definition format ('JSON' or 'JavaScript'). - * @return {!Array.} Array of block types defined. + * @return {!Array} Array of block types defined. */ FactoryUtils.defineAndGetBlockTypes = function(blockDefsString, format) { var blockTypes = []; diff --git a/demos/blockfactory/workspacefactory/wfactory_controller.js b/demos/blockfactory/workspacefactory/wfactory_controller.js index f71d984e0..02f9c8cda 100644 --- a/demos/blockfactory/workspacefactory/wfactory_controller.js +++ b/demos/blockfactory/workspacefactory/wfactory_controller.js @@ -490,8 +490,8 @@ WorkspaceFactoryController.prototype.changeSelectedCategory = function(name, return; } // Change colour of selected category. - selected.changeColor(colour); - this.view.setBorderColor(this.model.getSelectedId(), colour); + selected.changeColour(colour); + this.view.setBorderColour(this.model.getSelectedId(), colour); // Change category name. selected.changeName(name); this.view.updateCategoryName(name, this.model.getSelectedId()); @@ -588,9 +588,9 @@ WorkspaceFactoryController.prototype.loadCategoryByName = function(name) { + '. Rename your category and try again.'); return; } - if (!standardCategory.color && standardCategory.hue !== undefined) { + if (!standardCategory.colour && standardCategory.hue !== undefined) { // Calculate the hex colour based on the hue. - standardCategory.color = Blockly.hueToHex(standardCategory.hue); + standardCategory.colour = Blockly.hueToHex(standardCategory.hue); } // Transfers current flyout blocks to a category if it's the first category // created. @@ -607,8 +607,8 @@ WorkspaceFactoryController.prototype.loadCategoryByName = function(name) { var tab = this.view.addCategoryRow(copy.name, copy.id); this.addClickToSwitch(tab, copy.id); // Color the category tab in the view. - if (copy.color) { - this.view.setBorderColor(copy.id, copy.color); + if (copy.colour) { + this.view.setBorderColour(copy.id, copy.colour); } // Switch to loaded category. this.switchElement(copy.id); @@ -805,10 +805,10 @@ WorkspaceFactoryController.prototype.importToolboxFromTree_ = function(tree) { // Convert actual shadow blocks to user-generated shadow blocks. this.convertShadowBlocks(); - // Set category color. + // Set category colour. if (item.getAttribute('colour')) { - category.changeColor(item.getAttribute('colour')); - this.view.setBorderColor(category.id, category.color); + category.changeColour(item.getAttribute('colour')); + this.view.setBorderColour(category.id, category.colour); } // Set any custom tags. if (item.getAttribute('custom')) { @@ -887,7 +887,6 @@ WorkspaceFactoryController.prototype.clearAll = function() { if (!confirm(msg)) { return; } - var hasCategories = this.model.hasElements(); this.model.clearToolboxList(); this.view.clearToolboxTabs(); this.model.savePreloadXml(Blockly.utils.xml.createElement('xml')); @@ -1209,9 +1208,9 @@ WorkspaceFactoryController.prototype.importBlocks = function(file, format) { // If an imported block type is already defined, check if the user wants // to override the current block definition. if (controller.model.hasDefinedBlockTypes(blockTypes)) { - var msg = 'An imported block uses the same name as a block ' - + 'already in your toolbox. Are you sure you want to override the ' - + 'currently defined block?'; + var msg = 'An imported block uses the same name as a block ' + + 'already in your toolbox. Are you sure you want to override the ' + + 'currently defined block?'; var continueAnyway = confirm(msg); BlocklyDevTools.Analytics.onWarning(msg); if (!continueAnyway) { @@ -1222,8 +1221,8 @@ WorkspaceFactoryController.prototype.importBlocks = function(file, format) { var blocks = controller.generator.getDefinedBlocks(blockTypes); // Generate category XML and append to toolbox. var categoryXml = FactoryUtils.generateCategoryXml(blocks, categoryName); - // Get random color for category between 0 and 360. Gives each imported - // category a different color. + // Get random colour for category between 0 and 360. Gives each imported + // category a different colour. var randomColor = Math.floor(Math.random() * 360); categoryXml.setAttribute('colour', randomColor); controller.toolbox.appendChild(categoryXml); @@ -1251,7 +1250,7 @@ WorkspaceFactoryController.prototype.importBlocks = function(file, format) { /** * Updates the block library category in the toolbox workspace toolbox. * @param {!Element} categoryXml XML for the block library category. - * @param {!Array.} libBlockTypes Array of block types from the block + * @param {!Array} libBlockTypes Array of block types from the block * library. */ WorkspaceFactoryController.prototype.setBlockLibCategory = @@ -1259,7 +1258,7 @@ WorkspaceFactoryController.prototype.setBlockLibCategory = var blockLibCategory = document.getElementById('blockLibCategory'); // Set category ID so that it can be easily replaced, and set a standard, - // arbitrary block library color. + // arbitrary block library colour. categoryXml.id = 'blockLibCategory'; categoryXml.setAttribute('colour', 260); @@ -1278,7 +1277,7 @@ WorkspaceFactoryController.prototype.setBlockLibCategory = /** * Return the block types used in the custom toolbox and pre-loaded workspace. - * @return {!Array.} Block types used in the custom toolbox and + * @return {!Array} Block types used in the custom toolbox and * pre-loaded workspace. */ WorkspaceFactoryController.prototype.getAllUsedBlockTypes = function() { diff --git a/demos/blockfactory/workspacefactory/wfactory_generator.js b/demos/blockfactory/workspacefactory/wfactory_generator.js index 8f1f2756c..0e583657c 100644 --- a/demos/blockfactory/workspacefactory/wfactory_generator.js +++ b/demos/blockfactory/workspacefactory/wfactory_generator.js @@ -77,8 +77,8 @@ WorkspaceFactoryGenerator.prototype.generateToolboxXml = function() { var nextElement = Blockly.utils.xml.createElement('category'); nextElement.setAttribute('name', element.name); // Add a colour attribute if one exists. - if (element.color != null) { - nextElement.setAttribute('colour', element.color); + if (element.colour != null) { + nextElement.setAttribute('colour', element.colour); } // Add a custom attribute if one exists. if (element.custom != null) { @@ -212,8 +212,8 @@ WorkspaceFactoryGenerator.prototype.setShadowBlocksInHiddenWorkspace_ = /** * Given a set of block types, gets the Blockly.Block objects for each block * type. - * @param {!Array.} blockTypes Array of blocks that have been defined. - * @return {!Array.} Array of Blockly.Block objects corresponding + * @param {!Array} blockTypes Array of blocks that have been defined. + * @return {!Array} Array of Blockly.Block objects corresponding * to the array of blockTypes. */ WorkspaceFactoryGenerator.prototype.getDefinedBlocks = function(blockTypes) { diff --git a/demos/blockfactory/workspacefactory/wfactory_init.js b/demos/blockfactory/workspacefactory/wfactory_init.js index f7e80e8f8..cc1839a00 100644 --- a/demos/blockfactory/workspacefactory/wfactory_init.js +++ b/demos/blockfactory/workspacefactory/wfactory_init.js @@ -239,8 +239,8 @@ WorkspaceFactoryInit.assignWorkspaceFactoryClickHandlers_ = return; } document.getElementById('categoryName').value = selected.name; - document.getElementById('categoryColour').value = selected.color ? - selected.color.substring(1).toLowerCase() : ''; + document.getElementById('categoryColour').value = selected.colour ? + selected.colour.substring(1).toLowerCase() : ''; console.log(document.getElementById('categoryColour').value); // Link the colour picker to the field. cp_init('categoryColour'); diff --git a/demos/blockfactory/workspacefactory/wfactory_model.js b/demos/blockfactory/workspacefactory/wfactory_model.js index f5048bc43..c97e8d091 100644 --- a/demos/blockfactory/workspacefactory/wfactory_model.js +++ b/demos/blockfactory/workspacefactory/wfactory_model.js @@ -7,7 +7,7 @@ /** * @fileoverview Stores and updates information about state and categories * in workspace factory. Each list element is either a separator or a category, - * and each category stores its name, XML to load that category, color, + * and each category stores its name, XML to load that category, colour, * custom tags, and a unique ID making it possible to change category names and * move categories easily. Keeps track of the currently selected list * element. Also keeps track of all the user-created shadow blocks and @@ -246,7 +246,7 @@ WorkspaceFactoryModel.prototype.getSelectedXml = function() { /** * Return ordered list of ListElement objects. - * @return {!Array.} ordered list of ListElement objects + * @return {!Array} ordered list of ListElement objects */ WorkspaceFactoryModel.prototype.getToolboxList = function() { return this.toolboxList; @@ -360,7 +360,7 @@ WorkspaceFactoryModel.prototype.addCustomTag = function(category, tag) { * @param {!Element} xml The XML to be saved. */ WorkspaceFactoryModel.prototype.savePreloadXml = function(xml) { - this.preloadXml = xml + this.preloadXml = xml; }; /** @@ -383,7 +383,7 @@ WorkspaceFactoryModel.prototype.setOptions = function(options) { * Returns an array of all the block types currently being used in the toolbox * and the pre-loaded blocks. No duplicates. * TODO(evd2014): Move pushBlockTypesToList to FactoryUtils. - * @return {!Array.} Array of block types currently being used. + * @return {!Array} Array of block types currently being used. */ WorkspaceFactoryModel.prototype.getAllUsedBlockTypes = function() { var blockTypeList = []; @@ -424,7 +424,7 @@ WorkspaceFactoryModel.prototype.getAllUsedBlockTypes = function() { /** * Adds new imported block types to the list of current imported block types. - * @param {!Array.} blockTypes Array of block types imported. + * @param {!Array} blockTypes Array of block types imported. */ WorkspaceFactoryModel.prototype.addImportedBlockTypes = function(blockTypes) { this.importedBlockTypes = this.importedBlockTypes.concat(blockTypes); @@ -432,7 +432,7 @@ WorkspaceFactoryModel.prototype.addImportedBlockTypes = function(blockTypes) { /** * Updates block types in block library. - * @param {!Array.} blockTypes Array of block types in block library. + * @param {!Array} blockTypes Array of block types in block library. */ WorkspaceFactoryModel.prototype.updateLibBlockTypes = function(blockTypes) { this.libBlockTypes = blockTypes; @@ -445,8 +445,8 @@ WorkspaceFactoryModel.prototype.updateLibBlockTypes = function(blockTypes) { * @return {boolean} True if blockType is defined, false otherwise. */ WorkspaceFactoryModel.prototype.isDefinedBlockType = function(blockType) { - var isStandardBlock = StandardCategories.coreBlockTypes.indexOf(blockType) - != -1; + var isStandardBlock = + StandardCategories.coreBlockTypes.indexOf(blockType) != -1; var isLibBlock = this.libBlockTypes.indexOf(blockType) != -1; var isImportedBlock = this.importedBlockTypes.indexOf(blockType) != -1; return (isStandardBlock || isLibBlock || isImportedBlock); @@ -454,7 +454,7 @@ WorkspaceFactoryModel.prototype.isDefinedBlockType = function(blockType) { /** * Checks if any of the block types are already defined. - * @param {!Array.} blockTypes Array of block types. + * @param {!Array} blockTypes Array of block types. * @return {boolean} True if a block type in the array is already defined, * false if none of the blocks are already defined. */ @@ -479,8 +479,8 @@ ListElement = function(type, opt_name) { this.name = opt_name ? opt_name : null; // Unique ID of element. Does not change. this.id = Blockly.utils.genUid(); - // Color of category. Default is no color. Null if separator. - this.color = null; + // Colour of category. Default is no colour. Null if separator. + this.colour = null; // Stores a custom tag, if necessary. Null if no custom tag or separator. this.custom = null; }; @@ -510,7 +510,7 @@ ListElement.prototype.saveFromWorkspace = function(workspace) { * not a category. * @param {string} name New name of category. */ -ListElement.prototype.changeName = function (name) { +ListElement.prototype.changeName = function(name) { // Only update list elements that are categories. if (this.type != ListElement.TYPE_CATEGORY) { return; @@ -519,16 +519,16 @@ ListElement.prototype.changeName = function (name) { }; /** - * Sets the color of a category. If tries to set the color of something other + * Sets the colour of a category. If tries to set the colour of something other * than a category, returns. - * @param {?string} color The color that should be used for that category, + * @param {?string} colour The colour that should be used for that category, * or null if none. */ -ListElement.prototype.changeColor = function (color) { +ListElement.prototype.changeColour = function(colour) { if (this.type != ListElement.TYPE_CATEGORY) { return; } - this.color = color; + this.colour = colour; }; /** @@ -543,7 +543,7 @@ ListElement.prototype.copy = function() { // Copy all attributes except ID. copy.name = this.name; copy.xml = this.xml; - copy.color = this.color; + copy.colour = this.colour; copy.custom = this.custom; // Return copy. return copy; diff --git a/demos/blockfactory/workspacefactory/wfactory_view.js b/demos/blockfactory/workspacefactory/wfactory_view.js index 99922395f..cf1681e58 100644 --- a/demos/blockfactory/workspacefactory/wfactory_view.js +++ b/demos/blockfactory/workspacefactory/wfactory_view.js @@ -204,13 +204,13 @@ WorkspaceFactoryView.prototype.moveTabToIndex = }; /** - * Given a category ID and color, use that color to color the left border of the - * tab for that category. - * @param {string} id The ID of the category to color. + * Given a category ID and colour, use that colour to colour the left border of + * the tab for that category. + * @param {string} id The ID of the category to colour. * @param {?string} colour The colour for to be used for the border of the tab, * or null if none. Must be a valid CSS string. */ -WorkspaceFactoryView.prototype.setBorderColor = function(id, colour) { +WorkspaceFactoryView.prototype.setBorderColour = function(id, colour) { var style = this.tabMap[id].style; if (colour) { style.borderLeftWidth = '8px'; @@ -294,7 +294,7 @@ WorkspaceFactoryView.prototype.clearToolboxTabs = function() { * Given a set of blocks currently loaded user-generated shadow blocks, visually * marks them without making them actual shadow blocks (allowing them to still * be editable and movable). - * @param {!Array.} blocks Array of user-generated shadow blocks + * @param {!Array} blocks Array of user-generated shadow blocks * currently loaded. */ WorkspaceFactoryView.prototype.markShadowBlocks = function(blocks) { diff --git a/demos/blockfactory_old/factory.js b/demos/blockfactory_old/factory.js index 10c0adad1..a324a567e 100644 --- a/demos/blockfactory_old/factory.js +++ b/demos/blockfactory_old/factory.js @@ -278,7 +278,7 @@ function connectionLineJs_(functionName, typeName) { /** * Returns field strings and any config. * @param {!Blockly.Block} block Input block. - * @return {!Array.} Field strings. + * @return {!Array} Field strings. * @private */ function getFieldsJs_(block) { @@ -374,7 +374,7 @@ function getFieldsJs_(block) { /** * Returns field strings and any config. * @param {!Blockly.Block} block Input block. - * @return {!Array.} Array of static text and field configs. + * @return {!Array} Array of static text and field configs. * @private */ function getFieldsJson_(block) { @@ -504,7 +504,7 @@ function getOptTypesFrom(block, name) { * Fetch the type(s) defined in the given input. * @param {!Blockly.Block} block Block with input. * @param {string} name Name of the input. - * @return {!Array.} List of types. + * @return {!Array} List of types. * @private */ function getTypesFrom_(block, name) { @@ -558,7 +558,7 @@ function updateGenerator(block) { // Subclass of Blockly.FieldDropdown, must test first. code.push(makeVar('variable', name) + " = Blockly." + language + - ".variableDB_.getName(block.getFieldValue('" + name + + ".nameDB_.getName(block.getFieldValue('" + name + "'), Blockly.Variables.NAME_TYPE);"); } else if (field instanceof Blockly.FieldAngle) { // Subclass of Blockly.FieldTextInput, must test first. diff --git a/demos/code/msg/en.js b/demos/code/msg/en.js index d853826f0..113b84639 100644 --- a/demos/code/msg/en.js +++ b/demos/code/msg/en.js @@ -17,7 +17,7 @@ var MSG = { listVariable: "list", textVariable: "text", httpRequestError: "There was a problem with the request.", - linkAlert: "Share your blocks with this public link. We\'ll delete them if not used for a year. They are not associated with your account and handled as per Google\'s Privacy Policy. Please be sure not to include any private information.:\n\n%1", + linkAlert: "Share your blocks with this public link. We\'ll delete them if not used for a year. They are not associated with your account and handled as per Google\'s Privacy Policy. Please be sure not to include any private information.\n\n%1", hashError: "Sorry, '%1' doesn't correspond with any saved program.", xmlError: "Could not load your saved file. Perhaps it was created with a different version of Blockly?", badXml: "Error parsing XML:\n%1\n\nSelect 'OK' to abandon your changes or 'Cancel' to further edit the XML." diff --git a/demos/graph/index.html b/demos/graph/index.html index 2e68c8475..da2922e0f 100644 --- a/demos/graph/index.html +++ b/demos/graph/index.html @@ -298,7 +298,7 @@ Graph.drawVisualization = function() { /** * Plot points on the function y = f(x). * @param {string} code JavaScript code. - * @return {!Array.} 2D Array of points on the graph. + * @return {!Array} 2D Array of points on the graph. */ Graph.plot = function(code) { // Initialize a table with two column headings. diff --git a/demos/plane/soy/soyutils.js b/demos/plane/soy/soyutils.js index e18764c91..ca9191612 100644 --- a/demos/plane/soy/soyutils.js +++ b/demos/plane/soy/soyutils.js @@ -613,7 +613,7 @@ goog.string.StringBuffer.prototype.append = function(a1, opt_a2, var_args) { // directly to avoid arguments instantiation, another 2x improvement. this.buffer_[this.bufferLength_++] = a1; } else { - var arr = /**@type {Array.}*/(this.buffer_); + var arr = /**@type {Array}*/(this.buffer_); arr.push.apply(arr, arguments); this.bufferLength_ = this.buffer_.length; } @@ -1656,7 +1656,7 @@ soy.$$checkMapKey = function(key) { /** * Gets the keys in a map as an array. There are no guarantees on the order. * @param {Object} map The map to get the keys of. - * @return {Array.} The array of keys in the given map. + * @return {Array} The array of keys in the given map. */ soy.$$getMapKeys = function(map) { var mapKeys = []; @@ -1779,9 +1779,9 @@ soy.$$getDelegateFn = function( * Private helper soy.$$getDelegateFn(). This is the empty template function * that is returned whenever there's no delegate implementation found. * - * @param {Object.=} opt_data + * @param {Object=} opt_data * @param {soy.StringBuilder=} opt_sb - * @param {Object.=} opt_ijData + * @param {Object=} opt_ijData * @return {string} * @private */ @@ -2052,7 +2052,7 @@ soy.$$HTML5_VOID_ELEMENTS_ = new RegExp( * * @param {*} value The HTML to be escaped. May not be a string, but the * value will be coerced to a string. - * @param {Object.=} opt_tagAllowlist Has an own property whose + * @param {Object=} opt_tagAllowlist Has an own property whose * name is a lower-case tag name and whose value is {@code 1} for * each element that is allowed in the output. * @return {string} A representation of value without disallowed tags, @@ -2118,7 +2118,7 @@ soy.$$stripHtmlTags = function(value, opt_tagAllowlist) { * If {@code } is used for formatting, embedded HTML shouldn't be able * to use a mismatched {@code
} to break page layout. * - * @param {Array.} tags an array of tags that will be modified in place + * @param {Array} tags an array of tags that will be modified in place * include tags, the empty string, or concatenations of empty tags. * @return {string} zero or more closed tags that close all elements that are * opened in tags but not closed. @@ -2575,7 +2575,7 @@ soy.$$isLowSurrogate_ = function(ch) { /** * Cache of bidi formatter by context directionality, so we don't keep on * creating new objects. - * @type {!Object.} + * @type {!Object} * @private */ soy.$$bidiFormatterCache_ = {}; @@ -2799,7 +2799,7 @@ soy.esc.$$escapeUriHelper = function(v) { /** * Maps characters to the escaped versions for the named escape directives. - * @type {Object.} + * @type {Object} * @private */ soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_ = { @@ -2837,7 +2837,7 @@ soy.esc.$$REPLACER_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPAC /** * Maps characters to the escaped versions for the named escape directives. - * @type {Object.} + * @type {Object} * @private */ soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_ = { @@ -2889,7 +2889,7 @@ soy.esc.$$REPLACER_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_ = function(ch) { /** * Maps characters to the escaped versions for the named escape directives. - * @type {Object.} + * @type {Object} * @private */ soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_CSS_STRING_ = { @@ -2934,7 +2934,7 @@ soy.esc.$$REPLACER_FOR_ESCAPE_CSS_STRING_ = function(ch) { /** * Maps characters to the escaped versions for the named escape directives. - * @type {Object.} + * @type {Object} * @private */ soy.esc.$$ESCAPE_MAP_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_ = { @@ -3291,7 +3291,7 @@ soy.esc.$$LT_REGEX_ = /} + * @type {Object} * @private */ soy.esc.$$SAFE_TAG_ALLOWLIST_ = {'b': 1, 'br': 1, 'em': 1, 'i': 1, 's': 1, 'sub': 1, 'sup': 1, 'u': 1}; diff --git a/externs/generator-externs.js b/externs/generator-externs.js index 288c3aa2a..450735e25 100644 --- a/externs/generator-externs.js +++ b/externs/generator-externs.js @@ -13,6 +13,7 @@ goog.provide('Blockly'); goog.provide('Blockly.Generator'); goog.provide('Blockly.inputTypes'); goog.provide('Blockly.utils.global'); +goog.provide('Blockly.utils.object'); goog.provide('Blockly.utils.string'); var Blockly; diff --git a/generators/dart.js b/generators/dart.js index 1eb3a706a..9ed2e9876 100644 --- a/generators/dart.js +++ b/generators/dart.js @@ -83,71 +83,70 @@ Blockly.Dart.isInitialized = false; * @param {!Blockly.Workspace} workspace Workspace to generate code from. */ Blockly.Dart.init = function(workspace) { - // Create a dictionary of definitions to be printed before the code. - Blockly.Dart.definitions_ = Object.create(null); - // Create a dictionary mapping desired function names in definitions_ - // to actual function names (to avoid collisions with user functions). - Blockly.Dart.functionNames_ = Object.create(null); + // Call Blockly.Generator's init. + Object.getPrototypeOf(this).init.call(this); - if (!Blockly.Dart.variableDB_) { - Blockly.Dart.variableDB_ = - new Blockly.Names(Blockly.Dart.RESERVED_WORDS_); + if (!this.nameDB_) { + this.nameDB_ = new Blockly.Names(this.RESERVED_WORDS_); } else { - Blockly.Dart.variableDB_.reset(); + this.nameDB_.reset(); } - Blockly.Dart.variableDB_.setVariableMap(workspace.getVariableMap()); + this.nameDB_.setVariableMap(workspace.getVariableMap()); + this.nameDB_.populateVariables(workspace); + this.nameDB_.populateProcedures(workspace); var defvars = []; // Add developer variables (not created or named by the user). var devVarList = Blockly.Variables.allDeveloperVariables(workspace); for (var i = 0; i < devVarList.length; i++) { - defvars.push(Blockly.Dart.variableDB_.getName(devVarList[i], + defvars.push(this.nameDB_.getName(devVarList[i], Blockly.Names.DEVELOPER_VARIABLE_TYPE)); } // Add user variables, but only ones that are being used. var variables = Blockly.Variables.allUsedVarModels(workspace); for (var i = 0; i < variables.length; i++) { - defvars.push(Blockly.Dart.variableDB_.getName(variables[i].getId(), + defvars.push(this.nameDB_.getName(variables[i].getId(), Blockly.VARIABLE_CATEGORY_NAME)); } // Declare all of the variables. if (defvars.length) { - Blockly.Dart.definitions_['variables'] = + this.definitions_['variables'] = 'var ' + defvars.join(', ') + ';'; } this.isInitialized = true; }; /** - * Prepend the generated code with the variable definitions. + * Prepend the generated code with import statements and variable definitions. * @param {string} code Generated code. * @return {string} Completed code. */ Blockly.Dart.finish = function(code) { // Indent every line. if (code) { - code = Blockly.Dart.prefixLines(code, Blockly.Dart.INDENT); + code = this.prefixLines(code, this.INDENT); } code = 'main() {\n' + code + '}'; // Convert the definitions dictionary into a list. var imports = []; var definitions = []; - for (var name in Blockly.Dart.definitions_) { - var def = Blockly.Dart.definitions_[name]; + for (var name in this.definitions_) { + var def = this.definitions_[name]; if (def.match(/^import\s/)) { imports.push(def); } else { definitions.push(def); } } - // Clean up temporary data. - delete Blockly.Dart.definitions_; - delete Blockly.Dart.functionNames_; - Blockly.Dart.variableDB_.reset(); + // Call Blockly.Generator's finish. + code = Object.getPrototypeOf(this).finish.call(this, code); + this.isInitialized = false; + + this.nameDB_.reset(); var allDefs = imports.join('\n') + '\n\n' + definitions.join('\n\n'); return allDefs.replace(/\n\n+/g, '\n\n').replace(/\n*$/, '\n\n\n') + code; }; @@ -185,7 +184,7 @@ Blockly.Dart.quote_ = function(string) { * @protected */ Blockly.Dart.multiline_quote_ = function (string) { - var lines = string.split(/\n/g).map(Blockly.Dart.quote_); + var lines = string.split(/\n/g).map(this.quote_); // Join with the following, plus a newline: // + '\n' + return lines.join(' + \'\\n\' + \n'); @@ -208,13 +207,12 @@ Blockly.Dart.scrub_ = function(block, code, opt_thisOnly) { // Collect comment for this block. var comment = block.getCommentText(); if (comment) { - comment = Blockly.utils.string.wrap(comment, - Blockly.Dart.COMMENT_WRAP - 3); + comment = Blockly.utils.string.wrap(comment, this.COMMENT_WRAP - 3); if (block.getProcedureDef) { // Use documentation comment for function comments. - commentCode += Blockly.Dart.prefixLines(comment + '\n', '/// '); + commentCode += this.prefixLines(comment + '\n', '/// '); } else { - commentCode += Blockly.Dart.prefixLines(comment + '\n', '// '); + commentCode += this.prefixLines(comment + '\n', '// '); } } // Collect comments for all value arguments. @@ -223,16 +221,16 @@ Blockly.Dart.scrub_ = function(block, code, opt_thisOnly) { if (block.inputList[i].type == Blockly.inputTypes.VALUE) { var childBlock = block.inputList[i].connection.targetBlock(); if (childBlock) { - comment = Blockly.Dart.allNestedComments(childBlock); + comment = this.allNestedComments(childBlock); if (comment) { - commentCode += Blockly.Dart.prefixLines(comment, '// '); + commentCode += this.prefixLines(comment, '// '); } } } } } var nextBlock = block.nextConnection && block.nextConnection.targetBlock(); - var nextCode = opt_thisOnly ? '' : Blockly.Dart.blockToCode(nextBlock); + var nextCode = opt_thisOnly ? '' : this.blockToCode(nextBlock); return commentCode + code + nextCode; }; @@ -248,19 +246,19 @@ Blockly.Dart.scrub_ = function(block, code, opt_thisOnly) { Blockly.Dart.getAdjusted = function(block, atId, opt_delta, opt_negate, opt_order) { var delta = opt_delta || 0; - var order = opt_order || Blockly.Dart.ORDER_NONE; + var order = opt_order || this.ORDER_NONE; if (block.workspace.options.oneBasedIndex) { delta--; } var defaultAtIndex = block.workspace.options.oneBasedIndex ? '1' : '0'; if (delta) { - var at = Blockly.Dart.valueToCode(block, atId, - Blockly.Dart.ORDER_ADDITIVE) || defaultAtIndex; + var at = this.valueToCode(block, atId, + this.ORDER_ADDITIVE) || defaultAtIndex; } else if (opt_negate) { - var at = Blockly.Dart.valueToCode(block, atId, - Blockly.Dart.ORDER_UNARY_PREFIX) || defaultAtIndex; + var at = this.valueToCode(block, atId, + this.ORDER_UNARY_PREFIX) || defaultAtIndex; } else { - var at = Blockly.Dart.valueToCode(block, atId, order) || + var at = this.valueToCode(block, atId, order) || defaultAtIndex; } @@ -274,10 +272,10 @@ Blockly.Dart.getAdjusted = function(block, atId, opt_delta, opt_negate, // If the index is dynamic, adjust it in code. if (delta > 0) { at = at + ' + ' + delta; - var innerOrder = Blockly.Dart.ORDER_ADDITIVE; + var innerOrder = this.ORDER_ADDITIVE; } else if (delta < 0) { at = at + ' - ' + -delta; - var innerOrder = Blockly.Dart.ORDER_ADDITIVE; + var innerOrder = this.ORDER_ADDITIVE; } if (opt_negate) { if (delta) { @@ -285,7 +283,7 @@ Blockly.Dart.getAdjusted = function(block, atId, opt_delta, opt_negate, } else { at = '-' + at; } - var innerOrder = Blockly.Dart.ORDER_UNARY_PREFIX; + var innerOrder = this.ORDER_UNARY_PREFIX; } innerOrder = Math.floor(innerOrder); order = Math.floor(order); diff --git a/generators/dart/lists.js b/generators/dart/lists.js index bfd6e9378..9e5d7f074 100644 --- a/generators/dart/lists.js +++ b/generators/dart/lists.js @@ -83,7 +83,7 @@ Blockly.Dart['lists_getIndex'] = function(block) { // Cache non-trivial values to variables to prevent repeated look-ups. // Closure, which accesses and modifies 'list'. function cacheList() { - var listVar = Blockly.Dart.variableDB_.getDistinctName( + var listVar = Blockly.Dart.nameDB_.getDistinctName( 'tmp_list', Blockly.VARIABLE_CATEGORY_NAME); var code = 'List ' + listVar + ' = ' + list + ';\n'; list = listVar; @@ -100,7 +100,7 @@ Blockly.Dart['lists_getIndex'] = function(block) { 'import \'dart:math\' as Math;'; // We can use multiple statements. var code = cacheList(); - var xVar = Blockly.Dart.variableDB_.getDistinctName( + var xVar = Blockly.Dart.nameDB_.getDistinctName( 'tmp_x', Blockly.VARIABLE_CATEGORY_NAME); code += 'int ' + xVar + ' = new Math.Random().nextInt(' + list + '.length);\n'; @@ -199,7 +199,7 @@ Blockly.Dart['lists_getIndex'] = function(block) { 'import \'dart:math\' as Math;'; if (mode == 'REMOVE') { // We can use multiple statements. - var xVar = Blockly.Dart.variableDB_.getDistinctName( + var xVar = Blockly.Dart.nameDB_.getDistinctName( 'tmp_x', Blockly.VARIABLE_CATEGORY_NAME); var code = 'int ' + xVar + ' = new Math.Random().nextInt(' + list + '.length);\n'; @@ -247,7 +247,7 @@ Blockly.Dart['lists_setIndex'] = function(block) { if (list.match(/^\w+$/)) { return ''; } - var listVar = Blockly.Dart.variableDB_.getDistinctName( + var listVar = Blockly.Dart.nameDB_.getDistinctName( 'tmp_list', Blockly.VARIABLE_CATEGORY_NAME); var code = 'List ' + listVar + ' = ' + list + ';\n'; list = listVar; @@ -296,7 +296,7 @@ Blockly.Dart['lists_setIndex'] = function(block) { Blockly.Dart.definitions_['import_dart_math'] = 'import \'dart:math\' as Math;'; var code = cacheList(); - var xVar = Blockly.Dart.variableDB_.getDistinctName( + var xVar = Blockly.Dart.nameDB_.getDistinctName( 'tmp_x', Blockly.VARIABLE_CATEGORY_NAME); code += 'int ' + xVar + ' = new Math.Random().nextInt(' + list + '.length);\n'; diff --git a/generators/dart/loops.js b/generators/dart/loops.js index 4ab38ca66..2625ca92b 100644 --- a/generators/dart/loops.js +++ b/generators/dart/loops.js @@ -28,11 +28,11 @@ Blockly.Dart['controls_repeat_ext'] = function(block) { var branch = Blockly.Dart.statementToCode(block, 'DO'); branch = Blockly.Dart.addLoopTrap(branch, block); var code = ''; - var loopVar = Blockly.Dart.variableDB_.getDistinctName( + var loopVar = Blockly.Dart.nameDB_.getDistinctName( 'count', Blockly.VARIABLE_CATEGORY_NAME); var endVar = repeats; if (!repeats.match(/^\w+$/) && !Blockly.isNumber(repeats)) { - endVar = Blockly.Dart.variableDB_.getDistinctName( + endVar = Blockly.Dart.nameDB_.getDistinctName( 'repeat_end', Blockly.VARIABLE_CATEGORY_NAME); code += 'var ' + endVar + ' = ' + repeats + ';\n'; } @@ -61,7 +61,7 @@ Blockly.Dart['controls_whileUntil'] = function(block) { Blockly.Dart['controls_for'] = function(block) { // For loop. - var variable0 = Blockly.Dart.variableDB_.getName( + var variable0 = Blockly.Dart.nameDB_.getName( block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); var argument0 = Blockly.Dart.valueToCode(block, 'FROM', Blockly.Dart.ORDER_ASSIGNMENT) || '0'; @@ -91,19 +91,19 @@ Blockly.Dart['controls_for'] = function(block) { // Cache non-trivial values to variables to prevent repeated look-ups. var startVar = argument0; if (!argument0.match(/^\w+$/) && !Blockly.isNumber(argument0)) { - startVar = Blockly.Dart.variableDB_.getDistinctName( + startVar = Blockly.Dart.nameDB_.getDistinctName( variable0 + '_start', Blockly.VARIABLE_CATEGORY_NAME); code += 'var ' + startVar + ' = ' + argument0 + ';\n'; } var endVar = argument1; if (!argument1.match(/^\w+$/) && !Blockly.isNumber(argument1)) { - endVar = Blockly.Dart.variableDB_.getDistinctName( + endVar = Blockly.Dart.nameDB_.getDistinctName( variable0 + '_end', Blockly.VARIABLE_CATEGORY_NAME); code += 'var ' + endVar + ' = ' + argument1 + ';\n'; } // Determine loop direction at start, in case one of the bounds // changes during loop execution. - var incVar = Blockly.Dart.variableDB_.getDistinctName( + var incVar = Blockly.Dart.nameDB_.getDistinctName( variable0 + '_inc', Blockly.VARIABLE_CATEGORY_NAME); code += 'num ' + incVar + ' = '; if (Blockly.isNumber(increment)) { @@ -126,7 +126,7 @@ Blockly.Dart['controls_for'] = function(block) { Blockly.Dart['controls_forEach'] = function(block) { // For each loop. - var variable0 = Blockly.Dart.variableDB_.getName( + var variable0 = Blockly.Dart.nameDB_.getName( block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); var argument0 = Blockly.Dart.valueToCode(block, 'LIST', Blockly.Dart.ORDER_ASSIGNMENT) || '[]'; diff --git a/generators/dart/math.js b/generators/dart/math.js index 251047fdb..203b3f98d 100644 --- a/generators/dart/math.js +++ b/generators/dart/math.js @@ -240,7 +240,7 @@ Blockly.Dart['math_change'] = function(block) { // Add to a variable in place. var argument0 = Blockly.Dart.valueToCode(block, 'DELTA', Blockly.Dart.ORDER_ADDITIVE) || '0'; - var varName = Blockly.Dart.variableDB_.getName(block.getFieldValue('VAR'), + var varName = Blockly.Dart.nameDB_.getName(block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); return varName + ' = (' + varName + ' is num ? ' + varName + ' : 0) + ' + argument0 + ';\n'; diff --git a/generators/dart/procedures.js b/generators/dart/procedures.js index 123685fb7..046b7fc29 100644 --- a/generators/dart/procedures.js +++ b/generators/dart/procedures.js @@ -17,7 +17,7 @@ goog.require('Blockly.Dart'); Blockly.Dart['procedures_defreturn'] = function(block) { // Define a procedure with a return value. - var funcName = Blockly.Dart.variableDB_.getName(block.getFieldValue('NAME'), + var funcName = Blockly.Dart.nameDB_.getName(block.getFieldValue('NAME'), Blockly.PROCEDURE_CATEGORY_NAME); var xfix1 = ''; if (Blockly.Dart.STATEMENT_PREFIX) { @@ -50,7 +50,7 @@ Blockly.Dart['procedures_defreturn'] = function(block) { var args = []; var variables = block.getVars(); for (var i = 0; i < variables.length; i++) { - args[i] = Blockly.Dart.variableDB_.getName(variables[i], + args[i] = Blockly.Dart.nameDB_.getName(variables[i], Blockly.VARIABLE_CATEGORY_NAME); } var code = returnType + ' ' + funcName + '(' + args.join(', ') + ') {\n' + @@ -67,7 +67,7 @@ Blockly.Dart['procedures_defnoreturn'] = Blockly.Dart['procedures_defreturn']; Blockly.Dart['procedures_callreturn'] = function(block) { // Call a procedure with a return value. - var funcName = Blockly.Dart.variableDB_.getName(block.getFieldValue('NAME'), + var funcName = Blockly.Dart.nameDB_.getName(block.getFieldValue('NAME'), Blockly.PROCEDURE_CATEGORY_NAME); var args = []; var variables = block.getVars(); diff --git a/generators/dart/text.js b/generators/dart/text.js index 65c5d62f3..2a38da3ef 100644 --- a/generators/dart/text.js +++ b/generators/dart/text.js @@ -54,7 +54,7 @@ Blockly.Dart['text_join'] = function(block) { Blockly.Dart['text_append'] = function(block) { // Append to a variable in place. - var varName = Blockly.Dart.variableDB_.getName(block.getFieldValue('VAR'), + var varName = Blockly.Dart.nameDB_.getName(block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); var value = Blockly.Dart.valueToCode(block, 'TEXT', Blockly.Dart.ORDER_NONE) || '\'\''; diff --git a/generators/dart/variables.js b/generators/dart/variables.js index 2fe0a9e02..0b8f1fd4b 100644 --- a/generators/dart/variables.js +++ b/generators/dart/variables.js @@ -17,7 +17,7 @@ goog.require('Blockly.Dart'); Blockly.Dart['variables_get'] = function(block) { // Variable getter. - var code = Blockly.Dart.variableDB_.getName(block.getFieldValue('VAR'), + var code = Blockly.Dart.nameDB_.getName(block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); return [code, Blockly.Dart.ORDER_ATOMIC]; }; @@ -26,7 +26,7 @@ Blockly.Dart['variables_set'] = function(block) { // Variable setter. var argument0 = Blockly.Dart.valueToCode(block, 'VALUE', Blockly.Dart.ORDER_ASSIGNMENT) || '0'; - var varName = Blockly.Dart.variableDB_.getName(block.getFieldValue('VAR'), + var varName = Blockly.Dart.nameDB_.getName(block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); return varName + ' = ' + argument0 + ';\n'; }; diff --git a/generators/javascript.js b/generators/javascript.js index 7bedb4831..0c1cbe7cb 100644 --- a/generators/javascript.js +++ b/generators/javascript.js @@ -15,6 +15,7 @@ goog.provide('Blockly.JavaScript'); goog.require('Blockly.Generator'); goog.require('Blockly.inputTypes'); goog.require('Blockly.utils.global'); +goog.require('Blockly.utils.object'); goog.require('Blockly.utils.string'); @@ -85,7 +86,7 @@ Blockly.JavaScript.ORDER_NONE = 99; // (...) /** * List of outer-inner pairings that do NOT require parentheses. - * @type {!Array.>} + * @type {!Array>} */ Blockly.JavaScript.ORDER_OVERRIDES = [ // (foo()).bar -> foo().bar @@ -125,40 +126,37 @@ Blockly.JavaScript.isInitialized = false; * @param {!Blockly.Workspace} workspace Workspace to generate code from. */ Blockly.JavaScript.init = function(workspace) { - // Create a dictionary of definitions to be printed before the code. - Blockly.JavaScript.definitions_ = Object.create(null); - // Create a dictionary mapping desired function names in definitions_ - // to actual function names (to avoid collisions with user functions). - Blockly.JavaScript.functionNames_ = Object.create(null); + // Call Blockly.Generator's init. + Object.getPrototypeOf(this).init.call(this); - if (!Blockly.JavaScript.variableDB_) { - Blockly.JavaScript.variableDB_ = - new Blockly.Names(Blockly.JavaScript.RESERVED_WORDS_); + if (!this.nameDB_) { + this.nameDB_ = new Blockly.Names(this.RESERVED_WORDS_); } else { - Blockly.JavaScript.variableDB_.reset(); + this.nameDB_.reset(); } - Blockly.JavaScript.variableDB_.setVariableMap(workspace.getVariableMap()); + this.nameDB_.setVariableMap(workspace.getVariableMap()); + this.nameDB_.populateVariables(workspace); + this.nameDB_.populateProcedures(workspace); var defvars = []; // Add developer variables (not created or named by the user). var devVarList = Blockly.Variables.allDeveloperVariables(workspace); for (var i = 0; i < devVarList.length; i++) { - defvars.push(Blockly.JavaScript.variableDB_.getName(devVarList[i], + defvars.push(this.nameDB_.getName(devVarList[i], Blockly.Names.DEVELOPER_VARIABLE_TYPE)); } // Add user variables, but only ones that are being used. var variables = Blockly.Variables.allUsedVarModels(workspace); for (var i = 0; i < variables.length; i++) { - defvars.push(Blockly.JavaScript.variableDB_.getName(variables[i].getId(), + defvars.push(this.nameDB_.getName(variables[i].getId(), Blockly.VARIABLE_CATEGORY_NAME)); } // Declare all of the variables. if (defvars.length) { - Blockly.JavaScript.definitions_['variables'] = - 'var ' + defvars.join(', ') + ';'; + this.definitions_['variables'] = 'var ' + defvars.join(', ') + ';'; } this.isInitialized = true; }; @@ -170,14 +168,12 @@ Blockly.JavaScript.init = function(workspace) { */ Blockly.JavaScript.finish = function(code) { // Convert the definitions dictionary into a list. - var definitions = []; - for (var name in Blockly.JavaScript.definitions_) { - definitions.push(Blockly.JavaScript.definitions_[name]); - } - // Clean up temporary data. - delete Blockly.JavaScript.definitions_; - delete Blockly.JavaScript.functionNames_; - Blockly.JavaScript.variableDB_.reset(); + var definitions = Blockly.utils.object.values(this.definitions_); + // Call Blockly.Generator's finish. + code = Object.getPrototypeOf(this).finish.call(this, code); + this.isInitialized = false; + + this.nameDB_.reset(); return definitions.join('\n\n') + '\n\n\n' + code; }; @@ -217,7 +213,7 @@ Blockly.JavaScript.quote_ = function(string) { Blockly.JavaScript.multiline_quote_ = function(string) { // Can't use goog.string.quote since Google's style guide recommends // JS string literals use single quotes. - var lines = string.split(/\n/g).map(Blockly.JavaScript.quote_); + var lines = string.split(/\n/g).map(this.quote_); return lines.join(' + \'\\n\' +\n'); }; @@ -238,9 +234,8 @@ Blockly.JavaScript.scrub_ = function(block, code, opt_thisOnly) { // Collect comment for this block. var comment = block.getCommentText(); if (comment) { - comment = Blockly.utils.string.wrap(comment, - Blockly.JavaScript.COMMENT_WRAP - 3); - commentCode += Blockly.JavaScript.prefixLines(comment + '\n', '// '); + comment = Blockly.utils.string.wrap(comment, this.COMMENT_WRAP - 3); + commentCode += this.prefixLines(comment + '\n', '// '); } // Collect comments for all value arguments. // Don't collect comments for nested statements. @@ -248,16 +243,16 @@ Blockly.JavaScript.scrub_ = function(block, code, opt_thisOnly) { if (block.inputList[i].type == Blockly.inputTypes.VALUE) { var childBlock = block.inputList[i].connection.targetBlock(); if (childBlock) { - comment = Blockly.JavaScript.allNestedComments(childBlock); + comment = this.allNestedComments(childBlock); if (comment) { - commentCode += Blockly.JavaScript.prefixLines(comment, '// '); + commentCode += this.prefixLines(comment, '// '); } } } } } var nextBlock = block.nextConnection && block.nextConnection.targetBlock(); - var nextCode = opt_thisOnly ? '' : Blockly.JavaScript.blockToCode(nextBlock); + var nextCode = opt_thisOnly ? '' : this.blockToCode(nextBlock); return commentCode + code + nextCode; }; @@ -273,23 +268,22 @@ Blockly.JavaScript.scrub_ = function(block, code, opt_thisOnly) { Blockly.JavaScript.getAdjusted = function(block, atId, opt_delta, opt_negate, opt_order) { var delta = opt_delta || 0; - var order = opt_order || Blockly.JavaScript.ORDER_NONE; + var order = opt_order || this.ORDER_NONE; if (block.workspace.options.oneBasedIndex) { delta--; } var defaultAtIndex = block.workspace.options.oneBasedIndex ? '1' : '0'; if (delta > 0) { - var at = Blockly.JavaScript.valueToCode(block, atId, - Blockly.JavaScript.ORDER_ADDITION) || defaultAtIndex; + var at = this.valueToCode(block, atId, + this.ORDER_ADDITION) || defaultAtIndex; } else if (delta < 0) { - var at = Blockly.JavaScript.valueToCode(block, atId, - Blockly.JavaScript.ORDER_SUBTRACTION) || defaultAtIndex; + var at = this.valueToCode(block, atId, + this.ORDER_SUBTRACTION) || defaultAtIndex; } else if (opt_negate) { - var at = Blockly.JavaScript.valueToCode(block, atId, - Blockly.JavaScript.ORDER_UNARY_NEGATION) || defaultAtIndex; + var at = this.valueToCode(block, atId, + this.ORDER_UNARY_NEGATION) || defaultAtIndex; } else { - var at = Blockly.JavaScript.valueToCode(block, atId, order) || - defaultAtIndex; + var at = this.valueToCode(block, atId, order) || defaultAtIndex; } if (Blockly.isNumber(at)) { @@ -302,10 +296,10 @@ Blockly.JavaScript.getAdjusted = function(block, atId, opt_delta, opt_negate, // If the index is dynamic, adjust it in code. if (delta > 0) { at = at + ' + ' + delta; - var innerOrder = Blockly.JavaScript.ORDER_ADDITION; + var innerOrder = this.ORDER_ADDITION; } else if (delta < 0) { at = at + ' - ' + -delta; - var innerOrder = Blockly.JavaScript.ORDER_SUBTRACTION; + var innerOrder = this.ORDER_SUBTRACTION; } if (opt_negate) { if (delta) { @@ -313,7 +307,7 @@ Blockly.JavaScript.getAdjusted = function(block, atId, opt_delta, opt_negate, } else { at = '-' + at; } - var innerOrder = Blockly.JavaScript.ORDER_UNARY_NEGATION; + var innerOrder = this.ORDER_UNARY_NEGATION; } innerOrder = Math.floor(innerOrder); order = Math.floor(order); diff --git a/generators/javascript/lists.js b/generators/javascript/lists.js index 0311ad7d4..d40cc294b 100644 --- a/generators/javascript/lists.js +++ b/generators/javascript/lists.js @@ -174,7 +174,7 @@ Blockly.JavaScript['lists_setIndex'] = function(block) { if (list.match(/^\w+$/)) { return ''; } - var listVar = Blockly.JavaScript.variableDB_.getDistinctName( + var listVar = Blockly.JavaScript.nameDB_.getDistinctName( 'tmpList', Blockly.VARIABLE_CATEGORY_NAME); var code = 'var ' + listVar + ' = ' + list + ';\n'; list = listVar; @@ -220,7 +220,7 @@ Blockly.JavaScript['lists_setIndex'] = function(block) { break; case ('RANDOM'): var code = cacheList(); - var xVar = Blockly.JavaScript.variableDB_.getDistinctName( + var xVar = Blockly.JavaScript.nameDB_.getDistinctName( 'tmpX', Blockly.VARIABLE_CATEGORY_NAME); code += 'var ' + xVar + ' = Math.floor(Math.random() * ' + list + '.length);\n'; diff --git a/generators/javascript/loops.js b/generators/javascript/loops.js index 595906f84..690d6b9b5 100644 --- a/generators/javascript/loops.js +++ b/generators/javascript/loops.js @@ -28,11 +28,11 @@ Blockly.JavaScript['controls_repeat_ext'] = function(block) { var branch = Blockly.JavaScript.statementToCode(block, 'DO'); branch = Blockly.JavaScript.addLoopTrap(branch, block); var code = ''; - var loopVar = Blockly.JavaScript.variableDB_.getDistinctName( + var loopVar = Blockly.JavaScript.nameDB_.getDistinctName( 'count', Blockly.VARIABLE_CATEGORY_NAME); var endVar = repeats; if (!repeats.match(/^\w+$/) && !Blockly.isNumber(repeats)) { - endVar = Blockly.JavaScript.variableDB_.getDistinctName( + endVar = Blockly.JavaScript.nameDB_.getDistinctName( 'repeat_end', Blockly.VARIABLE_CATEGORY_NAME); code += 'var ' + endVar + ' = ' + repeats + ';\n'; } @@ -62,7 +62,7 @@ Blockly.JavaScript['controls_whileUntil'] = function(block) { Blockly.JavaScript['controls_for'] = function(block) { // For loop. - var variable0 = Blockly.JavaScript.variableDB_.getName( + var variable0 = Blockly.JavaScript.nameDB_.getName( block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); var argument0 = Blockly.JavaScript.valueToCode(block, 'FROM', Blockly.JavaScript.ORDER_ASSIGNMENT) || '0'; @@ -92,19 +92,19 @@ Blockly.JavaScript['controls_for'] = function(block) { // Cache non-trivial values to variables to prevent repeated look-ups. var startVar = argument0; if (!argument0.match(/^\w+$/) && !Blockly.isNumber(argument0)) { - startVar = Blockly.JavaScript.variableDB_.getDistinctName( + startVar = Blockly.JavaScript.nameDB_.getDistinctName( variable0 + '_start', Blockly.VARIABLE_CATEGORY_NAME); code += 'var ' + startVar + ' = ' + argument0 + ';\n'; } var endVar = argument1; if (!argument1.match(/^\w+$/) && !Blockly.isNumber(argument1)) { - endVar = Blockly.JavaScript.variableDB_.getDistinctName( + endVar = Blockly.JavaScript.nameDB_.getDistinctName( variable0 + '_end', Blockly.VARIABLE_CATEGORY_NAME); code += 'var ' + endVar + ' = ' + argument1 + ';\n'; } // Determine loop direction at start, in case one of the bounds // changes during loop execution. - var incVar = Blockly.JavaScript.variableDB_.getDistinctName( + var incVar = Blockly.JavaScript.nameDB_.getDistinctName( variable0 + '_inc', Blockly.VARIABLE_CATEGORY_NAME); code += 'var ' + incVar + ' = '; if (Blockly.isNumber(increment)) { @@ -127,7 +127,7 @@ Blockly.JavaScript['controls_for'] = function(block) { Blockly.JavaScript['controls_forEach'] = function(block) { // For each loop. - var variable0 = Blockly.JavaScript.variableDB_.getName( + var variable0 = Blockly.JavaScript.nameDB_.getName( block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); var argument0 = Blockly.JavaScript.valueToCode(block, 'LIST', Blockly.JavaScript.ORDER_ASSIGNMENT) || '[]'; @@ -137,11 +137,11 @@ Blockly.JavaScript['controls_forEach'] = function(block) { // Cache non-trivial values to variables to prevent repeated look-ups. var listVar = argument0; if (!argument0.match(/^\w+$/)) { - listVar = Blockly.JavaScript.variableDB_.getDistinctName( + listVar = Blockly.JavaScript.nameDB_.getDistinctName( variable0 + '_list', Blockly.VARIABLE_CATEGORY_NAME); code += 'var ' + listVar + ' = ' + argument0 + ';\n'; } - var indexVar = Blockly.JavaScript.variableDB_.getDistinctName( + var indexVar = Blockly.JavaScript.nameDB_.getDistinctName( variable0 + '_index', Blockly.VARIABLE_CATEGORY_NAME); branch = Blockly.JavaScript.INDENT + variable0 + ' = ' + listVar + '[' + indexVar + '];\n' + branch; diff --git a/generators/javascript/math.js b/generators/javascript/math.js index 2420a5a04..e31db236f 100644 --- a/generators/javascript/math.js +++ b/generators/javascript/math.js @@ -207,7 +207,7 @@ Blockly.JavaScript['math_change'] = function(block) { // Add to a variable in place. var argument0 = Blockly.JavaScript.valueToCode(block, 'DELTA', Blockly.JavaScript.ORDER_ADDITION) || '0'; - var varName = Blockly.JavaScript.variableDB_.getName( + var varName = Blockly.JavaScript.nameDB_.getName( block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); return varName + ' = (typeof ' + varName + ' == \'number\' ? ' + varName + ' : 0) + ' + argument0 + ';\n'; diff --git a/generators/javascript/procedures.js b/generators/javascript/procedures.js index 9d4cc4a71..9bf143ce4 100644 --- a/generators/javascript/procedures.js +++ b/generators/javascript/procedures.js @@ -17,7 +17,7 @@ goog.require('Blockly.JavaScript'); Blockly.JavaScript['procedures_defreturn'] = function(block) { // Define a procedure with a return value. - var funcName = Blockly.JavaScript.variableDB_.getName( + var funcName = Blockly.JavaScript.nameDB_.getName( block.getFieldValue('NAME'), Blockly.PROCEDURE_CATEGORY_NAME); var xfix1 = ''; if (Blockly.JavaScript.STATEMENT_PREFIX) { @@ -51,7 +51,7 @@ Blockly.JavaScript['procedures_defreturn'] = function(block) { var args = []; var variables = block.getVars(); for (var i = 0; i < variables.length; i++) { - args[i] = Blockly.JavaScript.variableDB_.getName(variables[i], + args[i] = Blockly.JavaScript.nameDB_.getName(variables[i], Blockly.VARIABLE_CATEGORY_NAME); } var code = 'function ' + funcName + '(' + args.join(', ') + ') {\n' + @@ -69,7 +69,7 @@ Blockly.JavaScript['procedures_defnoreturn'] = Blockly.JavaScript['procedures_callreturn'] = function(block) { // Call a procedure with a return value. - var funcName = Blockly.JavaScript.variableDB_.getName( + var funcName = Blockly.JavaScript.nameDB_.getName( block.getFieldValue('NAME'), Blockly.PROCEDURE_CATEGORY_NAME); var args = []; var variables = block.getVars(); diff --git a/generators/javascript/text.js b/generators/javascript/text.js index 8f669d7cc..6c18c58d0 100644 --- a/generators/javascript/text.js +++ b/generators/javascript/text.js @@ -80,7 +80,7 @@ Blockly.JavaScript['text_join'] = function(block) { Blockly.JavaScript['text_append'] = function(block) { // Append to a variable in place. - var varName = Blockly.JavaScript.variableDB_.getName( + var varName = Blockly.JavaScript.nameDB_.getName( block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); var value = Blockly.JavaScript.valueToCode(block, 'TEXT', Blockly.JavaScript.ORDER_NONE) || '\'\''; diff --git a/generators/javascript/variables.js b/generators/javascript/variables.js index 5ff961d2c..f7b89a3fe 100644 --- a/generators/javascript/variables.js +++ b/generators/javascript/variables.js @@ -17,7 +17,7 @@ goog.require('Blockly.JavaScript'); Blockly.JavaScript['variables_get'] = function(block) { // Variable getter. - var code = Blockly.JavaScript.variableDB_.getName(block.getFieldValue('VAR'), + var code = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); return [code, Blockly.JavaScript.ORDER_ATOMIC]; }; @@ -26,7 +26,7 @@ Blockly.JavaScript['variables_set'] = function(block) { // Variable setter. var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE', Blockly.JavaScript.ORDER_ASSIGNMENT) || '0'; - var varName = Blockly.JavaScript.variableDB_.getName( + var varName = Blockly.JavaScript.nameDB_.getName( block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); return varName + ' = ' + argument0 + ';\n'; }; diff --git a/generators/lua.js b/generators/lua.js index da3e750d0..54877523b 100644 --- a/generators/lua.js +++ b/generators/lua.js @@ -15,6 +15,7 @@ goog.provide('Blockly.Lua'); goog.require('Blockly.Generator'); goog.require('Blockly.inputTypes'); +goog.require('Blockly.utils.object'); goog.require('Blockly.utils.string'); @@ -91,19 +92,18 @@ Blockly.Lua.isInitialized = false; * @param {!Blockly.Workspace} workspace Workspace to generate code from. */ Blockly.Lua.init = function(workspace) { - // Create a dictionary of definitions to be printed before the code. - Blockly.Lua.definitions_ = Object.create(null); - // Create a dictionary mapping desired function names in definitions_ - // to actual function names (to avoid collisions with user functions). - Blockly.Lua.functionNames_ = Object.create(null); + // Call Blockly.Generator's init. + Object.getPrototypeOf(this).init.call(this); - if (!Blockly.Lua.variableDB_) { - Blockly.Lua.variableDB_ = - new Blockly.Names(Blockly.Lua.RESERVED_WORDS_); + if (!this.nameDB_) { + this.nameDB_ = new Blockly.Names(this.RESERVED_WORDS_); } else { - Blockly.Lua.variableDB_.reset(); + this.nameDB_.reset(); } - Blockly.Lua.variableDB_.setVariableMap(workspace.getVariableMap()); + this.nameDB_.setVariableMap(workspace.getVariableMap()); + this.nameDB_.populateVariables(workspace); + this.nameDB_.populateProcedures(workspace); + this.isInitialized = true; }; @@ -114,14 +114,12 @@ Blockly.Lua.init = function(workspace) { */ Blockly.Lua.finish = function(code) { // Convert the definitions dictionary into a list. - var definitions = []; - for (var name in Blockly.Lua.definitions_) { - definitions.push(Blockly.Lua.definitions_[name]); - } - // Clean up temporary data. - delete Blockly.Lua.definitions_; - delete Blockly.Lua.functionNames_; - Blockly.Lua.variableDB_.reset(); + var definitions = Blockly.utils.object.values(this.definitions_); + // Call Blockly.Generator's finish. + code = Object.getPrototypeOf(this).finish.call(this, code); + this.isInitialized = false; + + this.nameDB_.reset(); return definitions.join('\n\n') + '\n\n\n' + code; }; @@ -159,7 +157,7 @@ Blockly.Lua.quote_ = function(string) { * @protected */ Blockly.Lua.multiline_quote_ = function(string) { - var lines = string.split(/\n/g).map(Blockly.Lua.quote_); + var lines = string.split(/\n/g).map(this.quote_); // Join with the following, plus a newline: // .. '\n' .. return lines.join(' .. \'\\n\' ..\n'); @@ -182,9 +180,8 @@ Blockly.Lua.scrub_ = function(block, code, opt_thisOnly) { // Collect comment for this block. var comment = block.getCommentText(); if (comment) { - comment = Blockly.utils.string.wrap(comment, - Blockly.Lua.COMMENT_WRAP - 3); - commentCode += Blockly.Lua.prefixLines(comment, '-- ') + '\n'; + comment = Blockly.utils.string.wrap(comment, this.COMMENT_WRAP - 3); + commentCode += this.prefixLines(comment, '-- ') + '\n'; } // Collect comments for all value arguments. // Don't collect comments for nested statements. @@ -192,15 +189,15 @@ Blockly.Lua.scrub_ = function(block, code, opt_thisOnly) { if (block.inputList[i].type == Blockly.inputTypes.VALUE) { var childBlock = block.inputList[i].connection.targetBlock(); if (childBlock) { - comment = Blockly.Lua.allNestedComments(childBlock); + comment = this.allNestedComments(childBlock); if (comment) { - commentCode += Blockly.Lua.prefixLines(comment, '-- '); + commentCode += this.prefixLines(comment, '-- '); } } } } } var nextBlock = block.nextConnection && block.nextConnection.targetBlock(); - var nextCode = opt_thisOnly ? '' : Blockly.Lua.blockToCode(nextBlock); + var nextCode = opt_thisOnly ? '' : this.blockToCode(nextBlock); return commentCode + code + nextCode; }; diff --git a/generators/lua/lists.js b/generators/lua/lists.js index 5c3831a02..c134b4330 100644 --- a/generators/lua/lists.js +++ b/generators/lua/lists.js @@ -139,7 +139,7 @@ Blockly.Lua['lists_getIndex'] = function(block) { var atOrder = (where == 'FROM_END') ? Blockly.Lua.ORDER_ADDITIVE : Blockly.Lua.ORDER_NONE; var at = Blockly.Lua.valueToCode(block, 'AT', atOrder) || '1'; - var listVar = Blockly.Lua.variableDB_.getDistinctName( + var listVar = Blockly.Lua.nameDB_.getDistinctName( 'tmp_list', Blockly.VARIABLE_CATEGORY_NAME); at = getIndex_(listVar, where, at); var code = listVar + ' = ' + list + '\n' + @@ -218,7 +218,7 @@ Blockly.Lua['lists_setIndex'] = function(block) { !list.match(/^\w+$/)) { // `list` is an expression, so we may not evaluate it more than once. // We can use multiple statements. - var listVar = Blockly.Lua.variableDB_.getDistinctName( + var listVar = Blockly.Lua.nameDB_.getDistinctName( 'tmp_list', Blockly.VARIABLE_CATEGORY_NAME); code = listVar + ' = ' + list + '\n'; list = listVar; diff --git a/generators/lua/loops.js b/generators/lua/loops.js index be95737bc..5d3df45db 100644 --- a/generators/lua/loops.js +++ b/generators/lua/loops.js @@ -60,7 +60,7 @@ Blockly.Lua['controls_repeat_ext'] = function(block) { var branch = Blockly.Lua.statementToCode(block, 'DO'); branch = Blockly.Lua.addLoopTrap(branch, block); branch = Blockly.Lua.addContinueLabel_(branch); - var loopVar = Blockly.Lua.variableDB_.getDistinctName( + var loopVar = Blockly.Lua.nameDB_.getDistinctName( 'count', Blockly.VARIABLE_CATEGORY_NAME); var code = 'for ' + loopVar + ' = 1, ' + repeats + ' do\n' + branch + 'end\n'; @@ -86,7 +86,7 @@ Blockly.Lua['controls_whileUntil'] = function(block) { Blockly.Lua['controls_for'] = function(block) { // For loop. - var variable0 = Blockly.Lua.variableDB_.getName( + var variable0 = Blockly.Lua.nameDB_.getName( block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); var startVar = Blockly.Lua.valueToCode(block, 'FROM', Blockly.Lua.ORDER_NONE) || '0'; @@ -109,7 +109,7 @@ Blockly.Lua['controls_for'] = function(block) { code = ''; // Determine loop direction at start, in case one of the bounds // changes during loop execution. - incValue = Blockly.Lua.variableDB_.getDistinctName( + incValue = Blockly.Lua.nameDB_.getDistinctName( variable0 + '_inc', Blockly.VARIABLE_CATEGORY_NAME); code += incValue + ' = '; if (Blockly.isNumber(increment)) { @@ -129,7 +129,7 @@ Blockly.Lua['controls_for'] = function(block) { Blockly.Lua['controls_forEach'] = function(block) { // For each loop. - var variable0 = Blockly.Lua.variableDB_.getName( + var variable0 = Blockly.Lua.nameDB_.getName( block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); var argument0 = Blockly.Lua.valueToCode(block, 'LIST', Blockly.Lua.ORDER_NONE) || '{}'; diff --git a/generators/lua/math.js b/generators/lua/math.js index 23f0485e6..059ca437c 100644 --- a/generators/lua/math.js +++ b/generators/lua/math.js @@ -196,7 +196,7 @@ Blockly.Lua['math_change'] = function(block) { // Add to a variable in place. var argument0 = Blockly.Lua.valueToCode(block, 'DELTA', Blockly.Lua.ORDER_ADDITIVE) || '0'; - var varName = Blockly.Lua.variableDB_.getName( + var varName = Blockly.Lua.nameDB_.getName( block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); return varName + ' = ' + varName + ' + ' + argument0 + '\n'; }; diff --git a/generators/lua/procedures.js b/generators/lua/procedures.js index 156c3c7d9..c6bf77514 100644 --- a/generators/lua/procedures.js +++ b/generators/lua/procedures.js @@ -17,7 +17,7 @@ goog.require('Blockly.Lua'); Blockly.Lua['procedures_defreturn'] = function(block) { // Define a procedure with a return value. - var funcName = Blockly.Lua.variableDB_.getName( + var funcName = Blockly.Lua.nameDB_.getName( block.getFieldValue('NAME'), Blockly.PROCEDURE_CATEGORY_NAME); var xfix1 = ''; if (Blockly.Lua.STATEMENT_PREFIX) { @@ -51,7 +51,7 @@ Blockly.Lua['procedures_defreturn'] = function(block) { var args = []; var variables = block.getVars(); for (var i = 0; i < variables.length; i++) { - args[i] = Blockly.Lua.variableDB_.getName(variables[i], + args[i] = Blockly.Lua.nameDB_.getName(variables[i], Blockly.VARIABLE_CATEGORY_NAME); } var code = 'function ' + funcName + '(' + args.join(', ') + ')\n' + @@ -69,7 +69,7 @@ Blockly.Lua['procedures_defnoreturn'] = Blockly.Lua['procedures_callreturn'] = function(block) { // Call a procedure with a return value. - var funcName = Blockly.Lua.variableDB_.getName( + var funcName = Blockly.Lua.nameDB_.getName( block.getFieldValue('NAME'), Blockly.PROCEDURE_CATEGORY_NAME); var args = []; var variables = block.getVars(); diff --git a/generators/lua/text.js b/generators/lua/text.js index 12ceefe91..a24e37805 100644 --- a/generators/lua/text.js +++ b/generators/lua/text.js @@ -58,7 +58,7 @@ Blockly.Lua['text_join'] = function(block) { Blockly.Lua['text_append'] = function(block) { // Append to a variable in place. - var varName = Blockly.Lua.variableDB_.getName( + var varName = Blockly.Lua.nameDB_.getName( block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); var value = Blockly.Lua.valueToCode(block, 'TEXT', Blockly.Lua.ORDER_CONCATENATION) || '\'\''; diff --git a/generators/lua/variables.js b/generators/lua/variables.js index 9249a43e9..bbc00f39e 100644 --- a/generators/lua/variables.js +++ b/generators/lua/variables.js @@ -17,7 +17,7 @@ goog.require('Blockly.Lua'); Blockly.Lua['variables_get'] = function(block) { // Variable getter. - var code = Blockly.Lua.variableDB_.getName(block.getFieldValue('VAR'), + var code = Blockly.Lua.nameDB_.getName(block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); return [code, Blockly.Lua.ORDER_ATOMIC]; }; @@ -26,7 +26,7 @@ Blockly.Lua['variables_set'] = function(block) { // Variable setter. var argument0 = Blockly.Lua.valueToCode(block, 'VALUE', Blockly.Lua.ORDER_NONE) || '0'; - var varName = Blockly.Lua.variableDB_.getName( + var varName = Blockly.Lua.nameDB_.getName( block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); return varName + ' = ' + argument0 + '\n'; }; diff --git a/generators/php.js b/generators/php.js index 8cab5c231..9d4fb540c 100644 --- a/generators/php.js +++ b/generators/php.js @@ -14,6 +14,7 @@ goog.provide('Blockly.PHP'); goog.require('Blockly.Generator'); goog.require('Blockly.inputTypes'); +goog.require('Blockly.utils.object'); goog.require('Blockly.utils.string'); @@ -97,7 +98,7 @@ Blockly.PHP.ORDER_NONE = 99; // (...) /** * List of outer-inner pairings that do NOT require parentheses. - * @type {!Array.>} + * @type {!Array>} */ Blockly.PHP.ORDER_OVERRIDES = [ // (foo()).bar() -> foo().bar() @@ -129,38 +130,19 @@ Blockly.PHP.isInitialized = false; * @param {!Blockly.Workspace} workspace Workspace to generate code from. */ Blockly.PHP.init = function(workspace) { - // Create a dictionary of definitions to be printed before the code. - Blockly.PHP.definitions_ = Object.create(null); - // Create a dictionary mapping desired function names in definitions_ - // to actual function names (to avoid collisions with user functions). - Blockly.PHP.functionNames_ = Object.create(null); + // Call Blockly.Generator's init. + Object.getPrototypeOf(this).init.call(this); - if (!Blockly.PHP.variableDB_) { - Blockly.PHP.variableDB_ = - new Blockly.Names(Blockly.PHP.RESERVED_WORDS_, '$'); + if (!this.nameDB_) { + this.nameDB_ = new Blockly.Names(this.RESERVED_WORDS_, '$'); } else { - Blockly.PHP.variableDB_.reset(); + this.nameDB_.reset(); } - Blockly.PHP.variableDB_.setVariableMap(workspace.getVariableMap()); + this.nameDB_.setVariableMap(workspace.getVariableMap()); + this.nameDB_.populateVariables(workspace); + this.nameDB_.populateProcedures(workspace); - var defvars = []; - // Add developer variables (not created or named by the user). - var devVarList = Blockly.Variables.allDeveloperVariables(workspace); - for (var i = 0; i < devVarList.length; i++) { - defvars.push(Blockly.PHP.variableDB_.getName(devVarList[i], - Blockly.Names.DEVELOPER_VARIABLE_TYPE) + ';'); - } - - // Add user variables, but only ones that are being used. - var variables = Blockly.Variables.allUsedVarModels(workspace); - for (var i = 0, variable; variable = variables[i]; i++) { - defvars.push(Blockly.PHP.variableDB_.getName(variable.getId(), - Blockly.VARIABLE_CATEGORY_NAME) + ';'); - } - - // Declare all of the variables. - Blockly.PHP.definitions_['variables'] = defvars.join('\n'); this.isInitialized = true; }; @@ -171,14 +153,12 @@ Blockly.PHP.init = function(workspace) { */ Blockly.PHP.finish = function(code) { // Convert the definitions dictionary into a list. - var definitions = []; - for (var name in Blockly.PHP.definitions_) { - definitions.push(Blockly.PHP.definitions_[name]); - } - // Clean up temporary data. - delete Blockly.PHP.definitions_; - delete Blockly.PHP.functionNames_; - Blockly.PHP.variableDB_.reset(); + var definitions = Blockly.utils.object.values(this.definitions_); + // Call Blockly.Generator's finish. + code = Object.getPrototypeOf(this).finish.call(this, code); + this.isInitialized = false; + + this.nameDB_.reset(); return definitions.join('\n\n') + '\n\n\n' + code; }; @@ -214,7 +194,7 @@ Blockly.PHP.quote_ = function(string) { * @protected */ Blockly.PHP.multiline_quote_ = function (string) { - var lines = string.split(/\n/g).map(Blockly.PHP.quote_); + var lines = string.split(/\n/g).map(this.quote_); // Join with the following, plus a newline: // . "\n" . // Newline escaping only works in double-quoted strings. @@ -238,9 +218,8 @@ Blockly.PHP.scrub_ = function(block, code, opt_thisOnly) { // Collect comment for this block. var comment = block.getCommentText(); if (comment) { - comment = Blockly.utils.string.wrap(comment, - Blockly.PHP.COMMENT_WRAP - 3); - commentCode += Blockly.PHP.prefixLines(comment, '// ') + '\n'; + comment = Blockly.utils.string.wrap(comment, this.COMMENT_WRAP - 3); + commentCode += this.prefixLines(comment, '// ') + '\n'; } // Collect comments for all value arguments. // Don't collect comments for nested statements. @@ -248,16 +227,16 @@ Blockly.PHP.scrub_ = function(block, code, opt_thisOnly) { if (block.inputList[i].type == Blockly.inputTypes.VALUE) { var childBlock = block.inputList[i].connection.targetBlock(); if (childBlock) { - comment = Blockly.PHP.allNestedComments(childBlock); + comment = this.allNestedComments(childBlock); if (comment) { - commentCode += Blockly.PHP.prefixLines(comment, '// '); + commentCode += this.prefixLines(comment, '// '); } } } } } var nextBlock = block.nextConnection && block.nextConnection.targetBlock(); - var nextCode = opt_thisOnly ? '' : Blockly.PHP.blockToCode(nextBlock); + var nextCode = opt_thisOnly ? '' : this.blockToCode(nextBlock); return commentCode + code + nextCode; }; @@ -273,22 +252,22 @@ Blockly.PHP.scrub_ = function(block, code, opt_thisOnly) { Blockly.PHP.getAdjusted = function(block, atId, opt_delta, opt_negate, opt_order) { var delta = opt_delta || 0; - var order = opt_order || Blockly.PHP.ORDER_NONE; + var order = opt_order || this.ORDER_NONE; if (block.workspace.options.oneBasedIndex) { delta--; } var defaultAtIndex = block.workspace.options.oneBasedIndex ? '1' : '0'; if (delta > 0) { - var at = Blockly.PHP.valueToCode(block, atId, - Blockly.PHP.ORDER_ADDITION) || defaultAtIndex; + var at = this.valueToCode(block, atId, + this.ORDER_ADDITION) || defaultAtIndex; } else if (delta < 0) { - var at = Blockly.PHP.valueToCode(block, atId, - Blockly.PHP.ORDER_SUBTRACTION) || defaultAtIndex; + var at = this.valueToCode(block, atId, + this.ORDER_SUBTRACTION) || defaultAtIndex; } else if (opt_negate) { - var at = Blockly.PHP.valueToCode(block, atId, - Blockly.PHP.ORDER_UNARY_NEGATION) || defaultAtIndex; + var at = this.valueToCode(block, atId, + this.ORDER_UNARY_NEGATION) || defaultAtIndex; } else { - var at = Blockly.PHP.valueToCode(block, atId, order) || + var at = this.valueToCode(block, atId, order) || defaultAtIndex; } @@ -302,10 +281,10 @@ Blockly.PHP.getAdjusted = function(block, atId, opt_delta, opt_negate, // If the index is dynamic, adjust it in code. if (delta > 0) { at = at + ' + ' + delta; - var innerOrder = Blockly.PHP.ORDER_ADDITION; + var innerOrder = this.ORDER_ADDITION; } else if (delta < 0) { at = at + ' - ' + -delta; - var innerOrder = Blockly.PHP.ORDER_SUBTRACTION; + var innerOrder = this.ORDER_SUBTRACTION; } if (opt_negate) { if (delta) { @@ -313,7 +292,7 @@ Blockly.PHP.getAdjusted = function(block, atId, opt_delta, opt_negate, } else { at = '-' + at; } - var innerOrder = Blockly.PHP.ORDER_UNARY_NEGATION; + var innerOrder = this.ORDER_UNARY_NEGATION; } innerOrder = Math.floor(innerOrder); order = Math.floor(order); diff --git a/generators/php/lists.js b/generators/php/lists.js index a985ce430..e2c90baeb 100644 --- a/generators/php/lists.js +++ b/generators/php/lists.js @@ -257,7 +257,7 @@ Blockly.PHP['lists_setIndex'] = function(block) { if (list.match(/^\$\w+$/)) { return ''; } - var listVar = Blockly.PHP.variableDB_.getDistinctName( + var listVar = Blockly.PHP.nameDB_.getDistinctName( 'tmp_list', Blockly.VARIABLE_CATEGORY_NAME); var code = listVar + ' = &' + list + ';\n'; list = listVar; @@ -328,7 +328,7 @@ Blockly.PHP['lists_setIndex'] = function(block) { var list = Blockly.PHP.valueToCode(block, 'LIST', Blockly.PHP.ORDER_REFERENCE) || 'array()'; var code = cacheList(); - var xVar = Blockly.PHP.variableDB_.getDistinctName( + var xVar = Blockly.PHP.nameDB_.getDistinctName( 'tmp_x', Blockly.VARIABLE_CATEGORY_NAME); code += xVar + ' = rand(0, count(' + list + ')-1);\n'; if (mode == 'SET') { diff --git a/generators/php/loops.js b/generators/php/loops.js index 265bbe689..3917060f5 100644 --- a/generators/php/loops.js +++ b/generators/php/loops.js @@ -28,11 +28,11 @@ Blockly.PHP['controls_repeat_ext'] = function(block) { var branch = Blockly.PHP.statementToCode(block, 'DO'); branch = Blockly.PHP.addLoopTrap(branch, block); var code = ''; - var loopVar = Blockly.PHP.variableDB_.getDistinctName( + var loopVar = Blockly.PHP.nameDB_.getDistinctName( 'count', Blockly.VARIABLE_CATEGORY_NAME); var endVar = repeats; if (!repeats.match(/^\w+$/) && !Blockly.isNumber(repeats)) { - endVar = Blockly.PHP.variableDB_.getDistinctName( + endVar = Blockly.PHP.nameDB_.getDistinctName( 'repeat_end', Blockly.VARIABLE_CATEGORY_NAME); code += endVar + ' = ' + repeats + ';\n'; } @@ -61,7 +61,7 @@ Blockly.PHP['controls_whileUntil'] = function(block) { Blockly.PHP['controls_for'] = function(block) { // For loop. - var variable0 = Blockly.PHP.variableDB_.getName( + var variable0 = Blockly.PHP.nameDB_.getName( block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); var argument0 = Blockly.PHP.valueToCode(block, 'FROM', Blockly.PHP.ORDER_ASSIGNMENT) || '0'; @@ -91,19 +91,19 @@ Blockly.PHP['controls_for'] = function(block) { // Cache non-trivial values to variables to prevent repeated look-ups. var startVar = argument0; if (!argument0.match(/^\w+$/) && !Blockly.isNumber(argument0)) { - startVar = Blockly.PHP.variableDB_.getDistinctName( + startVar = Blockly.PHP.nameDB_.getDistinctName( variable0 + '_start', Blockly.VARIABLE_CATEGORY_NAME); code += startVar + ' = ' + argument0 + ';\n'; } var endVar = argument1; if (!argument1.match(/^\w+$/) && !Blockly.isNumber(argument1)) { - endVar = Blockly.PHP.variableDB_.getDistinctName( + endVar = Blockly.PHP.nameDB_.getDistinctName( variable0 + '_end', Blockly.VARIABLE_CATEGORY_NAME); code += endVar + ' = ' + argument1 + ';\n'; } // Determine loop direction at start, in case one of the bounds // changes during loop execution. - var incVar = Blockly.PHP.variableDB_.getDistinctName( + var incVar = Blockly.PHP.nameDB_.getDistinctName( variable0 + '_inc', Blockly.VARIABLE_CATEGORY_NAME); code += incVar + ' = '; if (Blockly.isNumber(increment)) { @@ -126,7 +126,7 @@ Blockly.PHP['controls_for'] = function(block) { Blockly.PHP['controls_forEach'] = function(block) { // For each loop. - var variable0 = Blockly.PHP.variableDB_.getName( + var variable0 = Blockly.PHP.nameDB_.getName( block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); var argument0 = Blockly.PHP.valueToCode(block, 'LIST', Blockly.PHP.ORDER_ASSIGNMENT) || '[]'; diff --git a/generators/php/math.js b/generators/php/math.js index 397dc5dc7..6acb56af3 100644 --- a/generators/php/math.js +++ b/generators/php/math.js @@ -205,7 +205,7 @@ Blockly.PHP['math_change'] = function(block) { // Add to a variable in place. var argument0 = Blockly.PHP.valueToCode(block, 'DELTA', Blockly.PHP.ORDER_ADDITION) || '0'; - var varName = Blockly.PHP.variableDB_.getName( + var varName = Blockly.PHP.nameDB_.getName( block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); return varName + ' += ' + argument0 + ';\n'; }; diff --git a/generators/php/procedures.js b/generators/php/procedures.js index d50004771..c5828d8e5 100644 --- a/generators/php/procedures.js +++ b/generators/php/procedures.js @@ -14,31 +14,31 @@ goog.provide('Blockly.PHP.procedures'); goog.require('Blockly.PHP'); + Blockly.PHP['procedures_defreturn'] = function(block) { // Define a procedure with a return value. // First, add a 'global' statement for every variable that is not shadowed by // a local parameter. var globals = []; - var varName; var workspace = block.workspace; var variables = Blockly.Variables.allUsedVarModels(workspace) || []; for (var i = 0, variable; variable = variables[i]; i++) { - varName = variable.name; + var varName = variable.name; if (block.getVars().indexOf(varName) == -1) { - globals.push(Blockly.PHP.variableDB_.getName(varName, + globals.push(Blockly.PHP.nameDB_.getName(varName, Blockly.VARIABLE_CATEGORY_NAME)); } } // Add developer variables. var devVarList = Blockly.Variables.allDeveloperVariables(workspace); for (var i = 0; i < devVarList.length; i++) { - globals.push(Blockly.PHP.variableDB_.getName(devVarList[i], + globals.push(Blockly.PHP.nameDB_.getName(devVarList[i], Blockly.Names.DEVELOPER_VARIABLE_TYPE)); } globals = globals.length ? Blockly.PHP.INDENT + 'global ' + globals.join(', ') + ';\n' : ''; - var funcName = Blockly.PHP.variableDB_.getName( + var funcName = Blockly.PHP.nameDB_.getName( block.getFieldValue('NAME'), Blockly.PROCEDURE_CATEGORY_NAME); var xfix1 = ''; if (Blockly.PHP.STATEMENT_PREFIX) { @@ -70,7 +70,7 @@ Blockly.PHP['procedures_defreturn'] = function(block) { var args = []; var variables = block.getVars(); for (var i = 0; i < variables.length; i++) { - args[i] = Blockly.PHP.variableDB_.getName(variables[i], + args[i] = Blockly.PHP.nameDB_.getName(variables[i], Blockly.VARIABLE_CATEGORY_NAME); } var code = 'function ' + funcName + '(' + args.join(', ') + ') {\n' + @@ -88,7 +88,7 @@ Blockly.PHP['procedures_defnoreturn'] = Blockly.PHP['procedures_callreturn'] = function(block) { // Call a procedure with a return value. - var funcName = Blockly.PHP.variableDB_.getName( + var funcName = Blockly.PHP.nameDB_.getName( block.getFieldValue('NAME'), Blockly.PROCEDURE_CATEGORY_NAME); var args = []; var variables = block.getVars(); diff --git a/generators/php/text.js b/generators/php/text.js index b598f7a13..dba05c41e 100644 --- a/generators/php/text.js +++ b/generators/php/text.js @@ -58,7 +58,7 @@ Blockly.PHP['text_join'] = function(block) { Blockly.PHP['text_append'] = function(block) { // Append to a variable in place. - var varName = Blockly.PHP.variableDB_.getName( + var varName = Blockly.PHP.nameDB_.getName( block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); var value = Blockly.PHP.valueToCode(block, 'TEXT', Blockly.PHP.ORDER_ASSIGNMENT) || '\'\''; diff --git a/generators/php/variables.js b/generators/php/variables.js index 5ac4849ff..db9738ba2 100644 --- a/generators/php/variables.js +++ b/generators/php/variables.js @@ -17,7 +17,7 @@ goog.require('Blockly.PHP'); Blockly.PHP['variables_get'] = function(block) { // Variable getter. - var code = Blockly.PHP.variableDB_.getName(block.getFieldValue('VAR'), + var code = Blockly.PHP.nameDB_.getName(block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); return [code, Blockly.PHP.ORDER_ATOMIC]; }; @@ -26,7 +26,7 @@ Blockly.PHP['variables_set'] = function(block) { // Variable setter. var argument0 = Blockly.PHP.valueToCode(block, 'VALUE', Blockly.PHP.ORDER_ASSIGNMENT) || '0'; - var varName = Blockly.PHP.variableDB_.getName( + var varName = Blockly.PHP.nameDB_.getName( block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); return varName + ' = ' + argument0 + ';\n'; }; diff --git a/generators/python.js b/generators/python.js index 707c948e7..2c317b75d 100644 --- a/generators/python.js +++ b/generators/python.js @@ -101,7 +101,7 @@ Blockly.Python.ORDER_NONE = 99; // (...) /** * List of outer-inner pairings that do NOT require parentheses. - * @type {!Array.>} + * @type {!Array>} */ Blockly.Python.ORDER_OVERRIDES = [ // (foo()).bar -> foo().bar @@ -138,46 +138,45 @@ Blockly.Python.isInitialized = false; * @this {Blockly.Generator} */ Blockly.Python.init = function(workspace) { + // Call Blockly.Generator's init. + Object.getPrototypeOf(this).init.call(this); + /** * Empty loops or conditionals are not allowed in Python. */ - Blockly.Python.PASS = this.INDENT + 'pass\n'; - // Create a dictionary of definitions to be printed before the code. - Blockly.Python.definitions_ = Object.create(null); - // Create a dictionary mapping desired function names in definitions_ - // to actual function names (to avoid collisions with user functions). - Blockly.Python.functionNames_ = Object.create(null); + this.PASS = this.INDENT + 'pass\n'; - if (!Blockly.Python.variableDB_) { - Blockly.Python.variableDB_ = - new Blockly.Names(Blockly.Python.RESERVED_WORDS_); + if (!this.nameDB_) { + this.nameDB_ = new Blockly.Names(this.RESERVED_WORDS_); } else { - Blockly.Python.variableDB_.reset(); + this.nameDB_.reset(); } - Blockly.Python.variableDB_.setVariableMap(workspace.getVariableMap()); + this.nameDB_.setVariableMap(workspace.getVariableMap()); + this.nameDB_.populateVariables(workspace); + this.nameDB_.populateProcedures(workspace); var defvars = []; // Add developer variables (not created or named by the user). var devVarList = Blockly.Variables.allDeveloperVariables(workspace); for (var i = 0; i < devVarList.length; i++) { - defvars.push(Blockly.Python.variableDB_.getName(devVarList[i], + defvars.push(this.nameDB_.getName(devVarList[i], Blockly.Names.DEVELOPER_VARIABLE_TYPE) + ' = None'); } // Add user variables, but only ones that are being used. var variables = Blockly.Variables.allUsedVarModels(workspace); for (var i = 0; i < variables.length; i++) { - defvars.push(Blockly.Python.variableDB_.getName(variables[i].getId(), + defvars.push(this.nameDB_.getName(variables[i].getId(), Blockly.VARIABLE_CATEGORY_NAME) + ' = None'); } - Blockly.Python.definitions_['variables'] = defvars.join('\n'); + this.definitions_['variables'] = defvars.join('\n'); this.isInitialized = true; }; /** - * Prepend the generated code with the variable definitions. + * Prepend the generated code with import statements and variable definitions. * @param {string} code Generated code. * @return {string} Completed code. */ @@ -185,18 +184,19 @@ Blockly.Python.finish = function(code) { // Convert the definitions dictionary into a list. var imports = []; var definitions = []; - for (var name in Blockly.Python.definitions_) { - var def = Blockly.Python.definitions_[name]; + for (var name in this.definitions_) { + var def = this.definitions_[name]; if (def.match(/^(from\s+\S+\s+)?import\s+\S+/)) { imports.push(def); } else { definitions.push(def); } } - // Clean up temporary data. - delete Blockly.Python.definitions_; - delete Blockly.Python.functionNames_; - Blockly.Python.variableDB_.reset(); + // Call Blockly.Generator's finish. + code = Object.getPrototypeOf(this).finish.call(this, code); + this.isInitialized = false; + + this.nameDB_.reset(); var allDefs = imports.join('\n') + '\n\n' + definitions.join('\n\n'); return allDefs.replace(/\n\n+/g, '\n\n').replace(/\n*$/, '\n\n\n') + code; }; @@ -242,7 +242,7 @@ Blockly.Python.quote_ = function(string) { * @protected */ Blockly.Python.multiline_quote_ = function(string) { - var lines = string.split(/\n/g).map(Blockly.Python.quote_); + var lines = string.split(/\n/g).map(this.quote_); // Join with the following, plus a newline: // + '\n' + return lines.join(' + \'\\n\' + \n'); @@ -265,9 +265,8 @@ Blockly.Python.scrub_ = function(block, code, opt_thisOnly) { // Collect comment for this block. var comment = block.getCommentText(); if (comment) { - comment = Blockly.utils.string.wrap(comment, - Blockly.Python.COMMENT_WRAP - 3); - commentCode += Blockly.Python.prefixLines(comment + '\n', '# '); + comment = Blockly.utils.string.wrap(comment, this.COMMENT_WRAP - 3); + commentCode += this.prefixLines(comment + '\n', '# '); } // Collect comments for all value arguments. // Don't collect comments for nested statements. @@ -275,16 +274,16 @@ Blockly.Python.scrub_ = function(block, code, opt_thisOnly) { if (block.inputList[i].type == Blockly.inputTypes.VALUE) { var childBlock = block.inputList[i].connection.targetBlock(); if (childBlock) { - comment = Blockly.Python.allNestedComments(childBlock); + comment = this.allNestedComments(childBlock); if (comment) { - commentCode += Blockly.Python.prefixLines(comment, '# '); + commentCode += this.prefixLines(comment, '# '); } } } } } var nextBlock = block.nextConnection && block.nextConnection.targetBlock(); - var nextCode = opt_thisOnly ? '' : Blockly.Python.blockToCode(nextBlock); + var nextCode = opt_thisOnly ? '' : this.blockToCode(nextBlock); return commentCode + code + nextCode; }; @@ -303,9 +302,8 @@ Blockly.Python.getAdjustedInt = function(block, atId, opt_delta, opt_negate) { delta--; } var defaultAtIndex = block.workspace.options.oneBasedIndex ? '1' : '0'; - var atOrder = delta ? Blockly.Python.ORDER_ADDITIVE : - Blockly.Python.ORDER_NONE; - var at = Blockly.Python.valueToCode(block, atId, atOrder) || defaultAtIndex; + var atOrder = delta ? this.ORDER_ADDITIVE : this.ORDER_NONE; + var at = this.valueToCode(block, atId, atOrder) || defaultAtIndex; if (Blockly.isNumber(at)) { // If the index is a naked number, adjust it right now. diff --git a/generators/python/lists.js b/generators/python/lists.js index 647cbc79a..71898e589 100644 --- a/generators/python/lists.js +++ b/generators/python/lists.js @@ -187,7 +187,7 @@ Blockly.Python['lists_setIndex'] = function(block) { if (list.match(/^\w+$/)) { return ''; } - var listVar = Blockly.Python.variableDB_.getDistinctName( + var listVar = Blockly.Python.nameDB_.getDistinctName( 'tmp_list', Blockly.VARIABLE_CATEGORY_NAME); var code = listVar + ' = ' + list + '\n'; list = listVar; @@ -228,7 +228,7 @@ Blockly.Python['lists_setIndex'] = function(block) { case 'RANDOM': Blockly.Python.definitions_['import_random'] = 'import random'; var code = cacheList(); - var xVar = Blockly.Python.variableDB_.getDistinctName( + var xVar = Blockly.Python.nameDB_.getDistinctName( 'tmp_x', Blockly.VARIABLE_CATEGORY_NAME); code += xVar + ' = int(random.random() * len(' + list + '))\n'; if (mode == 'SET') { diff --git a/generators/python/logic.js b/generators/python/logic.js index 67e06ac35..f01a20b8a 100644 --- a/generators/python/logic.js +++ b/generators/python/logic.js @@ -33,7 +33,7 @@ Blockly.Python['controls_if'] = function(block) { Blockly.Python.injectId(Blockly.Python.STATEMENT_SUFFIX, block), Blockly.Python.INDENT) + branchCode; } - code += (n == 0 ? 'if ' : 'elif ' ) + conditionCode + ':\n' + branchCode; + code += (n == 0 ? 'if ' : 'elif ') + conditionCode + ':\n' + branchCode; ++n; } while (block.getInput('IF' + n)); diff --git a/generators/python/loops.js b/generators/python/loops.js index 792d887b6..cc58dc2b9 100644 --- a/generators/python/loops.js +++ b/generators/python/loops.js @@ -32,7 +32,7 @@ Blockly.Python['controls_repeat_ext'] = function(block) { } var branch = Blockly.Python.statementToCode(block, 'DO'); branch = Blockly.Python.addLoopTrap(branch, block) || Blockly.Python.PASS; - var loopVar = Blockly.Python.variableDB_.getDistinctName( + var loopVar = Blockly.Python.nameDB_.getDistinctName( 'count', Blockly.VARIABLE_CATEGORY_NAME); var code = 'for ' + loopVar + ' in range(' + repeats + '):\n' + branch; return code; @@ -56,7 +56,7 @@ Blockly.Python['controls_whileUntil'] = function(block) { Blockly.Python['controls_for'] = function(block) { // For loop. - var variable0 = Blockly.Python.variableDB_.getName( + var variable0 = Blockly.Python.nameDB_.getName( block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); var argument0 = Blockly.Python.valueToCode(block, 'FROM', Blockly.Python.ORDER_NONE) || '0'; @@ -143,7 +143,7 @@ Blockly.Python['controls_for'] = function(block) { arg = 'float(' + arg + ')'; } else { // It's complicated. - var varName = Blockly.Python.variableDB_.getDistinctName( + var varName = Blockly.Python.nameDB_.getDistinctName( variable0 + suffix, Blockly.VARIABLE_CATEGORY_NAME); code += varName + ' = float(' + arg + ')\n'; arg = varName; @@ -172,7 +172,7 @@ Blockly.Python['controls_for'] = function(block) { Blockly.Python['controls_forEach'] = function(block) { // For each loop. - var variable0 = Blockly.Python.variableDB_.getName( + var variable0 = Blockly.Python.nameDB_.getName( block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); var argument0 = Blockly.Python.valueToCode(block, 'LIST', Blockly.Python.ORDER_RELATIONAL) || '[]'; diff --git a/generators/python/math.js b/generators/python/math.js index c5d3eb6db..74fa070df 100644 --- a/generators/python/math.js +++ b/generators/python/math.js @@ -226,7 +226,7 @@ Blockly.Python['math_change'] = function(block) { 'from numbers import Number'; var argument0 = Blockly.Python.valueToCode(block, 'DELTA', Blockly.Python.ORDER_ADDITIVE) || '0'; - var varName = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'), + var varName = Blockly.Python.nameDB_.getName(block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); return varName + ' = (' + varName + ' if isinstance(' + varName + ', Number) else 0) + ' + argument0 + '\n'; diff --git a/generators/python/procedures.js b/generators/python/procedures.js index 521b5e4cc..9840dc5ac 100644 --- a/generators/python/procedures.js +++ b/generators/python/procedures.js @@ -20,26 +20,25 @@ Blockly.Python['procedures_defreturn'] = function(block) { // First, add a 'global' statement for every variable that is not shadowed by // a local parameter. var globals = []; - var varName; var workspace = block.workspace; var variables = Blockly.Variables.allUsedVarModels(workspace) || []; - for (var i = 0, variable; variable = variables[i]; i++) { - varName = variable.name; + for (var i = 0, variable; (variable = variables[i]); i++) { + var varName = variable.name; if (block.getVars().indexOf(varName) == -1) { - globals.push(Blockly.Python.variableDB_.getName(varName, + globals.push(Blockly.Python.nameDB_.getName(varName, Blockly.VARIABLE_CATEGORY_NAME)); } } // Add developer variables. var devVarList = Blockly.Variables.allDeveloperVariables(workspace); for (var i = 0; i < devVarList.length; i++) { - globals.push(Blockly.Python.variableDB_.getName(devVarList[i], + globals.push(Blockly.Python.nameDB_.getName(devVarList[i], Blockly.Names.DEVELOPER_VARIABLE_TYPE)); } globals = globals.length ? Blockly.Python.INDENT + 'global ' + globals.join(', ') + '\n' : ''; - var funcName = Blockly.Python.variableDB_.getName( + var funcName = Blockly.Python.nameDB_.getName( block.getFieldValue('NAME'), Blockly.PROCEDURE_CATEGORY_NAME); var xfix1 = ''; if (Blockly.Python.STATEMENT_PREFIX) { @@ -73,7 +72,7 @@ Blockly.Python['procedures_defreturn'] = function(block) { var args = []; var variables = block.getVars(); for (var i = 0; i < variables.length; i++) { - args[i] = Blockly.Python.variableDB_.getName(variables[i], + args[i] = Blockly.Python.nameDB_.getName(variables[i], Blockly.VARIABLE_CATEGORY_NAME); } var code = 'def ' + funcName + '(' + args.join(', ') + '):\n' + @@ -91,7 +90,7 @@ Blockly.Python['procedures_defnoreturn'] = Blockly.Python['procedures_callreturn'] = function(block) { // Call a procedure with a return value. - var funcName = Blockly.Python.variableDB_.getName(block.getFieldValue('NAME'), + var funcName = Blockly.Python.nameDB_.getName(block.getFieldValue('NAME'), Blockly.PROCEDURE_CATEGORY_NAME); var args = []; var variables = block.getVars(); diff --git a/generators/python/text.js b/generators/python/text.js index 82fe8d056..0771f4ade 100644 --- a/generators/python/text.js +++ b/generators/python/text.js @@ -77,7 +77,7 @@ Blockly.Python['text_join'] = function(block) { elements[i] = Blockly.Python.valueToCode(block, 'ADD' + i, Blockly.Python.ORDER_NONE) || '\'\''; } - var tempVar = Blockly.Python.variableDB_.getDistinctName('x', + var tempVar = Blockly.Python.nameDB_.getDistinctName('x', Blockly.VARIABLE_CATEGORY_NAME); var code = '\'\'.join([str(' + tempVar + ') for ' + tempVar + ' in [' + elements.join(', ') + ']])'; @@ -87,7 +87,7 @@ Blockly.Python['text_join'] = function(block) { Blockly.Python['text_append'] = function(block) { // Append to a variable in place. - var varName = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'), + var varName = Blockly.Python.nameDB_.getName(block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); var value = Blockly.Python.valueToCode(block, 'TEXT', Blockly.Python.ORDER_NONE) || '\'\''; diff --git a/generators/python/variables.js b/generators/python/variables.js index f72f4c137..da259591c 100644 --- a/generators/python/variables.js +++ b/generators/python/variables.js @@ -17,7 +17,7 @@ goog.require('Blockly.Python'); Blockly.Python['variables_get'] = function(block) { // Variable getter. - var code = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'), + var code = Blockly.Python.nameDB_.getName(block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); return [code, Blockly.Python.ORDER_ATOMIC]; }; @@ -26,7 +26,7 @@ Blockly.Python['variables_set'] = function(block) { // Variable setter. var argument0 = Blockly.Python.valueToCode(block, 'VALUE', Blockly.Python.ORDER_NONE) || '0'; - var varName = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'), + var varName = Blockly.Python.nameDB_.getName(block.getFieldValue('VAR'), Blockly.VARIABLE_CATEGORY_NAME); return varName + ' = ' + argument0 + '\n'; }; diff --git a/msg/json/bcc.json b/msg/json/bcc.json index 9a13638bd..c8794faba 100644 --- a/msg/json/bcc.json +++ b/msg/json/bcc.json @@ -173,8 +173,8 @@ "TEXT_ISEMPTY_TOOLTIP": "اضافه‌کردن صحیح اگر متن فراهم‌شده خالی است.", "TEXT_INDEXOF_TOOLTIP": "شاخصی از اولین آخرین رخ‌داد متن اول در متن دوم بر می‌گرداند. اگر متن یافت نشد %1 باز می‌گرداند.", "TEXT_INDEXOF_TITLE": "در متن %1 %2 %3", - "TEXT_INDEXOF_OPERATOR_FIRST": "اولین رخداد متن را بیاب", - "TEXT_INDEXOF_OPERATOR_LAST": "آخرین رخداد متن را بیاب", + "TEXT_INDEXOF_OPERATOR_FIRST": "اولی نبشتانکء بیتگݔنا درگݔج", + "TEXT_INDEXOF_OPERATOR_LAST": "آھری نبشتانکء بیتگݔنا درگݔج", "TEXT_CHARAT_FROM_START": "گرفتن حرف #", "TEXT_CHARAT_FROM_END": "گرفتن حرف # از آخر", "TEXT_CHARAT_FIRST": "گرفتن اولین حرف", @@ -217,7 +217,7 @@ "LISTS_ISEMPTY_TITLE": "%1 خالی است", "LISTS_ISEMPTY_TOOLTIP": "اگر فهرست خالی است مقدار صجیج بر می‌گرداند.", "LISTS_INLIST": "مہ لیست‌ئا", - "LISTS_INDEX_OF_FIRST": "آخرین رخداد متن را بیاب", + "LISTS_INDEX_OF_FIRST": "آھری نبشتانکء بیتگݔنا درگݔج", "LISTS_INDEX_OF_LAST": "یافتن آخرین رخ‌داد مورد", "LISTS_INDEX_OF_TOOLTIP": "شاخصی از اولین/آخرین رخ‌داد مورد در فهرست را بر می‌گرداند. %1 بر می‌گرداند اگر متن موجود نبود.", "LISTS_GET_INDEX_GET": "گرفتن", @@ -253,7 +253,7 @@ "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "موردی به ته فهرست الحاق می‌کند.", "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "مورد را به صورت تصادفی در یک فهرست می‌افزاید.", "LISTS_GET_SUBLIST_START_FROM_START": "گرفتن زیرمجموعه‌ای از #", - "LISTS_GET_SUBLIST_START_FROM_END": "گرفتن زیرمجموعه‌ای از # از انتها", + "LISTS_GET_SUBLIST_START_FROM_END": "چݔر چیزے گِرَگ چہ # ءِ آھرا", "LISTS_GET_SUBLIST_START_FIRST": "گرفتن زیرمجموعه‌ای از ابتدا", "LISTS_GET_SUBLIST_END_FROM_START": "به #", "LISTS_GET_SUBLIST_END_FROM_END": "به # از انتها", diff --git a/msg/json/bs.json b/msg/json/bs.json new file mode 100644 index 000000000..561e98890 --- /dev/null +++ b/msg/json/bs.json @@ -0,0 +1,157 @@ +{ + "@metadata": { + "authors": [ + "Palapa", + "Semso98" + ] + }, + "VARIABLES_DEFAULT_NAME": "stavka", + "UNNAMED_KEY": "neimenovano", + "TODAY": "Danas", + "DUPLICATE_BLOCK": "Dupliciraj", + "ADD_COMMENT": "Dodaj komentar", + "REMOVE_COMMENT": "Ukloni komentare", + "DUPLICATE_COMMENT": "Kopiraj komentar", + "EXTERNAL_INPUTS": "Vanjski ulazi", + "INLINE_INPUTS": "Redni ulazi", + "DELETE_BLOCK": "Obriši blok", + "DELETE_X_BLOCKS": "Obriši %1 blokova", + "DELETE_ALL_BLOCKS": "Izbrisati svih %1 blokova?", + "CLEAN_UP": "Očisti blokove", + "COLLAPSE_BLOCK": "Skupi blok", + "COLLAPSE_ALL": "Skupi blokove", + "EXPAND_BLOCK": "Proširi blok", + "EXPAND_ALL": "Proširi blokove", + "DISABLE_BLOCK": "Onemogući blok", + "ENABLE_BLOCK": "Omogući blok", + "HELP": "Pomoć", + "UNDO": "Poništi", + "REDO": "Ponovi", + "CHANGE_VALUE_TITLE": "Promijeni vrijednost:", + "RENAME_VARIABLE": "Preimenuj varijablu...", + "RENAME_VARIABLE_TITLE": "Preimenuj sve \"%1\" varijable u:", + "NEW_VARIABLE": "Napravi varijablu...", + "NEW_STRING_VARIABLE": "Napravi varijablu niza...", + "NEW_NUMBER_VARIABLE": "Napravi varijablu broja...", + "NEW_COLOUR_VARIABLE": "Napravi varijablu boje...", + "NEW_VARIABLE_TYPE_TITLE": "Vrsta nove varijable:", + "NEW_VARIABLE_TITLE": "Ime nove varijable:", + "VARIABLE_ALREADY_EXISTS": "Varijabla s imenom \"%1\" već postoji.", + "VARIABLE_ALREADY_EXISTS_FOR_ANOTHER_TYPE": "Varijabla s imenom \"%1\" već postoji za drugu vrstu: \"%2\".", + "DELETE_VARIABLE_CONFIRMATION": "Izbrisati %1 upotrebu varijable \"%2\"?", + "CANNOT_DELETE_VARIABLE_PROCEDURE": "Ne mogu izbrisati varijablu \"%1\" jer je dio definicije funckije \"%2\"", + "DELETE_VARIABLE": "Izbriši varijablu \"%1\"", + "COLOUR_PICKER_HELPURL": "https://bs.wikipedia.org/wiki/Boja", + "COLOUR_PICKER_TOOLTIP": "Izaberi boju sa palete.", + "COLOUR_RANDOM_TITLE": "nasumična boja", + "COLOUR_RANDOM_TOOLTIP": "Odaberi boju nasumično.", + "COLOUR_RGB_TITLE": "boja sa", + "COLOUR_RGB_RED": "crvenom", + "COLOUR_RGB_GREEN": "zelenom", + "COLOUR_RGB_BLUE": "plavom", + "COLOUR_RGB_TOOLTIP": "Napravi boju s određenom količinom crvene, zelene i plave boje. Sve vrijednosti moraju biti između 0 i 100.", + "COLOUR_BLEND_TITLE": "pomiješaj", + "COLOUR_BLEND_COLOUR1": "boju 1", + "COLOUR_BLEND_COLOUR2": "boju 2", + "COLOUR_BLEND_RATIO": "odnos", + "COLOUR_BLEND_TOOLTIP": "Pomiješaj dvije boje zajedno sa zadanim odnosom (0.0 - 1.0).", + "CONTROLS_REPEAT_TITLE": "ponovi %1 puta", + "CONTROLS_REPEAT_INPUT_DO": "izvrši", + "CONTROLS_REPEAT_TOOLTIP": "Izvrši neku naredbu nekoliko puta.", + "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "ponavljati dok", + "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "ponavljati do", + "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Dok je vrijednost tačna, izvršava neke naredbe.", + "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Dok je vrijednost netačna, izvršava neke naredbe.", + "CONTROLS_FOR_TOOLTIP": "Neka varijabla \"%1\" uzima vrijednosti od početnog do krajnjeg broja, brojeći po određenom intervalu i neka izvršava određene blokove.", + "CONTROLS_FOR_TITLE": "broji sa %1 od %2 do %3 po %4", + "CONTROLS_FOREACH_TITLE": "za svaku stavku %1 na spisku %2", + "CONTROLS_FOREACH_TOOLTIP": "Za svaku stavku na spisku, dodjeljuje vrijednost stavke varijabli \"%1\", a zatim izvršava neke naredbe.", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "izađi iz petlje", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "nastavi sa sljedećom iteracijom petlje", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Napusti petlju koja sadrži ovaj blok.", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Preskoči ostatak ove petlje i nastavi sa sljedećom iteracijom.", + "CONTROLS_FLOW_STATEMENTS_WARNING": "Upozorenje: Ovaj blok se može koristiti samo unutar petlje.", + "CONTROLS_IF_TOOLTIP_1": "Ako je vrijednost tačna, izvršava neke naredbe.", + "CONTROLS_IF_TOOLTIP_2": "Ako je vrijednost tačna, izvršava neke naredbe. U suprotnom, izvršava drugi blok naredbi.", + "CONTROLS_IF_MSG_IF": "ako", + "CONTROLS_IF_MSG_ELSEIF": "inače ako", + "CONTROLS_IF_MSG_ELSE": "inače", + "CONTROLS_IF_ELSEIF_TOOLTIP": "Dodajte uslov bloku \"ako\".", + "IOS_OK": "U redu", + "IOS_CANCEL": "Otkaži", + "IOS_ERROR": "Greška", + "IOS_PROCEDURES_INPUTS": "ULAZI", + "IOS_PROCEDURES_ADD_INPUT": "+ Dodaj ulaz", + "IOS_PROCEDURES_ALLOW_STATEMENTS": "Dozvoli naredbe", + "IOS_VARIABLES_ADD_VARIABLE": "+ Dodaj varijablu", + "IOS_VARIABLES_ADD_BUTTON": "Dodaj", + "IOS_VARIABLES_RENAME_BUTTON": "Preimenuj", + "IOS_VARIABLES_DELETE_BUTTON": "Obriši", + "IOS_VARIABLES_VARIABLE_NAME": "Ime varijable", + "IOS_VARIABLES_EMPTY_NAME_ERROR": "Ne možete koristiti prazno ime varijable.", + "LOGIC_COMPARE_HELPURL": "https://bs.wikipedia.org/wiki/Nejednakost", + "LOGIC_OPERATION_AND": "i", + "LOGIC_OPERATION_OR": "ili", + "LOGIC_NEGATE_TITLE": "nije %1", + "LOGIC_BOOLEAN_TRUE": "tačno", + "LOGIC_BOOLEAN_FALSE": "netačno", + "LOGIC_BOOLEAN_TOOLTIP": "Vraća ili tačno ili netačno.", + "LOGIC_NULL": "bez vrijednosti", + "LOGIC_NULL_TOOLTIP": "Vraća \"bez vrijednosti\".", + "LOGIC_TERNARY_CONDITION": "test", + "LOGIC_TERNARY_IF_TRUE": "ako je tačno", + "LOGIC_TERNARY_IF_FALSE": "ako je netačno", + "MATH_NUMBER_HELPURL": "https://bs.wikipedia.org/wiki/Broj", + "MATH_NUMBER_TOOLTIP": "Broj.", + "MATH_ARITHMETIC_HELPURL": "https://bs.wikipedia.org/wiki/Aritmetika", + "MATH_ARITHMETIC_TOOLTIP_ADD": "Vraća zbir dva broja.", + "MATH_ARITHMETIC_TOOLTIP_MINUS": "Vraća razliku dva broja.", + "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Vraća proizvod dva broja.", + "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Vraća količnik dva broja.", + "MATH_ARITHMETIC_TOOLTIP_POWER": "Vraća prvi broj na eksponent drugog broja.", + "MATH_SINGLE_HELPURL": "https://bs.wikipedia.org/wiki/Kvadratni_korijen", + "MATH_SINGLE_OP_ROOT": "kvadratni korijen", + "MATH_SINGLE_TOOLTIP_ROOT": "Vraća kvadratni korijen broja", + "MATH_SINGLE_OP_ABSOLUTE": "apsolutno", + "MATH_SINGLE_TOOLTIP_ABS": "Vraća absolutnu vrijednost broja.", + "MATH_SINGLE_TOOLTIP_NEG": "Vraća negaciju broja.", + "MATH_SINGLE_TOOLTIP_LN": "Vraća prirodni logoritam broja.", + "MATH_SINGLE_TOOLTIP_LOG10": "Vraća logoritam broja za bazu 10.", + "MATH_SINGLE_TOOLTIP_EXP": "Vraća e na eksponent broja.", + "MATH_SINGLE_TOOLTIP_POW10": "Vraća 10 na eksponent broja.", + "MATH_TRIG_HELPURL": "https://bs.wikipedia.org/wiki/Trigonometrijska_funkcija", + "MATH_TRIG_TOOLTIP_SIN": "Vraća sinus stepena (ne radijana).", + "MATH_TRIG_TOOLTIP_COS": "Vraća kosinus stepena (ne radijana).", + "MATH_TRIG_TOOLTIP_TAN": "Vraća tangens stepena (ne radijana).", + "MATH_TRIG_TOOLTIP_ASIN": "Vraća arkussinus broja.", + "MATH_TRIG_TOOLTIP_ACOS": "Vraća arkuskosinus broja.", + "MATH_TRIG_TOOLTIP_ATAN": "Vraća arkustangens broja.", + "MATH_CONSTANT_HELPURL": "https://bs.wikipedia.org/wiki/Matemati%C4%8Dka_konstanta", + "MATH_CONSTANT_TOOLTIP": "Vraća jednu od uobičajenih konstanti: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…) ili ∞ (beskonačnost).", + "MATH_IS_EVEN": "je paran", + "MATH_IS_ODD": "je neparan", + "MATH_IS_PRIME": "je prost", + "MATH_IS_WHOLE": "je cijeli", + "MATH_IS_POSITIVE": "je pozitivan", + "MATH_IS_NEGATIVE": "je negativan", + "MATH_IS_DIVISIBLE_BY": "je djeljiv sa", + "MATH_IS_TOOLTIP": "Provjerava da li je broj paran, neparan, prost, cijeli, pozitivan, negativan ili je djeljiv s određenim brojem. Vraća tačno ili netačno.", + "MATH_CHANGE_TITLE": "promijeni %1 za %2", + "MATH_CHANGE_TOOLTIP": "Dodaj broj varijabli \"%1\".", + "MATH_ROUND_TOOLTIP": "Zaokružuje broj na veću ili manju vrijednost.", + "MATH_ROUND_OPERATOR_ROUND": "zaokruži", + "MATH_ROUND_OPERATOR_ROUNDUP": "zaokruži naviše", + "MATH_ROUND_OPERATOR_ROUNDDOWN": "zaokruži naniže", + "MATH_ONLIST_OPERATOR_SUM": "zbir spiska", + "MATH_ONLIST_TOOLTIP_SUM": "Vraća zbir svih brojeva sa spiska.", + "TEXT_LENGTH_TITLE": "dužina teksta %1", + "TEXT_ISEMPTY_TITLE": "%1 je prazan", + "LISTS_LENGTH_TITLE": "dužina spiska %1", + "LISTS_LENGTH_TOOLTIP": "Vraća dužinu spiska.", + "LISTS_ISEMPTY_TITLE": "%1 je prazan", + "LISTS_ISEMPTY_TOOLTIP": "Vraća \"tačno\" ako je spisak prazan.", + "LISTS_INLIST": "na spisku", + "LISTS_INDEX_OF_FIRST": "pronađi prvo pojavljivanje stavke", + "LISTS_INDEX_OF_LAST": "pronađi posljednje pojavljivanje stavke", + "PROCEDURES_MUTATORARG_TITLE": "ime ulaza:" +} diff --git a/msg/json/cs.json b/msg/json/cs.json index e8401a3e4..ed184e390 100644 --- a/msg/json/cs.json +++ b/msg/json/cs.json @@ -6,6 +6,7 @@ "Dita", "Dvorapa", "Espertus", + "Georg101", "Ilimanaq29", "Koo6", "Matěj Grabovský", diff --git a/msg/json/el.json b/msg/json/el.json index f209df26f..fbcb9b4e8 100644 --- a/msg/json/el.json +++ b/msg/json/el.json @@ -7,6 +7,7 @@ "GR", "Gchr", "Geraki", + "Giannaras99", "Glavkos", "KATRINE1992", "Namatreasure", @@ -47,18 +48,18 @@ "CHANGE_VALUE_TITLE": "Άλλαξε την τιμή:", "RENAME_VARIABLE": "Μετονόμασε τη μεταβλητή...", "RENAME_VARIABLE_TITLE": "Μετονόμασε όλες τις μεταβλητές «%1» σε:", - "NEW_VARIABLE": "Δημιουργήστε μεταβλητή", + "NEW_VARIABLE": "Δημιουργήστε μεταβλητή...", "NEW_STRING_VARIABLE": "Δημιουργία μεταβλητή συμβολοσειράς...", "NEW_NUMBER_VARIABLE": "Δημιουργία μεταβλητής αριθμού...", "NEW_COLOUR_VARIABLE": "Δημιουργία μεταβλητής χρώματος...", "NEW_VARIABLE_TYPE_TITLE": "Νέος τύπος μεταβλητής:", "NEW_VARIABLE_TITLE": "Νέο όνομα μεταβλητής:", - "VARIABLE_ALREADY_EXISTS": "Η μεταβλητή με το όνομα \"%1\" υπάρχει ήδη", + "VARIABLE_ALREADY_EXISTS": "Η μεταβλητή με το όνομα '%1' υπάρχει ήδη.", "VARIABLE_ALREADY_EXISTS_FOR_ANOTHER_TYPE": "Μια μεταβλητή με όνομα '%1' υπάρχει πάντα για έναν άλλο τύπο: '%2'.", - "DELETE_VARIABLE_CONFIRMATION": "Θέλετε να διαγράψετε το %1 που χρησιμοποιείτε της μεταβλητής '%2'?", + "DELETE_VARIABLE_CONFIRMATION": "Θέλετε να διαγράψετε το %1 που χρησιμοποιείτε από την μεταβλητή '%2'?", "CANNOT_DELETE_VARIABLE_PROCEDURE": "Δεν μπορώ να διαγράψω την μεταβλητή '%1' διότι είναι μέρος του ορισμού της λειτουργίας '%2'", "DELETE_VARIABLE": "Διαγράψτε την μεταβλητή '%1'", - "COLOUR_PICKER_HELPURL": "https://el.wikipedia.org/wiki/%CE%A7%CF%81%CF%8E%CE%BC%CE%B1", + "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/Color", "COLOUR_PICKER_TOOLTIP": "Επιτρέπει επιλογή χρώματος από την παλέτα.", "COLOUR_RANDOM_TITLE": "τυχαίο χρώμα", "COLOUR_RANDOM_TOOLTIP": "Επιλέγει χρώμα τυχαία.", @@ -67,7 +68,7 @@ "COLOUR_RGB_RED": "κόκκινο", "COLOUR_RGB_GREEN": "πράσινο", "COLOUR_RGB_BLUE": "μπλε", - "COLOUR_RGB_TOOLTIP": "Δημιουργεί χρώμα με το συγκεκριμένο ποσό του κόκκινου, πράσινου και μπλε που ορίζεις. Όλες οι τιμές πρέπει να είναι μεταξύ 0 και 100.", + "COLOUR_RGB_TOOLTIP": "Δημιουργήστε ένα χρώμα με την καθορισμένη ποσότητα κόκκινου, πράσινου και μπλε. Όλες οι τιμές πρέπει να είναι μεταξύ 0 και 100.", "COLOUR_BLEND_HELPURL": "https://meyerweb.com/eric/tools/color-blend/#:::rgbp", "COLOUR_BLEND_TITLE": "μείγμα", "COLOUR_BLEND_COLOUR1": "χρώμα 1", @@ -81,8 +82,8 @@ "CONTROLS_WHILEUNTIL_HELPURL": "https://github.com/google/blockly/wiki/Loops#repeat", "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "επανάλαβε ενώ", "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "επανάλαβε μέχρι", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Ενόσω μια τιμή είναι αληθής, τότε εκτελεί κάποιες εντολές.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Ενόσω μια τιμή είναι ψευδής, τότε εκτελεί κάποιες εντολές.", + "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Εφόσον μια τιμή είναι αληθής, τότε εκτελεί κάποιες εντολές.", + "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Εφόσον μια τιμή είναι ψευδής, τότε εκτελεί κάποιες εντολές.", "CONTROLS_FOR_HELPURL": "https://github.com/google/blockly/wiki/Loops#count-with", "CONTROLS_FOR_TOOLTIP": "Η μεταβλητή «%1» παίρνει τιμές ξεκινώντας από τον αριθμό έναρξης μέχρι τον αριθμό τέλους αυξάνοντας κάθε φορά με το καθορισμένο βήμα και εκτελώντας το καθορισμένο μπλοκ.", "CONTROLS_FOR_TITLE": "μέτρησε με %1 από το %2 έως το %3 ανά %4", diff --git a/msg/json/it.json b/msg/json/it.json index eb1ae3af4..85284c3fc 100644 --- a/msg/json/it.json +++ b/msg/json/it.json @@ -1,6 +1,7 @@ { "@metadata": { "authors": [ + "Ajeje Brazorf", "Albe Albe 460", "Albe Albe460", "Beta16", @@ -48,7 +49,7 @@ "NEW_VARIABLE_TYPE_TITLE": "Tipo della nuova variabile:", "NEW_VARIABLE_TITLE": "Nome della nuova variabile:", "VARIABLE_ALREADY_EXISTS": "Una variabile denominata '%1' esiste già.", - "VARIABLE_ALREADY_EXISTS_FOR_ANOTHER_TYPE": "Una variabile nominata '%1' esiste già per un'altro tipo: '%2'.", + "VARIABLE_ALREADY_EXISTS_FOR_ANOTHER_TYPE": "Una variabile nominata '%1' esiste già per un altro tipo: '%2'.", "DELETE_VARIABLE_CONFIRMATION": "Cancella %1 usi della variabile '%2'?", "CANNOT_DELETE_VARIABLE_PROCEDURE": "Non si può cancellare la variabile '%1' perché è parte della definizione della funzione '%2'", "DELETE_VARIABLE": "Cancella la variabile '%1'", diff --git a/msg/json/ja.json b/msg/json/ja.json index 63c8c89b2..ce2870b97 100644 --- a/msg/json/ja.json +++ b/msg/json/ja.json @@ -9,6 +9,7 @@ "Oda", "Omotecho", "Otokoume", + "RYU N", "Sgk", "Shirayuki", "Suiato", @@ -48,7 +49,7 @@ "NEW_NUMBER_VARIABLE": "数の変数を作る...", "NEW_COLOUR_VARIABLE": "色の変数を作る...", "NEW_VARIABLE_TYPE_TITLE": "新しい変数の型:", - "NEW_VARIABLE_TITLE": "新しい変数の名前:", + "NEW_VARIABLE_TITLE": "新しい変数の名前:", "VARIABLE_ALREADY_EXISTS": "変数名 '%1' は既に存在しています。", "VARIABLE_ALREADY_EXISTS_FOR_ANOTHER_TYPE": "'%2' 型の '%1' という名前の変数が既に存在します。", "DELETE_VARIABLE_CONFIRMATION": "%1か所で使われている変数 '%2' を削除しますか?", @@ -59,7 +60,7 @@ "COLOUR_RANDOM_TITLE": "ランダムな色", "COLOUR_RANDOM_TOOLTIP": "ランダムに色を選ぶ。", "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "色:", + "COLOUR_RGB_TITLE": "色:", "COLOUR_RGB_RED": "赤", "COLOUR_RGB_GREEN": "緑", "COLOUR_RGB_BLUE": "青", @@ -216,6 +217,7 @@ "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", "MATH_RANDOM_FLOAT_TITLE_RANDOM": "1未満の正の乱数", "MATH_RANDOM_FLOAT_TOOLTIP": "0.0以上で1.0未満の範囲の乱数を返します。", + "MATH_ATAN2_HELPURL": "https://en.wikipedia.org/wiki/Atan2", "MATH_ATAN2_TITLE": "X:%1 Y:%2のaran2", "MATH_ATAN2_TOOLTIP": "点 (X, Y) の逆関数を -180 度から 180度まで返します。", "TEXT_TEXT_HELPURL": "https://ja.wikipedia.org/wiki/文字列", diff --git a/msg/json/sd.json b/msg/json/sd.json index 666d47032..a127c3c4f 100644 --- a/msg/json/sd.json +++ b/msg/json/sd.json @@ -2,6 +2,7 @@ "@metadata": { "authors": [ "Aursani", + "Charan", "Indus Asia", "Mehtab ahmed", "Tweety" @@ -13,12 +14,12 @@ "ADD_COMMENT": "رايو ڏيو", "REMOVE_COMMENT": "رايو ڊاهيو", "DUPLICATE_COMMENT": "نقل رايو", - "EXTERNAL_INPUTS": "ٻاهرين داخلائون", + "EXTERNAL_INPUTS": "ٻاهريون داخلائون", "INLINE_INPUTS": "اِنلائين اِن پٽس", "DELETE_BLOCK": "بلاڪ ڊاهيو", "DELETE_X_BLOCKS": "1٪ بلاڪ ڊاهيو", "DELETE_ALL_BLOCKS": "سڀ %1 بلاڪ ڊاھيون؟", - "CLEAN_UP": "بندشون هٽايو", + "CLEAN_UP": "بلاڪ صاف ڪيو", "COLLAPSE_BLOCK": "بلاڪ ڍڪيو", "COLLAPSE_ALL": "بلاڪَ ڍڪيو", "EXPAND_BLOCK": "بلاڪ نمايو", @@ -26,7 +27,7 @@ "DISABLE_BLOCK": "بلاڪ کي غيرفعال بڻايو", "ENABLE_BLOCK": "بلاڪ کي فعال بڻايو", "HELP": "مدد", - "UNDO": "ڊاهيو", + "UNDO": "اڻڪريو", "REDO": "ٻيهر ڪريو", "CHANGE_VALUE_TITLE": "قدر بدلايو", "RENAME_VARIABLE": "ڦرڻي کي نئون نالو ڏيو...", diff --git a/msg/json/uk.json b/msg/json/uk.json index 9e81b2c27..ec63f3cdb 100644 --- a/msg/json/uk.json +++ b/msg/json/uk.json @@ -10,6 +10,7 @@ "Piramidion", "SimondR", "Visem", + "Ата", "아라" ] }, @@ -53,13 +54,13 @@ "COLOUR_PICKER_TOOLTIP": "Вибрати колір з палітри.", "COLOUR_RANDOM_TITLE": "випадковий колір", "COLOUR_RANDOM_TOOLTIP": "Вибрати колір навмання.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", + "COLOUR_RGB_HELPURL": "https://www.december.com/html/spec/colorpercompact.html", "COLOUR_RGB_TITLE": "колір з", "COLOUR_RGB_RED": "червоний", "COLOUR_RGB_GREEN": "зелений", "COLOUR_RGB_BLUE": "синій", "COLOUR_RGB_TOOLTIP": "Створити колір зі вказаними рівнями червоного, зеленого та синього. Усі значення мають бути від 0 до 100.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", + "COLOUR_BLEND_HELPURL": "https://meyerweb.com/eric/tools/color-blend/#:::rgbp", "COLOUR_BLEND_TITLE": "змішати", "COLOUR_BLEND_COLOUR1": "колір 1", "COLOUR_BLEND_COLOUR2": "колір 2", @@ -205,7 +206,7 @@ "MATH_ATAN2_TOOLTIP": "Повертає арктангенс точки (X, Y) у градусах від -180 до 180.", "TEXT_TEXT_HELPURL": "https://uk.wikipedia.org/wiki/Рядок_(програмування)", "TEXT_TEXT_TOOLTIP": "Символ, слово або рядок тексту.", - "TEXT_JOIN_HELPURL": "http://www.chemie.fu-berlin.de/chemnet/use/info/make/make_8.html", + "TEXT_JOIN_HELPURL": "https://github.com/google/blockly/wiki/Text#text-creation", "TEXT_JOIN_TITLE_CREATEWITH": "створити текст з", "TEXT_JOIN_TOOLTIP": "Створити фрагмент тексту шляхом з'єднування будь-якого числа елементів.", "TEXT_CREATE_JOIN_TITLE_JOIN": "приєднати", @@ -221,7 +222,7 @@ "TEXT_INDEXOF_TITLE": "у тексті %1 %2 %3.", "TEXT_INDEXOF_OPERATOR_FIRST": "знайти перше входження тексту", "TEXT_INDEXOF_OPERATOR_LAST": "знайти останнє входження тексту", - "TEXT_CHARAT_HELPURL": "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm", + "TEXT_CHARAT_HELPURL": "https://github.com/google/blockly/wiki/Text#extracting-text", "TEXT_CHARAT_TITLE": "з тексту %1 %2", "TEXT_CHARAT_FROM_START": "отримати символ #", "TEXT_CHARAT_FROM_END": "отримати символ # з кінця", diff --git a/package-lock.json b/package-lock.json index 5bd46e529..5996d2bf6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -85,18 +85,18 @@ "dev": true }, "@babel/runtime": { - "version": "7.13.10", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz", - "integrity": "sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz", + "integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==", "dev": true, "requires": { "regenerator-runtime": "^0.13.4" } }, "@babel/runtime-corejs3": { - "version": "7.13.10", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.13.10.tgz", - "integrity": "sha512-x/XYVQ1h684pp1mJwOV4CyvqZXqbc8CMsMGUnAbuc82ZCdv1U63w5RSUzgDSXQHG5Rps/kiksH6g2D5BuaKyXg==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.14.0.tgz", + "integrity": "sha512-0R0HTZWHLk6G8jIk0FtoX+AatCtKnswS98VhXwGImFc759PJRp4Tru0PQYZofyijTFUr+gT8Mu7sgXVJLQ0ceg==", "dev": true, "requires": { "core-js-pure": "^3.0.0", @@ -213,18 +213,18 @@ } }, "@blockly/block-test": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/@blockly/block-test/-/block-test-1.0.12.tgz", - "integrity": "sha512-N1hFTyjNYEan5zg6KcyyMo1/GpVUsMBS+Bbdgfea1Maj1+qXjEnr1Tem2M96gblzo5WQVWQadwqUEq/ozTK+Iw==", + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@blockly/block-test/-/block-test-1.0.14.tgz", + "integrity": "sha512-vLvlrqTUHTXUTtGJg/xrcZ+Nlv+j+h+76Qq7XtQZk4U6Fp0zyc5Zm+vVv5wvtxmxx+50wk35gKkj514Qrgmlwg==", "dev": true }, "@blockly/dev-tools": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@blockly/dev-tools/-/dev-tools-2.2.0.tgz", - "integrity": "sha512-zPqRCEzi4mSdEzX8tfF4JIQESeGu5+kSUebkuIAce2AC/xODGfZDLt6ARw8BgS0By5hENsttY0SIOvNQfm4maQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@blockly/dev-tools/-/dev-tools-2.3.0.tgz", + "integrity": "sha512-1zHbPRLrJGjoPDO8N157esf6yfGYD3V30NpK8sEmItZLNaJkpg8Dn01rSasYAuuNPJuRLKM4q0miMDP/r8aLeg==", "dev": true, "requires": { - "@blockly/block-test": "^1.0.12", + "@blockly/block-test": "^1.0.14", "chai": "^4.2.0", "dat.gui": "^0.7.7", "lodash.assign": "^4.2.0", @@ -234,23 +234,29 @@ }, "dependencies": { "@blockly/block-test": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/@blockly/block-test/-/block-test-1.0.12.tgz", - "integrity": "sha512-N1hFTyjNYEan5zg6KcyyMo1/GpVUsMBS+Bbdgfea1Maj1+qXjEnr1Tem2M96gblzo5WQVWQadwqUEq/ozTK+Iw==", + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@blockly/block-test/-/block-test-1.0.14.tgz", + "integrity": "sha512-vLvlrqTUHTXUTtGJg/xrcZ+Nlv+j+h+76Qq7XtQZk4U6Fp0zyc5Zm+vVv5wvtxmxx+50wk35gKkj514Qrgmlwg==", "dev": true } } }, + "@blockly/theme-dark": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@blockly/theme-dark/-/theme-dark-1.0.7.tgz", + "integrity": "sha512-ohZRlrbKnRtzp63mDh/9XRFnTnnpyG110ff2UjGYmEuBcWeazgY1aISufrPbOANnPDfVV5SZI9DQnNvXjdmP9w==", + "dev": true + }, "@blockly/theme-modern": { - "version": "2.1.14", - "resolved": "https://registry.npmjs.org/@blockly/theme-modern/-/theme-modern-2.1.14.tgz", - "integrity": "sha512-+jhpKdn8ipd+hjNuHjm1el326ANYWgTP8C7mwvmb23Rp3INTKqYOscUGgy3vJ/BBZhJ+mi4GGv0aYl1YabdLIw==", + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/@blockly/theme-modern/-/theme-modern-2.1.17.tgz", + "integrity": "sha512-zVqZK0uX9mmyaAToovOkojyHH5o0JciJGKZdC2New6a2hilBCdOAaF36/xQpscaczMrNPiOpFJvtmbT4aM90rQ==", "dev": true }, "@eslint/eslintrc": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", - "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.1.tgz", + "integrity": "sha512-5v7TDE9plVhvxQeWLXDTvFvJBdH6pEsdnl2g/dAptmuFEPedQ4Erq5rsDsX+mvAM610IhNaO2W5V1dOOnDKxkQ==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -335,9 +341,9 @@ "dev": true }, "@sinonjs/commons": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.2.tgz", - "integrity": "sha512-sruwd86RJHdsVf/AtBoijDmUqJp3B6hF/DGC23C+JaegnDHaZyewCjoVGTdg3J0uz3Zs7NnIT05OBOmML72lQw==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", "dev": true, "requires": { "type-detect": "4.0.8" @@ -402,6 +408,12 @@ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, + "@types/expect": { + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", + "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", + "dev": true + }, "@types/http-cache-semantics": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz", @@ -444,6 +456,16 @@ "@types/node": "*" } }, + "@types/vinyl": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.4.tgz", + "integrity": "sha512-2o6a2ixaVI2EbwBPg1QYLGQoHK56p/8X/sGfKbFC8N6sY9lfjsMf/GprtkQkSya0D4uRiutRZ2BWj7k3JvLsAQ==", + "dev": true, + "requires": { + "@types/expect": "^1.20.4", + "@types/node": "*" + } + }, "@types/which": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/which/-/which-1.3.2.tgz", @@ -467,21 +489,21 @@ "dev": true }, "@wdio/config": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@wdio/config/-/config-7.3.0.tgz", - "integrity": "sha512-sMvvGIVnie7h/c/h3Zuz6Zv5UMN97SBrKVGdK9v6MAWobCWXUTTfVV4E9gBk6pWwT+rIBByt/ygQ1Mqhk77EEA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@wdio/config/-/config-7.6.0.tgz", + "integrity": "sha512-SNm4qRU5dyvNBBvCu8q59wB3zBKNoKIMCktzA2I8kBq+QLyIcbda1rVuOvywUM+s7h9xVzet9eP5OaPK7VXkaA==", "dev": true, "requires": { - "@wdio/logger": "7.0.0", - "@wdio/types": "7.2.1", + "@wdio/logger": "7.5.3", + "@wdio/types": "7.6.0", "deepmerge": "^4.0.0", "glob": "^7.1.2" } }, "@wdio/logger": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-7.0.0.tgz", - "integrity": "sha512-P3inCmtc0ms1vnx3v25+U6ccD2dkiuBhaJwmIWPwSbQn8cNQ5AcQIbRWMbnzFHbJ/jSrVBnlwmUArW7L02Zpeg==", + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-7.5.3.tgz", + "integrity": "sha512-r9EADpm0ncS1bDQSWi/nhF9C59/WNLbdAAFlo782E9ItFCpDhNit3aQP9vETv1vFxJRjUIM8Fw/HW8zwPadkbw==", "dev": true, "requires": { "chalk": "^4.0.0", @@ -506,9 +528,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -557,33 +579,34 @@ } }, "@wdio/protocols": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-7.1.1.tgz", - "integrity": "sha512-JLwmuQcTsewP2z4DZ2J9mi+uTuVOzFeWMbbEwNjxKbXfD2zi+TGIarMkETGyW0EtQtVscQtbZcqdkvBPEye8iA==", + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-7.5.3.tgz", + "integrity": "sha512-lpNaKwxYhDSL6neDtQQYXvzMAw+u4PXx65ryeMEX82mkARgzSZps5Kyrg9ub7X4T17K1NPfnY6UhZEWg6cKJCg==", "dev": true }, "@wdio/repl": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-7.3.0.tgz", - "integrity": "sha512-T//qKHfPw3RiuR9hyzjFI/PYKV4pvxmcHoxjPG4NE+xvu1kj3vReArJk+vcsXELulcjIArDB1W60c0P5gjXSBg==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-7.6.0.tgz", + "integrity": "sha512-xaAs5HRi8oii+Zsf9FKQVQkMLSy6bQRSmWeCLGr04MlOwyQs8KM5FzzPpHlA+qBWgLr3ck1HdC7EiUqmLYYfIQ==", "dev": true, "requires": { - "@wdio/utils": "7.3.0" + "@wdio/utils": "7.6.0" } }, "@wdio/types": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@wdio/types/-/types-7.2.1.tgz", - "integrity": "sha512-05+nxO2I/9asQvjgTT2ZteDi7PguAruoOw1Vu8zAVqE+yP5YQxW1CX3galRost8UlQ6Vft/RgmsYLabdxJzzag==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-7.6.0.tgz", + "integrity": "sha512-BPPd7K6TpF4v1YaqUf+wDRwpys5asc7H7LDik4kHjLaGMwDfj+r0Goo3Z7xQn2fFdCuV99dkrI1N9vkgc2pDjA==", "dev": true, "requires": { + "@types/node": "^14.14.31", "got": "^11.8.1" }, "dependencies": { "@sindresorhus/is": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.0.tgz", - "integrity": "sha512-FyD2meJpDPjyNQejSjvnhpgI/azsQkA4lGbuu5BQZfjvJ9cbRZXzeWL2HceCekW4lixO9JPesIIQkSoLjeJHNQ==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", + "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==", "dev": true }, "@szmarczak/http-timer": { @@ -595,6 +618,12 @@ "defer-to-connect": "^2.0.0" } }, + "@types/node": { + "version": "14.17.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.0.tgz", + "integrity": "sha512-w8VZUN/f7SSbvVReb9SWp6cJFevxb4/nkG65yLAya//98WgocKm5PLDAtSs5CtJJJM+kHmJjO/6mmYW4MHShZA==", + "dev": true + }, "cacheable-request": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.1.tgz", @@ -681,9 +710,9 @@ "dev": true }, "p-cancelable": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.0.tgz", - "integrity": "sha512-HAZyB3ZodPo+BDpb4/Iu7Jv4P6cSazBz9ZM0ChhEXp70scx834aWCEjQRwgt41UzzejUAPdbqqONfRWTPYrPAQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", "dev": true }, "responselike": { @@ -698,13 +727,13 @@ } }, "@wdio/utils": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-7.3.0.tgz", - "integrity": "sha512-dEQEKsKdnrydzacK26K+XfhL9d/GrJIssw0ert614yqG1F6db8qhGugfSrufVqDgwe6+Pj4EEJsw9AWpKzj3pg==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-7.6.0.tgz", + "integrity": "sha512-nfbQCAToX01pUCyojF2osVmg9grHWf3kGnK9gD65GG9lPXEs76T/ACYUfo+gRgeNBq8UTeZOoHSrXOtQrCoEbQ==", "dev": true, "requires": { - "@wdio/logger": "7.0.0", - "@wdio/types": "7.2.1" + "@wdio/logger": "7.5.3", + "@wdio/types": "7.6.0" } }, "abab": { @@ -724,23 +753,15 @@ "acorn": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", - "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", - "dev": true + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==" }, "acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", + "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", "requires": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" - } + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" } }, "acorn-jsx": { @@ -750,9 +771,9 @@ "dev": true }, "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==" + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==" }, "agent-base": { "version": "6.0.2", @@ -973,6 +994,11 @@ "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", "dev": true }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=" + }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -1120,12 +1146,6 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true - }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", @@ -1263,9 +1283,9 @@ "dev": true }, "binaryextensions": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.1.2.tgz", - "integrity": "sha512-xVNN69YGDghOqCCtA6FI7avYrr02mTJjOgB0/f1VPD3pJC8QEvjTKWc4epDx8AqxxA75NI0QpVM2gPJXUbE4Tg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.3.0.tgz", + "integrity": "sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg==", "dev": true }, "bl": { @@ -1437,16 +1457,6 @@ } } }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1635,17 +1645,6 @@ } } }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - } - }, "clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", @@ -1817,14 +1816,14 @@ } }, "concurrently": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-6.0.0.tgz", - "integrity": "sha512-Ik9Igqnef2ONLjN2o/OVx1Ow5tymVvvEwQeYCQdD/oV+CN9oWhxLk7ibcBdOtv0UzBqHCEKRwbKceYoTK8t3fQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-6.1.0.tgz", + "integrity": "sha512-jy+xj49pvqeKjc2TAVXRIhrgPG51eBKDZti0kZ41kaWk9iLbyWBjH6KMFpW7peOLkEymD+ZM83Lx6UEy3N/M9g==", "dev": true, "requires": { "chalk": "^4.1.0", "date-fns": "^2.16.1", - "lodash": "^4.17.20", + "lodash": "^4.17.21", "read-pkg": "^5.2.0", "rxjs": "^6.6.3", "spawn-command": "^0.0.2-1", @@ -1843,9 +1842,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -1935,9 +1934,9 @@ } }, "core-js-pure": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.10.0.tgz", - "integrity": "sha512-CC582enhrFZStO4F8lGI7QL3SYx7/AIRc+IdSi3btrQGrVsTawo5K/crmKbRrQ+MOMhNX4v+PATn0k2NN6wI7A==", + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.12.1.tgz", + "integrity": "sha512-1cch+qads4JnDSWsvc7d6nzlKAippwjUlf6vykkTLW53VSV+NkE6muGBToAjEA8pG90cSfcud3JgVmW2ds5TaQ==", "dev": true }, "core-util-is": { @@ -1979,16 +1978,25 @@ } }, "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } } }, "css": { @@ -2071,19 +2079,19 @@ "dev": true }, "data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", "requires": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" } }, "date-fns": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.17.0.tgz", - "integrity": "sha512-ZEhqxUtEZeGgg9eHNSOAJ8O9xqSgiJdrL0lzSSfMF54x6KXWJiOH/xntSJ9YomJPrYH/p08t6gWjGWq1SDJlSA==", + "version": "2.21.3", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.21.3.tgz", + "integrity": "sha512-HeYdzCaFflc1i4tGbj7JKMjM4cKGYoyxwcIIkHzNgCkX8xXDNJDZXgDDVchIWpN4eQc3lH37WarduXFZJOtxfw==", "dev": true }, "debug": { @@ -2141,11 +2149,6 @@ } } }, - "decimal.js": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.1.tgz", - "integrity": "sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw==" - }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", @@ -2284,23 +2287,31 @@ "dev": true }, "devtools": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/devtools/-/devtools-7.3.0.tgz", - "integrity": "sha512-er7wXFKy9LyCi5t8ehAOU9puufh5cI90ku9f5KxUqSCZmoJUvj94rfE0SiU8tZCMcVTr5zjgeEU3CpkEH3EG3w==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/devtools/-/devtools-7.6.0.tgz", + "integrity": "sha512-N7A9rHlkeo8cQEgOpFjOmUQfIReERFe/nNU7CY7T1HO8JI2f57dzRzqq0jDlM4VtX4Y0/vQtkVzknZ9O1Ff3UA==", "dev": true, "requires": { - "@wdio/config": "7.3.0", - "@wdio/logger": "7.0.0", - "@wdio/protocols": "7.1.1", - "@wdio/types": "7.2.1", - "@wdio/utils": "7.3.0", + "@types/node": "^14.14.31", + "@wdio/config": "7.6.0", + "@wdio/logger": "7.5.3", + "@wdio/protocols": "7.5.3", + "@wdio/types": "7.6.0", + "@wdio/utils": "7.6.0", "chrome-launcher": "^0.13.1", "edge-paths": "^2.1.0", - "puppeteer-core": "^7.1.0", + "puppeteer-core": "^9.1.0", + "query-selector-shadow-dom": "^1.0.0", "ua-parser-js": "^0.7.21", "uuid": "^8.0.0" }, "dependencies": { + "@types/node": { + "version": "14.17.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.0.tgz", + "integrity": "sha512-w8VZUN/f7SSbvVReb9SWp6cJFevxb4/nkG65yLAya//98WgocKm5PLDAtSs5CtJJJM+kHmJjO/6mmYW4MHShZA==", + "dev": true + }, "uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -2310,9 +2321,9 @@ } }, "devtools-protocol": { - "version": "0.0.863986", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.863986.tgz", - "integrity": "sha512-WMf5KuRLsLwJMp9JdawSvoEpxZPqyyNeOZ3YR8QF8lE9IVHbbpdWeuXV22SJxPUemFeznvVlwSBeQz91nL+41A==", + "version": "0.0.882987", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.882987.tgz", + "integrity": "sha512-BXKWVSagixwFcGy+cHh6TEBL39f9hgDsVREAq+KaEaQy8Vn4a7Xhj70ClvZL9+S5M7U4800F9CSjUsAzkgsuRg==", "dev": true }, "diff": { @@ -2331,18 +2342,11 @@ } }, "domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", - "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", "requires": { - "webidl-conversions": "^5.0.0" - }, - "dependencies": { - "webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==" - } + "webidl-conversions": "^4.0.2" } }, "duplexer3": { @@ -2403,12 +2407,6 @@ } } }, - "editions": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz", - "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==", - "dev": true - }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -2510,7 +2508,6 @@ "version": "1.12.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.12.0.tgz", "integrity": "sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==", - "dev": true, "requires": { "esprima": "^3.1.3", "estraverse": "^4.2.0", @@ -2520,25 +2517,27 @@ } }, "eslint": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.23.0.tgz", - "integrity": "sha512-kqvNVbdkjzpFy0XOszNwjkKzZ+6TcwCQ/h+ozlcIWwaimBBuhlQ4nN6kbiM2L+OjDcznkTJxzYfRFH92sx4a0Q==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.27.0.tgz", + "integrity": "sha512-JZuR6La2ZF0UD384lcbnd0Cgg6QJjiCwhMD6eU4h/VGPcVGwawNNzKU41tgokGXnfjOOyI6QIffthhJTPzzuRA==", "dev": true, "requires": { "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.0", + "@eslint/eslintrc": "^0.4.1", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.0.1", "doctrine": "^3.0.0", "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", "eslint-scope": "^5.1.1", "eslint-utils": "^2.1.0", "eslint-visitor-keys": "^2.0.0", "espree": "^7.3.1", "esquery": "^1.4.0", "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "functional-red-black-tree": "^1.0.1", "glob-parent": "^5.0.0", @@ -2550,7 +2549,7 @@ "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", - "lodash": "^4.17.21", + "lodash.merge": "^4.6.2", "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", @@ -2559,7 +2558,7 @@ "semver": "^7.2.1", "strip-ansi": "^6.0.0", "strip-json-comments": "^3.1.0", - "table": "^6.0.4", + "table": "^6.0.9", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" }, @@ -2574,18 +2573,18 @@ } }, "@babel/helper-validator-identifier": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", "dev": true }, "@babel/highlight": { - "version": "7.13.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", - "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", + "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.12.11", + "@babel/helper-validator-identifier": "^7.14.0", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -2600,6 +2599,12 @@ "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true } } }, @@ -2610,9 +2615,9 @@ "dev": true }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -2660,21 +2665,22 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true }, "eslint-visitor-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, "glob-parent": { @@ -2687,9 +2693,9 @@ } }, "globals": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.7.0.tgz", - "integrity": "sha512-Aipsz6ZKRxa/xQkZhNg0qIWXT6x6rD46f6x/PCnBomlttdIyAPak4YD9jTmKpZ72uROSMU87qJtcgpgHaVchiA==", + "version": "13.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.9.0.tgz", + "integrity": "sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -2705,12 +2711,6 @@ "type-check": "~0.4.0" } }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -2725,12 +2725,6 @@ "word-wrap": "^1.2.3" } }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -2746,21 +2740,6 @@ "lru-cache": "^6.0.0" } }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, "strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", @@ -2793,24 +2772,9 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } } } }, - "eslint-plugin-es5": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-es5/-/eslint-plugin-es5-1.5.0.tgz", - "integrity": "sha512-Qxmfo7v2B7SGAEURJo0dpBweFf+JU15kSyALfiB2rXWcBuJ96r6X9kFHXFnhdopPHCaHjoQs1xQPUJVbGMb1AA==", - "dev": true - }, "eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -2864,8 +2828,7 @@ "esprima": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" }, "esquery": { "version": "1.4.0", @@ -2904,8 +2867,7 @@ "estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" }, "esutils": { "version": "2.0.3", @@ -2928,21 +2890,6 @@ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "dev": true }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, "exit-on-epipe": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", @@ -3197,12 +3144,13 @@ } }, "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "locate-path": "^3.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, "findup-sync": { @@ -3314,12 +3262,11 @@ "dev": true }, "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", "dev": true, "requires": { - "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" @@ -3908,9 +3855,9 @@ "dev": true }, "gaxios": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.1.0.tgz", - "integrity": "sha512-vb0to8xzGnA2qcgywAjtshOKKVDf2eQhJoiL6fHhgW5tVN7wNk7egnYIO9zotfn3lQ3De1VPdf7V5/BWfCtCmg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.2.0.tgz", + "integrity": "sha512-Ms7fNifGv0XVU+6eIyL9LB7RVESeML9+cMvkwGS70xyD6w2Z80wl6RiqiJ9k1KFlJCUTQqFFc8tXmPQfSKUe8g==", "dev": true, "requires": { "abort-controller": "^3.0.0", @@ -3940,25 +3887,6 @@ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true - } - } - }, "get-port": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", @@ -4095,79 +4023,56 @@ } }, "google-closure-compiler": { - "version": "20210302.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20210302.0.0.tgz", - "integrity": "sha512-dGZTQZjjAbM67CFB1f1XFDFpkGmZ6/kcnofwcRlEaIjMaCEfyb+NrshP6mAWy0IptsYYIU4n9aeSMyXzXlO3Mw==", + "version": "20210505.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20210505.0.0.tgz", + "integrity": "sha512-moeYaj4S6YTdOOvjv1ZLdUld/2YXw7q1GqUUHJJd+rE/uViyesozg8yKQZWcB3tvurhb+qEvFFet8CYoeaQHng==", "dev": true, "requires": { "chalk": "2.x", - "google-closure-compiler-java": "^20210302.0.0", - "google-closure-compiler-linux": "^20210302.0.0", - "google-closure-compiler-osx": "^20210302.0.0", - "google-closure-compiler-windows": "^20210302.0.0", + "google-closure-compiler-java": "^20210505.0.0", + "google-closure-compiler-linux": "^20210505.0.0", + "google-closure-compiler-osx": "^20210505.0.0", + "google-closure-compiler-windows": "^20210505.0.0", "minimist": "1.x", "vinyl": "2.x", "vinyl-sourcemaps-apply": "^0.2.0" } }, "google-closure-compiler-java": { - "version": "20210302.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-java/-/google-closure-compiler-java-20210302.0.0.tgz", - "integrity": "sha512-t4lSzS6y9e76eVCuyVN6xoBLBzBrVr3BzFWK8ogF+2TvOF92cEAbOHyZ/SV+P7tKBkB2MeEeOwOzcIVXNE0zkA==", + "version": "20210505.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-java/-/google-closure-compiler-java-20210505.0.0.tgz", + "integrity": "sha512-h+DfQAaaCLFmmtasOS8eyh0M4D+JInTJfEP4byV5R1cnMninpGGLHOG3PNgLLzkXkIO/fu4ILEcVzoGmgJEoMA==", "dev": true }, "google-closure-compiler-linux": { - "version": "20210302.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20210302.0.0.tgz", - "integrity": "sha512-tW0sScP38BvoqRXqDO6KWnZOLrV9E0xPi+rgqU0I7rXdCq1ZX7/8IuUtP3EIHW0sAFywtfmxlvR+V7nhy1hecA==", + "version": "20210505.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20210505.0.0.tgz", + "integrity": "sha512-ADN2kFfIR1NiR24kLYb4YkX4MeXDJaT5OfRQEkiuIdZMtd28oEkm80LxCGuC7ftKEixoMm3f9/OG01B4U+xsnA==", "dev": true, "optional": true }, "google-closure-compiler-osx": { - "version": "20210302.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-osx/-/google-closure-compiler-osx-20210302.0.0.tgz", - "integrity": "sha512-N9WgKJuHfDCKewyj8lS5D8LBAig860FidRQiuP9+eYfdnMkdWUv3IQvGpBHrnKafF0DLjeCSZXTMlEZ9N8qjgg==", + "version": "20210505.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-osx/-/google-closure-compiler-osx-20210505.0.0.tgz", + "integrity": "sha512-JTwdh23aD2pwRU4QZjujxp/+rGfhex3utNWEdUDRMNpUGstUK7XPCDG8jNBtUpyuRiXFnpZa90qButqRgotQBA==", "dev": true, "optional": true }, "google-closure-compiler-windows": { - "version": "20210302.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-windows/-/google-closure-compiler-windows-20210302.0.0.tgz", - "integrity": "sha512-axKAOwkcCqTeW4aRwHXp08m3rmoNQaGUhnTGmT9vAzO9Be7y/aFo3ckjDWfJZEQXnWgwy9dc1+gub0lQb7SATA==", + "version": "20210505.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-windows/-/google-closure-compiler-windows-20210505.0.0.tgz", + "integrity": "sha512-bKTbg/f4ak72OggEMaH/7oExqOO9dS+TxwGhoovYOt/YaVR/8MDfGdxsOhqoiboiFwYysTPz8bwINjYQK6AwnA==", "dev": true, "optional": true }, "google-closure-deps": { - "version": "20210202.0.0", - "resolved": "https://registry.npmjs.org/google-closure-deps/-/google-closure-deps-20210202.0.0.tgz", - "integrity": "sha512-4ikrvED7s1sYBvxvjctnq4mC55xAeFPYVgLh217no/KvVPwqOWDTdCu9PCOU3ew8BhpojAeiQ6MvIRxNrFNOIQ==", + "version": "20210406.0.0", + "resolved": "https://registry.npmjs.org/google-closure-deps/-/google-closure-deps-20210406.0.0.tgz", + "integrity": "sha512-4mn6qZ8u4c/9fhebKccxyN882l5/0O4nuJ+ibuxDy0y7XMgolSLNF/Gmg1HEhEgX00CF/JBKrc/rw0WVjnlSfw==", "dev": true, "requires": { - "argparse": "^1.0.9", "minimatch": "^3.0.4", - "yargs": "^12.0.2" - }, - "dependencies": { - "yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" - } - } + "yargs": "^16.2.0" } }, "got": { @@ -4431,14 +4336,24 @@ "dev": true }, "gulp-replace": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.0.0.tgz", - "integrity": "sha512-lgdmrFSI1SdhNMXZQbrC75MOl1UjYWlOWNbNRnz+F/KHmgxt3l6XstBoAYIdadwETFyG/6i+vWUSCawdC3pqOw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.1.3.tgz", + "integrity": "sha512-HcPHpWY4XdF8zxYkDODHnG2+7a3nD/Y8Mfu3aBgMiCFDW3X2GiOKXllsAmILcxe3KZT2BXoN18WrpEFm48KfLQ==", "dev": true, "requires": { - "istextorbinary": "2.2.1", - "readable-stream": "^2.0.1", - "replacestream": "^4.0.0" + "@types/node": "^14.14.41", + "@types/vinyl": "^2.0.4", + "istextorbinary": "^3.0.0", + "replacestream": "^4.0.3", + "yargs-parser": ">=5.0.0-security.0" + }, + "dependencies": { + "@types/node": { + "version": "14.14.44", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.44.tgz", + "integrity": "sha512-+gaugz6Oce6ZInfI/tK4Pq5wIIkJMEJUu92RB3Eu93mtj4wjjjz9EB5mLp5s1pSsLXdC/CPut/xF20ZzAQJbTA==", + "dev": true + } } }, "gulp-series": { @@ -4681,11 +4596,11 @@ "dev": true }, "html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", "requires": { - "whatwg-encoding": "^1.0.5" + "whatwg-encoding": "^1.0.1" } }, "http-cache-semantics": { @@ -4794,11 +4709,10 @@ "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", "dev": true }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=" }, "is-absolute": { "version": "1.0.0", @@ -4845,15 +4759,6 @@ "binary-extensions": "^1.0.0" } }, - "is-boolean-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", - "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", - "dev": true, - "requires": { - "call-bind": "^1.0.0" - } - }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -4909,9 +4814,9 @@ } }, "is-docker": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz", - "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "dev": true }, "is-extendable": { @@ -4967,12 +4872,6 @@ } } }, - "is-number-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", - "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", - "dev": true - }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -4988,11 +4887,6 @@ "isobject": "^3.0.1" } }, - "is-potential-custom-element-name": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz", - "integrity": "sha1-DFLlS8yjkbssSUsh6GJtczbG45c=" - }, "is-promise": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", @@ -5008,18 +4902,6 @@ "is-unc-path": "^1.0.0" } }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true - }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -5085,20 +4967,19 @@ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "istextorbinary": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", - "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-3.3.0.tgz", + "integrity": "sha512-Tvq1W6NAcZeJ8op+Hq7tdZ434rqnMx4CCZ7H0ff83uEloDvVbqAwaMTZcafKGJT0VHkYzuXUiCY4hlXQg6WfoQ==", "dev": true, "requires": { - "binaryextensions": "2", - "editions": "^1.3.3", - "textextensions": "2" + "binaryextensions": "^2.2.0", + "textextensions": "^3.2.0" } }, "js-green-licenses": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/js-green-licenses/-/js-green-licenses-3.0.0.tgz", - "integrity": "sha512-K7RxQh6ex1PAHzllVzBP2UO7i4xeKwhCUn01mOXl/LmZX9ExTxQf9CkahlyojXAsjGK60gfV2NbD2fhXOzIDlw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-green-licenses/-/js-green-licenses-3.0.1.tgz", + "integrity": "sha512-dKyO14U6LaDzJ5gNlvP/v1vkTW7TTXEKNxMHnkxqdYStcYVEJlfubfqbEageVzV41PWu7felyNbwawoEJ/RpYQ==", "dev": true, "requires": { "gaxios": "^4.0.0", @@ -5112,9 +4993,9 @@ }, "dependencies": { "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -5212,69 +5093,42 @@ } }, "jsdom": { - "version": "16.5.2", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.5.2.tgz", - "integrity": "sha512-JxNtPt9C1ut85boCbJmffaQ06NBnzkQY/MWO3YxPW8IWS38A26z+B1oBvA9LwKrytewdfymnhi4UNH3/RAgZrg==", + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-15.2.1.tgz", + "integrity": "sha512-fAl1W0/7T2G5vURSyxBzrJ1LSdQn6Tr5UX/xD4PXDx/PDgwygedfW6El/KIj3xJ7FU61TTYnc/l/B7P49Eqt6g==", "requires": { - "abab": "^2.0.5", - "acorn": "^8.1.0", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "html-encoding-sniffer": "^2.0.1", - "is-potential-custom-element-name": "^1.0.0", + "abab": "^2.0.0", + "acorn": "^7.1.0", + "acorn-globals": "^4.3.2", + "array-equal": "^1.0.0", + "cssom": "^0.4.1", + "cssstyle": "^2.0.0", + "data-urls": "^1.1.0", + "domexception": "^1.0.1", + "escodegen": "^1.11.1", + "html-encoding-sniffer": "^1.0.2", "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "request": "^2.88.2", - "request-promise-native": "^1.0.9", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", + "parse5": "5.1.0", + "pn": "^1.1.0", + "request": "^2.88.0", + "request-promise-native": "^1.0.7", + "saxes": "^3.1.9", + "symbol-tree": "^3.2.2", + "tough-cookie": "^3.0.1", + "w3c-hr-time": "^1.0.1", + "w3c-xmlserializer": "^1.1.2", + "webidl-conversions": "^4.0.2", "whatwg-encoding": "^1.0.5", "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.4", + "whatwg-url": "^7.0.0", + "ws": "^7.0.0", "xml-name-validator": "^3.0.0" }, "dependencies": { "acorn": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.1.0.tgz", - "integrity": "sha512-LWCF/Wn0nfHOmJ9rzQApGnxnvgfROzGilS8936rqN/lfcYkY9MYZzdMqN+2NJ4SlTc+m5HiSa+kNfDtI64dwUA==" - }, - "escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "requires": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - }, - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" - }, - "ws": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.4.tgz", - "integrity": "sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==" + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" } } }, @@ -5393,15 +5247,6 @@ "readable-stream": "^2.0.5" } }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, "lead": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", @@ -5509,13 +5354,12 @@ } }, "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "p-locate": "^4.1.0" } }, "lodash": { @@ -5589,6 +5433,11 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" + }, "lodash.template": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", @@ -5645,9 +5494,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -5731,15 +5580,6 @@ "kind-of": "^6.0.2" } }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "requires": { - "p-defer": "^1.0.0" - } - }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -5747,9 +5587,9 @@ "dev": true }, "map-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.1.0.tgz", - "integrity": "sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.2.1.tgz", + "integrity": "sha512-+WA2/1sPmDj1dlvvJmB5G6JKfY9dpn7EVBUL06+y6PoljPkh+6V1QihwxNkbcGxCRjt2b0F9K0taiCuo7MbdFQ==", "dev": true }, "map-visit": { @@ -5795,9 +5635,9 @@ "dev": true }, "marky": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.1.tgz", - "integrity": "sha512-md9k+Gxa3qLH6sUKpeC2CNkJK/Ld+bEz5X96nYwloqphQE0CKCVEKco/6jxEZixinqNdz5RFi/KaCyfbMDMAXQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.2.tgz", + "integrity": "sha512-k1dB2HNeaNyORco8ulVEhctyEGkKHb2YWAhDsxeFlW2nROIirsctBYzKwwS3Vza+sKTS1zO4Z+n9/+9WbGLIxQ==", "dev": true }, "matchdep": { @@ -5841,17 +5681,6 @@ "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", "dev": true }, - "mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - } - }, "memoizee": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", @@ -5899,9 +5728,9 @@ } }, "hosted-git-info": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", - "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", + "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -5917,14 +5746,14 @@ } }, "normalize-package-data": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.0.tgz", - "integrity": "sha512-6lUjEI0d3v6kFrtgA/lOx4zHCWULXsFNIjHolnZCKCTLA6m/G625cdn3O7eNmT0iD3jfo6HZ9cdImGZwf21prw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.2.tgz", + "integrity": "sha512-6CdZocmfGaKnIHPVFhJJZ3GuR8SsLKvDANFp47Jmy51aKIr8akjAWTSxtpI+MBgBFdSMRyo4hMpDlT6dTffgZg==", "dev": true, "requires": { - "hosted-git-info": "^3.0.6", - "resolve": "^1.17.0", - "semver": "^7.3.2", + "hosted-git-info": "^4.0.1", + "resolve": "^1.20.0", + "semver": "^7.3.4", "validate-npm-package-license": "^3.0.1" } }, @@ -5937,68 +5766,12 @@ "p-limit": "^2.2.0" } }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true - } - } - }, "read-pkg-up": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", @@ -6019,19 +5792,19 @@ } }, "resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "dev": true, "requires": { - "is-core-module": "^2.1.0", + "is-core-module": "^2.2.0", "path-parse": "^1.0.6" } }, "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -6044,9 +5817,9 @@ "dev": true }, "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "version": "20.2.7", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz", + "integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==", "dev": true } } @@ -6073,24 +5846,18 @@ } }, "mime-db": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", - "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==" + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", + "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==" }, "mime-types": { - "version": "2.1.29", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", - "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", + "version": "2.1.30", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", + "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", "requires": { - "mime-db": "1.46.0" + "mime-db": "1.47.0" } }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, "mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", @@ -6171,9 +5938,9 @@ "dev": true }, "mocha": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.2.tgz", - "integrity": "sha512-UdmISwr/5w+uXLPKspgoV7/RXZwKRTiTjJ2/AC5ZiEztIoOYdfKb19+9jNmEInzx5pBsCyJQzarAxqIGBNYJhg==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", + "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", @@ -6210,9 +5977,9 @@ "dev": true }, "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, "requires": { "normalize-path": "^3.0.0", @@ -6403,12 +6170,6 @@ "p-limit": "^3.0.2" } }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, "readdirp": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", @@ -6515,12 +6276,6 @@ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, "nise": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", @@ -6577,29 +6332,29 @@ } }, "npm-package-arg": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.0.tgz", - "integrity": "sha512-/ep6QDxBkm9HvOhOg0heitSd7JHA1U7y1qhhlRlteYYAi9Pdb/ZV7FW5aHpkrpM8+P+4p/jjR8zCyKPBMBjSig==", + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.2.tgz", + "integrity": "sha512-6Eem455JsSMJY6Kpd3EyWE+n5hC+g9bSyHr9K9U2zqZb7+02+hObQ2c0+8iDk/mNF+8r1MhY44WypKJAkySIYA==", "dev": true, "requires": { - "hosted-git-info": "^3.0.6", - "semver": "^7.0.0", + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", "validate-npm-package-name": "^3.0.0" }, "dependencies": { "hosted-git-info": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", - "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", + "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, "requires": { "lru-cache": "^6.0.0" } }, "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -6607,15 +6362,6 @@ } } }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -6768,41 +6514,12 @@ "readable-stream": "^2.0.1" } }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true, - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, "p-cancelable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", "dev": true }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", - "dev": true - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", - "dev": true - }, "p-limit": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", @@ -6813,12 +6530,12 @@ } }, "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "requires": { - "p-limit": "^2.0.0" + "p-limit": "^2.2.0" } }, "p-try": { @@ -6892,9 +6609,9 @@ "dev": true }, "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==" }, "pascalcase": { "version": "0.1.1", @@ -6909,9 +6626,9 @@ "dev": true }, "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, "path-is-absolute": { @@ -6921,9 +6638,9 @@ "dev": true }, "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, "path-parse": { @@ -7001,9 +6718,9 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", + "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", "dev": true }, "pinkie": { @@ -7028,42 +6745,6 @@ "dev": true, "requires": { "find-up": "^4.0.0" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - } } }, "plugin-error": { @@ -7078,6 +6759,11 @@ "extend-shallow": "^3.0.2" } }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==" + }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -7180,13 +6866,13 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "puppeteer-core": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-7.1.0.tgz", - "integrity": "sha512-2wjKs3L1rYuoVNNtRR/GbAGjbt6LF8DRUxcg/UoCQZrzjfppWlrIqiHRF5uBzJk+Nc0w7ZkvVzKQCvB5PFqFdA==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-9.1.1.tgz", + "integrity": "sha512-zbedbitVIGhmgz0nt7eIdLsnaoVZSlNJfBivqm2w67T8LR2bU1dvnruDZ8nQO0zn++Iet7zHbAOdnuS5+H2E7A==", "dev": true, "requires": { "debug": "^4.1.0", - "devtools-protocol": "0.0.847576", + "devtools-protocol": "0.0.869402", "extract-zip": "^2.0.0", "https-proxy-agent": "^5.0.0", "node-fetch": "^2.6.1", @@ -7200,9 +6886,9 @@ }, "dependencies": { "devtools-protocol": { - "version": "0.0.847576", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.847576.tgz", - "integrity": "sha512-0M8kobnSQE0Jmly7Mhbeq0W/PpZfnuK+WjN2ZRVPbGqYwCHCioAVp84H0TcLimgECcN5H976y5QiXMGBC9JKmg==", + "version": "0.0.869402", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.869402.tgz", + "integrity": "sha512-VvlVYY+VDJe639yHs5PHISzdWTLL3Aw8rO4cvUtwvoxFd6FHbE4OpHHcde52M6096uYYazAmd4l0o5VuFRO2WA==", "dev": true } } @@ -7212,6 +6898,12 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, + "query-selector-shadow-dom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/query-selector-shadow-dom/-/query-selector-shadow-dom-1.0.0.tgz", + "integrity": "sha512-bK0/0cCI+R8ZmOF1QjT7HupDUYCxbf/9TJgAmSXQxZpftXmTAeil9DRoCnTDkWbvOyZzhcMBwKpptWcdkGFIMg==", + "dev": true + }, "quick-lru": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", @@ -7661,9 +7353,9 @@ "dev": true }, "rgb2hex": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.2.3.tgz", - "integrity": "sha512-clEe0m1xv+Tva1B/TOepuIcvLAxP0U+sCDfgt1SX1HmI2Ahr5/Cd/nzJM1e78NKVtWdoo0s33YehpFA8UfIShQ==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.2.5.tgz", + "integrity": "sha512-22MOP1Rh7sAo1BZpDG6R5RFYzR2lYEgwq7HEmyW2qcsOqR2lQKmn+O//xV3YG/0rrhMC6KVX2hU+ZXuaw9a5bw==", "dev": true }, "rimraf": { @@ -7676,9 +7368,9 @@ } }, "rxjs": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", - "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -7704,11 +7396,11 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-3.1.11.tgz", + "integrity": "sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g==", "requires": { - "xmlchars": "^2.2.0" + "xmlchars": "^2.1.1" } }, "selenium-standalone": { @@ -7920,9 +7612,9 @@ } }, "serialize-error": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-8.0.1.tgz", - "integrity": "sha512-r5o60rWFS+8/b49DNAbB+GXZA0SpDpuWE758JxDKgRTga05r3U5lwyksE91dYKDhXSmnu36RALj615E6Aj5pSg==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-8.1.0.tgz", + "integrity": "sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -7975,24 +7667,18 @@ } }, "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "requires": { - "shebang-regex": "^1.0.0" + "shebang-regex": "^3.0.0" } }, "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, "sinon": { @@ -8454,12 +8140,6 @@ "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", "dev": true }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, "strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", @@ -8500,26 +8180,23 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, "table": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/table/-/table-6.0.9.tgz", - "integrity": "sha512-F3cLs9a3hL1Z7N4+EkSscsel3z55XT950AvB05bwayrNg5T1/gykXtigioTAjbltvbMSJvvhFCbnf6mX+ntnJQ==", + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", + "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", "dev": true, "requires": { "ajv": "^8.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", "lodash.clonedeep": "^4.5.0", - "lodash.flatten": "^4.4.0", "lodash.truncate": "^4.4.2", "slice-ansi": "^4.0.0", - "string-width": "^4.2.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0" }, "dependencies": { "ajv": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.0.1.tgz", - "integrity": "sha512-46ZA4TalFcLLqX1dEU3dhdY38wAtDydJ4e7QQTVekLUTzXkb1LfqU6VOBXC/a9wiv4T094WURqJH6ZitF92Kqw==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.5.0.tgz", + "integrity": "sha512-Y2l399Tt1AguU3BPRP9Fn4eN+Or+StUGWCUpbnFyXSo8NZ9S4uj+AG2pjs5apK+ZMOwYOz1+a+VKvKH7CudXgQ==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -8625,9 +8302,9 @@ "dev": true }, "textextensions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.5.0.tgz", - "integrity": "sha512-1IkVr355eHcomgK7fgj1Xsokturx6L5S2JRT5WcRdA6v5shk9sxWuO/w/VbpQexwkXJMQIa/j1dBi3oo7+HhcA==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-3.3.0.tgz", + "integrity": "sha512-mk82dS8eRABNbeVJrEiN5/UMSCliINAuz8mkUwH4SwslkNP//gbEzlWNS5au0z5Dpx40SQxzqZevZkn+WYJ9Dw==", "dev": true }, "through": { @@ -8782,28 +8459,21 @@ } }, "tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", + "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==", "requires": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.1.2" - }, - "dependencies": { - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" - } + "ip-regex": "^2.1.0", + "psl": "^1.1.28", + "punycode": "^2.1.1" } }, "tr46": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.0.2.tgz", - "integrity": "sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", "requires": { - "punycode": "^2.1.1" + "punycode": "^2.1.0" } }, "tree-kill": { @@ -8891,9 +8561,9 @@ } }, "ua-parser-js": { - "version": "0.7.26", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.26.tgz", - "integrity": "sha512-VwIvGlFNmpKbjzRt51jpbbFTrKIEgGHxIwA8Y69K1Bqc6bTIV7TaGGABOkghSFQWsLmcRB4drGvpfv9z2szqoQ==", + "version": "0.7.28", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.28.tgz", + "integrity": "sha512-6Gurc1n//gjp9eQNXjD9O3M/sMwVtN5S8Lv9bvOYBfKfDNiIIhqiyi01vMBO45u4zkDE420w/e0se7Vs+sIg+g==", "dev": true }, "uc.micro": { @@ -9203,32 +8873,35 @@ } }, "w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz", + "integrity": "sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg==", "requires": { + "domexception": "^1.0.1", + "webidl-conversions": "^4.0.2", "xml-name-validator": "^3.0.0" } }, "webdriver": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-7.3.0.tgz", - "integrity": "sha512-Qb6kO26wt8OQEetEJ+DQ06XBALfduP0wc+exXw0QZFyf3C0PmAPSuZGIl0NtSaQ5fuLeVJawFKtVecGXxDekbQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-7.6.0.tgz", + "integrity": "sha512-3IaaKhCP9onAmKcvEZ+2O08Q61DLRUEf0E1Ck8uXMxq8D9WjvVoSIdJ10AppaHuxK8PFXeymS2Y2klKVyUeMow==", "dev": true, "requires": { - "@wdio/config": "7.3.0", - "@wdio/logger": "7.0.0", - "@wdio/protocols": "7.1.1", - "@wdio/types": "7.2.1", - "@wdio/utils": "7.3.0", + "@types/node": "^14.14.31", + "@wdio/config": "7.6.0", + "@wdio/logger": "7.5.3", + "@wdio/protocols": "7.5.3", + "@wdio/types": "7.6.0", + "@wdio/utils": "7.6.0", "got": "^11.0.2", "lodash.merge": "^4.6.1" }, "dependencies": { "@sindresorhus/is": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.0.tgz", - "integrity": "sha512-FyD2meJpDPjyNQejSjvnhpgI/azsQkA4lGbuu5BQZfjvJ9cbRZXzeWL2HceCekW4lixO9JPesIIQkSoLjeJHNQ==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", + "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==", "dev": true }, "@szmarczak/http-timer": { @@ -9240,6 +8913,12 @@ "defer-to-connect": "^2.0.0" } }, + "@types/node": { + "version": "14.17.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.0.tgz", + "integrity": "sha512-w8VZUN/f7SSbvVReb9SWp6cJFevxb4/nkG65yLAya//98WgocKm5PLDAtSs5CtJJJM+kHmJjO/6mmYW4MHShZA==", + "dev": true + }, "cacheable-request": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.1.tgz", @@ -9326,9 +9005,9 @@ "dev": true }, "p-cancelable": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.0.tgz", - "integrity": "sha512-HAZyB3ZodPo+BDpb4/Iu7Jv4P6cSazBz9ZM0ChhEXp70scx834aWCEjQRwgt41UzzejUAPdbqqONfRWTPYrPAQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", "dev": true }, "responselike": { @@ -9343,26 +9022,27 @@ } }, "webdriverio": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-7.3.0.tgz", - "integrity": "sha512-0ttSA2TfD14KrQWJKMfxFrMn5YeXQd9h/1cfHqLyX1iaZBNRIgrPfYWfp7/E3iKbCli2Y2NpRhSaLBgyj3IgiQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-7.6.0.tgz", + "integrity": "sha512-o93L4dD4Ia0WOXghuv7Aj4vuSkK/eIDKRf7G5+dwh/j0myw3v2PKXC9pIG7Bxvp9exax5h/1NM+IFbvkTQAOlA==", "dev": true, "requires": { "@types/aria-query": "^4.2.1", - "@wdio/config": "7.3.0", - "@wdio/logger": "7.0.0", - "@wdio/protocols": "7.1.1", - "@wdio/repl": "7.3.0", - "@wdio/types": "7.2.1", - "@wdio/utils": "7.3.0", + "@types/node": "^14.14.31", + "@wdio/config": "7.6.0", + "@wdio/logger": "7.5.3", + "@wdio/protocols": "7.5.3", + "@wdio/repl": "7.6.0", + "@wdio/types": "7.6.0", + "@wdio/utils": "7.6.0", "archiver": "^5.0.0", "aria-query": "^4.2.2", "atob": "^2.1.2", "css-shorthand-properties": "^1.1.1", "css-value": "^0.0.1", - "devtools": "7.3.0", - "devtools-protocol": "^0.0.863986", - "fs-extra": "^9.0.1", + "devtools": "7.6.0", + "devtools-protocol": "^0.0.882987", + "fs-extra": "^10.0.0", "get-port": "^5.1.1", "grapheme-splitter": "^1.0.2", "lodash.clonedeep": "^4.5.0", @@ -9370,17 +9050,26 @@ "lodash.isplainobject": "^4.0.6", "lodash.zip": "^4.2.0", "minimatch": "^3.0.4", - "puppeteer-core": "^7.1.0", + "puppeteer-core": "^9.1.0", + "query-selector-shadow-dom": "^1.0.0", "resq": "^1.9.1", - "rgb2hex": "0.2.3", + "rgb2hex": "0.2.5", "serialize-error": "^8.0.0", - "webdriver": "7.3.0" + "webdriver": "7.6.0" + }, + "dependencies": { + "@types/node": { + "version": "14.17.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.0.tgz", + "integrity": "sha512-w8VZUN/f7SSbvVReb9SWp6cJFevxb4/nkG65yLAya//98WgocKm5PLDAtSs5CtJJJM+kHmJjO/6mmYW4MHShZA==", + "dev": true + } } }, "webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==" + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" }, "whatwg-encoding": { "version": "1.0.5", @@ -9396,13 +9085,13 @@ "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" }, "whatwg-url": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.5.0.tgz", - "integrity": "sha512-fy+R77xWv0AiqfLl4nuGUlQ3/6b5uNfQ4WAbGQVMYshCTCCPK9psC1nWh3XHuxGVCtlcDDQPQW1csmmIQo+fwg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", "requires": { - "lodash": "^4.7.0", - "tr46": "^2.0.2", - "webidl-conversions": "^6.1.0" + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" } }, "which": { @@ -9414,12 +9103,6 @@ "isexe": "^2.0.0" } }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, "wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", @@ -9502,8 +9185,7 @@ "ws": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.4.tgz", - "integrity": "sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==", - "dev": true + "integrity": "sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==" }, "xml-name-validator": { "version": "3.0.0", @@ -9527,12 +9209,6 @@ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -9659,14 +9335,10 @@ } }, "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "version": "20.2.7", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz", + "integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==", + "dev": true }, "yargs-unparser": { "version": "2.0.0", diff --git a/package.json b/package.json index b1491d69c..6adb5f0a1 100644 --- a/package.json +++ b/package.json @@ -63,15 +63,15 @@ "devDependencies": { "@blockly/block-test": "^1.0.0", "@blockly/dev-tools": "^2.0.1", + "@blockly/theme-dark": "^1.0.0", "@blockly/theme-modern": "^2.1.1", "babel-eslint": "^10.1.0", "chai": "^4.2.0", "clang-format": "^1.5.0", "concurrently": "^6.0.0", "eslint": "^7.6.0", - "eslint-plugin-es5": "^1.5.0", - "google-closure-compiler": "^20210302.0.0", - "google-closure-deps": "^20210202.0.0", + "google-closure-compiler": "^20210505.0.0", + "google-closure-deps": "^20210406.0.0", "gulp": "^4.0.2", "gulp-concat": "^2.6.1", "gulp-insert": "^0.5.0", diff --git a/scripts/gulpfiles/appengine_tasks.js b/scripts/gulpfiles/appengine_tasks.js index 08fb3ea85..e07b9f60f 100644 --- a/scripts/gulpfiles/appengine_tasks.js +++ b/scripts/gulpfiles/appengine_tasks.js @@ -59,6 +59,7 @@ function copyAppengineSrc() { function copyPlaygroundDeps() { const playgroundDeps = [ './node_modules/@blockly/dev-tools/dist/index.js', + './node_modules/@blockly/theme-dark/dist/index.js', './node_modules/@blockly/theme-modern/dist/index.js', './node_modules/@blockly/block-test/dist/index.js', ]; diff --git a/scripts/gulpfiles/build_tasks.js b/scripts/gulpfiles/build_tasks.js index 40adbbaab..6553e8872 100644 --- a/scripts/gulpfiles/build_tasks.js +++ b/scripts/gulpfiles/build_tasks.js @@ -133,7 +133,7 @@ function compile(compilerOptions, opt_verbose, opt_warnings_as_error, /** * Helper method for possibly adding the Closure library into a sources array. - * @param {Array.} srcs + * @param {Array} srcs */ function maybeAddClosureLibrary(srcs) { if (argv.closureLibrary) { @@ -155,7 +155,7 @@ function maybeAddClosureLibrary(srcs) { * A helper method to return an closure compiler output wrapper that wraps the * body in a Universal Module Definition. * @param {string} namespace The export namespace. - * @param {Array.} dependencies An array of dependencies to inject. + * @param {Array} dependencies An array of dependencies to inject. */ function outputWrapperUMD(namespace, dependencies) { const amdDeps = dependencies.map(d => '\'' + d.amd + '\'' ).join(', '); @@ -398,7 +398,7 @@ return gulp.src(maybeAddClosureLibrary(['core/**/**/*.js'])) const requires = `goog.addDependency("base.js", [], []); // Load Blockly. -goog.require('Blockly.requires') +goog.require('Blockly.requires'); `; fs.writeFileSync('blockly_uncompressed.js', header + diff --git a/scripts/gulpfiles/package_tasks.js b/scripts/gulpfiles/package_tasks.js index 94754617f..bf79b7a6e 100644 --- a/scripts/gulpfiles/package_tasks.js +++ b/scripts/gulpfiles/package_tasks.js @@ -28,7 +28,7 @@ const packageDistribution = 'dist'; /** * A helper method for wrapping a file into a Universal Module Definition. * @param {string} namespace The export namespace. - * @param {Array.} dependencies An array of dependencies to inject. + * @param {Array} dependencies An array of dependencies to inject. */ function packageUMD(namespace, dependencies) { return gulp.umd({ @@ -42,7 +42,7 @@ function packageUMD(namespace, dependencies) { /** * A helper method for wrapping a file into a CommonJS module for Node.js. * @param {string} namespace The export namespace. - * @param {Array.} dependencies An array of dependencies to inject. + * @param {Array} dependencies An array of dependencies to inject. */ function packageCommonJS(namespace, dependencies) { return gulp.umd({ diff --git a/scripts/package/node/core.js b/scripts/package/node/core.js index 8f7745304..7935f0cc5 100644 --- a/scripts/package/node/core.js +++ b/scripts/package/node/core.js @@ -23,8 +23,8 @@ Blockly.setLocale = function (locale) { // Override textToDomDocument and provide Node.js alternatives to DOMParser and // XMLSerializer. if (typeof Blockly.utils.global.document !== 'object') { - Blockly.utils.global.DOMParser = require("jsdom/lib/jsdom/living").DOMParser; - Blockly.utils.global.XMLSerializer = require("jsdom/lib/jsdom/living").XMLSerializer; + Blockly.utils.global.DOMParser = require('jsdom/lib/jsdom/living').DOMParser; + Blockly.utils.global.XMLSerializer = require('jsdom/lib/jsdom/living').XMLSerializer; var doc = Blockly.utils.xml.textToDomDocument( ''); Blockly.utils.xml.document = function() { diff --git a/tests/compile/compile.sh b/tests/compile/compile.sh deleted file mode 100755 index c916eba5a..000000000 --- a/tests/compile/compile.sh +++ /dev/null @@ -1,114 +0,0 @@ -#!/bin/bash -# -# Deprecation warning: (July 2020) -# This advanced compilation test script has been deprecated in favour of -# npm run test:compile:advanced -# -# The script will be removed from Blockly core in Q4 of 2020. -# -echo "Deprecation warning: (July 2020)" -echo "This advanced compilation test script has been deprecated in favour of" -echo " npm run test:compile:advanced" -echo "" -echo "The script will be removed from Blockly core in Q4 of 2020." -echo "" - -echo "Executing compile.sh from $(pwd)" - -# Find the Blockly project root if pwd is the root -# or if pwd is the directory containing this script. -if [ -f ./main.js ] && [ -f ./compile.sh ]; then - BLOCKLY_ROOT="../.." -elif [ -f tests/compile/compile.sh ]; then - BLOCKLY_ROOT="." -else - echo "ERROR: Cannot determine BLOCKLY_ROOT" 1>&2; - exit 1 -fi - -# Test for npm and node_modules directory. -if command -v npm >/dev/null 2>&1; then - NODE_MODULES=$(npm root) - # npm root will invent a location based on pwd if it can't find - # one, such as when the project has not been `npm install`ed. - # Clear the variable if the directory doesn't already exist. - [[ ! -d $NODE_MODULES ]] && NODE_MODULES="" -fi - -# Find the Closure Compiler. -if [ -n $NODE_MODULES ] && \ - [ -s $NODE_MODULES/google-closure-compiler-java/compiler.jar ]; then - COMPILER=$NODE_MODULES/google-closure-compiler-java/compiler.jar - echo "Found npm google-closure-compiler:" - echo " $COMPILER" - npm list google-closure-compiler | grep google-closure-compiler -else - COMPILER_JARS=$(find $BLOCKLY_ROOT/tests/compile/ -maxdepth 1 -name "*compiler*.jar") - if [ -n "$COMPILER_JARS" ]; then - if [ $(echo "$COMPILER_JARS" | wc -l) -ne 1 ]; then - echo "ERROR: Found too many Closure *compiler*.jar files:" 1>&2; - echo "$COMPILER_JARS" 1>&2; - exit 1 - fi - COMPILER=$COMPILER_JARS - echo "Found local Closure compiler .jar:" - echo " $COMPILER" - else - echo "ERROR: Closure Compiler not found." 1>&2; - echo "Either npm install google-closure-compiler" 1>&2; - echo "Or download from this URL, and place jar file in current directory." 1>&2; - echo "https://dl.google.com/closure-compiler/compiler-latest.zip" 1>&2; - exit 1 - fi -fi - -if [ -f "$BLOCKLY_ROOT/tests/compile/main_compressed.js" ]; then - echo "Removing previous output." - rm "$BLOCKLY_ROOT/tests/compile/main_compressed.js" -fi - -tempPath="$BLOCKLY_ROOT/temp_core" -corePath="$BLOCKLY_ROOT/core/*" -mkdir $tempPath -cp $corePath $tempPath -# Copy over all files in core and any subdirectories to the temp_core directory. -for dir in "$corePath/" ; do - # For all files in the directory and any subdirectories rename them to - # include the subirectory name and copy them to temporary directory. - # Ex: subdir/file.js -> temp_core/subdir_file.js - for file in $(find $dir -name \*.js); do - # Replace all / with _ and remove core - newName="${file//\//_}" - newName="${newName//._core_/}" - newFilePath="$tempPath/$newName" - cp $file $newFilePath - done -done - -echo "Compiling Blockly..." -COMPILATION_COMMAND="java -jar $COMPILER --js='$BLOCKLY_ROOT/tests/compile/main.js' \ - --js='$tempPath/**.js' \ - --js='$BLOCKLY_ROOT/tests/blocks/**.js' \ - --js='$BLOCKLY_ROOT/blocks/**.js' \ - --js='$BLOCKLY_ROOT/generators/**.js' \ - --generate_exports \ - --externs $BLOCKLY_ROOT/externs/goog-externs.js \ - --externs $BLOCKLY_ROOT/externs/svg-externs.js \ - --compilation_level ADVANCED_OPTIMIZATIONS \ - --language_in ECMASCRIPT5_STRICT \ - --language_out ECMASCRIPT5_STRICT \ - --dependency_mode=PRUNE --entry_point=Main \ - --js_output_file $BLOCKLY_ROOT/tests/compile/main_compressed.js" -echo "$COMPILATION_COMMAND" -$COMPILATION_COMMAND -EXIT_CODE=$? -echo "Compiler exit code: $EXIT_CODE" -if [ "$EXIT_CODE" -eq 0 ] && [ -s "$BLOCKLY_ROOT/tests/compile/main_compressed.js" ]; then - echo "Compilation SUCCESS." -else - echo "Compilation FAIL." - exit 1 -fi - -# Cleanup temp_core directory -rm -r $tempPath diff --git a/tests/compile/index.html b/tests/compile/index.html index 1ec1ce85a..8ffadca88 100644 --- a/tests/compile/index.html +++ b/tests/compile/index.html @@ -24,7 +24,7 @@

To run this test manually, download closure-compiler-vxxxxxxxx.jar, - place it in this directory, then run compile.sh from the command line.

+ place it in this directory, then run `npm run test:compile:advanced` from the command line.

Measure the size of main_compressed.js (295kb as of October 2017), then reload this page and see if Blockly works.

diff --git a/tests/generators/golden/generated.php b/tests/generators/golden/generated.php index 8066edb69..9d6436125 100644 --- a/tests/generators/golden/generated.php +++ b/tests/generators/golden/generated.php @@ -1,32 +1,3 @@ -$unittestResults; -$test_name; -$naked; -$proc_x; -$proc_y; -$func_x; -$func_y; -$func_a; -$n; -$ok; -$log; -$count; -$varToChange; -$rand; -$item; -$text; -$number_of_calls; -$list2; -$proc_z; -$func_z; -$x; -$proc_w; -$func_c; -$if2; -$i; -$loglist; -$changing_list; -$list_copy; - function unittest_report() { global $unittestResults; // Create test report. diff --git a/tests/generators/unittest_dart.js b/tests/generators/unittest_dart.js index 7b8861351..51a7aa7ac 100644 --- a/tests/generators/unittest_dart.js +++ b/tests/generators/unittest_dart.js @@ -12,7 +12,7 @@ Blockly.Dart['unittest_main'] = function(block) { // Container for unit tests. - var resultsVar = Blockly.Dart.variableDB_.getName('unittestResults', + var resultsVar = Blockly.Dart.nameDB_.getName('unittestResults', Blockly.Names.DEVELOPER_VARIABLE_TYPE); var functionName = Blockly.Dart.provideFunction_( 'unittest_report', @@ -61,7 +61,7 @@ Blockly.Dart['unittest_main'] = function(block) { }; Blockly.Dart['unittest_main'].defineAssert_ = function() { - var resultsVar = Blockly.Dart.variableDB_.getName('unittestResults', + var resultsVar = Blockly.Dart.nameDB_.getName('unittestResults', Blockly.Names.DEVELOPER_VARIABLE_TYPE); var functionName = Blockly.Dart.provideFunction_( 'unittest_assertequals', @@ -129,7 +129,7 @@ Blockly.Dart['unittest_assertvalue'] = function(block) { Blockly.Dart['unittest_fail'] = function(block) { // Always assert an error. - var resultsVar = Blockly.Dart.variableDB_.getName('unittestResults', + var resultsVar = Blockly.Dart.nameDB_.getName('unittestResults', Blockly.Names.DEVELOPER_VARIABLE_TYPE); var message = Blockly.Dart.quote_(block.getFieldValue('MESSAGE')); var functionName = Blockly.Dart.provideFunction_( diff --git a/tests/generators/unittest_javascript.js b/tests/generators/unittest_javascript.js index 9e843f368..5c67e2a63 100644 --- a/tests/generators/unittest_javascript.js +++ b/tests/generators/unittest_javascript.js @@ -12,7 +12,7 @@ Blockly.JavaScript['unittest_main'] = function(block) { // Container for unit tests. - var resultsVar = Blockly.JavaScript.variableDB_.getName('unittestResults', + var resultsVar = Blockly.JavaScript.nameDB_.getName('unittestResults', Blockly.Names.DEVELOPER_VARIABLE_TYPE); var functionName = Blockly.JavaScript.provideFunction_( 'unittest_report', @@ -62,7 +62,7 @@ Blockly.JavaScript['unittest_main'] = function(block) { }; Blockly.JavaScript['unittest_main'].defineAssert_ = function(block) { - var resultsVar = Blockly.JavaScript.variableDB_.getName('unittestResults', + var resultsVar = Blockly.JavaScript.nameDB_.getName('unittestResults', Blockly.Names.DEVELOPER_VARIABLE_TYPE); var functionName = Blockly.JavaScript.provideFunction_( 'assertEquals', @@ -133,7 +133,7 @@ Blockly.JavaScript['unittest_assertvalue'] = function(block) { Blockly.JavaScript['unittest_fail'] = function(block) { // Always assert an error. - var resultsVar = Blockly.JavaScript.variableDB_.getName('unittestResults', + var resultsVar = Blockly.JavaScript.nameDB_.getName('unittestResults', Blockly.Names.DEVELOPER_VARIABLE_TYPE); var message = Blockly.JavaScript.quote_(block.getFieldValue('MESSAGE')); var functionName = Blockly.JavaScript.provideFunction_( diff --git a/tests/generators/unittest_lua.js b/tests/generators/unittest_lua.js index cc3e0eb81..ab1370252 100644 --- a/tests/generators/unittest_lua.js +++ b/tests/generators/unittest_lua.js @@ -12,7 +12,7 @@ Blockly.Lua['unittest_main'] = function(block) { // Container for unit tests. - var resultsVar = Blockly.Lua.variableDB_.getName('unittestResults', + var resultsVar = Blockly.Lua.nameDB_.getName('unittestResults', Blockly.Names.DEVELOPER_VARIABLE_TYPE); var functionName = Blockly.Lua.provideFunction_( 'unittest_report', @@ -60,7 +60,7 @@ Blockly.Lua['unittest_main'] = function(block) { }; Blockly.Lua['unittest_main'].defineAssert_ = function(block) { - var resultsVar = Blockly.Lua.variableDB_.getName('unittestResults', + var resultsVar = Blockly.Lua.nameDB_.getName('unittestResults', Blockly.Names.DEVELOPER_VARIABLE_TYPE); var functionName = Blockly.Lua.provideFunction_( 'assertEquals', @@ -139,7 +139,7 @@ Blockly.Lua['unittest_assertvalue'] = function(block) { Blockly.Lua['unittest_fail'] = function(block) { // Always assert an error. - var resultsVar = Blockly.Lua.variableDB_.getName('unittestResults', + var resultsVar = Blockly.Lua.nameDB_.getName('unittestResults', Blockly.Names.DEVELOPER_VARIABLE_TYPE); var message = Blockly.Lua.quote_(block.getFieldValue('MESSAGE')); var functionName = Blockly.Lua.provideFunction_( diff --git a/tests/generators/unittest_php.js b/tests/generators/unittest_php.js index 391b5332f..253df5641 100644 --- a/tests/generators/unittest_php.js +++ b/tests/generators/unittest_php.js @@ -12,7 +12,7 @@ Blockly.PHP['unittest_main'] = function(block) { // Container for unit tests. - var resultsVar = Blockly.PHP.variableDB_.getName('unittestResults', + var resultsVar = Blockly.PHP.nameDB_.getName('unittestResults', Blockly.Names.DEVELOPER_VARIABLE_TYPE); var functionName = Blockly.PHP.provideFunction_( 'unittest_report', @@ -62,7 +62,7 @@ Blockly.PHP['unittest_main'] = function(block) { }; Blockly.PHP['unittest_main'].defineAssert_ = function(block) { - var resultsVar = Blockly.PHP.variableDB_.getName('unittestResults', + var resultsVar = Blockly.PHP.nameDB_.getName('unittestResults', Blockly.Names.DEVELOPER_VARIABLE_TYPE); var functionName = Blockly.PHP.provideFunction_( 'assertEquals', @@ -119,7 +119,7 @@ Blockly.PHP['unittest_assertvalue'] = function(block) { Blockly.PHP['unittest_fail'] = function(block) { // Always assert an error. - var resultsVar = Blockly.PHP.variableDB_.getName('unittestResults', + var resultsVar = Blockly.PHP.nameDB_.getName('unittestResults', Blockly.Names.DEVELOPER_VARIABLE_TYPE); var message = Blockly.PHP.quote_(block.getFieldValue('MESSAGE')); var functionName = Blockly.PHP.provideFunction_( diff --git a/tests/generators/unittest_python.js b/tests/generators/unittest_python.js index e00dc1b6f..ce18142a6 100644 --- a/tests/generators/unittest_python.js +++ b/tests/generators/unittest_python.js @@ -12,7 +12,7 @@ Blockly.Python['unittest_main'] = function(block) { // Container for unit tests. - var resultsVar = Blockly.Python.variableDB_.getName('unittestResults', + var resultsVar = Blockly.Python.nameDB_.getName('unittestResults', Blockly.Names.DEVELOPER_VARIABLE_TYPE); var functionName = Blockly.Python.provideFunction_( 'unittest_report', @@ -58,7 +58,7 @@ Blockly.Python['unittest_main'] = function(block) { }; Blockly.Python['unittest_main'].defineAssert_ = function() { - var resultsVar = Blockly.Python.variableDB_.getName('unittestResults', + var resultsVar = Blockly.Python.nameDB_.getName('unittestResults', Blockly.Names.DEVELOPER_VARIABLE_TYPE); var functionName = Blockly.Python.provideFunction_( 'assertEquals', @@ -107,7 +107,7 @@ Blockly.Python['unittest_assertvalue'] = function(block) { Blockly.Python['unittest_fail'] = function(block) { // Always assert an error. - var resultsVar = Blockly.Python.variableDB_.getName('unittestResults', + var resultsVar = Blockly.Python.nameDB_.getName('unittestResults', Blockly.Names.DEVELOPER_VARIABLE_TYPE); var message = Blockly.Python.quote_(block.getFieldValue('MESSAGE')); var functionName = Blockly.Python.provideFunction_( diff --git a/tests/mocha/connection_test.js b/tests/mocha/connection_test.js index 73882b90b..118d27412 100644 --- a/tests/mocha/connection_test.js +++ b/tests/mocha/connection_test.js @@ -156,9 +156,6 @@ suite('Connection', function() { teardown(function() { workspaceTeardown.call(this, this.workspace); - delete Blockly.Blocks['stack_block']; - delete Blockly.Blocks['row_block']; - delete Blockly.Blocks['statement_block']; }); suite('Add - No Block Connected', function() { @@ -784,4 +781,952 @@ suite('Connection', function() { }); }); }); + + suite('getConnectionForOrphanedOutput', function() { + setup(function() { + this.workspace = new Blockly.Workspace(); + + Blockly.defineBlocksWithJsonArray([ + { + 'type': 'input', + 'message0': '%1', + 'args0': [ + { + 'type': 'input_value', + 'name': 'INPUT', + 'check': 'check' + } + ], + }, + { + 'type': 'output', + 'message0': '', + 'output': 'check', + }, + ]); + }); + + teardown(function() { + workspaceTeardown.call(this, this.workspace); + }); + + suite('No available spots', function() { + setup(function() { + Blockly.defineBlocksWithJsonArray([ + { + 'type': 'output_and_statements', + 'message0': '%1 %2', + 'args0': [ + { + 'type': 'input_statement', + 'name': 'INPUT', + 'check': 'check' + }, + { + 'type': 'input_statement', + 'name': 'INPUT2', + 'check': 'check' + } + ], + 'output': 'check', + }, + { + 'type': 'output_and_inputs', + 'message0': '%1 %2', + 'args0': [ + { + 'type': 'input_value', + 'name': 'INPUT', + 'check': 'check2' + }, + { + 'type': 'input_value', + 'name': 'INPUT2', + 'check': 'check2' + } + ], + 'output': 'check', + }, + { + 'type': 'check_to_check2', + 'message0': '%1', + 'args0': [ + { + 'type': 'input_value', + 'name': 'INPUT', + 'check': 'check2' + }, + ], + 'output': 'check', + }, + { + 'type': 'check2_to_check', + 'message0': '%1', + 'args0': [ + { + 'type': 'input_value', + 'name': 'CHECK2TOCHECKINPUT', + 'check': 'check' + }, + ], + 'output': 'check2', + }, + ]); + }); + + test('No connection', function() { + const parent = this.workspace.newBlock('input'); + const oldChild = this.workspace.newBlock('output'); + const newChild = this.workspace.newBlock('output'); + + parent.getInput('INPUT').connection.connect(oldChild.outputConnection); + chai.assert.notExists( + Blockly.Connection.getConnectionForOrphanedOutput(oldChild, newChild)); + }); + + test('All statements', function() { + const parent = this.workspace.newBlock('input'); + const oldChild = this.workspace.newBlock('output_and_statements'); + const newChild = this.workspace.newBlock('output'); + + parent.getInput('INPUT').connection.connect(oldChild.outputConnection); + chai.assert.notExists( + Blockly.Connection.getConnectionForOrphanedOutput(oldChild, newChild)); + }); + + test('Bad checks', function() { + const parent = this.workspace.newBlock('input'); + const oldChild = this.workspace.newBlock('output_and_inputs'); + const newChild = this.workspace.newBlock('output'); + + parent.getInput('INPUT').connection.connect(oldChild.outputConnection); + chai.assert.notExists( + Blockly.Connection.getConnectionForOrphanedOutput(oldChild, newChild)); + }); + + test('Through different types', function() { + const parent = this.workspace.newBlock('input'); + const oldChild = this.workspace.newBlock('check_to_check2'); + const otherChild = this.workspace.newBlock('check2_to_check'); + const newChild = this.workspace.newBlock('output'); + + parent.getInput('INPUT').connection + .connect(oldChild.outputConnection); + oldChild.getInput('INPUT').connection + .connect(otherChild.outputConnection); + + chai.assert.notExists( + Blockly.Connection.getConnectionForOrphanedOutput(oldChild, newChild)); + }); + }); + + suite('Multiple available spots', function() { + setup(function() { + Blockly.defineBlocksWithJsonArray([ + { + 'type': 'multiple_inputs', + 'message0': '%1 %2', + 'args0': [ + { + 'type': 'input_value', + 'name': 'INPUT', + 'check': 'check' + }, + { + 'type': 'input_value', + 'name': 'INPUT2', + 'check': 'check' + }, + ], + 'output': 'check', + }, + { + 'type': 'single_input', + 'message0': '%1', + 'args0': [ + { + 'type': 'input_value', + 'name': 'INPUT', + 'check': 'check' + }, + ], + 'output': 'check', + }, + ]); + }); + + suite('No shadows', function() { + test('Top block', function() { + const parent = this.workspace.newBlock('input'); + const oldChild = this.workspace.newBlock('multiple_inputs'); + const newChild = this.workspace.newBlock('output'); + + parent.getInput('INPUT').connection.connect(oldChild.outputConnection); + chai.assert.notExists( + Blockly.Connection.getConnectionForOrphanedOutput(oldChild, newChild)); + }); + + test('Child blocks', function() { + const parent = this.workspace.newBlock('input'); + const oldChild = this.workspace.newBlock('multiple_inputs'); + const childX = this.workspace.newBlock('single_input'); + const childY = this.workspace.newBlock('single_input'); + const newChild = this.workspace.newBlock('output'); + + parent.getInput('INPUT').connection.connect(oldChild.outputConnection); + oldChild.getInput('INPUT').connection.connect(childX.outputConnection); + oldChild.getInput('INPUT2').connection.connect(childY.outputConnection); + + chai.assert.notExists( + Blockly.Connection.getConnectionForOrphanedOutput(oldChild, newChild)); + }); + + test('Spots filled', function() { + const parent = this.workspace.newBlock('input'); + const oldChild = this.workspace.newBlock('multiple_inputs'); + const otherChild = this.workspace.newBlock('output'); + const newChild = this.workspace.newBlock('output'); + + parent.getInput('INPUT').connection + .connect(oldChild.outputConnection); + oldChild.getInput('INPUT').connection + .connect(otherChild.outputConnection); + + chai.assert.notExists( + Blockly.Connection.getConnectionForOrphanedOutput(oldChild, newChild)); + }); + }); + + suite('Shadows', function() { + test('Top block', function() { + const parent = this.workspace.newBlock('input'); + const oldChild = this.workspace.newBlock('multiple_inputs'); + const newChild = this.workspace.newBlock('output'); + + parent.getInput('INPUT').connection.connect(oldChild.outputConnection); + oldChild.getInput('INPUT').connection.setShadowDom( + Blockly.Xml.textToDom('') + .firstChild); + oldChild.getInput('INPUT2').connection.setShadowDom( + Blockly.Xml.textToDom('') + .firstChild); + + chai.assert.notExists( + Blockly.Connection.getConnectionForOrphanedOutput(oldChild, newChild)); + }); + + test('Child blocks', function() { + const parent = this.workspace.newBlock('input'); + const oldChild = this.workspace.newBlock('multiple_inputs'); + const childX = this.workspace.newBlock('single_input'); + const childY = this.workspace.newBlock('single_input'); + const newChild = this.workspace.newBlock('output'); + + parent.getInput('INPUT').connection.connect(oldChild.outputConnection); + oldChild.getInput('INPUT').connection.connect(childX.outputConnection); + oldChild.getInput('INPUT2').connection.connect(childY.outputConnection); + childX.getInput('INPUT').connection.setShadowDom( + Blockly.Xml.textToDom('') + .firstChild); + childY.getInput('INPUT').connection.setShadowDom( + Blockly.Xml.textToDom('') + .firstChild); + + chai.assert.notExists( + Blockly.Connection.getConnectionForOrphanedOutput(oldChild, newChild)); + }); + + test('Spots filled', function() { + const parent = this.workspace.newBlock('input'); + const oldChild = this.workspace.newBlock('multiple_inputs'); + const otherChild = this.workspace.newBlock('output'); + const newChild = this.workspace.newBlock('output'); + + parent.getInput('INPUT').connection + .connect(oldChild.outputConnection); + oldChild.getInput('INPUT').connection + .connect(otherChild.outputConnection); + oldChild.getInput('INPUT2').connection.setShadowDom( + Blockly.Xml.textToDom('') + .firstChild); + + chai.assert.notExists( + Blockly.Connection.getConnectionForOrphanedOutput(oldChild, newChild)); + }); + }); + }); + + suite('Single available spot', function() { + setup(function() { + Blockly.defineBlocksWithJsonArray([ + { + 'type': 'single_input', + 'message0': '%1', + 'args0': [ + { + 'type': 'input_value', + 'name': 'INPUT', + 'check': 'check' + }, + ], + 'output': 'check', + }, + ]); + }); + + test('No shadows', function() { + const parent = this.workspace.newBlock('input'); + const oldChild = this.workspace.newBlock('single_input'); + const newChild = this.workspace.newBlock('output'); + + parent.getInput('INPUT').connection.connect(oldChild.outputConnection); + + const result = Blockly.Connection + .getConnectionForOrphanedOutput(oldChild, newChild); + chai.assert.exists(result); + chai.assert.equal(result.getParentInput().name, 'INPUT'); + }); + + test('Shadows', function() { + const parent = this.workspace.newBlock('input'); + const oldChild = this.workspace.newBlock('single_input'); + const newChild = this.workspace.newBlock('output'); + + parent.getInput('INPUT').connection.connect(oldChild.outputConnection); + oldChild.getInput('INPUT').connection.setShadowDom( + Blockly.Xml.textToDom('') + .firstChild); + + const result = Blockly.Connection + .getConnectionForOrphanedOutput(oldChild, newChild); + chai.assert.exists(result); + chai.assert.equal(result.getParentInput().name, 'INPUT'); + }); + }); + }); + + suite('Connect', function() { + setup(function() { + this.workspace = new Blockly.Workspace(); + Blockly.defineBlocksWithJsonArray([ + { + "type": "stack_block", + "message0": "%1", + "args0": [ + { + "type": "field_input", + "name": "FIELD", + "text": "default" + } + ], + "previousStatement": 'check1', + "nextStatement": 'check1' + }, + { + "type": "stack_block_1to2", + "message0": "", + "previousStatement": 'check1', + "nextStatement": 'check2' + }, + { + "type": "stack_block_2to1", + "message0": "", + "previousStatement": 'check2', + "nextStatement": 'check1' + }, + { + "type": "stack_block_noend", + "message0": "", + "previousStatement": 'check1', + }, + { + "type": "row_block", + "message0": "%1 %2", + "args0": [ + { + "type": "field_input", + "name": "FIELD", + "text": "default" + }, + { + "type": "input_value", + "name": "INPUT", + "check": 'check1' + } + ], + "output": 'check1' + }, + { + "type": "row_block_1to2", + "message0": "%1", + "args0": [ + { + "type": "input_value", + "name": "INPUT", + "check": 'check1' + } + ], + "output": 'check2' + }, + { + "type": "row_block_2to1", + "message0": "%1", + "args0": [ + { + "type": "input_value", + "name": "INPUT", + "check": 'check2' + } + ], + "output": 'check1' + }, + { + "type": "row_block_noend", + "message0": "", + "output": 'check1' + }, + { + "type": "statement_block", + "message0": "%1 %2", + "args0": [ + { + "type": "field_input", + "name": "FIELD", + "text": "default" + }, + { + "type": "input_statement", + "name": "STATEMENT", + "check": 'check1' + } + ], + "previousStatement": 'check1', + "nextStatement": 'check1' + }, + { + "type": "statement_block_1to2", + "message0": "%1", + "args0": [ + { + "type": "input_statement", + "name": "STATEMENT", + "check": 'check1' + } + ], + "previousStatement": 'check1', + "nextStatement": 'check2' + }, + { + "type": "statement_block_2to1", + "message0": "%1", + "args0": [ + { + "type": "input_statement", + "name": "STATEMENT", + "check": 'check2' + } + ], + "previousStatement": 'check2', + "nextStatement": 'check1' + }, + { + "type": "statement_block_noend", + "message0": "%1", + "args0": [ + { + "type": "input_statement", + "name": "STATEMENT", + "check": 'check1' + } + ], + "previousStatement": 'check1', + }, + ]); + + // Used to make sure we don't get stray shadow blocks or anything. + this.assertBlockCount = function(count) { + chai.assert.equal(this.workspace.getAllBlocks().length, count); + }; + }); + + suite('Disconnect from old parent', function() { + test('Value', function() { + var oldParent = this.workspace.newBlock('row_block'); + var newParent = this.workspace.newBlock('row_block'); + var child = this.workspace.newBlock('row_block'); + + oldParent.getInput('INPUT').connection.connect(child.outputConnection); + newParent.getInput('INPUT').connection.connect(child.outputConnection); + + chai.assert.isFalse( + oldParent.getInput('INPUT').connection.isConnected()); + this.assertBlockCount(3); + }); + + test('Statement', function() { + var oldParent = this.workspace.newBlock('statement_block'); + var newParent = this.workspace.newBlock('statement_block'); + var child = this.workspace.newBlock('stack_block'); + + oldParent.getInput('STATEMENT').connection + .connect(child.previousConnection); + newParent.getInput('STATEMENT').connection + .connect(child.previousConnection); + + chai.assert.isFalse( + oldParent.getInput('STATEMENT').connection.isConnected()); + this.assertBlockCount(3); + }); + + test('Next', function() { + var oldParent = this.workspace.newBlock('stack_block'); + var newParent = this.workspace.newBlock('stack_block'); + var child = this.workspace.newBlock('stack_block'); + + oldParent.nextConnection.connect(child.previousConnection); + newParent.nextConnection.connect(child.previousConnection); + + chai.assert.isFalse(oldParent.nextConnection.isConnected()); + this.assertBlockCount(3); + }); + }); + + suite('Shadow dissolves', function() { + test('Value', function() { + var newParent = this.workspace.newBlock('row_block'); + var child = this.workspace.newBlock('row_block'); + var xml = Blockly.Xml.textToDom( + '' + ); + newParent.getInput('INPUT').connection.setShadowDom(xml); + chai.assert.isTrue(newParent.getInputTargetBlock('INPUT').isShadow()); + + newParent.getInput('INPUT').connection.connect(child.outputConnection); + + chai.assert.isFalse(newParent.getInputTargetBlock('INPUT').isShadow()); + this.assertBlockCount(2); + }); + + test('Statement', function() { + var newParent = this.workspace.newBlock('statement_block'); + var child = this.workspace.newBlock('stack_block'); + var xml = Blockly.Xml.textToDom( + '' + ); + newParent.getInput('STATEMENT').connection.setShadowDom(xml); + chai.assert.isTrue( + newParent.getInputTargetBlock('STATEMENT').isShadow()); + + newParent.getInput('STATEMENT').connection + .connect(child.previousConnection); + + chai.assert.isFalse( + newParent.getInputTargetBlock('STATEMENT').isShadow()); + this.assertBlockCount(2); + }); + + test('Next', function() { + var newParent = this.workspace.newBlock('stack_block'); + var child = this.workspace.newBlock('stack_block'); + var xml = Blockly.Xml.textToDom( + '' + ); + newParent.nextConnection.setShadowDom(xml); + chai.assert.isTrue(newParent.getNextBlock().isShadow()); + + newParent.nextConnection.connect(child.previousConnection); + + chai.assert.isFalse(newParent.getNextBlock().isShadow()); + this.assertBlockCount(2); + }); + }); + + suite('Saving shadow values', function() { + test('Value', function() { + var newParent = this.workspace.newBlock('row_block'); + var child = this.workspace.newBlock('row_block'); + var xml = Blockly.Xml.textToDom( + '' + ); + newParent.getInput('INPUT').connection.setShadowDom(xml); + newParent.getInputTargetBlock('INPUT').setFieldValue('new', 'FIELD'); + + newParent.getInput('INPUT').connection.connect(child.outputConnection); + newParent.getInput('INPUT').connection.disconnect(); + + const target = newParent.getInputTargetBlock('INPUT'); + chai.assert.isTrue(target.isShadow()); + chai.assert.equal(target.getFieldValue('FIELD'), 'new'); + this.assertBlockCount(3); + }); + + test('Statement', function() { + var newParent = this.workspace.newBlock('statement_block'); + var child = this.workspace.newBlock('stack_block'); + var xml = Blockly.Xml.textToDom( + '' + ); + newParent.getInput('STATEMENT').connection.setShadowDom(xml); + newParent.getInputTargetBlock('STATEMENT') + .setFieldValue('new', 'FIELD'); + + newParent.getInput('STATEMENT').connection + .connect(child.previousConnection); + newParent.getInput('STATEMENT').connection.disconnect(); + + const target = newParent.getInputTargetBlock('STATEMENT'); + chai.assert.isTrue(target.isShadow()); + chai.assert.equal(target.getFieldValue('FIELD'), 'new'); + this.assertBlockCount(3); + }); + + test('Next', function() { + var newParent = this.workspace.newBlock('stack_block'); + var child = this.workspace.newBlock('stack_block'); + var xml = Blockly.Xml.textToDom( + '' + ); + newParent.nextConnection.setShadowDom(xml); + newParent.getNextBlock().setFieldValue('new', 'FIELD'); + + newParent.nextConnection.connect(child.previousConnection); + newParent.nextConnection.disconnect(); + + const target = newParent.getNextBlock(); + chai.assert.isTrue(target.isShadow()); + chai.assert.equal(target.getFieldValue('FIELD'), 'new'); + this.assertBlockCount(3); + }); + }); + + suite('Reattach or bump orphan', function() { + suite('Value', function() { + // Only one test for this b/c tested by getConnectionForOrphanedOutput. + test('Simple', function() { + var parent = this.workspace.newBlock('row_block'); + var oldChild = this.workspace.newBlock('row_block'); + var newChild = this.workspace.newBlock('row_block'); + parent.getInput('INPUT').connection.connect(oldChild.outputConnection); + var spy = sinon.spy( + Blockly.Connection, 'getConnectionForOrphanedOutput'); + + parent.getInput('INPUT').connection.connect(newChild.outputConnection); + + chai.assert.isTrue(parent.getInput('INPUT').connection.isConnected()); + chai.assert.equal(parent.getInputTargetBlock('INPUT'), newChild); + chai.assert.isTrue(newChild.getInput('INPUT').connection.isConnected()); + chai.assert.equal(newChild.getInputTargetBlock('INPUT'), oldChild); + // Make sure it is actually getting called, so all functionality has + // been tested. + // Future people: if you ever stop calling this function you need to + // add more tests for reattaching orphans. + chai.assert.isTrue(spy.calledOnce); + this.assertBlockCount(3); + }); + + test('Bump', function() { + var parent = this.workspace.newBlock('row_block'); + var oldChild = this.workspace.newBlock('row_block'); + var newChild = this.workspace.newBlock('row_block_noend'); + parent.getInput('INPUT').connection.connect(oldChild.outputConnection); + var spy = sinon.spy(oldChild.outputConnection, 'onFailedConnect'); + + parent.getInput('INPUT').connection.connect(newChild.outputConnection); + + chai.assert.isTrue(parent.getInput('INPUT').connection.isConnected()); + chai.assert.equal(parent.getInputTargetBlock('INPUT'), newChild); + chai.assert.isTrue(spy.calledOnce); + this.assertBlockCount(3); + }); + }); + + suite('Statement', function() { + suite('No shadows', function() { + test('Simple', function() { + var parent = this.workspace.newBlock('statement_block'); + var oldChild = this.workspace.newBlock('stack_block'); + var newChild = this.workspace.newBlock('stack_block'); + parent.getInput('STATEMENT').connection + .connect(oldChild.previousConnection); + + parent.getInput('STATEMENT').connection + .connect(newChild.previousConnection); + + chai.assert.isTrue( + parent.getInput('STATEMENT').connection.isConnected()); + chai.assert.equal( + parent.getInputTargetBlock('STATEMENT'), newChild); + chai.assert.isTrue(newChild.nextConnection.isConnected()); + chai.assert.equal(newChild.getNextBlock(), oldChild); + this.assertBlockCount(3); + }); + + test('Bad check in between', function() { + var parent = this.workspace.newBlock('statement_block'); + var oldChild = this.workspace.newBlock('stack_block'); + var newChild1 = this.workspace.newBlock('stack_block_1to2'); + var newChild2 = this.workspace.newBlock('stack_block_2to1'); + parent.getInput('STATEMENT').connection + .connect(oldChild.previousConnection); + newChild1.nextConnection.connect(newChild2.previousConnection); + + parent.getInput('STATEMENT').connection + .connect(newChild1.previousConnection); + + chai.assert.isTrue( + parent.getInput('STATEMENT').connection.isConnected()); + chai.assert.equal( + parent.getInputTargetBlock('STATEMENT'), newChild1); + chai.assert.isTrue(newChild2.nextConnection.isConnected()); + chai.assert.equal(newChild2.getNextBlock(), oldChild); + this.assertBlockCount(4); + }); + + test('Bad check at end', function() { + var parent = this.workspace.newBlock('statement_block'); + var oldChild = this.workspace.newBlock('stack_block'); + var newChild = this.workspace.newBlock('stack_block_1to2'); + parent.getInput('STATEMENT').connection + .connect(oldChild.previousConnection); + var spy = sinon.spy(oldChild.previousConnection, 'onFailedConnect'); + + parent.getInput('STATEMENT').connection + .connect(newChild.previousConnection); + + chai.assert.isTrue( + parent.getInput('STATEMENT').connection.isConnected()); + chai.assert.equal( + parent.getInputTargetBlock('STATEMENT'), newChild); + chai.assert.isFalse(newChild.nextConnection.isConnected()); + chai.assert.isTrue(spy.calledOnce); + this.assertBlockCount(3); + }); + + test('No end connection', function() { + var parent = this.workspace.newBlock('statement_block'); + var oldChild = this.workspace.newBlock('stack_block'); + var newChild = this.workspace.newBlock('stack_block_noend'); + parent.getInput('STATEMENT').connection + .connect(oldChild.previousConnection); + var spy = sinon.spy(oldChild.previousConnection, 'onFailedConnect'); + + parent.getInput('STATEMENT').connection + .connect(newChild.previousConnection); + + chai.assert.isTrue( + parent.getInput('STATEMENT').connection.isConnected()); + chai.assert.equal( + parent.getInputTargetBlock('STATEMENT'), newChild); + chai.assert.isTrue(spy.calledOnce); + this.assertBlockCount(3); + }); + }); + + suite('Shadows', function() { + test('Simple', function() { + var parent = this.workspace.newBlock('statement_block'); + var oldChild = this.workspace.newBlock('stack_block'); + var newChild = this.workspace.newBlock('stack_block'); + parent.getInput('STATEMENT').connection + .connect(oldChild.previousConnection); + var xml = Blockly.Xml.textToDom( + '' + ); + newChild.nextConnection.setShadowDom(xml); + + parent.getInput('STATEMENT').connection + .connect(newChild.previousConnection); + + chai.assert.isTrue( + parent.getInput('STATEMENT').connection.isConnected()); + chai.assert.equal( + parent.getInputTargetBlock('STATEMENT'), newChild); + chai.assert.isTrue(newChild.nextConnection.isConnected()); + chai.assert.equal(newChild.getNextBlock(), oldChild); + this.assertBlockCount(3); + }); + + test('Bad check in between', function() { + var parent = this.workspace.newBlock('statement_block'); + var oldChild = this.workspace.newBlock('stack_block'); + var newChild1 = this.workspace.newBlock('stack_block_1to2'); + var newChild2 = this.workspace.newBlock('stack_block_2to1'); + parent.getInput('STATEMENT').connection + .connect(oldChild.previousConnection); + newChild1.nextConnection.connect(newChild2.previousConnection); + var xml = Blockly.Xml.textToDom( + '' + ); + newChild2.nextConnection.setShadowDom(xml); + + parent.getInput('STATEMENT').connection + .connect(newChild1.previousConnection); + + chai.assert.isTrue( + parent.getInput('STATEMENT').connection.isConnected()); + chai.assert.equal( + parent.getInputTargetBlock('STATEMENT'), newChild1); + chai.assert.isTrue(newChild2.nextConnection.isConnected()); + chai.assert.equal(newChild2.getNextBlock(), oldChild); + this.assertBlockCount(4); + }); + + test('Bad check at end', function() { + var parent = this.workspace.newBlock('statement_block'); + var oldChild = this.workspace.newBlock('stack_block'); + var newChild = this.workspace.newBlock('stack_block_1to2'); + parent.getInput('STATEMENT').connection + .connect(oldChild.previousConnection); + var xml = Blockly.Xml.textToDom( + '' + ); + newChild.nextConnection.setShadowDom(xml); + var spy = sinon.spy(oldChild.previousConnection, 'onFailedConnect'); + + parent.getInput('STATEMENT').connection + .connect(newChild.previousConnection); + + chai.assert.isTrue( + parent.getInput('STATEMENT').connection.isConnected()); + chai.assert.equal( + parent.getInputTargetBlock('STATEMENT'), newChild); + chai.assert.isTrue(newChild.nextConnection.isConnected()); + chai.assert.isTrue(newChild.getNextBlock().isShadow()); + chai.assert.isTrue(spy.calledOnce); + this.assertBlockCount(4); + }); + }); + }); + + suite('Next', function() { + suite('No shadows', function() { + test('Simple', function() { + var parent = this.workspace.newBlock('stack_block'); + var oldChild = this.workspace.newBlock('stack_block'); + var newChild = this.workspace.newBlock('stack_block'); + parent.nextConnection.connect(oldChild.previousConnection); + + parent.nextConnection.connect(newChild.previousConnection); + + chai.assert.isTrue(parent.nextConnection.isConnected()); + chai.assert.equal(parent.getNextBlock(), newChild); + chai.assert.isTrue(newChild.nextConnection.isConnected()); + chai.assert.equal(newChild.getNextBlock(), oldChild); + this.assertBlockCount(3); + }); + + test('Bad check in between', function() { + var parent = this.workspace.newBlock('stack_block'); + var oldChild = this.workspace.newBlock('stack_block'); + var newChild1 = this.workspace.newBlock('stack_block_1to2'); + var newChild2 = this.workspace.newBlock('stack_block_2to1'); + parent.nextConnection.connect(oldChild.previousConnection); + newChild1.nextConnection.connect(newChild2.previousConnection); + + parent.nextConnection.connect(newChild1.previousConnection); + + chai.assert.isTrue(parent.nextConnection.isConnected()); + chai.assert.equal(parent.getNextBlock(), newChild1); + chai.assert.isTrue(newChild2.nextConnection.isConnected()); + chai.assert.equal(newChild2.getNextBlock(), oldChild); + this.assertBlockCount(4); + }); + + test('Bad check at end', function() { + var parent = this.workspace.newBlock('stack_block'); + var oldChild = this.workspace.newBlock('stack_block'); + var newChild = this.workspace.newBlock('stack_block_1to2'); + parent.nextConnection.connect(oldChild.previousConnection); + var spy = sinon.spy(oldChild.previousConnection, 'onFailedConnect'); + + parent.nextConnection.connect(newChild.previousConnection); + + chai.assert.isTrue(parent.nextConnection.isConnected()); + chai.assert.equal(parent.getNextBlock(), newChild); + chai.assert.isFalse(newChild.nextConnection.isConnected()); + chai.assert.isTrue(spy.calledOnce); + this.assertBlockCount(3); + }); + + test('No end connection', function() { + var parent = this.workspace.newBlock('stack_block'); + var oldChild = this.workspace.newBlock('stack_block'); + var newChild = this.workspace.newBlock('stack_block_noend'); + parent.nextConnection.connect(oldChild.previousConnection); + var spy = sinon.spy(oldChild.previousConnection, 'onFailedConnect'); + + parent.nextConnection.connect(newChild.previousConnection); + + chai.assert.isTrue(parent.nextConnection.isConnected()); + chai.assert.equal(parent.getNextBlock(), newChild); + chai.assert.isTrue(spy.calledOnce); + this.assertBlockCount(3); + }); + }); + + suite('Shadows', function() { + test('Simple', function() { + var parent = this.workspace.newBlock('stack_block'); + var oldChild = this.workspace.newBlock('stack_block'); + var newChild = this.workspace.newBlock('stack_block'); + parent.nextConnection.connect(oldChild.previousConnection); + var xml = Blockly.Xml.textToDom( + '' + ); + newChild.nextConnection.setShadowDom(xml); + + parent.nextConnection.connect(newChild.previousConnection); + + chai.assert.isTrue(parent.nextConnection.isConnected()); + chai.assert.equal(parent.getNextBlock(), newChild); + chai.assert.isTrue(newChild.nextConnection.isConnected()); + chai.assert.equal(newChild.getNextBlock(), oldChild); + this.assertBlockCount(3); + }); + + test('Bad check in between', function() { + var parent = this.workspace.newBlock('stack_block'); + var oldChild = this.workspace.newBlock('stack_block'); + var newChild1 = this.workspace.newBlock('stack_block_1to2'); + var newChild2 = this.workspace.newBlock('stack_block_2to1'); + parent.nextConnection.connect(oldChild.previousConnection); + newChild1.nextConnection.connect(newChild2.previousConnection); + var xml = Blockly.Xml.textToDom( + '' + ); + newChild2.nextConnection.setShadowDom(xml); + + parent.nextConnection.connect(newChild1.previousConnection); + + chai.assert.isTrue(parent.nextConnection.isConnected()); + chai.assert.equal(parent.getNextBlock(), newChild1); + chai.assert.isTrue(newChild2.nextConnection.isConnected()); + chai.assert.equal(newChild2.getNextBlock(), oldChild); + this.assertBlockCount(4); + }); + + test('Bad check at end', function() { + var parent = this.workspace.newBlock('stack_block'); + var oldChild = this.workspace.newBlock('stack_block'); + var newChild = this.workspace.newBlock('stack_block_1to2'); + parent.nextConnection.connect(oldChild.previousConnection); + var xml = Blockly.Xml.textToDom( + '' + ); + newChild.nextConnection.setShadowDom(xml); + var spy = sinon.spy(oldChild.previousConnection, 'onFailedConnect'); + + parent.nextConnection.connect(newChild.previousConnection); + + chai.assert.isTrue(parent.nextConnection.isConnected()); + chai.assert.equal(parent.getNextBlock(), newChild); + chai.assert.isTrue(newChild.nextConnection.isConnected()); + chai.assert.isTrue(newChild.getNextBlock().isShadow()); + chai.assert.isTrue(spy.calledOnce); + this.assertBlockCount(4); + }); + }); + }); + }); + }); }); diff --git a/tests/mocha/event_test.js b/tests/mocha/event_test.js index c53850ebb..01771c3c5 100644 --- a/tests/mocha/event_test.js +++ b/tests/mocha/event_test.js @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +goog.require('Blockly.WorkspaceComment'); + suite('Events', function() { setup(function() { sharedTestSetup.call(this, {fireEventsNow: false}); @@ -910,6 +912,19 @@ suite('Events', function() { chai.assert.equal(filteredEvents[0].newValue, 'item2'); }); + test('Merge viewport change events', function() { + var events = [ + new Blockly.Events.ViewportChange(1, 2, 3, this.workspace, 4), + new Blockly.Events.ViewportChange(5, 6, 7, this.workspace, 8) + ]; + var filteredEvents = Blockly.Events.filter(events, true); + chai.assert.equal(filteredEvents.length, 1); // second change event merged into first + chai.assert.equal(filteredEvents[0].viewTop, 5); + chai.assert.equal(filteredEvents[0].viewLeft, 6); + chai.assert.equal(filteredEvents[0].scale, 7); + chai.assert.equal(filteredEvents[0].oldScale, 8); + }); + test('Merge ui events', function() { var block1 = this.workspace.newBlock('field_variable_test_block', '1'); var block2 = this.workspace.newBlock('field_variable_test_block', '2'); diff --git a/tests/mocha/names_test.js b/tests/mocha/names_test.js index c8abefd71..698a6a6ce 100644 --- a/tests/mocha/names_test.js +++ b/tests/mocha/names_test.js @@ -21,7 +21,7 @@ suite('Names', function() { test('Safe name', function() { var varDB = new Blockly.Names('window,door'); chai.assert.equal(varDB.safeName_(''), 'unnamed','SafeName empty.'); - chai.assert.equal( varDB.safeName_('foobar'), 'foobar','SafeName ok.'); + chai.assert.equal(varDB.safeName_('foobar'), 'foobar','SafeName ok.'); chai.assert.equal(varDB.safeName_('9lives'), 'my_9lives', 'SafeName number start.'); chai.assert.equal(varDB.safeName_('lives9'), 'lives9', 'SafeName number end.'); chai.assert.equal(varDB.safeName_('!@#$'), '____', 'SafeName special chars.'); @@ -38,6 +38,9 @@ suite('Names', function() { chai.assert.equal(varDB.getName('Foo.bar', 'proc'), 'Foo_bar3', 'Name add #4.'); chai.assert.equal(varDB.getName('Foo.bar', 'var'), 'Foo_bar', 'Name get #1b.'); chai.assert.equal(varDB.getName('Foo.bar', 'proc'), 'Foo_bar3', 'Name get #4.'); + + chai.assert.equal(String(varDB.getUserNames('var')), 'foo.bar,foo bar,door', 'Get var names.'); + chai.assert.equal(String(varDB.getUserNames('proc')), 'foo.bar', 'Get proc names.'); }); test('Get distinct name', function() { diff --git a/tests/mocha/procedures_test.js b/tests/mocha/procedures_test.js index 95791ef63..48803bcbd 100644 --- a/tests/mocha/procedures_test.js +++ b/tests/mocha/procedures_test.js @@ -18,7 +18,7 @@ suite('Procedures', function() { teardown(function() { sharedTestTeardown.call(this); }); - + suite('allProcedures', function() { test('Only Procedures', function() { var noReturnBlock = new Blockly.Block(this.workspace, 'procedures_defnoreturn'); @@ -367,6 +367,51 @@ suite('Procedures', function() { }); }); + suite('getDefinition - Modified cases', function() { + setup(function() { + Blockly.Blocks['new_proc'] = { + init: function() { }, + getProcedureDef: function() { + return [this.name, [], false]; + }, + name: 'test' + }; + + Blockly.Blocks['nested_proc'] = { + init: function() { + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + }, + getProcedureDef: function() { + return [this.name, [], false]; + }, + name: 'test', + }; + }); + + teardown(function() { + delete Blockly.Blocks['new_proc']; + delete Blockly.Blocks['nested_proc']; + }); + + test('Custom procedure block', function() { + // Do not require procedures to be the built-in procedures. + var defBlock = new Blockly.Block(this.workspace, 'new_proc'); + var def = Blockly.Procedures.getDefinition('test', this.workspace); + chai.assert.equal(def, defBlock); + }); + + test('Stacked procedures', function() { + var blockA = new Blockly.Block(this.workspace, 'nested_proc'); + var blockB = new Blockly.Block(this.workspace, 'nested_proc'); + blockA.name = 'a'; + blockB.name = 'b'; + blockA.nextConnection.connect(blockB.previousConnection); + var def = Blockly.Procedures.getDefinition('b', this.workspace); + chai.assert.equal(def, blockB); + }); + }); + const testSuites = [ {title: 'procedures_defreturn', hasReturn: true, defType: 'procedures_defreturn', callType: 'procedures_callreturn'}, diff --git a/tests/mocha/toolbox_test.js b/tests/mocha/toolbox_test.js index 19d88e4ab..ed49e7136 100644 --- a/tests/mocha/toolbox_test.js +++ b/tests/mocha/toolbox_test.js @@ -34,6 +34,8 @@ suite('Toolbox', function() { test('Init called -> Toolbox is subscribed to background and foreground colour', function() { var themeManager = this.toolbox.workspace_.getThemeManager(); var themeManagerSpy = sinon.spy(themeManager, 'subscribe'); + var componentManager = this.toolbox.workspace_.getComponentManager(); + sinon.stub(componentManager, 'addComponent'); this.toolbox.init(); sinon.assert.calledWith(themeManagerSpy, this.toolbox.HtmlDiv, 'toolboxBackgroundColour', 'background-color'); @@ -42,10 +44,14 @@ suite('Toolbox', function() { }); test('Init called -> Render is called', function() { var renderSpy = sinon.spy(this.toolbox, 'render'); + var componentManager = this.toolbox.workspace_.getComponentManager(); + sinon.stub(componentManager, 'addComponent'); this.toolbox.init(); sinon.assert.calledOnce(renderSpy); }); test('Init called -> Flyout is initialized', function() { + var componentManager = this.toolbox.workspace_.getComponentManager(); + sinon.stub(componentManager, 'addComponent'); this.toolbox.init(); chai.assert.isDefined(this.toolbox.flyout_); }); diff --git a/tests/playgrounds/advanced_playground.html b/tests/playgrounds/advanced_playground.html index b142a6a00..87e1f37e2 100644 --- a/tests/playgrounds/advanced_playground.html +++ b/tests/playgrounds/advanced_playground.html @@ -67,6 +67,7 @@ +