Добавьте поле плагина в Block Factory

Инструменты разработчика Blockly позволяют создавать пользовательские блоки с помощью блоков! Они поддерживают поля, опубликованные как плагины, в дополнение к полям, поставляемым с ядром Blockly. Если вы создали пользовательское поле, вы можете добавить его поддержку в Block Factory, следуя этому руководству. Пользовательское поле должно быть опубликовано в npm, прежде чем вы сможете добавить его поддержку. Вам также необходимо обновлять своё поле, чтобы оно соответствовало изменениям в Blockly, иначе нам, возможно, придётся удалить его из Block Factory в будущем.

Развитие на блочном заводе

Исходный код Block Factory находится в репозитории blockly-samples в каталоге examples/developer-tools .

Чтобы внести изменения в инструменты разработчика в blockly-samples, необходимо выполнить стандартные шаги для разработки в blockly-samples. Однако, в отличие от работы с плагинами, вам потребуется запустить npm install непосредственно из каталога examples/developer-tools , а не в корневом каталоге blockly-samples.

Установить плагин

Чтобы Block Factory отображал ваше настраиваемое поле в предварительном просмотре, необходимо установить его. Добавьте поле как npm-зависимость developer-tools. Затем зарегистрируйте его или выполните другие необходимые настройки в файле developer-tools/src/blocks/index.ts .

Создать блок для поля

Поскольку Block Factory использует блоки для создания пользовательских блоков, вам понадобится блок, представляющий ваше пользовательское поле.

Создайте определение блока

Вам необходимо разработать блок для вашего поля; если вы хотите получить метаданные, вы можете создать его с помощью Block Factory! Блок должен позволять пользователю настраивать параметры, необходимые для вашего поля, такие как значения по умолчанию и имя. Добавьте это определение блока в файл developer-tools/src/blocks/fields.ts и импортируйте его в файл developer-tools/src/blocks/index.ts .

Добавить блок в набор инструментов

Далее вам нужно добавить этот блок в определение панели инструментов, чтобы сделать его доступным для пользователей. Определение панели инструментов находится в файле developer-tools/src/toolbox.ts . Ваш блок должен быть добавлен в категорию «Поля».

Генераторы кода

Block Factory работает на основе системы генератора кода, с которой вы уже знакомы по Blockly. Каждый блок имеет генератор блочного кода для каждого типа выходных данных, генерируемых Block Factory, а родительские блоки собирают код для дочерних блоков в нужный выходной файл. Чтобы добавить поддержку настраиваемого поля, вам потребуется добавить функции генератора блочного кода для каждого класса генератора кода.

Создайте файл для блока поля в каталоге output-generators/fields . В этот файл нужно добавить генераторы блочного кода для каждого из следующих генераторов. Импортируйте этот файл в файл blocks/index.ts чтобы функции генератора блочного кода были загружены в приложение.

Определение JavaScript

Функция javascriptDefinitionGenerator создаёт код, который будет включён в определение JavaScript для блока, содержащего ваше настраиваемое поле. Обычно это означает, что генератор блочного кода должен вернуть строку кода, которая выглядит так .appendField(new YourFieldConstructor(arg1, arg2), 'userSpecifiedName') . Обратите внимание, что эта строка кода не содержит точку с запятой, поскольку входные данные, содержащие несколько полей, будут содержать несколько вызовов appendField , связанных между собой. Аргументы в конструкторе извлекаются из значений, заданных пользователем для блока поля. Вот пример этого генератора блочного кода для FieldAngle :

javascriptDefinitionGenerator.forBlock['field_angle'] = function (
  block: Blockly.Block,
  generator: JavascriptDefinitionGenerator,
): string {
  const name = generator.quote_(block.getFieldValue('FIELDNAME'));
  const angle = block.getFieldValue('ANGLE');
  return `.appendField(new FieldAngle(${angle}), ${name})`;
};

Угловой блок, который пользователь перетащил из категории «Поля» панели инструментов Block Factory, имеет два поля:

  • FIELDNAME : пользователь может задать имя поля в своем пользовательском блоке.
  • ANGLE : пользователь может установить значение угла по умолчанию

В этом генераторе блочного кода мы получаем значение угла по умолчанию и передаём его как единственный аргумент конструктору FieldAngle . Имя поля всегда передаётся как второй аргумент в appendField .

определение JSON

jsonDefinitionGenerator работает аналогично, но выводит часть определения блока JSON, соответствующую вашему полю. Обычно этот код представляет собой JSON-объект, включающий:

  • type : соответствует имени вашего поля в реестре полей Blockly
  • name : пользователь может задать имя поля в своем пользовательском блоке
  • любые другие пользовательские свойства, необходимые для метода инициализации JSON вашего поля.

Вот еще пример из FieldAngle :

jsonDefinitionGenerator.forBlock['field_angle'] = function (
  block: Blockly.Block,
  generator: JsonDefinitionGenerator,
): string {
  const code = {
    type: 'field_angle',
    name: block.getFieldValue('FIELDNAME'),
    angle: block.getFieldValue('ANGLE'),
  };
  return JSON.stringify(code);
};

Заголовки кода

Генератор заголовков кода создаёт выходные данные, отображаемые в фабрике блоков. Этот вывод можно переключать между импортом esmodule и тегами скриптов в зависимости от того, как пользователь хочет загрузить код, поэтому фактически существует два разных экземпляра генератора: по одному для каждого случая. Вам необходимо добавить генератор блочного кода для каждого из них. Вот пример для FieldAngle :

importHeaderGenerator.forBlock['field_angle'] = function (
  block: Blockly.Block,
  generator: CodeHeaderGenerator,
): string {
  generator.addHeaderLine(
    `import {registerFieldAngle, FieldAngle} from '@blockly/field-angle';`,
  );
  generator.addHeaderLine(`registerFieldAngle();`);
  return '';
};

scriptHeaderGenerator.forBlock['field_angle'] = function (
  block: Blockly.Block,
  generator: CodeHeaderGenerator,
): string {
  generator.addHeaderLine(
    `<script src="https://unpkg.com/@blockly/field-angle"></script>`,
  );
  generator.addHeaderLine(`registerFieldAngle();`);
  return '';
};

Эти генераторы имеют метод addHeaderLine , позволяющий указать строку кода, которая должна быть вызвана перед использованием поля. Обычно это включает в себя такие действия, как импорт поля или его загрузка через тег скрипта, а также, возможно, вызов функции, которая зарегистрирует поле в реестре полей Blockly.

Для этих двух генераторов блочного кода весь код должен быть добавлен посредством вызовов addHeaderLine . Эта функция гарантирует, что каждая строка заголовка будет отображаться только один раз, даже если ваш блок настраиваемых полей используется несколько раз в одном блоке. Генератор блочного кода должен возвращать пустую строку.

Заглушка генератора

Наконец, у нас есть генератор, который создаёт заглушку для поля. В этом генераторе блочного кода вы будете писать код, который генерирует код, помогающий пользователю писать код, который генерирует код. Всё ещё запутались? Всё проще, чем кажется!

Заглушка генератора для пользовательского блока включает в себя готовую переменную, представляющую каждое поле блока. Затем пользователю необходимо выполнить TODO , чтобы собрать все эти переменные в итоговую строку кода, которую вернёт его пользовательский блок. Это означает, что обычно всё, что нужно сделать вашему генератору блочного кода, — это вернуть строку, создающую эту пользовательскую переменную. Допустим, пользователь создаёт пользовательский блок, который добавит солнечные лучи на холст. Он добавляет к блоку поле угла и называет его "SUN_DIRECTION" . Заглушка генератора для этого блока будет включать строку const angle_sun_direction = block.getFieldValue("SUN_DIRECTION"); . Это строка кода, которую должен вернуть наш генератор блочного кода для поля угла:

generatorStubGenerator.forBlock['field_angle'] = function (
  block: Blockly.Block,
  generator: GeneratorStubGenerator,
): string {
  const name = block.getFieldValue('FIELDNAME');
  const fieldVar = generator.createVariableName('angle', name);
  return `const ${fieldVar} = block.getFieldValue(${generator.quote_(
    name,
  )});\n`;
};

Чтобы получить стандартизированное имя для переменной, вы можете вызвать generator.createVariableName и передать тип вашего поля (например, angle , number и т. д.) вместе с тем, как пользователь назвал свое поле.

Проверьте это

После того, как вы напишете все эти фрагменты, вы сможете запустить Block Factory, выполнив команду npm start в каталоге blockly-samples/examples/developer-tools . Вы сможете перетащить блок из категории полей, добавить его к входным данным блока и наблюдать за изменением выходных данных. Убедитесь, что предварительный просмотр блока выглядит корректно, а код для каждого из разделов выходных данных корректен.