Issue #3628772: Validate the content type template and edit it with a JSON editor

Closes #3628772. First of the content type template issues of #3445654.

The template field of the content type form becomes a JSON editor, and the template is validated when the content type is saved.

Content type form

  • JSON editor: the template textarea is replaced with a CodeMirror 6 editor that marks problems while typing:
    • Errors: invalid JSON (with line and column), a template that isn't a list, blocks that aren't [name, attributes, inner blocks], invalid block names.
    • Warnings: unknown core/* and drupal/* blocks, attribute values of the wrong type or not in the attribute's enum, mappingFields of fields or properties the content type doesn't have.
    • Infos: unknown attributes, and blocks of other namespaces, which a theme or module must register.
  • Format button: lays the template out with one block per line and nested inner blocks.
  • Validation on save: JSON and structure. Block names aren't checked on the server, since themes register blocks in JS.
  • Template lock: it is disabled while the template is empty. Saving without a template sets it to None (the TODO in gutenberg_form_alter()).

Node form

  • Invalid templates saved before this change are ignored instead of breaking the form. {} made MappingFieldsHelper::getMappedFields() throw a TypeError.
  • A mapping of a field the content type doesn't have no longer throws.
  • The editor ignores a lock without a template, which prevented inserting any block.

Notes for review

  • New gutenberg.template service (TemplateManager): validate(), getTemplate(), and getCatalog(), which provides the blocks and fields the editor lints against. Also BlocksLibraryManager::getBlockDefinitions().
  • New packages/template-editor/ package (drupal-template-editor library). CodeMirror is bundled: 361 KiB minified, 119 KiB gzipped, loaded on the content type form only.
  • gutenberg.libraries.yml: the new entry was added by hand. Regenerating the file with gutenberg-dependencies.php reorders it and drops dependencies that were added by hand.

Tests

  • PHPUnit, ContentTypeEditTest: validation errors, the trimmed save, the lock without a template, the catalog, and the node form with invalid saved templates.
  • Playwright, template-editor.spec.mjs: the editor, its markers, Format, saving, new content starting with the template, the server error, and the lint rules.

CI

  • Composer job artifact: it went over the GitLab artifact size limit ("413 Request Entity Too Large") with this MR and today's phpstan update. Half of its 175 MB was core's node_modules.
  • Fix: _COMPOSER_YARN_INSTALL: '0' keeps it out. The module lints with its own packages, and the jobs that need core's packages (cspell) install them themselves.
  • PHPStan 2.3.0: CI now installs this version, which reports closure.unusedUse in ScanDir::scan(), although the closure uses $root_dirs. The closure is now a loop. It isn't ignored, since PHPStan asks not to.
Edited by Marco Fernandes

Merge request reports

Loading
Loading