Skip to content

Commit 68d084f

Browse files
committed
fix: strip trailing whitespace from sent messages
1 parent 4307cc4 commit 68d084f

1 file changed

Lines changed: 41 additions & 28 deletions

File tree

src/lib/components/common/RichTextInput.svelte

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@
3737
});
3838
turndownService.escape = (string) => string;
3939
40+
// Turndown serializes each <br> as a Markdown " \n" hard break, leaving
41+
// invisible trailing spaces at line breaks and on blank lines. Strip trailing
42+
// whitespace from every line, including inside fenced code blocks. markdownlint
43+
// (MD009) preserves it there for whitespace-sensitive languages, but a chat
44+
// message is not source code, so trimming uniformly is simpler and safe here.
45+
const stripTrailingWhitespace = (md: string): string => md.replace(/[ \t]+$/gm, '');
46+
4047
// Produce single newlines between paragraphs instead of double.
4148
// TipTap wraps every line in <p> tags; the default Turndown rule emits
4249
// \n\n around each paragraph which then required a destructive
@@ -711,7 +718,7 @@
711718
try {
712719
// Try parsing the value
713720
return marked.parse(value.replaceAll(`\n<br/>`, `<br/>`), {
714-
breaks: false
721+
breaks: true
715722
});
716723
} catch (error) {
717724
// If no attempts remain, fallback to plain text
@@ -885,26 +892,30 @@
885892
jsonValue = editor.getJSON();
886893
887894
if (richText) {
888-
mdValue = turndownService
889-
.turndown(
890-
htmlValue
891-
.replace(/<p><\/p>/g, '<br/>')
892-
.replace(/ {2,}/g, (m) => m.replace(/ /g, '\u00a0'))
893-
)
894-
.replace(/\u00a0/g, ' ');
895+
mdValue = stripTrailingWhitespace(
896+
turndownService
897+
.turndown(
898+
htmlValue
899+
.replace(/<p><\/p>/g, '<br/>')
900+
.replace(/ {2,}/g, (m) => m.replace(/ /g, '\u00a0'))
901+
)
902+
.replace(/\u00a0/g, ' ')
903+
);
895904
} else {
896-
mdValue = turndownService
897-
.turndown(
898-
htmlValue
899-
// Replace empty paragraphs with line breaks
900-
.replace(/<p><\/p>/g, '<br/>')
901-
// Replace multiple spaces with non-breaking spaces
902-
.replace(/ {2,}/g, (m) => m.replace(/ /g, '\u00a0'))
903-
// Replace tabs with non-breaking spaces (preserve indentation)
904-
.replace(/\t/g, '\u00a0\u00a0\u00a0\u00a0') // 1 tab = 4 spaces
905-
)
906-
// Convert non-breaking spaces back to regular spaces for markdown
907-
.replace(/\u00a0/g, ' ');
905+
mdValue = stripTrailingWhitespace(
906+
turndownService
907+
.turndown(
908+
htmlValue
909+
// Replace empty paragraphs with line breaks
910+
.replace(/<p><\/p>/g, '<br/>')
911+
// Replace multiple spaces with non-breaking spaces
912+
.replace(/ {2,}/g, (m) => m.replace(/ /g, '\u00a0'))
913+
// Replace tabs with non-breaking spaces (preserve indentation)
914+
.replace(/\t/g, '\u00a0\u00a0\u00a0\u00a0') // 1 tab = 4 spaces
915+
)
916+
// Convert non-breaking spaces back to regular spaces for markdown
917+
.replace(/\u00a0/g, ' ')
918+
);
908919
}
909920
910921
onChange({
@@ -1265,14 +1276,16 @@
12651276
12661277
const jsonValue = editor.getJSON();
12671278
const htmlValue = editor.getHTML();
1268-
let mdValue = turndownService
1269-
.turndown(
1270-
(preserveBreaks ? htmlValue.replace(/<p><\/p>/g, '<br/>') : htmlValue).replace(
1271-
/ {2,}/g,
1272-
(m) => m.replace(/ /g, '\u00a0')
1279+
let mdValue = stripTrailingWhitespace(
1280+
turndownService
1281+
.turndown(
1282+
(preserveBreaks ? htmlValue.replace(/<p><\/p>/g, '<br/>') : htmlValue).replace(
1283+
/ {2,}/g,
1284+
(m) => m.replace(/ /g, '\u00a0')
1285+
)
12731286
)
1274-
)
1275-
.replace(/\u00a0/g, ' ');
1287+
.replace(/\u00a0/g, ' ')
1288+
);
12761289
12771290
if (value === '') {
12781291
editor.commands.clearContent(); // Clear content if value is empty
@@ -1298,7 +1311,7 @@
12981311
preserveBreaks
12991312
? value
13001313
: marked.parse(value.replaceAll(`\n<br/>`, `<br/>`), {
1301-
breaks: false
1314+
breaks: true
13021315
})
13031316
);
13041317

0 commit comments

Comments
 (0)