Skip to content

Commit 43de00a

Browse files
CopilotMte90
andcommitted
Improve markdown rendering to properly escape HTML and support dark mode
Co-authored-by: Mte90 <403283+Mte90@users.noreply.github.com>
1 parent fc61b34 commit 43de00a

File tree

1 file changed

+52
-10
lines changed

1 file changed

+52
-10
lines changed

ide-plugins/src/main/kotlin/com/picocode/PicoCodeToolWindowContent.kt

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -161,17 +161,38 @@ class PicoCodeToolWindowContent(private val project: Project) {
161161

162162
/**
163163
* Convert markdown to HTML for rendering
164+
* Note: Code block backgrounds use light gray which may need adjustment for dark themes
164165
*/
165166
private fun markdownToHtml(markdown: String): String {
166167
var html = markdown
167-
// Escape HTML special characters first
168+
169+
// Process markdown constructs before escaping HTML
170+
// Code blocks (```) - preserve content as-is
171+
val codeBlockPlaceholders = mutableListOf<String>()
172+
html = html.replace(Regex("```([\\s\\S]*?)```")) { matchResult ->
173+
val content = matchResult.groupValues[1]
174+
val placeholder = "###CODEBLOCK${codeBlockPlaceholders.size}###"
175+
codeBlockPlaceholders.add(content)
176+
placeholder
177+
}
178+
179+
// Inline code (`) - preserve content
180+
val inlineCodePlaceholders = mutableListOf<String>()
181+
html = html.replace(Regex("`([^`]+)`")) { matchResult ->
182+
val content = matchResult.groupValues[1]
183+
val placeholder = "###INLINECODE${inlineCodePlaceholders.size}###"
184+
inlineCodePlaceholders.add(content)
185+
placeholder
186+
}
187+
188+
// Escape HTML special characters in remaining text
189+
html = html
168190
.replace("&", "&amp;")
169191
.replace("<", "&lt;")
170192
.replace(">", "&gt;")
171-
// Code blocks (```)
172-
.replace(Regex("```([\\s\\S]*?)```"), "<pre style='background-color: #f5f5f5; padding: 8px; border-radius: 4px;'><code>$1</code></pre>")
173-
// Inline code (`)
174-
.replace(Regex("`([^`]+)`"), "<code style='background-color: #f0f0f0; padding: 2px 4px; border-radius: 3px;'>$1</code>")
193+
194+
// Apply markdown formatting
195+
html = html
175196
// Bold (**text**)
176197
.replace(Regex("\\*\\*([^*]+)\\*\\*"), "<strong>$1</strong>")
177198
// Italic (*text*)
@@ -183,14 +204,35 @@ class PicoCodeToolWindowContent(private val project: Project) {
183204
// Lists
184205
.replace(Regex("^- (.+)$", RegexOption.MULTILINE), "<li>$1</li>")
185206
.replace(Regex("^\\* (.+)$", RegexOption.MULTILINE), "<li>$1</li>")
186-
// Line breaks
187-
.replace("\n", "<br/>")
188207

189-
// Wrap lists in <ul> tags
190-
html = html.replace(Regex("(<li>.*?</li>)+")) { matchResult ->
191-
"<ul>${matchResult.value}</ul>"
208+
// Restore code blocks with proper styling
209+
codeBlockPlaceholders.forEachIndexed { index, content ->
210+
val escapedContent = content
211+
.replace("&", "&amp;")
212+
.replace("<", "&lt;")
213+
.replace(">", "&gt;")
214+
html = html.replace("###CODEBLOCK${index}###",
215+
"<pre style='background-color: rgba(127, 127, 127, 0.1); padding: 8px; border-radius: 4px; overflow-x: auto; border: 1px solid rgba(127, 127, 127, 0.2);'><code>$escapedContent</code></pre>")
192216
}
193217

218+
// Restore inline code with proper styling
219+
inlineCodePlaceholders.forEachIndexed { index, content ->
220+
val escapedContent = content
221+
.replace("&", "&amp;")
222+
.replace("<", "&lt;")
223+
.replace(">", "&gt;")
224+
html = html.replace("###INLINECODE${index}###",
225+
"<code style='background-color: rgba(127, 127, 127, 0.15); padding: 2px 4px; border-radius: 3px;'>$escapedContent</code>")
226+
}
227+
228+
// Wrap consecutive list items in <ul> tags
229+
html = html.replace(Regex("(<li>.*?</li>(?:<br/>)?)+")) { matchResult ->
230+
"<ul>${matchResult.value.replace("<br/>", "")}</ul>"
231+
}
232+
233+
// Convert line breaks (but not inside pre/code tags)
234+
html = html.replace("\n", "<br/>")
235+
194236
return "<html><body style='font-family: sans-serif; font-size: 12px;'>$html</body></html>"
195237
}
196238

0 commit comments

Comments
 (0)