Skip to content

Commit bee465e

Browse files
committed
fix: formatting error
1 parent f14777a commit bee465e

File tree

2 files changed

+128
-5
lines changed

2 files changed

+128
-5
lines changed

src/renderer/components/FormattingToolbar.tsx

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,49 @@ export function FormattingToolbar({ editor }: FormattingToolbarProps) {
2121
const toggleUnderline = () => editor.chain().focus().toggleUnderline().run();
2222
const toggleStrike = () => editor.chain().focus().toggleStrike().run();
2323
const toggleCode = () => editor.chain().focus().toggleCode().run();
24-
const toggleCodeBlock = () => editor.chain().focus().toggleCodeBlock().run();
24+
const toggleCodeBlock = () => {
25+
const { from } = editor.state.selection;
26+
27+
// Check if we're in a code block already
28+
if (editor.isActive("codeBlock")) {
29+
// If we're in a code block, convert back to paragraph
30+
editor.chain().focus().toggleCodeBlock().run();
31+
} else {
32+
// Check if current node contains mentions
33+
const $from = editor.state.doc.resolve(from);
34+
const currentNode = $from.parent;
35+
let hasMentions = false;
36+
37+
// Check if the current paragraph has mention nodes
38+
if (currentNode.content) {
39+
currentNode.content.forEach((node) => {
40+
if (node.type.name === "mention") {
41+
hasMentions = true;
42+
}
43+
});
44+
}
45+
46+
if (hasMentions) {
47+
// If there are mentions, create code block on a new line after current paragraph
48+
const endOfParagraph = $from.end($from.depth);
49+
50+
editor
51+
.chain()
52+
.focus()
53+
.setTextSelection(endOfParagraph)
54+
.insertContent([
55+
{
56+
type: "codeBlock",
57+
content: [{ type: "text", text: "" }],
58+
},
59+
])
60+
.run();
61+
} else {
62+
// No mentions, use the normal toggle
63+
editor.chain().focus().toggleCodeBlock().run();
64+
}
65+
}
66+
};
2567
const toggleBlockquote = () =>
2668
editor.chain().focus().toggleBlockquote().run();
2769
const toggleBulletList = () =>
@@ -37,7 +79,30 @@ export function FormattingToolbar({ editor }: FormattingToolbarProps) {
3779
};
3880

3981
const setHeading = (level: 1 | 2 | 3 | 4 | 5 | 6) => {
40-
editor.chain().focus().toggleHeading({ level }).run();
82+
const { from, to } = editor.state.selection;
83+
84+
// If there's a text selection, wrap it in a new paragraph and convert to heading
85+
if (from !== to) {
86+
const selectedText = editor.state.doc.textBetween(from, to);
87+
editor
88+
.chain()
89+
.focus()
90+
.deleteSelection()
91+
.insertContent([
92+
{
93+
type: "heading",
94+
attrs: { level },
95+
content: [{ type: "text", text: selectedText }],
96+
},
97+
{
98+
type: "paragraph",
99+
},
100+
])
101+
.run();
102+
} else {
103+
// No selection, toggle heading for current block
104+
editor.chain().focus().toggleHeading({ level }).run();
105+
}
41106
};
42107

43108
const getCurrentHeading = () => {
@@ -70,7 +135,29 @@ export function FormattingToolbar({ editor }: FormattingToolbarProps) {
70135
value={getCurrentHeading()}
71136
onValueChange={(value) => {
72137
if (value === "paragraph") {
73-
editor.chain().focus().setParagraph().run();
138+
const { from, to } = editor.state.selection;
139+
140+
// If there's a text selection, wrap it in a new paragraph
141+
if (from !== to) {
142+
const selectedText = editor.state.doc.textBetween(from, to);
143+
editor
144+
.chain()
145+
.focus()
146+
.deleteSelection()
147+
.insertContent([
148+
{
149+
type: "paragraph",
150+
content: [{ type: "text", text: selectedText }],
151+
},
152+
{
153+
type: "paragraph",
154+
},
155+
])
156+
.run();
157+
} else {
158+
// No selection, set current block to paragraph
159+
editor.chain().focus().setParagraph().run();
160+
}
74161
} else {
75162
setHeading(parseInt(value, 10) as 1 | 2 | 3 | 4 | 5 | 6);
76163
}

src/renderer/components/RichTextEditor.tsx

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,10 +244,46 @@ export function RichTextEditor({
244244
event.preventDefault();
245245
editor?.chain().focus().toggleStrike().run();
246246
return true;
247-
case "C":
247+
case "C": {
248248
event.preventDefault();
249-
editor?.chain().focus().toggleCodeBlock().run();
249+
// Use the same logic as the toolbar button
250+
const { from } = editor?.state.selection || { from: 0 };
251+
const $from = editor?.state.doc.resolve(from);
252+
const currentNode = $from?.parent;
253+
let hasMentions = false;
254+
255+
if (editor?.isActive("codeBlock")) {
256+
editor.chain().focus().toggleCodeBlock().run();
257+
} else if (currentNode?.content) {
258+
currentNode.content.forEach((node) => {
259+
if (node.type.name === "mention") {
260+
hasMentions = true;
261+
}
262+
});
263+
264+
if (hasMentions) {
265+
// If there are mentions, create code block on a new line after current paragraph
266+
const endOfParagraph = $from?.end($from.depth) || 0;
267+
268+
editor
269+
?.chain()
270+
.focus()
271+
.setTextSelection(endOfParagraph)
272+
.insertContent([
273+
{
274+
type: "codeBlock",
275+
content: [{ type: "text", text: "" }],
276+
},
277+
])
278+
.run();
279+
} else {
280+
editor?.chain().focus().toggleCodeBlock().run();
281+
}
282+
} else {
283+
editor?.chain().focus().toggleCodeBlock().run();
284+
}
250285
return true;
286+
}
251287
case "B":
252288
event.preventDefault();
253289
editor?.chain().focus().toggleBlockquote().run();

0 commit comments

Comments
 (0)