[#3574404] Enforce non-empty required string validation in JSON Editor

Summary

Adds client-side enforcement of non-empty values for required string fields in the Patternkit JSON Editor. JSON Schema's required keyword only checks that a property is present — it does not reject empty or whitespace-only strings. This fix adds a custom validator and submission gates so required string fields that are left blank produce inline "Value required" errors and block form saves.

Also fixes a missing showValidationErrors() implementation in DrupalMediaEditor (the parent AbstractEditor method is a no-op), so validation errors now display inline on media fields.

Depends on: !180 (merged) — this branch is rebased on top of 3576066-refresh-json-editor and requires that MR to merge first.

Note on server-side parity: Server-side validation (swaggest/php-json-schema) checks only property presence, so empty required strings still pass server-side. Full-stack enforcement is tracked separately.


Changes

modules/patternkit_media_library/js/patternkit.jsoneditor.media_library.js

  • Override showValidationErrors() in DrupalMediaEditor. The parent AbstractEditor implementation is a no-op; this override filters errors by path and calls theme.addInputError() / theme.removeInputError() to render inline messages on media fields.

js/patternkit.jsoneditor.js

  • In setDefaults(), register a custom validator that iterates schema.required, checks type === 'string', and emits an error_notempty error for empty or whitespace-only values. Registration is guarded by a patternkitRequiredStringValidator flag to prevent duplicate registration across multiple attach cycles.
  • In onSubmit(), run validate() before allowing native (non-AJAX) form submission; call showValidationErrors() and cancel the event if errors are found.
  • Add validateBeforeAjaxSubmit() — blocks AJAX submission when errors are present, displays inline errors, resets ajax.ajaxing, and re-enables the submit button so subsequent attempts are not silently ignored.
  • Refactor beforeSerialize/beforeSubmit AJAX wrappers:
    • Replace hasOwnProperty wrap-once guards with explicit _patternkitBeforeSerializeWrapped / _patternkitBeforeSubmitWrapped sentinel flags (safe across DOM replacements).
    • Resolve the active editor instance at call time instead of capturing a closure reference (prevents stale-instance bugs after AJAX rebuilds).
    • Add !window.patternkitEditor.detaching guard (carried over from !180 (merged)).
    • Call validateBeforeAjaxSubmit() in the beforeSubmit wrapper; return false to cancel submission when validation fails.
    • Explicitly return the result of the previous beforeSubmit handler so Drupal's AJAX system can honour cancellation signals.

.cspell-project-words.txt

  • Add notempty to the project CSpell dictionary.

Testing

Manual

  1. Add a Patternkit block with at least one required string field to a Layout Builder node and save.
  2. Re-open the block configuration and clear the required field.
  3. Click Update — confirm the field shows a "Value required" error and the form does not submit.
  4. Fill in the field and click Update — confirm the block saves successfully.
  5. Repeat steps 2–4 using a media field (requires patternkit_media_library) to verify inline error display on media widgets.
  6. Click Update pattern to confirm the schema-refresh workflow from !180 (merged) still functions correctly alongside the new validation.

Automated

No automated tests are included in this MR. The validation behaviour is covered through manual testing and the existing test suite in !180 (merged).

Merge request reports

Loading