From 3f792a64343ec71f2f43f2bd77007394b69b84cb Mon Sep 17 00:00:00 2001 From: Kendrick Bollens Date: Thu, 23 Jul 2026 11:21:51 +0200 Subject: [PATCH] =?UTF-8?q?Web-Editor:=20robustes=20Einf=C3=BCgen=20aus=20?= =?UTF-8?q?externen=20Quellen=20(E-Mails)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TinyMCEs Standard-Paste nutzt bei externem Inhalt einen fragilen Pastebin-Fallback, der bei manchen Quellen (E-Mail-Clients) still fehlschlägt → "nichts passiert". Interner Copy/Paste ging, weil TinyMCE dabei text/html selbst auf die Zwischenablage setzt. Eigener paste-Handler liest text/html bzw. text/plain direkt aus und fügt es deterministisch ein (Formatierung bleibt erhalten, Office/Outlook- Fragment wird ausgeschnitten). Interner Paste und Bild-Paste bleiben dem Standard-Handler überlassen. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_011GkKJBbiNV421xfCbXikGV --- web-editor/public/app.js | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/web-editor/public/app.js b/web-editor/public/app.js index 1459522..0c303c3 100644 --- a/web-editor/public/app.js +++ b/web-editor/public/app.js @@ -374,6 +374,38 @@ ed = editor; editor.on('init', function () { edReady = true; }); editor.on('input ExecCommand Undo Redo SetContent paste', function () { if (!suppressDirty) markDirty(); }); + // Robustes Einfügen aus externen Quellen (z.B. E-Mails). TinyMCEs eigener + // Fallback (verstecktes „Pastebin"-Feld) schlägt bei manchen Quellen still + // fehl → „nichts passiert". Wir lesen die Zwischenablage direkt aus und + // fügen HTML mitsamt Formatierung ein. Interner Copy/Paste (funktioniert + // bereits) und Bild-Paste bleiben dem Standard-Handler überlassen. + editor.on('paste', function (e) { + const cd = e.clipboardData; + if (!cd) return; // keine Zwischenablage → Standard-Handler versuchen lassen + let html = ''; + try { html = cd.getData('text/html') || ''; } catch (_) {} + // TinyMCE-interner Inhalt trägt diesen Marker → Standard-Pfad übernehmen. + if (html.indexOf('x-tinymce/html') !== -1) return; + let text = ''; + try { text = cd.getData('text/plain') || ''; } catch (_) {} + // Reines Bild (Screenshot o.ä.) → TinyMCEs Bildverarbeitung übernehmen. + const hasImage = + (cd.types && Array.prototype.indexOf.call(cd.types, 'Files') !== -1) || + (cd.items && Array.prototype.some.call(cd.items, function (it) { return it.kind === 'file' && /^image\//.test(it.type); })); + if (!html && !text && hasImage) return; + if (!html && !text) return; // nichts Brauchbares → Standard-Fallback lassen + e.preventDefault(); // unterdrückt den fragilen TinyMCE-Standard-Handler + let content; + if (html) { + // Office/Outlook markieren die eigentliche Auswahl per Fragment-Kommentar. + const frag = /([\s\S]*?)/i.exec(html); + content = frag ? frag[1] : html; + } else { + content = editor.dom.encode(text).replace(/\r\n?|\n/g, '
'); + } + editor.insertContent(content); + markDirty(); + }); }, }).then(() => { edReady = true; }); }