From 80f3a642a3c3e773a6f0d785d9b95e0dbd56c8e6 Mon Sep 17 00:00:00 2001 From: Ed Zynda Date: Mon, 30 Mar 2026 15:02:01 +0300 Subject: [PATCH] refactor: migrate markdown rendering from glamour to herald-md - Replace glamour-based markdown rendering with herald/herald-md - Update go.mod and go.sum with new dependencies - Refactor styles.go to use Typography cache instead of TermRenderer - Update enhanced_styles.go for compatibility - Update btca.config.jsonc configuration --- btca.config.jsonc | 6 + go.mod | 7 +- go.sum | 17 +- internal/ui/enhanced_styles.go | 6 +- internal/ui/styles.go | 336 +++++++-------------------------- 5 files changed, 85 insertions(+), 287 deletions(-) diff --git a/btca.config.jsonc b/btca.config.jsonc index aa5bcc55..a44e3c2e 100644 --- a/btca.config.jsonc +++ b/btca.config.jsonc @@ -82,6 +82,12 @@ "name": "herald", "url": "https://github.com/indaco/herald", "branch": "main" + }, + { + "type": "git", + "name": "herald-md", + "url": "https://github.com/indaco/herald-md", + "branch": "main" } ], "model": "claude-haiku-4-5", diff --git a/go.mod b/go.mod index a1dd0c99..d87d0a8f 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/charmbracelet/log v1.0.0 github.com/coder/acp-go-sdk v0.6.3 github.com/indaco/herald v0.10.0 + github.com/indaco/herald-md v0.1.0 github.com/mark3labs/mcp-go v0.46.0 github.com/spf13/cobra v1.10.2 github.com/spf13/viper v1.21.0 @@ -45,7 +46,6 @@ require ( github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.18 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.41.10 // indirect github.com/aws/smithy-go v1.24.2 // indirect - github.com/aymerick/douceur v0.2.0 // indirect github.com/catppuccin/go v0.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/charmbracelet/anthropic-sdk-go v0.0.0-20260223140439-63879b0b8dab // indirect @@ -81,18 +81,15 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect github.com/googleapis/gax-go/v2 v2.20.0 // indirect - github.com/gorilla/css v1.0.1 // indirect github.com/gorilla/websocket v1.5.3 // indirect github.com/kaptinlin/go-i18n v0.3.0 // indirect github.com/kaptinlin/jsonpointer v0.4.17 // indirect github.com/kaptinlin/jsonschema v0.7.7 // indirect github.com/kaptinlin/messageformat-go v0.4.19 // indirect - github.com/microcosm-cc/bluemonday v1.0.27 // indirect github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect github.com/muesli/mango v0.2.0 // indirect github.com/muesli/mango-cobra v1.3.0 // indirect github.com/muesli/mango-pflag v0.2.0 // indirect - github.com/muesli/reflow v0.3.0 // indirect github.com/muesli/roff v0.1.0 // indirect github.com/pelletier/go-toml/v2 v2.3.0 // indirect github.com/sagikazarmark/locafero v0.12.0 // indirect @@ -106,7 +103,6 @@ require ( github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/yosida95/uritemplate/v3 v3.0.2 // indirect github.com/yuin/goldmark v1.8.2 // indirect - github.com/yuin/goldmark-emoji v1.0.6 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 // indirect @@ -129,7 +125,6 @@ require ( require ( github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect - github.com/charmbracelet/glamour v1.0.0 github.com/charmbracelet/x/ansi v0.11.6 github.com/charmbracelet/x/term v0.2.2 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect diff --git a/go.sum b/go.sum index fcc097c8..43c4d7e2 100644 --- a/go.sum +++ b/go.sum @@ -68,8 +68,6 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymanbagabas/go-udiff v0.4.1 h1:OEIrQ8maEeDBXQDoGCbbTTXYJMYRCRO1fnodZ12Gv5o= github.com/aymanbagabas/go-udiff v0.4.1/go.mod h1:0L9PGwj20lrtmEMeyw4WKJ/TMyDtvAoK9bf2u/mNo3w= -github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= -github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/catppuccin/go v0.3.0 h1:d+0/YicIq+hSTo5oPuRi5kOpqkVA5tAsU6dNhvRu+aY= github.com/catppuccin/go v0.3.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= @@ -80,8 +78,6 @@ github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q= github.com/charmbracelet/fang v1.0.0 h1:jESBY40agJOlLYnnv9jE0mLqDGTxEk0hkOnx7YGyRlQ= github.com/charmbracelet/fang v1.0.0/go.mod h1:P5/DNb9DddQ0Z0dbc0P3ol4/ix5Po7Ofr2KMBfAqoCo= -github.com/charmbracelet/glamour v1.0.0 h1:AWMLOVFHTsysl4WV8T8QgkQ0s/ZNZo7CiE4WKhk8l08= -github.com/charmbracelet/glamour v1.0.0/go.mod h1:DSdohgOBkMr2ZQNhw4LZxSGpx3SvpeujNoXrQyH2hxo= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834 h1:ZR7e0ro+SZZiIZD7msJyA+NjkCNNavuiPBLgerbOziE= @@ -179,8 +175,6 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= github.com/googleapis/gax-go/v2 v2.20.0 h1:NIKVuLhDlIV74muWlsMM4CcQZqN6JJ20Qcxd9YMuYcs= github.com/googleapis/gax-go/v2 v2.20.0/go.mod h1:But/NJU6TnZsrLai/xBAQLLz+Hc7fHZJt/hsCz3Fih4= -github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= -github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= @@ -189,6 +183,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/indaco/herald v0.10.0 h1:XzahEKX6cr50qZQrUdA3QrQBHg8uGm5jETD0UDi21BI= github.com/indaco/herald v0.10.0/go.mod h1:T5g1+XLYvpjouhzAGHnAHDCKizhESkoV6+QPZ3DhgWA= +github.com/indaco/herald-md v0.1.0 h1:zmYudYo+uamzKTBcIffJVJYrqk9xDNnVrTh+de2zciw= +github.com/indaco/herald-md v0.1.0/go.mod h1:Z1HxPCbSn+/+TFzOM/UbsmKeEk/28NNI6JOTileKXto= github.com/kaptinlin/go-i18n v0.3.0 h1:wP76dvYg04bvwTb+8NB+CmdZ2kL7lSSCQ9B/kFv7QHo= github.com/kaptinlin/go-i18n v0.3.0/go.mod h1:pVcu9qsW5pOIOoZFJXesRYmLos1vMQrby70JPAoWmJU= github.com/kaptinlin/jsonpointer v0.4.17 h1:mY9k8ciWncxbsECyaxKnR0MdmxamNdp2tLQkAKVrtSk= @@ -209,11 +205,8 @@ github.com/mark3labs/mcp-go v0.46.0 h1:8KRibF4wcKejbLsHxCA/QBVUr5fQ9nwz/n8lGqmaA github.com/mark3labs/mcp-go v0.46.0/go.mod h1:JKTC7R2LLVagkEWK7Kwu7DbmA6iIvnNAod6yrHiQMag= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.21 h1:jJKAZiQH+2mIinzCJIaIG9Be1+0NR+5sz/lYEEjdM8w= github.com/mattn/go-runewidth v0.0.21/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= -github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= -github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= @@ -224,8 +217,6 @@ github.com/muesli/mango-cobra v1.3.0 h1:vQy5GvPg3ndOSpduxutqFoINhWk3vD5K2dXo5E8p github.com/muesli/mango-cobra v1.3.0/go.mod h1:Cj1ZrBu3806Qw7UjxnAUgE+7tllUBj1NCLQDwwGx19E= github.com/muesli/mango-pflag v0.2.0 h1:QViokgKDZQCzKhYe1zH8D+UlPJzBSGoP9yx0hBG0t5k= github.com/muesli/mango-pflag v0.2.0/go.mod h1:X9LT1p/pbGA1wjvEbtwnixujKErkP0jVmrxwrw3fL0Y= -github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= -github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= github.com/muesli/roff v0.1.0 h1:YD0lalCotmYuF5HhZliKWlIx7IEhiXeSfq7hNjFqGF8= github.com/muesli/roff v0.1.0/go.mod h1:pjAHQM9hdUUwm/krAfrLGgJkXJ+YuhtsfZ42kieB2Ig= github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= @@ -238,8 +229,6 @@ github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgm github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= @@ -281,8 +270,6 @@ github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zI github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4= github.com/yuin/goldmark v1.8.2 h1:kEGpgqJXdgbkhcOgBxkC0X0PmoPG1ZyoZ117rDVp4zE= github.com/yuin/goldmark v1.8.2/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= -github.com/yuin/goldmark-emoji v1.0.6 h1:QWfF2FYaXwL74tfGOW5izeiZepUDroDJfWubQI9HTHs= -github.com/yuin/goldmark-emoji v1.0.6/go.mod h1:ukxJDKFpdFb5x0a5HqbdlcKtebh086iJpI31LTKmWuA= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0 h1:yI1/OhfEPy7J9eoa6Sj051C7n5dvpj0QX8g4sRchg04= diff --git a/internal/ui/enhanced_styles.go b/internal/ui/enhanced_styles.go index 28c37103..8d6355ce 100644 --- a/internal/ui/enhanced_styles.go +++ b/internal/ui/enhanced_styles.go @@ -35,11 +35,11 @@ func GetTheme() Theme { // SetTheme updates the global UI theme, affecting all subsequent rendering // operations. This allows runtime theme switching for different visual preferences. -// It also invalidates the markdownRendererCache so the next call to -// GetMarkdownRenderer picks up the new theme's colors. +// It also invalidates the markdownTypographyCache so the next call to +// GetMarkdownTypography picks up the new theme. func SetTheme(theme Theme) { currentTheme = theme - markdownRendererCache = nil // invalidate cached renderer; colors may have changed + markdownTypographyCache = nil // invalidate cached renderer; colors may have changed } // MarkdownThemeColors defines colors for markdown rendering and syntax highlighting. diff --git a/internal/ui/styles.go b/internal/ui/styles.go index 3da58ec3..bbe7ed61 100644 --- a/internal/ui/styles.go +++ b/internal/ui/styles.go @@ -1,19 +1,11 @@ package ui import ( - "fmt" - "image/color" - "charm.land/lipgloss/v2" - "github.com/charmbracelet/glamour" - "github.com/charmbracelet/glamour/ansi" + "github.com/indaco/herald" + heraldmd "github.com/indaco/herald-md" ) -// uintPtr returns a pointer to u. Used by ansi.StyleConfig fields. -// -//go:fix inline -func uintPtr(u uint) *uint { return new(u) } - // BaseStyle returns a new, empty lipgloss style that can be customized with // additional styling methods. This serves as the foundation for building more // complex styled components. @@ -21,265 +13,83 @@ func BaseStyle() lipgloss.Style { return lipgloss.NewStyle() } -// colorHex converts a color.Color to a hex string suitable for ansi.StyleConfig. -func colorHex(c color.Color) string { - r, g, b, _ := c.RGBA() - return fmt.Sprintf("#%02x%02x%02x", r>>8, g>>8, b>>8) -} - -// colorHexPtr returns a pointer to the hex string of a color.Color. -func colorHexPtr(c color.Color) *string { - s := colorHex(c) - return &s -} - -// markdownRendererCache holds the last-created TermRenderer so we avoid -// re-initializing a full goldmark parser on every streaming flush tick. -// The cache is keyed by width; it is invalidated (set to nil) by SetTheme -// whenever the active theme changes. +// markdownTypographyCache holds the last-created Typography instance for +// herald-md rendering. It is cached to avoid re-initialization on every +// streaming flush tick. The cache is invalidated by SetTheme when the +// active theme changes. // This is only accessed from BubbleTea's single-threaded Update/View cycle, // so no mutex is required. -var ( - markdownRendererCache *glamour.TermRenderer - markdownRendererWidth int -) +var markdownTypographyCache *herald.Typography -// GetMarkdownRenderer returns a glamour.TermRenderer configured for our theme -// and the given content width. The renderer is cached by width — it is only -// rebuilt when the width changes, avoiding expensive goldmark re-initialization -// on every streaming flush tick. -func GetMarkdownRenderer(width int) *glamour.TermRenderer { - if markdownRendererCache != nil && markdownRendererWidth == width { - return markdownRendererCache +// GetMarkdownTypography returns a herald.Typography configured with our +// active theme colors. The typography is cached and only rebuilt when +// the theme changes via SetTheme. +func GetMarkdownTypography() *herald.Typography { + if markdownTypographyCache != nil { + return markdownTypographyCache } - r, _ := glamour.NewTermRenderer( - glamour.WithStyles(generateMarkdownStyleConfig()), - glamour.WithWordWrap(width), - ) - markdownRendererCache = r - markdownRendererWidth = width - return r + + theme := GetTheme() + md := theme.Markdown + + // Build herald theme from our theme colors + hty := herald.Theme{ + // Headings - use heading color + H1: lipgloss.NewStyle().Foreground(md.Heading).Bold(true), + H2: lipgloss.NewStyle().Foreground(md.Heading).Bold(true), + H3: lipgloss.NewStyle().Foreground(md.Heading).Bold(true), + H4: lipgloss.NewStyle().Foreground(md.Heading).Bold(true), + H5: lipgloss.NewStyle().Foreground(md.Heading).Bold(true), + H6: lipgloss.NewStyle().Foreground(md.Muted).Bold(true), + + // Text blocks + Paragraph: lipgloss.NewStyle().Foreground(md.Text), + Blockquote: lipgloss.NewStyle().Foreground(md.Muted).Italic(true), + CodeInline: lipgloss.NewStyle().Foreground(md.Code), + CodeBlock: lipgloss.NewStyle().Foreground(md.Code), + HR: lipgloss.NewStyle().Foreground(md.Muted), + + // Lists + ListBullet: lipgloss.NewStyle().Foreground(md.Text), + ListItem: lipgloss.NewStyle().Foreground(md.Text), + + // Inline styles + Bold: lipgloss.NewStyle().Foreground(md.Strong).Bold(true), + Italic: lipgloss.NewStyle().Foreground(md.Emph).Italic(true), + Strikethrough: lipgloss.NewStyle().Foreground(md.Muted).Strikethrough(true), + Link: lipgloss.NewStyle().Foreground(md.Link).Underline(true), + + // Definition lists + DT: lipgloss.NewStyle().Foreground(md.Text).Bold(true), + DD: lipgloss.NewStyle().Foreground(md.Muted), + + // Key-value + KVKey: lipgloss.NewStyle().Foreground(md.Text).Bold(true), + KVValue: lipgloss.NewStyle().Foreground(md.Text), + + // Badges/Tags - use semantic colors + Badge: lipgloss.NewStyle().Foreground(md.Text).Bold(true), + SuccessBadge: lipgloss.NewStyle().Foreground(theme.Success).Bold(true), + WarningBadge: lipgloss.NewStyle().Foreground(theme.Warning).Bold(true), + ErrorBadge: lipgloss.NewStyle().Foreground(theme.Error).Bold(true), + InfoBadge: lipgloss.NewStyle().Foreground(theme.Info).Bold(true), + + // Heading decorations + H1UnderlineChar: "═", + H2UnderlineChar: "─", + H3UnderlineChar: "·", + } + + ty := herald.New(herald.WithTheme(hty)) + markdownTypographyCache = ty + return ty } -// generateMarkdownStyleConfig creates an ansi.StyleConfig from the active theme. -func generateMarkdownStyleConfig() ansi.StyleConfig { - md := GetTheme().Markdown - text := colorHexPtr(md.Text) - muted := colorHexPtr(md.Muted) - heading := colorHexPtr(md.Heading) - emph := colorHexPtr(md.Emph) - strong := colorHexPtr(md.Strong) - link := colorHexPtr(md.Link) - code := colorHexPtr(md.Code) - errClr := colorHexPtr(md.Error) - keyword := colorHexPtr(md.Keyword) - str := colorHexPtr(md.String) - number := colorHexPtr(md.Number) - comment := colorHexPtr(md.Comment) - - return ansi.StyleConfig{ - Document: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - BlockPrefix: "", - BlockSuffix: "", - Color: text, - }, - Margin: uintPtr(0), - }, - BlockQuote: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Color: muted, - Italic: new(true), - Prefix: "┃ ", - }, - Indent: uintPtr(1), - }, - List: ansi.StyleList{ - LevelIndent: 0, - StyleBlock: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Color: text, - }, - }, - }, - Heading: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - BlockSuffix: "\n", - Color: heading, - Bold: new(true), - }, - }, - H1: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "# ", - Color: heading, - Bold: new(true), - }, - }, - H2: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "## ", - Color: heading, - Bold: new(true), - }, - }, - H3: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "### ", - Color: heading, - Bold: new(true), - }, - }, - H4: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "#### ", - Color: heading, - Bold: new(true), - }, - }, - H5: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "##### ", - Color: heading, - Bold: new(true), - }, - }, - H6: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "###### ", - Color: heading, - Bold: new(true), - }, - }, - Strikethrough: ansi.StylePrimitive{ - CrossedOut: new(true), - Color: muted, - }, - Emph: ansi.StylePrimitive{ - Color: emph, - Italic: new(true), - }, - Strong: ansi.StylePrimitive{ - Bold: new(true), - Color: strong, - }, - HorizontalRule: ansi.StylePrimitive{ - Color: muted, - Format: "\n─────────────────────────────────────────\n", - }, - Item: ansi.StylePrimitive{ - BlockPrefix: "• ", - Color: text, - }, - Enumeration: ansi.StylePrimitive{ - BlockPrefix: ". ", - Color: text, - }, - Task: ansi.StyleTask{ - StylePrimitive: ansi.StylePrimitive{}, - Ticked: "[✓] ", - Unticked: "[ ] ", - }, - Link: ansi.StylePrimitive{ - Color: link, - Underline: new(true), - }, - LinkText: ansi.StylePrimitive{ - Color: link, - Bold: new(true), - }, - Image: ansi.StylePrimitive{ - Color: link, - Underline: new(true), - Format: "🖼 {{.text}}", - }, - ImageText: ansi.StylePrimitive{ - Color: link, - Format: "{{.text}}", - }, - Code: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Color: code, - Prefix: "", - Suffix: "", - }, - }, - CodeBlock: ansi.StyleCodeBlock{ - StyleBlock: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "", - Color: code, - }, - Margin: uintPtr(0), - }, - Chroma: &ansi.Chroma{ - Text: ansi.StylePrimitive{Color: text}, - Error: ansi.StylePrimitive{Color: errClr}, - Comment: ansi.StylePrimitive{Color: comment}, - CommentPreproc: ansi.StylePrimitive{Color: keyword}, - Keyword: ansi.StylePrimitive{Color: keyword}, - KeywordReserved: ansi.StylePrimitive{Color: keyword}, - KeywordNamespace: ansi.StylePrimitive{Color: keyword}, - KeywordType: ansi.StylePrimitive{Color: keyword}, - Operator: ansi.StylePrimitive{Color: text}, - Punctuation: ansi.StylePrimitive{Color: text}, - Name: ansi.StylePrimitive{Color: text}, - NameBuiltin: ansi.StylePrimitive{Color: text}, - NameTag: ansi.StylePrimitive{Color: keyword}, - NameAttribute: ansi.StylePrimitive{Color: text}, - NameClass: ansi.StylePrimitive{Color: keyword}, - NameConstant: ansi.StylePrimitive{Color: text}, - NameDecorator: ansi.StylePrimitive{Color: text}, - NameFunction: ansi.StylePrimitive{Color: text}, - LiteralNumber: ansi.StylePrimitive{Color: number}, - LiteralString: ansi.StylePrimitive{Color: str}, - LiteralStringEscape: ansi.StylePrimitive{ - Color: keyword, - }, - GenericDeleted: ansi.StylePrimitive{Color: errClr}, - GenericEmph: ansi.StylePrimitive{ - Color: emph, - Italic: new(true), - }, - GenericInserted: ansi.StylePrimitive{Color: str}, - GenericStrong: ansi.StylePrimitive{ - Color: strong, - Bold: new(true), - }, - GenericSubheading: ansi.StylePrimitive{ - Color: heading, - }, - }, - }, - Table: ansi.StyleTable{ - StyleBlock: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - BlockPrefix: "\n", - BlockSuffix: "\n", - }, - }, - CenterSeparator: new("┼"), - ColumnSeparator: new("│"), - RowSeparator: new("─"), - }, - DefinitionDescription: ansi.StylePrimitive{ - BlockPrefix: "\n ❯ ", - Color: link, - }, - Text: ansi.StylePrimitive{ - Color: text, - }, - Paragraph: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Color: text, - }, - }, - } -} - -// toMarkdown renders markdown content using glamour. +// toMarkdown renders markdown content using herald-md. +// The width parameter is currently unused as herald handles wrapping +// based on terminal width internally. func toMarkdown(content string, width int) string { - r := GetMarkdownRenderer(width) - rendered, _ := r.Render(content) + ty := GetMarkdownTypography() + rendered := heraldmd.Render(ty, []byte(content)) return rendered }