mirror of
https://github.com/laurent22/joplin.git
synced 2025-01-26 18:58:21 +02:00
Desktop: Fixes #8978: Rich text editor: Fix repeated newline characters discarded on save to markdown (#9199)
This commit is contained in:
parent
a38fe11bbe
commit
6593025051
@ -15,7 +15,4 @@ however.
|
|||||||
Because it isn't
|
Because it isn't
|
||||||
|
|
||||||
necessary.
|
necessary.
|
||||||
|
<br/><br/><br/>...
|
||||||
|
|
||||||
|
|
||||||
...
|
|
4
packages/app-cli/tests/html_to_md/repeated_brs.html
Normal file
4
packages/app-cli/tests/html_to_md/repeated_brs.html
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
A<br/><br/><br/>test.<br/>
|
||||||
|
|
||||||
|
A single <br/><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.
|
5
packages/app-cli/tests/html_to_md/repeated_brs.md
Normal file
5
packages/app-cli/tests/html_to_md/repeated_brs.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
A
|
||||||
|
<br/><br/>test.
|
||||||
|
A single <br/>
|
||||||
|
can use two spaces at the end of the line, but
|
||||||
|
<br/>the markdown renderer discards these if the line is otherwise empty.
|
@ -45,11 +45,18 @@ rules.paragraph = {
|
|||||||
rules.lineBreak = {
|
rules.lineBreak = {
|
||||||
filter: 'br',
|
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
|
// Code blocks may include <br/>s -- replacing them should not be necessary
|
||||||
// in code blocks.
|
// in code blocks.
|
||||||
const brReplacement = node.isCode ? '' : options.br;
|
if (node.isCode) {
|
||||||
return brReplacement + '\n'
|
brReplacement = '\n';
|
||||||
|
} else if (previousNode && previousNode.nodeName === 'BR') {
|
||||||
|
brReplacement = '<br/>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return brReplacement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,27 +165,32 @@ TurndownService.prototype = {
|
|||||||
function process (parentNode, escapeContent = 'auto') {
|
function process (parentNode, escapeContent = 'auto') {
|
||||||
if (this.options.disableEscapeContent) escapeContent = false;
|
if (this.options.disableEscapeContent) escapeContent = false;
|
||||||
|
|
||||||
var self = this
|
let output = '';
|
||||||
return reduce.call(parentNode.childNodes, function (output, node) {
|
let previousNode = null;
|
||||||
node = new Node(node, self.options)
|
|
||||||
|
for (let node of parentNode.childNodes) {
|
||||||
|
node = new Node(node, this.options);
|
||||||
|
|
||||||
var replacement = ''
|
var replacement = ''
|
||||||
if (node.nodeType === 3) {
|
if (node.nodeType === 3) {
|
||||||
if (node.isCode || escapeContent === false) {
|
if (node.isCode || escapeContent === false) {
|
||||||
replacement = node.nodeValue
|
replacement = node.nodeValue
|
||||||
} else {
|
} 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: <p>" is still rendered as "This is a tag: <p>"
|
// Escape < and > so that, for example, this kind of HTML text: "This is a tag: <p>" is still rendered as "This is a tag: <p>"
|
||||||
// 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).
|
// 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, '<$1>');
|
replacement = replacement.replace(/<(.+?)>/g, '<$1>');
|
||||||
}
|
}
|
||||||
} else if (node.nodeType === 1) {
|
} 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
|
* Converts an element node to its Markdown equivalent
|
||||||
* @private
|
* @private
|
||||||
* @param {HTMLElement} node The node to convert
|
* @param {HTMLElement} node The node to convert
|
||||||
|
* @param {HTMLElement|null} previousNode The node immediately before this node.
|
||||||
* @returns A Markdown representation of the node
|
* @returns A Markdown representation of the node
|
||||||
* @type String
|
* @type String
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function replacementForNode (node) {
|
function replacementForNode (node, previousNode) {
|
||||||
var rule = this.rules.forNode(node)
|
var rule = this.rules.forNode(node)
|
||||||
var content = process.call(this, node, rule.escapeContent ? rule.escapeContent(node) : 'auto')
|
var content = process.call(this, node, rule.escapeContent ? rule.escapeContent(node) : 'auto')
|
||||||
var whitespace = node.flankingWhitespace
|
var whitespace = node.flankingWhitespace
|
||||||
@ -223,7 +229,7 @@ function replacementForNode (node) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
whitespace.leading +
|
whitespace.leading +
|
||||||
rule.replacement(content, node, this.options) +
|
rule.replacement(content, node, this.options, previousNode) +
|
||||||
whitespace.trailing
|
whitespace.trailing
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user