Skip BBCode buttons that are already present
authorAlexander Ebert <ebert@woltlab.com>
Sat, 9 Sep 2023 14:51:24 +0000 (16:51 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Sat, 9 Sep 2023 14:51:24 +0000 (16:51 +0200)
See https://www.woltlab.com/community/thread/301518-ckeditor-eigenes-men%C3%BC/?postID=1938077#post1938077

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

index e65673ece8f2fb3ebae152ac4cb5f10a5c084c87..7e3aaf99e8ff0ca4351586601ad0d94654cdb488 100644 (file)
@@ -24,7 +24,13 @@ import { setup as setupSubmitOnEnter } from "./Ckeditor/SubmitOnEnter";
 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";
+import type {
+  ClassicEditor,
+  CodeBlockConfig,
+  EditorConfig,
+  Element as CkeElement,
+  ToolbarConfigItem,
+} from "./Ckeditor/Types";
 import { setupSubmitShortcut } from "./Ckeditor/Keyboard";
 import { setup as setupLayer } from "./Ckeditor/Layer";
 import { browser, touch } from "../Environment";
@@ -217,13 +223,34 @@ function initializeConfiguration(
     features,
   });
 
-  for (const { name } of bbcodes) {
-    (configuration.toolbar as any).push(`woltlabBbcode_${name}`);
+  const toolbar = configuration.toolbar as ToolbarConfigItem[];
+  for (let { name } of bbcodes) {
+    name = `woltlabBbcode_${name}`;
+
+    if (hasToolbarButton(toolbar, name)) {
+      continue;
+    }
+
+    toolbar.push(name);
   }
 
   return configuration;
 }
 
+function hasToolbarButton(items: ToolbarConfigItem[], name: string): boolean {
+  for (const item of items) {
+    if (typeof item === "string") {
+      if (item === name) {
+        return true;
+      }
+    } else if (hasToolbarButton(item.items, name)) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 export async function setupCkeditor(
   element: HTMLElement,
   features: Features,
index 24850ee961a8275406dccf21c62c0352c4cbba70..dc84e799fe1e34391fca7c76fedef9ae3d55db9b 100644 (file)
@@ -19,7 +19,7 @@ export type { Element } from "@ckeditor/ckeditor5-engine";
 import type {} from "@ckeditor/ckeditor5-autosave";
 import type {} from "@ckeditor/ckeditor5-mention";
 
-import type { EditorConfig as UpstreamEditorConfig } from "@ckeditor/ckeditor5-core";
+import type { EditorConfig as UpstreamEditorConfig, ToolbarConfigItem } from "@ckeditor/ckeditor5-core";
 
 type WoltlabBbcodeButton = {
   icon?: string;
@@ -33,4 +33,4 @@ interface EditorConfig extends UpstreamEditorConfig {
   woltlabBbcode?: WoltlabBbcodeConfig;
 }
 
-export type { EditorConfig };
+export type { EditorConfig, ToolbarConfigItem };
index 820b20c926e90ffb263f7b5c3a44bd2be0d8ebbf..a24f1f9ccbf2a2472e7ec77bd44d59668e1cdc58 100644 (file)
@@ -155,11 +155,29 @@ define(["require", "exports", "tslib", "./Ckeditor/Attachment", "./Ckeditor/Medi
             configuration,
             features,
         });
-        for (const { name } of bbcodes) {
-            configuration.toolbar.push(`woltlabBbcode_${name}`);
+        const toolbar = configuration.toolbar;
+        for (let { name } of bbcodes) {
+            name = `woltlabBbcode_${name}`;
+            if (hasToolbarButton(toolbar, name)) {
+                continue;
+            }
+            toolbar.push(name);
         }
         return configuration;
     }
+    function hasToolbarButton(items, name) {
+        for (const item of items) {
+            if (typeof item === "string") {
+                if (item === name) {
+                    return true;
+                }
+            }
+            else if (hasToolbarButton(item.items, name)) {
+                return true;
+            }
+        }
+        return false;
+    }
     async function setupCkeditor(element, features, bbcodes, codeBlockLanguages) {
         if (instances.has(element)) {
             throw new TypeError(`Cannot initialize the editor for '${element.id}' twice.`);