Improve highlighting and add QoL changes
This commit is contained in:
145
markdown.go
Normal file
145
markdown.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/charmbracelet/glamour"
|
||||
"github.com/charmbracelet/glamour/styles"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
)
|
||||
|
||||
var commentMarkdownRenderers sync.Map
|
||||
var quoteRailStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#777777"))
|
||||
|
||||
func renderCommentMarkdown(markdown string, width int) []string {
|
||||
if strings.TrimSpace(markdown) == "" {
|
||||
return nil
|
||||
}
|
||||
width = max(10, width)
|
||||
markdown = normalizeGitHubAlerts(markdown)
|
||||
var (
|
||||
result []string
|
||||
block []string
|
||||
blockQuote bool
|
||||
haveBlock bool
|
||||
)
|
||||
flush := func() {
|
||||
if len(block) == 0 {
|
||||
return
|
||||
}
|
||||
blockWidth := width
|
||||
if blockQuote {
|
||||
blockWidth = max(8, width-2)
|
||||
}
|
||||
lines := renderMarkdownFragment(strings.Join(block, "\n"), blockWidth)
|
||||
if haveBlock && len(lines) > 0 {
|
||||
result = append(result, "")
|
||||
}
|
||||
if blockQuote {
|
||||
rail := quoteRailStyle.Render("│ ")
|
||||
for i := range lines {
|
||||
lines[i] = rail + lines[i]
|
||||
}
|
||||
}
|
||||
result = append(result, lines...)
|
||||
haveBlock = haveBlock || len(lines) > 0
|
||||
block = nil
|
||||
}
|
||||
|
||||
for _, line := range strings.Split(markdown, "\n") {
|
||||
content, quoted := stripQuoteMarker(line)
|
||||
if len(block) > 0 && quoted != blockQuote {
|
||||
flush()
|
||||
}
|
||||
blockQuote = quoted
|
||||
block = append(block, content)
|
||||
}
|
||||
flush()
|
||||
return trimMarkdownLines(result)
|
||||
}
|
||||
|
||||
func renderMarkdownFragment(markdown string, width int) []string {
|
||||
if strings.TrimSpace(markdown) == "" {
|
||||
return nil
|
||||
}
|
||||
renderer, err := commentMarkdownRenderer(width)
|
||||
if err != nil {
|
||||
return fallbackCommentLines(markdown, width)
|
||||
}
|
||||
rendered, err := renderer.Render(markdown)
|
||||
if err != nil {
|
||||
return fallbackCommentLines(markdown, width)
|
||||
}
|
||||
return trimMarkdownLines(strings.Split(strings.Trim(rendered, "\n"), "\n"))
|
||||
}
|
||||
|
||||
func commentMarkdownRenderer(width int) (*glamour.TermRenderer, error) {
|
||||
if cached, ok := commentMarkdownRenderers.Load(width); ok {
|
||||
return cached.(*glamour.TermRenderer), nil
|
||||
}
|
||||
style := styles.DarkStyleConfig
|
||||
zero := uint(0)
|
||||
style.Document.Margin = &zero
|
||||
style.Code.Prefix = ""
|
||||
style.Code.Suffix = ""
|
||||
renderer, err := glamour.NewTermRenderer(
|
||||
glamour.WithStyles(style),
|
||||
glamour.WithWordWrap(width),
|
||||
glamour.WithTableWrap(true),
|
||||
glamour.WithPreservedNewLines(),
|
||||
glamour.WithEmoji(),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
actual, _ := commentMarkdownRenderers.LoadOrStore(width, renderer)
|
||||
return actual.(*glamour.TermRenderer), nil
|
||||
}
|
||||
|
||||
func stripQuoteMarker(line string) (string, bool) {
|
||||
trimmed := strings.TrimLeft(line, " \t")
|
||||
if !strings.HasPrefix(trimmed, ">") {
|
||||
return line, false
|
||||
}
|
||||
content := strings.TrimPrefix(trimmed, ">")
|
||||
content = strings.TrimPrefix(content, " ")
|
||||
return content, true
|
||||
}
|
||||
|
||||
func normalizeGitHubAlerts(markdown string) string {
|
||||
alerts := map[string]string{
|
||||
"[!NOTE]": "ℹ **Note**",
|
||||
"[!TIP]": "◆ **Tip**",
|
||||
"[!IMPORTANT]": "❗ **Important**",
|
||||
"[!WARNING]": "⚠ **Warning**",
|
||||
"[!CAUTION]": "⛔ **Caution**",
|
||||
}
|
||||
lines := strings.Split(markdown, "\n")
|
||||
for i, line := range lines {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
if !strings.HasPrefix(trimmed, ">") {
|
||||
continue
|
||||
}
|
||||
label := strings.TrimSpace(strings.TrimPrefix(trimmed, ">"))
|
||||
if replacement, ok := alerts[strings.ToUpper(label)]; ok {
|
||||
prefix := line[:strings.Index(line, ">")+1]
|
||||
lines[i] = prefix + " " + replacement
|
||||
}
|
||||
}
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
func fallbackCommentLines(markdown string, width int) []string {
|
||||
return strings.Split(wrap(markdown, max(10, width)), "\n")
|
||||
}
|
||||
|
||||
func trimMarkdownLines(lines []string) []string {
|
||||
for len(lines) > 0 && strings.TrimSpace(lines[0]) == "" {
|
||||
lines = lines[1:]
|
||||
}
|
||||
for len(lines) > 0 && strings.TrimSpace(lines[len(lines)-1]) == "" {
|
||||
lines = lines[:len(lines)-1]
|
||||
}
|
||||
return lines
|
||||
}
|
||||
Reference in New Issue
Block a user