feat: Add a JSON Block definition interface (#9613)

This commit is contained in:
Heliacer
2026-04-02 20:16:54 +02:00
committed by GitHub
parent 0efc502ad5
commit 0bdae1497b
3 changed files with 161 additions and 10 deletions
+9 -10
View File
@@ -1721,8 +1721,8 @@ export class Block {
// Validate that each arg has a corresponding message
let n = 0;
while (json['args' + n]) {
if (json['message' + n] === undefined) {
while (json[`args${n}`]) {
if (json[`message${n}`] === undefined) {
throw Error(
warningPrefix +
`args${n} must have a corresponding message (message${n}).`,
@@ -1732,14 +1732,13 @@ export class Block {
}
// Set basic properties of block.
// Makes styles backward compatible with old way of defining hat style.
if (json['style'] && json['style'].hat) {
this.hat = json['style'].hat;
// Handle legacy style object format for backwards compatibility
if (json['style'] && typeof json['style'] === 'object') {
this.hat = (json['style'] as {hat?: string}).hat;
// Must set to null so it doesn't error when checking for style and
// colour.
json['style'] = null;
}
if (json['style'] && json['colour']) {
throw Error(warningPrefix + 'Must not have both a colour and a style.');
} else if (json['style']) {
@@ -1750,12 +1749,12 @@ export class Block {
// Interpolate the message blocks.
let i = 0;
while (json['message' + i] !== undefined) {
while (json[`message${i}`] !== undefined) {
this.interpolate(
json['message' + i],
json['args' + i] || [],
json[`message${i}`] || '',
json[`args${i}`] || [],
// Backwards compatibility: lastDummyAlign aliases implicitAlign.
json['implicitAlign' + i] || json['lastDummyAlign' + i],
json[`implicitAlign${i}`] || (json as any)[`lastDummyAlign${i}`],
warningPrefix,
);
i++;
@@ -0,0 +1,126 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {FieldCheckboxFromJsonConfig} from '../field_checkbox.js';
import {FieldDropdownFromJsonConfig} from '../field_dropdown';
import {FieldImageFromJsonConfig} from '../field_image';
import {FieldNumberFromJsonConfig} from '../field_number';
import {FieldTextInputFromJsonConfig} from '../field_textinput';
import {FieldVariableFromJsonConfig} from '../field_variable';
import {Align} from '../inputs/align.js';
/**
* Defines the JSON structure for a block definition.
*
* @example
* ```typescript
* const blockDef: JsonBlockDefinition = {
* type: 'custom_block',
* message0: 'move %1 steps',
* args0: [
* {
* 'type': 'field_number',
* 'name': 'INPUT',
* },
* ],
* previousStatement: null,
* nextStatement: null,
* };
* ```
*/
export interface JsonBlockDefinition {
type: string;
style?: string | null;
colour?: string | number;
output?: string | string[] | null;
previousStatement?: string | string[] | null;
nextStatement?: string | string[] | null;
outputShape?: number;
inputsInline?: boolean;
tooltip?: string;
helpUrl?: string;
extensions?: string[];
mutator?: string;
enableContextMenu?: boolean;
suppressPrefixSuffix?: boolean;
[key: `message${number}`]: string | undefined;
[key: `args${number}`]: JsonBlockArg[] | undefined;
[key: `implicitAlign${number}`]: string | undefined;
}
export type JsonBlockArg =
| InputValueArg
| InputStatementArg
| InputDummyArg
| InputEndRowArg
| FieldInputArg
| FieldNumberArg
| FieldDropdownArg
| FieldCheckboxArg
| FieldImageArg
| FieldVariableArg
| UnknownArg;
interface UnknownArg {
type: string;
[key: string]: unknown;
}
/** Input args */
interface InputValueArg {
type: 'input_value';
name?: string;
check?: string | string[];
align?: Align;
}
interface InputStatementArg {
type: 'input_statement';
name?: string;
check?: string | string[];
}
interface InputDummyArg {
type: 'input_dummy';
name?: string;
}
interface InputEndRowArg {
type: 'input_end_row';
name?: string;
}
/** Field args */
interface FieldInputArg extends FieldTextInputFromJsonConfig {
type: 'field_input';
name?: string;
}
interface FieldNumberArg extends FieldNumberFromJsonConfig {
type: 'field_number';
name?: string;
}
interface FieldDropdownArg extends FieldDropdownFromJsonConfig {
type: 'field_dropdown';
name?: string;
}
interface FieldCheckboxArg extends FieldCheckboxFromJsonConfig {
type: 'field_checkbox';
name?: string;
}
interface FieldImageArg extends FieldImageFromJsonConfig {
type: 'field_image';
name?: string;
}
interface FieldVariableArg extends FieldVariableFromJsonConfig {
type: 'field_variable';
name?: string;
}
@@ -0,0 +1,26 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {defineBlocksWithJsonArray} from 'blockly-test/core';
import type {JsonBlockDefinition} from 'blockly-test/core/interfaces/i_json_block_definition';
import './different_user_input';
const mitosisBlockDefinition: JsonBlockDefinition = {
type: 'mitosis_block',
message0: 'split cell %1',
args0: [
{
type: 'field_mitosis',
name: 'CELL',
cellId: 'cell-A',
},
],
previousStatement: null,
nextStatement: null,
};
defineBlocksWithJsonArray([mitosisBlockDefinition]);