diff --git a/static/style.css b/static/style.css index cc6862d..a9d2258 100644 --- a/static/style.css +++ b/static/style.css @@ -7,9 +7,12 @@ html { #chat-messages .message-content pre { overflow-x: auto; white-space: pre; - max-width: 662px; position: relative; - border-radius: 8px; + max-width: 685px; + border-radius: 0px 0px 8px 8px; + background-color: #2c2c2c; + margin-top: 0; + /* Remove top margin to align with header */ } #chat-messages .message-content pre code { @@ -18,10 +21,24 @@ html { white-space: inherit; } +.code-header { + display: flex; + justify-content: space-between; + align-items: center; + background-color: #515151; + border-radius: 8px 8px 0 0; + /* Rounded corners on top */ + padding: 5px 10px 10px 10px; + margin-bottom: -8px; + /* Overlap with pre element */ +} + .copy-button { - position: absolute; - top: 5px; - right: 5px; + background: none; + border: none; + cursor: pointer; + font-size: 14px; + color: #ffffff; } .content { @@ -30,6 +47,7 @@ html { color: #ffffff; } + /* Style for the overall chat container */ #chat-messages { diff --git a/utils.go b/utils.go index 8703545..94a6761 100644 --- a/utils.go +++ b/utils.go @@ -10,34 +10,69 @@ import ( "github.com/yuin/goldmark" highlighting "github.com/yuin/goldmark-highlighting" + "github.com/yuin/goldmark/parser" + "github.com/yuin/goldmark/renderer/html" ) +var md goldmark.Markdown + +func init() { + md = goldmark.New(goldmark.WithExtensions(highlighting.NewHighlighting(highlighting.WithStyle("monokai"))), + goldmark.WithParserOptions( + parser.WithAutoHeadingID(), + ), + goldmark.WithRendererOptions( + html.WithHardWraps(), + html.WithXHTML(), + )) +} + func markdownToHTML(markdownText string) string { var buf bytes.Buffer - md := goldmark.New( - goldmark.WithExtensions( - highlighting.NewHighlighting(highlighting.WithStyle("monokai")), - ), - ) + if err := md.Convert([]byte(markdownText), &buf); err != nil { fmt.Println("failed to convert markdown to HTML") panic(err) } - return addCopyButtonsToCode(buf.String()) + return addCodeHeader(buf.String(), extractLanguages(markdownText)) } -func addCopyButtonsToCode(htmlContent string) string { - buttonHTML := `` +func extractLanguages(markdownText string) []string { + // Regular expression to match code blocks and capture the language identifier + re := regexp.MustCompile("(?s)```([a-zA-Z0-9]*)\n.*?```") - // Regular expression pattern to match
 elements and insert the button right before 
+	matches := re.FindAllStringSubmatch(markdownText, -1)
+	languages := make([]string, 0, len(matches))
+
+	for _, match := range matches {
+		if len(match) > 1 {
+			languages = append(languages, match[1])
+		} else {
+			languages = append(languages, "")
+		}
+	}
+
+	return languages
+}
+
+func addCodeHeader(htmlContent string, languages []string) string {
+	// Regular expression pattern to match 
 elements
 	pattern := `(]*>)`
 
 	// Compile the regular expression
 	re := regexp.MustCompile(pattern)
 
 	// Replace each matched 
 element with the updated HTML
-	updatedHTML := re.ReplaceAllString(htmlContent, "$1"+buttonHTML)
+	updatedHTML := re.ReplaceAllStringFunc(htmlContent, func(match string) string {
+		var language string
+		if len(languages) > 0 {
+			language = languages[0]
+			languages = languages[1:]
+		}
+		headerHTML := fmt.Sprintf(`
%s
`, language) + return headerHTML + match + }) return updatedHTML } diff --git a/views/layouts/main.html b/views/layouts/main.html index 52bfdb8..06f329f 100644 --- a/views/layouts/main.html +++ b/views/layouts/main.html @@ -26,7 +26,7 @@