Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 7 additions & 15 deletions packages/lexical-markdown/src/MarkdownExport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,13 +203,11 @@ function exportTextFormat(
): string {
// This function handles the case of a string looking like this: " foo "
// Where it would be invalid markdown to generate: "** foo **"
// If the node has no format, we use the original text.
// Otherwise, we escape leading and trailing whitespaces to their corresponding code points,
// ensuring the returned string maintains its original formatting, e.g., "**   foo   **".
let output =
node.getFormat() === 0
? textContent
: escapeLeadingAndTrailingWhitespaces(textContent);
// We instead want to trim the whitespace out, apply formatting, and then
// bring the whitespace back. So our returned string looks like this: " **foo** "
// However, we do not want to export any formatting if the string is just whitespace: " "
const frozenString = textContent.trim();
let output = frozenString;

if (!node.hasFormat('code')) {
// Escape any markdown characters in the text content
Expand Down Expand Up @@ -288,9 +286,9 @@ function exportTextFormat(
break;
}

output = openingTags + output + closingTagsAfter;
output = output ? openingTags + output + closingTagsAfter : output;
// Replace trimmed version of textContent ensuring surrounding whitespace is not modified
return closingTagsBefore + output;
return closingTagsBefore + textContent.replace(frozenString, () => output);
}

// Get next or previous text sibling a text node, including cases
Expand Down Expand Up @@ -345,9 +343,3 @@ function hasFormat(
): boolean {
return $isTextNode(node) && node.hasFormat(format);
}

function escapeLeadingAndTrailingWhitespaces(textContent: string) {
return textContent.replace(/^\s+|\s+$/g, (match) => {
return [...match].map((char) => '&#' + char.codePointAt(0) + ';').join('');
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -408,17 +408,14 @@ describe('Markdown', () => {
{
html: '<p><b><strong style="white-space: pre-wrap;">Hello </strong></b><s><b><strong style="white-space: pre-wrap;">world</strong></b></s><span style="white-space: pre-wrap;">!</span></p>',
md: '**Hello ~~world~~**!',
mdAfterExport: '**Hello&#32;~~world~~**!',
},
{
html: '<p><s><b><strong style="white-space: pre-wrap;">Hello </strong></b></s><s><i><b><strong style="white-space: pre-wrap;">world</strong></b></i></s><s><span style="white-space: pre-wrap;">!</span></s></p>',
md: '**~~Hello *world*~~**~~!~~',
mdAfterExport: '**~~Hello&#32;*world*~~**~~!~~',
},
{
html: '<p><i><em style="white-space: pre-wrap;">Hello </em></i><i><b><strong style="white-space: pre-wrap;">world</strong></b></i><i><em style="white-space: pre-wrap;">!</em></i></p>',
md: '*Hello **world**!*',
mdAfterExport: '*Hello&#32;**world**!*',
},
{
html: '<p><span style="white-space: pre-wrap;">hello world</span></p>',
Expand Down Expand Up @@ -603,26 +600,20 @@ describe('Markdown', () => {
{
html: '<p><span style="white-space: pre-wrap;">Text </span><b><strong style="white-space: pre-wrap;">boldstart </strong></b><a href="https://lexical.dev"><b><strong style="white-space: pre-wrap;">text</strong></b></a><b><strong style="white-space: pre-wrap;"> boldend</strong></b><span style="white-space: pre-wrap;"> text</span></p>',
md: 'Text **boldstart [text](https://lexical.dev) boldend** text',
mdAfterExport:
'Text **boldstart&#32;[text](https://lexical.dev)&#32;boldend** text',
},
{
html: '<p><span style="white-space: pre-wrap;">Text </span><b><strong style="white-space: pre-wrap;">boldstart </strong></b><a href="https://lexical.dev"><b><code spellcheck="false" style="white-space: pre-wrap;"><strong>text</strong></code></b></a><b><strong style="white-space: pre-wrap;"> boldend</strong></b><span style="white-space: pre-wrap;"> text</span></p>',
md: 'Text **boldstart [`text`](https://lexical.dev) boldend** text',
mdAfterExport:
'Text **boldstart&#32;[`text`](https://lexical.dev)&#32;boldend** text',
},
{
html: '<p><span style="white-space: pre-wrap;">It </span><s><i><b><strong style="white-space: pre-wrap;">works </strong></b></i></s><a href="https://lexical.io"><s><i><b><strong style="white-space: pre-wrap;">with links</strong></b></i></s></a><span style="white-space: pre-wrap;"> too</span></p>',
md: 'It ~~___works [with links](https://lexical.io)___~~ too',
mdAfterExport:
'It ***~~works&#32;[with links](https://lexical.io)~~*** too',
mdAfterExport: 'It ***~~works [with links](https://lexical.io)~~*** too',
},
{
html: '<p><span style="white-space: pre-wrap;">It </span><s><i><b><strong style="white-space: pre-wrap;">works </strong></b></i></s><a href="https://lexical.io"><s><i><b><strong style="white-space: pre-wrap;">with links</strong></b></i></s></a><s><i><b><strong style="white-space: pre-wrap;"> too</strong></b></i></s><span style="white-space: pre-wrap;">!</span></p>',
md: 'It ~~___works [with links](https://lexical.io) too___~~!',
mdAfterExport:
'It ***~~works&#32;[with links](https://lexical.io)&#32;too~~***!',
mdAfterExport: 'It ***~~works [with links](https://lexical.io) too~~***!',
},
{
html: '<p><a href="https://lexical.dev"><span style="white-space: pre-wrap;">link</span></a><a href="https://lexical.dev"><span style="white-space: pre-wrap;">link2</span></a></p>',
Expand Down Expand Up @@ -682,10 +673,6 @@ describe('Markdown', () => {
html: '<p><span style="white-space: pre-wrap;">*Hello* world</span></p>',
md: '\\*Hello\\* world',
},
{
html: '<p><b><strong style="white-space: pre-wrap;">&nbsp;</strong></b></p>',
md: '**&#160;**',
},
{
html: '<p><a href="https://lexical.dev"><span style="white-space: pre-wrap;">[h]ello</span></a><a href="https://lexical.dev"><span style="white-space: pre-wrap;">h[e]llo</span></a></p>',
md: '[[h]ello](https://lexical.dev)[h[e]llo](https://lexical.dev)',
Expand All @@ -706,6 +693,11 @@ describe('Markdown', () => {
html: '<p><span style="white-space: pre-wrap;">[](https://lexical.dev)</span></p>',
md: '[](https://lexical.dev)',
},
{
html: '<p><b><strong style="white-space: pre-wrap;"> </strong></b></p>',
md: ' ',
skipImport: true,
},
];

for (const {
Expand Down
6 changes: 1 addition & 5 deletions packages/lexical-markdown/src/importTextTransformers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,6 @@ export function importTextTransformers(

// Handle escape characters
const textContent = textNode.getTextContent();
const escapedText = textContent
.replace(/\\([*_`~\\])/g, '$1')
.replace(/&#(\d+);/g, (_, codePoint) => {
return String.fromCodePoint(codePoint);
});
const escapedText = textContent.replace(/\\([*_`~\\])/g, '$1');
textNode.setTextContent(escapedText);
}