Improved the paste results from MS Word
authorAlexander Ebert <ebert@woltlab.com>
Mon, 19 Aug 2019 14:06:38 +0000 (16:06 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Mon, 19 Aug 2019 14:06:38 +0000 (16:06 +0200)
Fixes #3028

wcfsetup/install/files/js/3rdParty/redactor2/plugins/WoltLabClean.js
wcfsetup/install/files/js/3rdParty/redactor2/redactor.js

index 062f165b2b19571e48a05ba5ca3861566959180c..3aa87e0a7155fe78e8285d3fc4a1feb6542c73d6 100644 (file)
@@ -153,6 +153,10 @@ $.Redactor.prototype.WoltLabClean = function() {
                                        
                                        return WCF.String.escapeHTML(html);
                                }
+
+                               if (this.clean.isHtmlMsWord(html)) {
+                                       html = this.clean.cleanMsWord(html);
+                               }
                                
                                var div = elCreate('div');
                                div.innerHTML = html.replace(/@@@WOLTLAB-P-ALIGN-(?:left|right|center|justify)@@@/g, '');
index 7f23936a8697de9dbdc39b8427a72982815d1ffd..626949283a7d21e6f1ca67986bb4cf8ba366c0ea 100644 (file)
                                        html = html.replace(/<!--[\s\S]*?-->/g, '');
                                        html = html.replace(/<o:p>[\s\S]*?<\/o:p>/gi, '');
                                        html = html.replace(/\n/g, ' ');
-                                       html = html.replace(/<br\s?\/?>|<\/p>|<\/div>|<\/li>|<\/td>/gi, '\n\n');
+                                       html = html.replace(/<\/p>/gi, '</p><p><br data-redactor="br"></p>');
+                                       html = html.replace(/<\/div>|<\/li>|<\/td>/gi, '\n\n');
                                        
-                                       // lists
                                        var $div = $('<div/>').html(html);
                                        
+                                       // Find any <p> that contains a <br> and split it into separate paragraphs.
+                                       /** @var {Element} br */
+                                       elBySelAll('br', $div[0], function(br) {
+                                               if (elData(br, 'redactor') === 'br') {
+                                                       br.removeAttribute('data-redactor');
+                                               }
+                                               else {
+                                                       var parent = br.parentNode;
+                                                       if (parent && parent.nodeName === 'P') {
+                                                               var paragraph = elCreate('p');
+                                                               while (br.nextSibling) {
+                                                                       paragraph.appendChild(br.nextSibling);
+                                                               }
+                                                               parent.parentNode.insertBefore(paragraph, parent.nextSibling);
+                                                               elRemove(br);
+                                                       }
+                                               }
+                                       });
+
+                                       // lists
                                        var lastList = false;
                                        var lastLevel = 1;
                                        var listsIds = [];
                                        });
                                        
                                        $div.find('[data-level][data-list]').removeAttr('data-level data-list');
+                                       
+                                       // Find lists at the top level that are surrounded by `<p><br></p>`.
+                                       elBySelAll('ol, ul', $div[0], function(list) {
+                                               ['nextElementSibling', 'previousElementSibling'].forEach(function(property) {
+                                                       var sibling = list[property];
+                                                       while (sibling && sibling.nodeName === 'P' && sibling.className === '') {
+                                                               if (sibling.innerHTML !== '<br>') {
+                                                                       break;
+                                                               }
+                                                               
+                                                               elRemove(sibling);
+                                                               sibling = list[property];
+                                                       }
+                                               });
+                                       });
+                                       
                                        html = $div.html();
                                        
                                        return html;