Suport for nesting of blocks on format
authorAlexander Ebert <ebert@woltlab.com>
Sat, 2 Feb 2019 11:06:39 +0000 (12:06 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Sat, 2 Feb 2019 11:06:39 +0000 (12:06 +0100)
wcfsetup/install/files/js/3rdParty/redactor2/plugins/WoltLabBlock.js

index ffa6ea6d5007f8155ab9aa7f3214cc9070a7e5aa..15b206078ad6687ff6b2a106508c82c7339cec4b 100644 (file)
@@ -2,6 +2,8 @@ $.Redactor.prototype.WoltLabBlock = function() {
        "use strict";
        
        return {
+               preserveBlocks: ['pre', 'woltlab-quote', 'woltlab-spoiler'],
+               
                init: function() {
                        this.block.tags = ['p', 'blockquote', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'figure'];
                        
@@ -76,8 +78,8 @@ $.Redactor.prototype.WoltLabBlock = function() {
                                return replaced;
                        }).bind(this);
                        
-                       var mpFormatUncollapsed = this.block.formatUncollapsed;
                        this.block.formatUncollapsed = (function(tag, attr, value, type) {
+                               var block, i;
                                this.selection.save();
                                
                                this.selection.blocks().forEach(function(block) {
@@ -94,10 +96,63 @@ $.Redactor.prototype.WoltLabBlock = function() {
                                
                                this.selection.restore();
                                
-                               var replaced = mpFormatUncollapsed.call(this, tag, attr, value, type);
+                               this.selection.save();
+                               
+                               var replaced = [];
+                               var blocks = this.selection.blocks();
+                               
+                               if (blocks[0] && ($(blocks[0]).hasClass('redactor-in') || $(blocks[0]).hasClass(
+                                       'redactor-box'))) {
+                                       blocks = this.core.editor().find(this.opts.blockTags.join(', '));
+                               }
+                               
+                               var len = blocks.length;
+                               for (i = 0; i < len; i++) {
+                                       var currentTag = blocks[i].tagName.toLowerCase();
+                                       if ($.inArray(currentTag, this.block.tags) !== -1 && currentTag !== 'figure') {
+                                               if (tag !== 'pre' && this.WoltLabBlock.preserveBlocks.indexOf(blocks[i].nodeName.toLowerCase()) !== -1) {
+                                                       block = elCreate(tag);
+                                                       blocks[i].parentNode.insertBefore(block, blocks[i]);
+                                                       block.appendChild(blocks[i]);
+                                                       block = $(block);
+                                               }
+                                               else {
+                                                       block = this.utils.replaceToTag(blocks[i], tag);
+                                               }
+                                               
+                                               if (typeof attr === 'object') {
+                                                       type = value;
+                                                       for (var key in attr) {
+                                                               block = this.block.setAttr(block, key, attr[key], type);
+                                                       }
+                                               }
+                                               else {
+                                                       block = this.block.setAttr(block, attr, value, type);
+                                               }
+                                               
+                                               replaced.push(block);
+                                               this.block.removeInlineTags(block);
+                                       }
+                               }
+                               
+                               this.selection.restore();
                                
-                               var block, firstBlock = null;
-                               for (var i = 0, length = replaced.length; i < length; i++) {
+                               // combine pre
+                               if (tag === 'pre' && replaced.length !== 0) {
+                                       var first = replaced[0];
+                                       $.each(replaced, function (i, s) {
+                                               if (i !== 0) {
+                                                       $(first).append("\n" + $.trim(s.html()));
+                                                       $(s).remove();
+                                               }
+                                       });
+                                       
+                                       replaced = [];
+                                       replaced.push(first);
+                               }
+                               
+                               var firstBlock = null;
+                               for (i = 0, length = replaced.length; i < length; i++) {
                                        block = replaced[i][0];
                                        
                                        this.WoltLabBlock._paragraphize(block);
@@ -185,12 +240,41 @@ $.Redactor.prototype.WoltLabBlock = function() {
                                return;
                        }
                        
-                       var paragraph = elCreate('p');
-                       while (block.childNodes.length) {
-                               paragraph.appendChild(block.childNodes[0]);
+                       // Check if there is at least one child that is not a block itself.
+                       var child, hasNonBlocks = false;
+                       for (var i = 0, length = block.childNodes.length; i < length; i++) {
+                               child = block.childNodes[i];
+                               if (child.nodeType === Node.TEXT_NODE) {
+                                       hasNonBlocks = true;
+                                       break;
+                               }
+                               else if (child.nodeType === Node.ELEMENT_NODE && this.block.tags.indexOf(child.nodeName.toLowerCase()) === -1) {
+                                       hasNonBlocks = true;
+                                       break;
+                               }
                        }
                        
-                       block.appendChild(paragraph);
+                       if (!hasNonBlocks) {
+                               return;
+                       }
+                       
+                       var node = block.childNodes[0], nextNode, p = null;
+                       while (node) {
+                               nextNode = node.nextSibling;
+                               if (node.nodeType !== Node.ELEMENT_NODE || this.block.tags.indexOf(node.nodeName.toLowerCase()) === -1) {
+                                       if (p === null) {
+                                               p = elCreate('p');
+                                               block.insertBefore(p, node);
+                                       }
+                                       
+                                       p.appendChild(node);
+                               }
+                               else if (p !== null) {
+                                       p = null;
+                               }
+                               
+                               node = nextNode;
+                       }
                }
        }
 };