1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00

Desktop: Fixes #8978: Rich text editor: Fix repeated newline characters discarded on save to markdown (#9199)

This commit is contained in:
Henry Heino 2023-11-07 03:59:35 -08:00 committed by GitHub
parent a38fe11bbe
commit 6593025051
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 35 additions and 16 deletions

View File

@ -15,7 +15,4 @@ however.
Because it isn't
necessary.
...
<br/><br/><br/>...

View File

@ -0,0 +1,4 @@
A<br/><br/><br/>test.<br/>
A single &lt;br/&gt;<br/>can use two spaces at the end of the line,
but<br/><br/>the markdown renderer discards these if the line is otherwise empty.

View File

@ -0,0 +1,5 @@
A
<br/><br/>test.
A single &lt;br/&gt;
can use two spaces at the end of the line, but
<br/>the markdown renderer discards these if the line is otherwise empty.

View File

@ -45,11 +45,18 @@ rules.paragraph = {
rules.lineBreak = {
filter: 'br',
replacement: function (content, node, options) {
replacement: function (_content, node, options, previousNode) {
let brReplacement = options.br + '\n';
// Code blocks may include <br/>s -- replacing them should not be necessary
// in code blocks.
const brReplacement = node.isCode ? '' : options.br;
return brReplacement + '\n'
if (node.isCode) {
brReplacement = '\n';
} else if (previousNode && previousNode.nodeName === 'BR') {
brReplacement = '<br/>';
}
return brReplacement;
}
}

View File

@ -165,27 +165,32 @@ TurndownService.prototype = {
function process (parentNode, escapeContent = 'auto') {
if (this.options.disableEscapeContent) escapeContent = false;
var self = this
return reduce.call(parentNode.childNodes, function (output, node) {
node = new Node(node, self.options)
let output = '';
let previousNode = null;
for (let node of parentNode.childNodes) {
node = new Node(node, this.options);
var replacement = ''
if (node.nodeType === 3) {
if (node.isCode || escapeContent === false) {
replacement = node.nodeValue
} else {
replacement = self.escape(node.nodeValue)
replacement = this.escape(node.nodeValue);
// Escape < and > so that, for example, this kind of HTML text: "This is a tag: &lt;p&gt;" is still rendered as "This is a tag: &lt;p&gt;"
// and not "This is a tag: <p>". If the latter, it means the HTML will be rendered if the viewer supports HTML (which, in Joplin, it does).
replacement = replacement.replace(/<(.+?)>/g, '&lt;$1&gt;');
}
} else if (node.nodeType === 1) {
replacement = replacementForNode.call(self, node)
replacement = replacementForNode.call(this, node, previousNode);
}
return join(output, replacement)
}, '')
output = join(output, replacement);
previousNode = node;
}
return output;
}
/**
@ -211,11 +216,12 @@ function postProcess (output) {
* Converts an element node to its Markdown equivalent
* @private
* @param {HTMLElement} node The node to convert
* @param {HTMLElement|null} previousNode The node immediately before this node.
* @returns A Markdown representation of the node
* @type String
*/
function replacementForNode (node) {
function replacementForNode (node, previousNode) {
var rule = this.rules.forNode(node)
var content = process.call(this, node, rule.escapeContent ? rule.escapeContent(node) : 'auto')
var whitespace = node.flankingWhitespace
@ -223,7 +229,7 @@ function replacementForNode (node) {
return (
whitespace.leading +
rule.replacement(content, node, this.options) +
rule.replacement(content, node, this.options, previousNode) +
whitespace.trailing
)
}