release: Merge branch 'rc/v11.2.0' into rc/v12.0.0

This commit is contained in:
Aaron Dodson
2024-12-04 12:06:12 -08:00
329 changed files with 7487 additions and 7805 deletions

View File

@@ -6,6 +6,7 @@
// Former goog.module ID: Blockly.libraryBlocks
import type {BlockDefinition} from '../core/blocks.js';
import * as lists from './lists.js';
import * as logic from './logic.js';
import * as loops from './loops.js';
@@ -14,7 +15,6 @@ import * as procedures from './procedures.js';
import * as texts from './text.js';
import * as variables from './variables.js';
import * as variablesDynamic from './variables_dynamic.js';
import type {BlockDefinition} from '../core/blocks.js';
export {
lists,

View File

@@ -6,22 +6,22 @@
// Former goog.module ID: Blockly.libraryBlocks.lists
import * as fieldRegistry from '../core/field_registry.js';
import * as xmlUtils from '../core/utils/xml.js';
import {Align} from '../core/inputs/align.js';
import type {Block} from '../core/block.js';
import type {Connection} from '../core/connection.js';
import type {BlockSvg} from '../core/block_svg.js';
import type {FieldDropdown} from '../core/field_dropdown.js';
import {Msg} from '../core/msg.js';
import {MutatorIcon} from '../core/icons/mutator_icon.js';
import type {Workspace} from '../core/workspace.js';
import {
createBlockDefinitionsFromJsonArray,
defineBlocks,
} from '../core/common.js';
import type {Connection} from '../core/connection.js';
import '../core/field_dropdown.js';
import type {FieldDropdown} from '../core/field_dropdown.js';
import * as fieldRegistry from '../core/field_registry.js';
import {MutatorIcon} from '../core/icons/mutator_icon.js';
import {Align} from '../core/inputs/align.js';
import {ValueInput} from '../core/inputs/value_input.js';
import {Msg} from '../core/msg.js';
import * as xmlUtils from '../core/utils/xml.js';
import type {Workspace} from '../core/workspace.js';
/**
* A dictionary of the block definitions provided by this module.
@@ -412,6 +412,24 @@ const LISTS_GETINDEX = {
this.appendDummyInput()
.appendField(modeMenu, 'MODE')
.appendField('', 'SPACE');
const menu = fieldRegistry.fromJson({
type: 'field_dropdown',
options: this.WHERE_OPTIONS,
}) as FieldDropdown;
menu.setValidator(
/** @param value The input value. */
function (this: FieldDropdown, value: string) {
const oldValue: string | null = this.getValue();
const oldAt = oldValue === 'FROM_START' || oldValue === 'FROM_END';
const newAt = value === 'FROM_START' || value === 'FROM_END';
if (newAt !== oldAt) {
const block = this.getSourceBlock() as GetIndexBlock;
block.updateAt_(newAt);
}
return undefined;
},
);
this.appendDummyInput().appendField(menu, 'WHERE');
this.appendDummyInput('AT');
if (Msg['LISTS_GET_INDEX_TAIL']) {
this.appendDummyInput('TAIL').appendField(Msg['LISTS_GET_INDEX_TAIL']);
@@ -577,31 +595,6 @@ const LISTS_GETINDEX = {
} else {
this.appendDummyInput('AT');
}
const menu = fieldRegistry.fromJson({
type: 'field_dropdown',
options: this.WHERE_OPTIONS,
}) as FieldDropdown;
menu.setValidator(
/**
* @param value The input value.
* @returns Null if the field has been replaced; otherwise undefined.
*/
function (this: FieldDropdown, value: string) {
const newAt = value === 'FROM_START' || value === 'FROM_END';
// The 'isAt' variable is available due to this function being a
// closure.
if (newAt !== isAt) {
const block = this.getSourceBlock() as GetIndexBlock;
block.updateAt_(newAt);
// This menu has been destroyed and replaced. Update the
// replacement.
block.setFieldValue(value, 'WHERE');
return null;
}
return undefined;
},
);
this.getInput('AT')!.appendField(menu, 'WHERE');
if (Msg['LISTS_GET_INDEX_TAIL']) {
this.moveInputBefore('TAIL', null);
}
@@ -644,6 +637,24 @@ const LISTS_SETINDEX = {
this.appendDummyInput()
.appendField(operationDropdown, 'MODE')
.appendField('', 'SPACE');
const menu = fieldRegistry.fromJson({
type: 'field_dropdown',
options: this.WHERE_OPTIONS,
}) as FieldDropdown;
menu.setValidator(
/** @param value The input value. */
function (this: FieldDropdown, value: string) {
const oldValue: string | null = this.getValue();
const oldAt = oldValue === 'FROM_START' || oldValue === 'FROM_END';
const newAt = value === 'FROM_START' || value === 'FROM_END';
if (newAt !== oldAt) {
const block = this.getSourceBlock() as SetIndexBlock;
block.updateAt_(newAt);
}
return undefined;
},
);
this.appendDummyInput().appendField(menu, 'WHERE');
this.appendDummyInput('AT');
this.appendValueInput('TO').appendField(Msg['LISTS_SET_INDEX_INPUT_TO']);
this.setInputsInline(true);
@@ -756,36 +767,10 @@ const LISTS_SETINDEX = {
} else {
this.appendDummyInput('AT');
}
const menu = fieldRegistry.fromJson({
type: 'field_dropdown',
options: this.WHERE_OPTIONS,
}) as FieldDropdown;
menu.setValidator(
/**
* @param value The input value.
* @returns Null if the field has been replaced; otherwise undefined.
*/
function (this: FieldDropdown, value: string) {
const newAt = value === 'FROM_START' || value === 'FROM_END';
// The 'isAt' variable is available due to this function being a
// closure.
if (newAt !== isAt) {
const block = this.getSourceBlock() as SetIndexBlock;
block.updateAt_(newAt);
// This menu has been destroyed and replaced. Update the
// replacement.
block.setFieldValue(value, 'WHERE');
return null;
}
return undefined;
},
);
this.moveInputBefore('AT', 'TO');
if (this.getInput('ORDINAL')) {
this.moveInputBefore('ORDINAL', 'TO');
}
this.getInput('AT')!.appendField(menu, 'WHERE');
},
};
blocks['lists_setIndex'] = LISTS_SETINDEX;
@@ -818,7 +803,30 @@ const LISTS_GETSUBLIST = {
this.appendValueInput('LIST')
.setCheck('Array')
.appendField(Msg['LISTS_GET_SUBLIST_INPUT_IN_LIST']);
const createMenu = (n: 1 | 2): FieldDropdown => {
const menu = fieldRegistry.fromJson({
type: 'field_dropdown',
options:
this[('WHERE_OPTIONS_' + n) as 'WHERE_OPTIONS_1' | 'WHERE_OPTIONS_2'],
}) as FieldDropdown;
menu.setValidator(
/** @param value The input value. */
function (this: FieldDropdown, value: string) {
const oldValue: string | null = this.getValue();
const oldAt = oldValue === 'FROM_START' || oldValue === 'FROM_END';
const newAt = value === 'FROM_START' || value === 'FROM_END';
if (newAt !== oldAt) {
const block = this.getSourceBlock() as GetSublistBlock;
block.updateAt_(n, newAt);
}
return undefined;
},
);
return menu;
};
this.appendDummyInput('WHERE1_INPUT').appendField(createMenu(1), 'WHERE1');
this.appendDummyInput('AT1');
this.appendDummyInput('WHERE2_INPUT').appendField(createMenu(2), 'WHERE2');
this.appendDummyInput('AT2');
if (Msg['LISTS_GET_SUBLIST_TAIL']) {
this.appendDummyInput('TAIL').appendField(Msg['LISTS_GET_SUBLIST_TAIL']);
@@ -896,35 +904,10 @@ const LISTS_GETSUBLIST = {
} else {
this.appendDummyInput('AT' + n);
}
const menu = fieldRegistry.fromJson({
type: 'field_dropdown',
options:
this[('WHERE_OPTIONS_' + n) as 'WHERE_OPTIONS_1' | 'WHERE_OPTIONS_2'],
}) as FieldDropdown;
menu.setValidator(
/**
* @param value The input value.
* @returns Null if the field has been replaced; otherwise undefined.
*/
function (this: FieldDropdown, value: string) {
const newAt = value === 'FROM_START' || value === 'FROM_END';
// The 'isAt' variable is available due to this function being a
// closure.
if (newAt !== isAt) {
const block = this.getSourceBlock() as GetSublistBlock;
block.updateAt_(n, newAt);
// This menu has been destroyed and replaced.
// Update the replacement.
block.setFieldValue(value, 'WHERE' + n);
return null;
}
},
);
this.getInput('AT' + n)!.appendField(menu, 'WHERE' + n);
if (n === 1) {
this.moveInputBefore('AT1', 'AT2');
this.moveInputBefore('AT1', 'WHERE2_INPUT');
if (this.getInput('ORDINAL1')) {
this.moveInputBefore('ORDINAL1', 'AT2');
this.moveInputBefore('ORDINAL1', 'WHERE2_INPUT');
}
}
if (Msg['LISTS_GET_SUBLIST_TAIL']) {

View File

@@ -6,22 +6,22 @@
// Former goog.module ID: Blockly.libraryBlocks.logic
import * as Events from '../core/events/events.js';
import * as Extensions from '../core/extensions.js';
import * as xmlUtils from '../core/utils/xml.js';
import type {Abstract as AbstractEvent} from '../core/events/events_abstract.js';
import type {Block} from '../core/block.js';
import type {BlockSvg} from '../core/block_svg.js';
import type {Connection} from '../core/connection.js';
import {Msg} from '../core/msg.js';
import type {Workspace} from '../core/workspace.js';
import {
createBlockDefinitionsFromJsonArray,
defineBlocks,
} from '../core/common.js';
import type {Connection} from '../core/connection.js';
import * as Events from '../core/events/events.js';
import type {Abstract as AbstractEvent} from '../core/events/events_abstract.js';
import * as Extensions from '../core/extensions.js';
import '../core/field_dropdown.js';
import '../core/field_label.js';
import '../core/icons/mutator_icon.js';
import {Msg} from '../core/msg.js';
import * as xmlUtils from '../core/utils/xml.js';
import type {Workspace} from '../core/workspace.js';
/**
* A dictionary of the block definitions provided by this module.

View File

@@ -6,27 +6,27 @@
// Former goog.module ID: Blockly.libraryBlocks.loops
import type {Abstract as AbstractEvent} from '../core/events/events_abstract.js';
import type {Block} from '../core/block.js';
import {
createBlockDefinitionsFromJsonArray,
defineBlocks,
} from '../core/common.js';
import * as ContextMenu from '../core/contextmenu.js';
import type {
ContextMenuOption,
LegacyContextMenuOption,
} from '../core/contextmenu_registry.js';
import * as Events from '../core/events/events.js';
import * as Extensions from '../core/extensions.js';
import {Msg} from '../core/msg.js';
import {
createBlockDefinitionsFromJsonArray,
defineBlocks,
} from '../core/common.js';
import type {Abstract as AbstractEvent} from '../core/events/events_abstract.js';
import * as eventUtils from '../core/events/utils.js';
import * as Extensions from '../core/extensions.js';
import '../core/field_dropdown.js';
import '../core/field_label.js';
import '../core/field_number.js';
import '../core/field_variable.js';
import '../core/icons/warning_icon.js';
import {FieldVariable} from '../core/field_variable.js';
import '../core/icons/warning_icon.js';
import {Msg} from '../core/msg.js';
import {WorkspaceSvg} from '../core/workspace_svg.js';
/**

View File

@@ -6,18 +6,18 @@
// Former goog.module ID: Blockly.libraryBlocks.math
import * as Extensions from '../core/extensions.js';
import type {FieldDropdown} from '../core/field_dropdown.js';
import * as xmlUtils from '../core/utils/xml.js';
import type {Block} from '../core/block.js';
import {
createBlockDefinitionsFromJsonArray,
defineBlocks,
} from '../core/common.js';
import * as Extensions from '../core/extensions.js';
import '../core/field_dropdown.js';
import type {FieldDropdown} from '../core/field_dropdown.js';
import '../core/field_label.js';
import '../core/field_number.js';
import '../core/field_variable.js';
import * as xmlUtils from '../core/utils/xml.js';
/**
* A dictionary of the block definitions provided by this module.

View File

@@ -6,43 +6,43 @@
// Former goog.module ID: Blockly.libraryBlocks.procedures
import * as ContextMenu from '../core/contextmenu.js';
import * as Events from '../core/events/events.js';
import * as Procedures from '../core/procedures.js';
import * as Variables from '../core/variables.js';
import * as Xml from '../core/xml.js';
import * as fieldRegistry from '../core/field_registry.js';
import * as xmlUtils from '../core/utils/xml.js';
import type {Abstract as AbstractEvent} from '../core/events/events_abstract.js';
import {Align} from '../core/inputs/align.js';
import type {Block} from '../core/block.js';
import type {BlockSvg} from '../core/block_svg.js';
import type {BlockCreate} from '../core/events/events_block_create.js';
import type {BlockChange} from '../core/events/events_block_change.js';
import type {BlockDefinition} from '../core/blocks.js';
import * as common from '../core/common.js';
import {defineBlocks} from '../core/common.js';
import {config} from '../core/config.js';
import type {Connection} from '../core/connection.js';
import * as ContextMenu from '../core/contextmenu.js';
import type {
ContextMenuOption,
LegacyContextMenuOption,
} from '../core/contextmenu_registry.js';
import * as Events from '../core/events/events.js';
import type {Abstract as AbstractEvent} from '../core/events/events_abstract.js';
import type {BlockChange} from '../core/events/events_block_change.js';
import type {BlockCreate} from '../core/events/events_block_create.js';
import * as eventUtils from '../core/events/utils.js';
import {FieldCheckbox} from '../core/field_checkbox.js';
import {FieldLabel} from '../core/field_label.js';
import * as fieldRegistry from '../core/field_registry.js';
import {FieldTextInput} from '../core/field_textinput.js';
import {Msg} from '../core/msg.js';
import '../core/icons/comment_icon.js';
import {MutatorIcon as Mutator} from '../core/icons/mutator_icon.js';
import {Names} from '../core/names.js';
import '../core/icons/warning_icon.js';
import {Align} from '../core/inputs/align.js';
import type {
IVariableModel,
IVariableState,
} from '../core/interfaces/i_variable_model.js';
import {Msg} from '../core/msg.js';
import {Names} from '../core/names.js';
import * as Procedures from '../core/procedures.js';
import * as xmlUtils from '../core/utils/xml.js';
import * as Variables from '../core/variables.js';
import type {Workspace} from '../core/workspace.js';
import type {WorkspaceSvg} from '../core/workspace_svg.js';
import {config} from '../core/config.js';
import {defineBlocks} from '../core/common.js';
import '../core/icons/comment_icon.js';
import '../core/icons/warning_icon.js';
import * as common from '../core/common.js';
import * as Xml from '../core/xml.js';
/** A dictionary of the block definitions provided by this module. */
export const blocks: {[key: string]: BlockDefinition} = {};
@@ -1108,6 +1108,14 @@ const PROCEDURE_CALL_COMMON = {
xml.appendChild(block);
Xml.domToWorkspace(xml, this.workspace);
Events.setGroup(false);
} else if (!def.isEnabled()) {
this.setDisabledReason(
true,
DISABLED_PROCEDURE_DEFINITION_DISABLED_REASON,
);
this.setWarningText(
Msg['PROCEDURES_CALL_DISABLED_DEF_WARNING'].replace('%1', name),
);
}
} else if (event.type === Events.BLOCK_DELETE) {
// Look for the case where a procedure definition has been deleted,
@@ -1215,7 +1223,7 @@ blocks['procedures_callreturn'] = {
this.appendDummyInput('TOPROW').appendField('', 'NAME');
this.setOutput(true);
this.setStyle('procedure_blocks');
// Tooltip is set in domToMutation.
// Tooltip is set in renameProcedure.
this.setHelpUrl(Msg['PROCEDURES_CALLRETURN_HELPURL']);
this.arguments_ = [];
this.argumentVarModels_ = [];

View File

@@ -6,25 +6,25 @@
// Former goog.module ID: Blockly.libraryBlocks.texts
import * as Extensions from '../core/extensions.js';
import * as fieldRegistry from '../core/field_registry.js';
import * as xmlUtils from '../core/utils/xml.js';
import {Align} from '../core/inputs/align.js';
import type {Block} from '../core/block.js';
import type {BlockSvg} from '../core/block_svg.js';
import {Connection} from '../core/connection.js';
import {FieldImage} from '../core/field_image.js';
import {FieldDropdown} from '../core/field_dropdown.js';
import {FieldTextInput} from '../core/field_textinput.js';
import {Msg} from '../core/msg.js';
import {MutatorIcon} from '../core/icons/mutator_icon.js';
import type {Workspace} from '../core/workspace.js';
import {
createBlockDefinitionsFromJsonArray,
defineBlocks,
} from '../core/common.js';
import {Connection} from '../core/connection.js';
import * as Extensions from '../core/extensions.js';
import {FieldDropdown} from '../core/field_dropdown.js';
import {FieldImage} from '../core/field_image.js';
import * as fieldRegistry from '../core/field_registry.js';
import {FieldTextInput} from '../core/field_textinput.js';
import '../core/field_variable.js';
import {MutatorIcon} from '../core/icons/mutator_icon.js';
import {Align} from '../core/inputs/align.js';
import {ValueInput} from '../core/inputs/value_input.js';
import {Msg} from '../core/msg.js';
import * as xmlUtils from '../core/utils/xml.js';
import type {Workspace} from '../core/workspace.js';
/**
* A dictionary of the block definitions provided by this module.
@@ -216,7 +216,30 @@ const GET_SUBSTRING_BLOCK = {
this.appendValueInput('STRING')
.setCheck('String')
.appendField(Msg['TEXT_GET_SUBSTRING_INPUT_IN_TEXT']);
const createMenu = (n: 1 | 2): FieldDropdown => {
const menu = fieldRegistry.fromJson({
type: 'field_dropdown',
options:
this[('WHERE_OPTIONS_' + n) as 'WHERE_OPTIONS_1' | 'WHERE_OPTIONS_2'],
}) as FieldDropdown;
menu.setValidator(
/** @param value The input value. */
function (this: FieldDropdown, value: any): null | undefined {
const oldValue: string | null = this.getValue();
const oldAt = oldValue === 'FROM_START' || oldValue === 'FROM_END';
const newAt = value === 'FROM_START' || value === 'FROM_END';
if (newAt !== oldAt) {
const block = this.getSourceBlock() as GetSubstringBlock;
block.updateAt_(n, newAt);
}
return undefined;
},
);
return menu;
};
this.appendDummyInput('WHERE1_INPUT').appendField(createMenu(1), 'WHERE1');
this.appendDummyInput('AT1');
this.appendDummyInput('WHERE2_INPUT').appendField(createMenu(2), 'WHERE2');
this.appendDummyInput('AT2');
if (Msg['TEXT_GET_SUBSTRING_TAIL']) {
this.appendDummyInput('TAIL').appendField(Msg['TEXT_GET_SUBSTRING_TAIL']);
@@ -288,37 +311,10 @@ const GET_SUBSTRING_BLOCK = {
this.removeInput('TAIL', true);
this.appendDummyInput('TAIL').appendField(Msg['TEXT_GET_SUBSTRING_TAIL']);
}
const menu = fieldRegistry.fromJson({
type: 'field_dropdown',
options:
this[('WHERE_OPTIONS_' + n) as 'WHERE_OPTIONS_1' | 'WHERE_OPTIONS_2'],
}) as FieldDropdown;
menu.setValidator(
/**
* @param value The input value.
* @returns Null if the field has been replaced; otherwise undefined.
*/
function (this: FieldDropdown, value: any): null | undefined {
const newAt = value === 'FROM_START' || value === 'FROM_END';
// The 'isAt' variable is available due to this function being a
// closure.
if (newAt !== isAt) {
const block = this.getSourceBlock() as GetSubstringBlock;
block.updateAt_(n, newAt);
// This menu has been destroyed and replaced.
// Update the replacement.
block.setFieldValue(value, 'WHERE' + n);
return null;
}
return undefined;
},
);
this.getInput('AT' + n)!.appendField(menu, 'WHERE' + n);
if (n === 1) {
this.moveInputBefore('AT1', 'AT2');
this.moveInputBefore('AT1', 'WHERE2_INPUT');
if (this.getInput('ORDINAL1')) {
this.moveInputBefore('ORDINAL1', 'AT2');
this.moveInputBefore('ORDINAL1', 'WHERE2_INPUT');
}
}
},
@@ -438,6 +434,11 @@ const PROMPT_COMMON = {
domToMutation: function (this: PromptCommonBlock, xmlElement: Element) {
this.updateType_(xmlElement.getAttribute('type')!);
},
// These blocks do not need JSO serialization hooks (saveExtraState
// and loadExtraState) because the state of this object is already
// encoded in the dropdown values.
// XML hooks are kept for backwards compatibility.
};
blocks['text_prompt_ext'] = {
@@ -468,16 +469,11 @@ blocks['text_prompt_ext'] = {
: Msg['TEXT_PROMPT_TOOLTIP_NUMBER'];
});
},
// This block does not need JSO serialization hooks (saveExtraState and
// loadExtraState) because the state of this object is already encoded in the
// dropdown values.
// XML hooks are kept for backwards compatibility.
};
type PromptBlock = Block & PromptCommonMixin & QuoteImageMixin;
const TEXT_PROMPT_BLOCK = {
blocks['text_prompt'] = {
...PROMPT_COMMON,
/**
* Block for prompt function (internal message).
@@ -520,8 +516,6 @@ const TEXT_PROMPT_BLOCK = {
},
};
blocks['text_prompt'] = TEXT_PROMPT_BLOCK;
blocks['text_count'] = {
/**
* Block for counting how many times one string appears within another string.
@@ -666,7 +660,7 @@ const QUOTE_IMAGE_MIXIN = {
* closing double quote. The selected quote will be adapted for RTL blocks.
*
* @param open If the image should be open quote (“ in LTR).
* Otherwise, a closing quote is used (” in LTR).
* Otherwise, a closing quote is used (” in LTR).
* @returns The new field.
*/
newQuote_: function (this: QuoteImageBlock, open: boolean): FieldImage {

View File

@@ -6,22 +6,22 @@
// Former goog.module ID: Blockly.libraryBlocks.variables
import * as ContextMenu from '../core/contextmenu.js';
import * as Extensions from '../core/extensions.js';
import * as Variables from '../core/variables.js';
import type {Block} from '../core/block.js';
import type {
ContextMenuOption,
LegacyContextMenuOption,
} from '../core/contextmenu_registry.js';
import {FieldVariable} from '../core/field_variable.js';
import {Msg} from '../core/msg.js';
import type {WorkspaceSvg} from '../core/workspace_svg.js';
import {
createBlockDefinitionsFromJsonArray,
defineBlocks,
} from '../core/common.js';
import * as ContextMenu from '../core/contextmenu.js';
import type {
ContextMenuOption,
LegacyContextMenuOption,
} from '../core/contextmenu_registry.js';
import * as Extensions from '../core/extensions.js';
import '../core/field_label.js';
import {FieldVariable} from '../core/field_variable.js';
import {Msg} from '../core/msg.js';
import * as Variables from '../core/variables.js';
import type {WorkspaceSvg} from '../core/workspace_svg.js';
/**
* A dictionary of the block definitions provided by this module.

View File

@@ -6,23 +6,23 @@
// Former goog.module ID: Blockly.libraryBlocks.variablesDynamic
import * as ContextMenu from '../core/contextmenu.js';
import * as Extensions from '../core/extensions.js';
import * as Variables from '../core/variables.js';
import {Abstract as AbstractEvent} from '../core/events/events_abstract.js';
import type {Block} from '../core/block.js';
import type {
ContextMenuOption,
LegacyContextMenuOption,
} from '../core/contextmenu_registry.js';
import {FieldVariable} from '../core/field_variable.js';
import {Msg} from '../core/msg.js';
import type {WorkspaceSvg} from '../core/workspace_svg.js';
import {
createBlockDefinitionsFromJsonArray,
defineBlocks,
} from '../core/common.js';
import * as ContextMenu from '../core/contextmenu.js';
import type {
ContextMenuOption,
LegacyContextMenuOption,
} from '../core/contextmenu_registry.js';
import {Abstract as AbstractEvent} from '../core/events/events_abstract.js';
import * as Extensions from '../core/extensions.js';
import '../core/field_label.js';
import {FieldVariable} from '../core/field_variable.js';
import {Msg} from '../core/msg.js';
import * as Variables from '../core/variables.js';
import type {WorkspaceSvg} from '../core/workspace_svg.js';
/**
* A dictionary of the block definitions provided by this module.