Skip to content

Commit 48df7bb

Browse files
authored
fix: Preserve line breaks in user chat messages (#388)
- Fixes a bug that was preventing line breaks from being preserved in user chat messages
1 parent 8d37e5c commit 48df7bb

File tree

2 files changed

+44
-5
lines changed

2 files changed

+44
-5
lines changed

apps/array/src/renderer/features/message-editor/tiptap/useDraftSync.ts

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ function tiptapJsonToEditorContent(json: JSONContent): EditorContent {
99
const traverse = (node: JSONContent) => {
1010
if (node.type === "text" && node.text) {
1111
segments.push({ type: "text", text: node.text });
12+
} else if (node.type === "hardBreak") {
13+
// Shift+Enter creates a hard break within a paragraph
14+
// Use two trailing spaces + newline for markdown line break (<br>)
15+
segments.push({ type: "text", text: " \n" });
1216
} else if (node.type === "mentionChip" && node.attrs) {
1317
segments.push({
1418
type: "chip",
@@ -18,6 +22,15 @@ function tiptapJsonToEditorContent(json: JSONContent): EditorContent {
1822
label: node.attrs.label,
1923
},
2024
});
25+
} else if (node.type === "doc" && node.content) {
26+
// Add double newlines between paragraphs for markdown rendering
27+
// (single newlines in markdown become spaces, double newlines create paragraph breaks)
28+
for (let i = 0; i < node.content.length; i++) {
29+
if (i > 0) {
30+
segments.push({ type: "text", text: "\n\n" });
31+
}
32+
traverse(node.content[i]);
33+
}
2134
} else if (node.content) {
2235
for (const child of node.content) {
2336
traverse(child);
@@ -30,13 +43,33 @@ function tiptapJsonToEditorContent(json: JSONContent): EditorContent {
3043
}
3144

3245
function editorContentToTiptapJson(content: EditorContent): JSONContent {
33-
const paragraphContent: JSONContent[] = [];
46+
const paragraphs: JSONContent[] = [];
47+
let currentParagraphContent: JSONContent[] = [];
48+
49+
const flushParagraph = () => {
50+
paragraphs.push({ type: "paragraph", content: currentParagraphContent });
51+
currentParagraphContent = [];
52+
};
3453

3554
for (const seg of content.segments) {
3655
if (seg.type === "text") {
37-
paragraphContent.push({ type: "text", text: seg.text });
56+
const paragraphParts = seg.text.split("\n\n");
57+
for (let i = 0; i < paragraphParts.length; i++) {
58+
if (i > 0) {
59+
flushParagraph();
60+
}
61+
const lineParts = paragraphParts[i].split(/ {2}\n|\n/);
62+
for (let j = 0; j < lineParts.length; j++) {
63+
if (j > 0) {
64+
currentParagraphContent.push({ type: "hardBreak" });
65+
}
66+
if (lineParts[j]) {
67+
currentParagraphContent.push({ type: "text", text: lineParts[j] });
68+
}
69+
}
70+
}
3871
} else {
39-
paragraphContent.push({
72+
currentParagraphContent.push({
4073
type: "mentionChip",
4174
attrs: {
4275
type: seg.chip.type,
@@ -47,9 +80,15 @@ function editorContentToTiptapJson(content: EditorContent): JSONContent {
4780
}
4881
}
4982

83+
flushParagraph();
84+
85+
if (paragraphs.length === 0) {
86+
paragraphs.push({ type: "paragraph", content: [] });
87+
}
88+
5089
return {
5190
type: "doc",
52-
content: [{ type: "paragraph", content: paragraphContent }],
91+
content: paragraphs,
5392
};
5493
}
5594

apps/array/src/renderer/features/message-editor/tiptap/useTiptapEditor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ export function useTiptapEditor(options: UseTiptapEditorOptions) {
173173

174174
const textToInsert = paths.map((p) => `"${p}"`).join(" ");
175175

176-
view.dispatch(view.state.tr.insertText(textToInsert + " ", pos));
176+
view.dispatch(view.state.tr.insertText(`${textToInsert} `, pos));
177177
return true;
178178
}
179179

0 commit comments

Comments
 (0)