Workaround for custom elements being chopped up by outdenting an empty `li`
authorAlexander Ebert <ebert@woltlab.com>
Sat, 22 Aug 2020 00:14:17 +0000 (02:14 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Sat, 22 Aug 2020 00:14:17 +0000 (02:14 +0200)
Reproducible test case:
```
<woltlab-spoiler>
  <ul>
    <li>Test</li>
    <li>T</li> <!-- Backspace this item -->
  </ul>
</woltlab-spoiler>
```

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

index 8fb05c90cee26d95ec74f695e5e95c6c99391c72..ea84419f40a4e930f6ee28b477fc057a4f004f85 100644 (file)
                                                this.indent.repositionItem($item);
                                        }
                                        
+                                       var tmpWrapper = null;
                                        if ($item.length === 0) {
+                                               // `formatBlock` does not handle custom elements gracefully, always
+                                               // treating them as inline elements, causing these to be chopped up
+                                               // into separate elements. We can mitigate this problem by introducing
+                                               // a temporary intermediate `<div>` which will serve as a block wrapper.
+                                               var block = this.selection.block();
+                                               if (block && block.nodeName.indexOf('-') !== -1) {
+                                                       this.selection.save();
+                                                       
+                                                       tmpWrapper = elCreate('div');
+                                                       while (block.childNodes.length) {
+                                                               tmpWrapper.appendChild(block.childNodes[0]);
+                                                       }
+                                                       block.appendChild(tmpWrapper);
+                                                       
+                                                       this.selection.restore();
+                                               }
+                                               
                                                document.execCommand('formatblock', false, 'p');
                                                $item = $(this.selection.current());
                                                var $next = $item.next();
                                        
                                        // normalize
                                        this.selection.save();
+                                       
+                                       if (tmpWrapper !== null) {
+                                               var parent = tmpWrapper.parentNode;
+                                               while (tmpWrapper.childNodes.length) {
+                                                       parent.insertBefore(tmpWrapper.childNodes[0], tmpWrapper);
+                                               }
+                                               parent.removeChild(tmpWrapper);
+                                       }
+                                       
                                        this.indent.removeEmpty();
                                        this.indent.normalize();
                                        this.selection.restore();