@@ -16,7 +16,7 @@ class CodeFence(
16
16
val devinEndRegex = Regex (" </devin>" )
17
17
18
18
fun parse (content : String ): CodeFence {
19
- val languageRegex = Regex (" ```([\\ w#+ ]*)" )
19
+ val languageRegex = Regex (" \\ s* ```([\\ w#+ ]*)" )
20
20
val lines = content.lines()
21
21
22
22
val startMatch = devinStartRegex.find(content)
@@ -38,21 +38,28 @@ class CodeFence(
38
38
var codeStarted = false
39
39
var codeClosed = false
40
40
var languageId: String? = null
41
+ var codeIndentation = " "
41
42
val codeBuilder = StringBuilder ()
42
43
43
44
for (line in lines) {
44
45
if (! codeStarted) {
45
- val matchResult: MatchResult ? = languageRegex.find(line.trimStart())
46
+ val trimmedLine = line.trimStart()
47
+ val matchResult: MatchResult ? = languageRegex.find(trimmedLine)
46
48
if (matchResult != null ) {
47
- val substring = matchResult.groups[1 ]?.value
49
+ // Store the indentation to match it when looking for the closing fence
50
+ codeIndentation = line.substring(0 , line.length - trimmedLine.length)
51
+ val substring = matchResult.groups[1 ]?.value?.trim()
48
52
languageId = substring
49
53
codeStarted = true
50
54
}
51
- } else if (line.startsWith(" ```" )) {
52
- codeClosed = true
53
- break
54
55
} else {
55
- codeBuilder.append(line).append(" \n " )
56
+ val trimmedLine = line.trimStart()
57
+ if (trimmedLine == " ```" ) {
58
+ codeClosed = true
59
+ break
60
+ } else {
61
+ codeBuilder.append(line).append(" \n " )
62
+ }
56
63
}
57
64
}
58
65
@@ -112,7 +119,7 @@ class CodeFence(
112
119
}
113
120
114
121
val devinRegexBlock = Regex (" (?<=^|\\ n)```devin\\ n([\\ s\\ S]*?)\\ n```\\ n" )
115
- val normalCodeBlock = Regex (" ```([\\ w#+ ]*)\\ n" )
122
+ val normalCodeBlock = Regex (" \\ s* ```([\\ w#+ ]*)\\ n" )
116
123
117
124
fun preProcessDevinBlock (content : String ): String {
118
125
var currentContent = content
@@ -135,17 +142,21 @@ class CodeFence(
135
142
}
136
143
137
144
private fun parseMarkdownContent (content : String , codeFences : MutableList <CodeFence >) {
138
- val languageRegex = Regex (" ```([\\ w#+ ]*)" )
145
+ val languageRegex = Regex (" \\ s* ```([\\ w#+ ]*)" )
139
146
val lines = content.lines()
140
147
141
148
var codeStarted = false
142
149
var languageId: String? = null
143
150
val codeBuilder = StringBuilder ()
144
151
val textBuilder = StringBuilder ()
152
+ var codeIndentation = " "
145
153
146
- for (line in lines) {
154
+ for (i in lines.indices) {
155
+ val line = lines[i]
147
156
if (! codeStarted) {
148
- val matchResult = languageRegex.find(line.trimStart())
157
+ // Check for code block start with any indentation
158
+ val trimmedLine = line.trimStart()
159
+ val matchResult = languageRegex.find(trimmedLine)
149
160
if (matchResult != null ) {
150
161
if (textBuilder.isNotEmpty()) {
151
162
val textBlock = CodeFence (
@@ -156,13 +167,20 @@ class CodeFence(
156
167
textBuilder.clear()
157
168
}
158
169
159
- languageId = matchResult.groups[1 ]?.value
170
+ // Store the indentation to match it when looking for the closing fence
171
+ codeIndentation = line.substring(0 , line.length - trimmedLine.length)
172
+ languageId = matchResult.groups[1 ]?.value?.trim()
160
173
codeStarted = true
161
174
} else {
162
175
textBuilder.append(line).append(" \n " )
163
176
}
164
177
} else {
165
- if (line.startsWith(" ```" )) {
178
+ // Check if this line contains the closing fence with the same or similar indentation
179
+ val trimmedLine = line.trimStart()
180
+
181
+ // Allow for some flexibility in indentation for the closing fence
182
+ // This helps with numbered lists where indentation might vary slightly
183
+ if (trimmedLine == " ```" ) {
166
184
val codeContent = codeBuilder.trim().toString()
167
185
val codeFence = CodeFence (
168
186
findLanguage(languageId ? : " markdown" ),
@@ -176,6 +194,7 @@ class CodeFence(
176
194
codeBuilder.clear()
177
195
codeStarted = false
178
196
languageId = null
197
+ codeIndentation = " "
179
198
} else {
180
199
codeBuilder.append(line).append(" \n " )
181
200
}
0 commit comments