From a9dd887d10ab80a1c072b64fceb3f597caa88166 Mon Sep 17 00:00:00 2001 From: erdgeist Date: Fri, 28 Aug 2026 03:05:57 +0200 Subject: Normalise pasted markup in the editor Pads and word processors paste block-level divs used as paragraphs, empty divs used as blank lines, whitespace-only inline formatting and per-character runs of identical tags. paste_preprocess resolves each into the semantics it stood for. --- public/javascripts/admin_interface.js | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'public/javascripts/admin_interface.js') diff --git a/public/javascripts/admin_interface.js b/public/javascripts/admin_interface.js index ffebb694..b2bcaf29 100644 --- a/public/javascripts/admin_interface.js +++ b/public/javascripts/admin_interface.js @@ -32,6 +32,43 @@ $(document).ready(function () { 'img': 'inline-image inline-image--full inline-image--half inline-image--left inline-image--right', 'a': 'glightbox' }, + paste_preprocess: function (editor, args) { + var doc = new DOMParser().parseFromString(args.content, 'text/html'); + var blocks = 'p,h1,h2,h3,h4,h5,h6,ul,ol,li,blockquote,table,pre,div'; + + // Innermost first, so a nested div is resolved before its parent. + Array.from(doc.querySelectorAll('div')).reverse().forEach(function (div) { + if (div.textContent.trim() === '' && !div.querySelector('img')) { + div.remove(); + } else if (div.querySelector(blocks)) { + div.replaceWith.apply(div, Array.from(div.childNodes)); + } else { + var p = doc.createElement('p'); + while (div.firstChild) { p.appendChild(div.firstChild); } + div.replaceWith(p); + } + }); + + doc.querySelectorAll('strong,em,b,i,span,u').forEach(function (el) { + if (el.textContent.trim() === '' && !el.querySelector('img')) { + el.replaceWith.apply(el, Array.from(el.childNodes)); + } + }); + + ['strong', 'em', 'b', 'i', 'u'].forEach(function (tag) { + doc.querySelectorAll(tag).forEach(function (el) { + var next = el.nextSibling; + while (next && next.nodeName && next.nodeName.toLowerCase() === tag) { + while (next.firstChild) { el.appendChild(next.firstChild); } + var after = next.nextSibling; + next.remove(); + next = after; + } + }); + }); + + args.content = doc.body.innerHTML; + }, setup: function(editor) { editor.on('init', function() { cccms.setup_autosave(); -- cgit v1.3