Index: js/xf/editor.js
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/js/xf/editor.js b/js/xf/editor.js
--- a/js/xf/editor.js (revision Staged)
+++ b/js/xf/editor.js (date 1631194909291)
@@ -902,7 +902,7 @@
$output = $children;
}
- return $output.html();
+ return XF.EditorHelpers.normalizeBrForEditor($output.html());
},
watchEditorHeight: function()
@@ -1320,6 +1320,8 @@
ed.html.insert(html);
ed.undo.saveStep();
XF.Element.initialize(ed.$el);
+
+ XF.EditorHelpers.normalizeAfterInsert(ed);
}
this.scrollToCursor();
@@ -1939,6 +1941,8 @@
ed.selection.restore();
ed.placeholder.hide();
ed.undo.saveStep();
+
+ XF.EditorHelpers.normalizeAfterInsert(ed);
},
insertCode: function(ed, type, code)
@@ -1969,6 +1973,8 @@
ed.undo.saveStep();
ed.html.insert(output);
ed.undo.saveStep();
+
+ XF.EditorHelpers.normalizeAfterInsert(ed);
},
insertSpoiler: function(ed, title)
@@ -1986,6 +1992,96 @@
XF.EditorHelpers.wrapSelectionText(ed, open, '[/SPOILER]', true);
},
+ normalizeBrForEditor: function (content)
+ {
+ var asString = typeof content === 'string',
+ $fragWrapper;
+
+ if (asString)
+ {
+ $fragWrapper = $('<div />').html(content);
+ }
+ else
+ {
+ $fragWrapper = content;
+ }
+
+ var checkNodeMatch = function ($node, elementType)
+ {
+ var node = $node.get(0);
+
+ return ($node.is(elementType)
+ && node.className === ''
+ && !node.hasAttribute('id')
+ && !node.hasAttribute('style'));
+ };
+
+ // Workaround editor behaviour that a <br> should not be the first or last child of a <p> tag
+ // <p><br>...</p>; editor can delete too many lines
+ // <p>...<br></p>; editor can delete too few lines
+
+ $fragWrapper.children('p').each(function ()
+ {
+ if (this.childNodes.length !== 1)
+ {
+ return;
+ }
+
+ var $firstChild = $(this.childNodes[0]);
+
+ if (checkNodeMatch($firstChild, 'span'))
+ {
+ $(this).html($firstChild.html());
+ }
+ });
+
+ $fragWrapper.children('p').each(function()
+ {
+ if (this.childNodes.length <= 1)
+ {
+ return;
+ }
+
+ var $firstChild = $(this.childNodes[0]);
+
+ if (checkNodeMatch($firstChild, 'br'))
+ {
+ $(this).before($('<p>').append($firstChild));
+ }
+ });
+
+ $fragWrapper.children('p').each(function()
+ {
+ if (this.childNodes.length <= 1)
+ {
+ return;
+ }
+
+ var $lastChild = $(this.childNodes[this.childNodes.length - 1]);
+
+ if (checkNodeMatch($lastChild, 'br'))
+ {
+ $lastChild.remove();
+ }
+ });
+
+ return asString ? $fragWrapper.html() : $fragWrapper;
+ },
+
+ normalizeAfterInsert: function(ed)
+ {
+ var selected = ed.html.getSelected();
+
+ if (/<br>\s*<\/p>/.test(selected))
+ {
+ XF.EditorHelpers.normalizeBrForEditor(ed.$el);
+ // remove the last undo step and replace it with the corrected html version
+ ed.undo_index--;
+ ed.undo_stack.pop();
+ ed.undo.saveStep();
+ }
+ },
+
isPreviewAvailable: function($textarea)
{
if (!$textarea.data('preview-url') && !$textarea.closest('form').data('preview-url'))