Normalize HTML before inserting it into CKEditor
authorAlexander Ebert <ebert@woltlab.com>
Fri, 4 Aug 2023 10:23:43 +0000 (12:23 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Fri, 4 Aug 2023 10:23:43 +0000 (12:23 +0200)
Fixes https://www.woltlab.com/community/thread/300657-quoting-pre-6-0-posts-does-not-normalize-the-old-paragraph-behavior/

ts/WoltLabSuite/Core/Component/Ckeditor.ts
ts/WoltLabSuite/Core/Component/Ckeditor/Normalizer.ts
wcfsetup/install/files/js/WoltLabSuite/Core/Component/Ckeditor.js
wcfsetup/install/files/js/WoltLabSuite/Core/Component/Ckeditor/Normalizer.js

index 54dbf90a6117dd36590c9cd2bffd16c35d143e4d..c8eb2853db60822882a0a68c792ba5372187941a 100644 (file)
@@ -21,7 +21,7 @@ import { deleteDraft, initializeAutosave, setupRestoreDraft } from "./Ckeditor/A
 import { createConfigurationFor, Features } from "./Ckeditor/Configuration";
 import { dispatchToCkeditor } from "./Ckeditor/Event";
 import { setup as setupSubmitOnEnter } from "./Ckeditor/SubmitOnEnter";
-import { normalizeLegacyMessage } from "./Ckeditor/Normalizer";
+import { normalizeLegacyHtml, normalizeLegacyMessage } from "./Ckeditor/Normalizer";
 import { element as scrollToElement } from "../Ui/Scroll";
 import Devtools from "../Devtools";
 import { ClassicEditor, CodeBlockConfig, EditorConfig, Element as CkeElement } from "./Ckeditor/Types";
@@ -78,6 +78,8 @@ class Ckeditor {
   }
 
   insertHtml(html: string): void {
+    html = normalizeLegacyHtml(html);
+
     this.#editor.model.change((writer) => {
       const viewFragment = this.#editor.data.processor.toView(html);
       const modelFragment = this.#editor.data.toModel(viewFragment);
index 0ad32f1db0bfe61076d6973e1341663c0902f7ad..6bb2cfc914cd5411e21cae6145b410088b8cf055 100644 (file)
@@ -151,18 +151,22 @@ function imageToFigure(img: HTMLImageElement, alignmentClass: string): void {
   }
 }
 
-export function normalizeLegacyMessage(element: HTMLElement): void {
-  if (!(element instanceof HTMLTextAreaElement)) {
-    throw new TypeError("Expected the element to be a <textarea>.");
-  }
-
+export function normalizeLegacyHtml(html: string): string {
   const div = document.createElement("div");
-  div.innerHTML = element.value;
+  div.innerHTML = html;
 
   normalizeBr(div);
   const paragraphs = getPossibleSpacerParagraphs(div);
   reduceSpacerParagraphs(paragraphs);
   convertFloatingImages(div);
 
-  element.value = div.innerHTML;
+  return div.innerHTML;
+}
+
+export function normalizeLegacyMessage(element: HTMLElement): void {
+  if (!(element instanceof HTMLTextAreaElement)) {
+    throw new TypeError("Expected the element to be a <textarea>.");
+  }
+
+  element.value = normalizeLegacyHtml(element.value);
 }
index 98de8ccdcadae677726d54d99389be1591ea3ffe..d4d75af6cd2e9e168a4754fded4edd26ddc0051e 100644 (file)
@@ -60,6 +60,7 @@ define(["require", "exports", "tslib", "./Ckeditor/Attachment", "./Ckeditor/Medi
             return this.#editor.data.get();
         }
         insertHtml(html) {
+            html = (0, Normalizer_1.normalizeLegacyHtml)(html);
             this.#editor.model.change((writer) => {
                 const viewFragment = this.#editor.data.processor.toView(html);
                 const modelFragment = this.#editor.data.toModel(viewFragment);
index c3095a6cd5c670a319015a91120374be76da514c..f276d195873148ca408576283babc52123c020b7 100644 (file)
@@ -14,7 +14,7 @@
 define(["require", "exports", "tslib", "../../Dom/Util"], function (require, exports, tslib_1, Util_1) {
     "use strict";
     Object.defineProperty(exports, "__esModule", { value: true });
-    exports.normalizeLegacyMessage = void 0;
+    exports.normalizeLegacyMessage = exports.normalizeLegacyHtml = void 0;
     Util_1 = tslib_1.__importDefault(Util_1);
     function normalizeBr(div) {
         div.querySelectorAll("br").forEach((br) => {
@@ -131,17 +131,21 @@ define(["require", "exports", "tslib", "../../Dom/Util"], function (require, exp
             paragraph.remove();
         }
     }
-    function normalizeLegacyMessage(element) {
-        if (!(element instanceof HTMLTextAreaElement)) {
-            throw new TypeError("Expected the element to be a <textarea>.");
-        }
+    function normalizeLegacyHtml(html) {
         const div = document.createElement("div");
-        div.innerHTML = element.value;
+        div.innerHTML = html;
         normalizeBr(div);
         const paragraphs = getPossibleSpacerParagraphs(div);
         reduceSpacerParagraphs(paragraphs);
         convertFloatingImages(div);
-        element.value = div.innerHTML;
+        return div.innerHTML;
+    }
+    exports.normalizeLegacyHtml = normalizeLegacyHtml;
+    function normalizeLegacyMessage(element) {
+        if (!(element instanceof HTMLTextAreaElement)) {
+            throw new TypeError("Expected the element to be a <textarea>.");
+        }
+        element.value = normalizeLegacyHtml(element.value);
     }
     exports.normalizeLegacyMessage = normalizeLegacyMessage;
 });