Skip to content

Commit b609c16

Browse files
committed
Merge branch 'code-block-formatting-fix'
2 parents 63d6073 + 52be545 commit b609c16

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed

src/lib/utils/parseIncompleteMarkdown.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,31 @@ const hasCompleteCodeBlock = (text: string): boolean => {
1818
return tripleBackticks > 0 && tripleBackticks % 2 === 0 && text.includes("\n");
1919
};
2020

21+
// Returns the start index of the currently open fenced code block, or -1 if none
22+
const getOpenCodeFenceIndex = (text: string): number => {
23+
let openFenceIndex = -1;
24+
let inFence = false;
25+
26+
for (const match of text.matchAll(/```/g)) {
27+
const index = match.index ?? -1;
28+
if (index === -1) {
29+
continue;
30+
}
31+
32+
if (inFence) {
33+
// This fence closes the current block
34+
inFence = false;
35+
openFenceIndex = -1;
36+
} else {
37+
// This fence opens a new block
38+
inFence = true;
39+
openFenceIndex = index;
40+
}
41+
}
42+
43+
return openFenceIndex;
44+
};
45+
2146
// Handles incomplete links and images by preserving them with a special marker
2247
const handleIncompleteLinksAndImages = (text: string): string => {
2348
// First check for incomplete URLs: [text](partial-url or ![text](partial-url without closing )
@@ -84,6 +109,12 @@ const handleIncompleteBold = (text: string): string => {
84109
// Check if the bold marker is in a list item context
85110
// Find the position of the matched bold marker
86111
const markerIndex = text.lastIndexOf(boldMatch[1]);
112+
113+
// Don't process if the marker is inside an incomplete code block
114+
const openFenceIndex = getOpenCodeFenceIndex(text);
115+
if (openFenceIndex !== -1 && markerIndex > openFenceIndex) {
116+
return text;
117+
}
87118
const beforeMarker = text.substring(0, markerIndex);
88119
const lastNewlineBeforeMarker = beforeMarker.lastIndexOf("\n");
89120
const lineStart = lastNewlineBeforeMarker === -1 ? 0 : lastNewlineBeforeMarker + 1;
@@ -111,6 +142,11 @@ const handleIncompleteBold = (text: string): string => {
111142

112143
// Completes incomplete italic formatting with double underscores (__)
113144
const handleIncompleteDoubleUnderscoreItalic = (text: string): string => {
145+
// Don't process if inside a complete code block
146+
if (hasCompleteCodeBlock(text)) {
147+
return text;
148+
}
149+
114150
const italicMatch = text.match(italicPattern);
115151

116152
if (italicMatch) {
@@ -125,6 +161,12 @@ const handleIncompleteDoubleUnderscoreItalic = (text: string): string => {
125161
// Check if the underscore marker is in a list item context
126162
// Find the position of the matched underscore marker
127163
const markerIndex = text.lastIndexOf(italicMatch[1]);
164+
165+
// Don't process if the marker is inside an incomplete code block
166+
const openFenceIndex = getOpenCodeFenceIndex(text);
167+
if (openFenceIndex !== -1 && markerIndex > openFenceIndex) {
168+
return text;
169+
}
128170
const beforeMarker = text.substring(0, markerIndex);
129171
const lastNewlineBeforeMarker = beforeMarker.lastIndexOf("\n");
130172
const lineStart = lastNewlineBeforeMarker === -1 ? 0 : lastNewlineBeforeMarker + 1;
@@ -210,6 +252,12 @@ const handleIncompleteSingleAsteriskItalic = (text: string): string => {
210252
return text;
211253
}
212254

255+
// Don't process if the marker is inside an incomplete code block
256+
const openFenceIndex = getOpenCodeFenceIndex(text);
257+
if (openFenceIndex !== -1 && firstSingleAsteriskIndex > openFenceIndex) {
258+
return text;
259+
}
260+
213261
// Get content after the first single asterisk
214262
const contentAfterFirstAsterisk = text.substring(firstSingleAsteriskIndex + 1);
215263

@@ -329,6 +377,12 @@ const handleIncompleteSingleUnderscoreItalic = (text: string): string => {
329377
return text;
330378
}
331379

380+
// Don't process if the marker is inside an incomplete code block
381+
const openFenceIndex = getOpenCodeFenceIndex(text);
382+
if (openFenceIndex !== -1 && firstSingleUnderscoreIndex > openFenceIndex) {
383+
return text;
384+
}
385+
332386
// Get content after the first single underscore
333387
const contentAfterFirstUnderscore = text.substring(firstSingleUnderscoreIndex + 1);
334388

@@ -535,6 +589,15 @@ const handleIncompleteBoldItalic = (text: string): string => {
535589
return text;
536590
}
537591

592+
// Find the position of the matched bold-italic marker
593+
const markerIndex = text.lastIndexOf(boldItalicMatch[1]);
594+
595+
// Don't process if the marker is inside an incomplete code block
596+
const openFenceIndex = getOpenCodeFenceIndex(text);
597+
if (openFenceIndex !== -1 && markerIndex > openFenceIndex) {
598+
return text;
599+
}
600+
538601
const tripleAsteriskCount = countTripleAsterisks(text);
539602
if (tripleAsteriskCount % 2 === 1) {
540603
return `${text}***`;

0 commit comments

Comments
 (0)