From 69b2bdffbfd0f4388cf5364b637c1566207797da Mon Sep 17 00:00:00 2001
From: Jochen Roth <jochen.roth@b13.com>
Date: Mon, 3 Jul 2023 15:02:04 +0200
Subject: [PATCH] [BUGFIX] Make RTE validate required

Currently, the RTE did not validate when required=true
was set.

This has been changed to update the source on change
which triggers validation again.

Resolves: #100838
Releases: main, 12.4
Change-Id: I3bc9a9c43d23d8334f3f5694ef52f626d12c424c
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/79776
Tested-by: Andreas Nedbal <andy@pixelde.su>
Reviewed-by: Andreas Nedbal <andy@pixelde.su>
Tested-by: core-ci <typo3@b13.com>
---
 Build/Sources/TypeScript/rte_ckeditor/ckeditor5.ts           | 5 +++++
 .../rte_ckeditor/Resources/Public/JavaScript/ckeditor5.js    | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/Build/Sources/TypeScript/rte_ckeditor/ckeditor5.ts b/Build/Sources/TypeScript/rte_ckeditor/ckeditor5.ts
index 6b220d44b190..b015b4726b81 100644
--- a/Build/Sources/TypeScript/rte_ckeditor/ckeditor5.ts
+++ b/Build/Sources/TypeScript/rte_ckeditor/ckeditor5.ts
@@ -2,6 +2,7 @@ import { html, LitElement, TemplateResult } from 'lit';
 import { customElement, property, query } from 'lit/decorators';
 import type { PluginInterface } from '@ckeditor/ckeditor5-core/src/plugin';
 import { CKEditor5, Core, WordCount } from '@typo3/ckeditor5-bundle';
+import { SourceEditing } from '@ckeditor/ckeditor5-source-editing';
 
 interface CKEditor5Config {
   // in TYPO3 always `items` property is used, skipping `string[]`
@@ -135,7 +136,11 @@ export class CKEditor5Element extends LitElement {
             this.applyEditableElementStyles(editor);
             this.handleWordCountPlugin(editor);
             this.applyReadOnly(editor);
+            const sourceEditingPlugin = editor.plugins.get('SourceEditing') as SourceEditing;
             editor.model.document.on('change:data', (): void => {
+              if(!sourceEditingPlugin.isSourceEditingMode) {
+                editor.updateSourceElement()
+              }
               this.target.dispatchEvent(new Event('change', { bubbles: true, cancelable: true }));
             });
 
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/ckeditor5.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/ckeditor5.js
index a5824bc18b99..78d009bd4c60 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/ckeditor5.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/ckeditor5.js
@@ -18,4 +18,4 @@ var __decorate=function(t,e,o,i){var n,r=arguments.length,s=r<3?e:null===i?i=Obj
         rows="18"
         data-formengine-validation-rules="${this.formEngine.validationRules}"
         >${this.formEngine.value}</textarea>
-    `}firstUpdated(){if(!(this.target instanceof HTMLElement))throw new Error("No rich-text content target found.");const t=(this.options.importModules||[]).map((t=>import(t)));Promise.all(t).then((t=>{const e=t.filter((t=>t.default)).map((t=>t.default)),o=CKEditor5.builtinPlugins.concat(e),i=[].concat(...o.filter((t=>t.overrides?.length>0)).map((t=>t.overrides))),n=o.filter((t=>!i.includes(t))),r={toolbar:this.options.toolbar,plugins:n,typo3link:this.options.typo3link||null,removePlugins:this.options.removePlugins||[]};this.options.language&&(r.language=this.options.language),this.options.style&&(r.style=this.options.style),this.options.wordCount&&(r.wordCount=this.options.wordCount),this.options.table&&(r.table=this.options.table),this.options.heading&&(r.heading=this.options.heading),this.options.alignment&&(r.alignment=this.options.alignment),CKEditor5.create(this.target,r).then((t=>{this.applyEditableElementStyles(t),this.handleWordCountPlugin(t),this.applyReadOnly(t),t.model.document.on("change:data",(()=>{this.target.dispatchEvent(new Event("change",{bubbles:!0,cancelable:!0}))})),this.options.debug&&window.CKEditorInspector.attach(t,{isCollapsed:!0})}))}))}applyEditableElementStyles(t){const e=t.editing.view,o={"min-height":this.options.height,"min-width":this.options.width};Object.keys(o).forEach((t=>{let i=o[t];i&&(isFinite(i)&&!Number.isNaN(parseFloat(i))&&(i+="px"),e.change((o=>{o.setStyle(t,i,e.document.getRoot())})))}))}handleWordCountPlugin(t){if(t.plugins.has("WordCount")&&(this.options?.wordCount?.displayWords||this.options?.wordCount?.displayCharacters)){const e=t.plugins.get("WordCount");this.renderRoot.appendChild(e.wordCountContainer)}}applyReadOnly(t){this.options.readOnly&&t.enableReadOnlyMode("typo3-lock")}};__decorate([property({type:Object})],CKEditor5Element.prototype,"options",void 0),__decorate([property({type:Object,attribute:"form-engine"})],CKEditor5Element.prototype,"formEngine",void 0),__decorate([query("textarea")],CKEditor5Element.prototype,"target",void 0),CKEditor5Element=__decorate([customElement("typo3-rte-ckeditor-ckeditor5")],CKEditor5Element);export{CKEditor5Element};
\ No newline at end of file
+    `}firstUpdated(){if(!(this.target instanceof HTMLElement))throw new Error("No rich-text content target found.");const t=(this.options.importModules||[]).map((t=>import(t)));Promise.all(t).then((t=>{const e=t.filter((t=>t.default)).map((t=>t.default)),o=CKEditor5.builtinPlugins.concat(e),i=[].concat(...o.filter((t=>t.overrides?.length>0)).map((t=>t.overrides))),n=o.filter((t=>!i.includes(t))),r={toolbar:this.options.toolbar,plugins:n,typo3link:this.options.typo3link||null,removePlugins:this.options.removePlugins||[]};this.options.language&&(r.language=this.options.language),this.options.style&&(r.style=this.options.style),this.options.wordCount&&(r.wordCount=this.options.wordCount),this.options.table&&(r.table=this.options.table),this.options.heading&&(r.heading=this.options.heading),this.options.alignment&&(r.alignment=this.options.alignment),CKEditor5.create(this.target,r).then((t=>{this.applyEditableElementStyles(t),this.handleWordCountPlugin(t),this.applyReadOnly(t);const e=t.plugins.get("SourceEditing");t.model.document.on("change:data",(()=>{e.isSourceEditingMode||t.updateSourceElement(),this.target.dispatchEvent(new Event("change",{bubbles:!0,cancelable:!0}))})),this.options.debug&&window.CKEditorInspector.attach(t,{isCollapsed:!0})}))}))}applyEditableElementStyles(t){const e=t.editing.view,o={"min-height":this.options.height,"min-width":this.options.width};Object.keys(o).forEach((t=>{let i=o[t];i&&(isFinite(i)&&!Number.isNaN(parseFloat(i))&&(i+="px"),e.change((o=>{o.setStyle(t,i,e.document.getRoot())})))}))}handleWordCountPlugin(t){if(t.plugins.has("WordCount")&&(this.options?.wordCount?.displayWords||this.options?.wordCount?.displayCharacters)){const e=t.plugins.get("WordCount");this.renderRoot.appendChild(e.wordCountContainer)}}applyReadOnly(t){this.options.readOnly&&t.enableReadOnlyMode("typo3-lock")}};__decorate([property({type:Object})],CKEditor5Element.prototype,"options",void 0),__decorate([property({type:Object,attribute:"form-engine"})],CKEditor5Element.prototype,"formEngine",void 0),__decorate([query("textarea")],CKEditor5Element.prototype,"target",void 0),CKEditor5Element=__decorate([customElement("typo3-rte-ckeditor-ckeditor5")],CKEditor5Element);export{CKEditor5Element};
\ No newline at end of file
-- 
GitLab