okami.mom/glamour

git clone https://git.nkp.pet/okami.mom/glamour

Ayman BagabasMerge pull request #408 from charmbracelet/v2-expcf874d7

main
6.8 KiB279 linesraw

Glamour v2 Upgrade Guide

This guide will help you migrate from Glamour v1 to v2. Most upgrades are straightforward and can be completed in minutes.

Update Import Paths

Required: All imports must use the new charm.land module path with /v2:

-import "github.com/charmbracelet/glamour"
-import "github.com/charmbracelet/glamour/ansi"
-import "github.com/charmbracelet/glamour/styles"
+import "charm.land/glamour/v2"
+import "charm.land/glamour/v2/ansi"
+import "charm.land/glamour/v2/styles"

Update Dependencies

go get charm.land/glamour/v2@latest

If you need color downsampling (most apps do):

go get charm.land/lipgloss/v2@latest

Remove Auto Style Detection

Breaking: WithAutoStyle() has been removed. The default style is now "dark".

-r, _ := glamour.NewTermRenderer(
-    glamour.WithAutoStyle(),
-)
+r, _ := glamour.NewTermRenderer(
+    // "dark" is the default, or specify explicitly
+    glamour.WithStylePath("dark"),
+)

If you were relying on automatic style selection based on terminal background, you'll need to choose the style explicitly:

// For light backgrounds
r, _ := glamour.NewTermRenderer(glamour.WithStylePath("light"))

// For dark backgrounds (default)
r, _ := glamour.NewTermRenderer(glamour.WithStylePath("dark"))

// Other built-in styles: "pink", "dracula", "tokyo-night", "ascii"
r, _ := glamour.NewTermRenderer(glamour.WithStylePath("dracula"))

Want to detect the terminal background yourself? You can use Lip Gloss:

import "charm.land/lipgloss/v2"

// Detect if we're on a dark background
isDark := lipgloss.HasDarkBackground()

style := "dark"
if !isDark {
    style = "light"
}

r, _ := glamour.NewTermRenderer(glamour.WithStylePath(style))

Handle Color Downsampling Explicitly

Breaking: WithColorProfile() has been removed. Use Lip Gloss for color adaptation:

-import "github.com/muesli/termenv"
-
-r, _ := glamour.NewTermRenderer(
-    glamour.WithColorProfile(termenv.TrueColor),
-)
-out, _ := r.Render(markdown)
-fmt.Print(out)
+import "charm.land/lipgloss/v2"
+
+r, _ := glamour.NewTermRenderer(
+    glamour.WithWordWrap(80),
+)
+out, _ := r.Render(markdown)
+
+// Lip Gloss handles color downsampling based on terminal capabilities
+lipgloss.Print(out)

Why the change? Glamour is now pure — it always produces the same output for the same input. This makes it more predictable and testable. Lip Gloss handles the terminal-specific color adaptation when you're ready to display the output.

If you don't need color adaptation (e.g., you know you're always outputting TrueColor):

r, _ := glamour.NewTermRenderer(glamour.WithWordWrap(80))
out, _ := r.Render(markdown)
fmt.Print(out)  // Direct output, no downsampling

Remove Overline Styles

Breaking: The Overlined field has been removed from style configurations.

If you have custom styles using Overlined:

 StylePrimitive: ansi.StylePrimitive{
     Bold:      &trueBool,
     Underline: &trueBool,
-    Overlined: &trueBool,
 }

Overline was rarely supported across terminals and not widely used. If you need similar visual separation, consider alternatives like underline, bold, inverse, or background colors.

Update Custom Style Definitions

If you maintain custom StyleConfig definitions, update the import paths:

-import "github.com/charmbracelet/glamour/ansi"
+import "charm.land/glamour/v2/ansi"

 var myStyle = &ansi.StyleConfig{
     // Your custom style definition
     Document: ansi.StyleBlock{
         StylePrimitive: ansi.StylePrimitive{
             Color: stringPtr("#E6DB74"),
         },
     },
 }

The structure is the same; only the import path changes.

Verify Custom Writers (Advanced)

If you implemented custom margin or padding writers using ansi.MarginWriter:

  1. Ensure you call .Close() on all writer instances
  2. The new IndentWriter and PaddingWriter types are available for custom use
import "charm.land/glamour/v2/ansi"

mw := ansi.NewMarginWriter(ctx, w, style)
defer mw.Close()  // Important: always close writers now

// Write your content
io.WriteString(mw, content)

This improves memory management and prevents resource leaks.

Example Migration

Here's a complete before/after example:

Before (v1)

package main

import (
    "fmt"
    "github.com/charmbracelet/glamour"
    "github.com/muesli/termenv"
)

func main() {
    md := `# Hello World

This is **Glamour v1**!
`
    
    r, _ := glamour.NewTermRenderer(
        glamour.WithAutoStyle(),
        glamour.WithColorProfile(termenv.TrueColor),
        glamour.WithWordWrap(80),
    )
    
    out, _ := r.Render(md)
    fmt.Print(out)
}

After (v2)

package main

import (
    "fmt"
    "charm.land/glamour/v2"
    "charm.land/lipgloss/v2"
)

func main() {
    md := `# Hello World

This is **Glamour v2**!
`
    
    r, _ := glamour.NewTermRenderer(
        glamour.WithStylePath("dark"),  // or omit for default
        glamour.WithWordWrap(80),
    )
    
    out, _ := r.Render(md)
    lipgloss.Print(out)  // Handles color downsampling
}

Testing Your Migration

After making changes:

  1. Run your tests — Ensure all tests pass with the new version
  2. Visual check — Render sample markdown and verify output looks correct
  3. Check wrapping — Pay special attention to text wrapping if you have CJK or emoji content (it should be better now!)
  4. Test hyperlinks — If you use autolinks, verify they render correctly

Common Issues

"cannot find package"

Make sure you've updated your go.mod:

go get charm.land/glamour/v2

And that all imports use the new path with /v2.

Colors look wrong

If colors aren't displaying correctly, make sure you're using lipgloss.Print() instead of fmt.Print():

out, _ := r.Render(markdown)
lipgloss.Print(out)  // Not fmt.Print(out)

Text wrapping issues

Glamour v2 has improved text wrapping, especially for CJK characters and emojis. If you're seeing wrapping issues, it's likely a regression. Please open an issue!

Need Help?

If you run into issues during migration:

Feedback

Migrated successfully? Having trouble? We'd love to hear about it!


Welcome to Glamour v2! 💄

Part of Charm.

<a href="https://charm.sh/"><img alt="The Charm logo" src="https://stuff.charm.sh/charm-badge.jpg" width="400"></a>

Charm热爱开源 • Charm loves open source

1# Glamour v2 Upgrade Guide
2
3This guide will help you migrate from Glamour v1 to v2. Most upgrades are straightforward and can be completed in minutes.
4
5## Update Import Paths
6
7**Required:** All imports must use the new `charm.land` module path with `/v2`:
8
9```diff
10-import "github.com/charmbracelet/glamour"
11-import "github.com/charmbracelet/glamour/ansi"
12-import "github.com/charmbracelet/glamour/styles"
13+import "charm.land/glamour/v2"
14+import "charm.land/glamour/v2/ansi"
15+import "charm.land/glamour/v2/styles"
16```
17
18## Update Dependencies
19
20```bash
21go get charm.land/glamour/v2@latest
22```
23
24If you need color downsampling (most apps do):
25
26```bash
27go get charm.land/lipgloss/v2@latest
28```
29
30## Remove Auto Style Detection
31
32**Breaking:** `WithAutoStyle()` has been removed. The default style is now `"dark"`.
33
34```diff
35-r, _ := glamour.NewTermRenderer(
36-    glamour.WithAutoStyle(),
37-)
38+r, _ := glamour.NewTermRenderer(
39+    // "dark" is the default, or specify explicitly
40+    glamour.WithStylePath("dark"),
41+)
42```
43
44If you were relying on automatic style selection based on terminal background, you'll need to choose the style explicitly:
45
46```go
47// For light backgrounds
48r, _ := glamour.NewTermRenderer(glamour.WithStylePath("light"))
49
50// For dark backgrounds (default)
51r, _ := glamour.NewTermRenderer(glamour.WithStylePath("dark"))
52
53// Other built-in styles: "pink", "dracula", "tokyo-night", "ascii"
54r, _ := glamour.NewTermRenderer(glamour.WithStylePath("dracula"))
55```
56
57Want to detect the terminal background yourself? You can use Lip Gloss:
58
59```go
60import "charm.land/lipgloss/v2"
61
62// Detect if we're on a dark background
63isDark := lipgloss.HasDarkBackground()
64
65style := "dark"
66if !isDark {
67    style = "light"
68}
69
70r, _ := glamour.NewTermRenderer(glamour.WithStylePath(style))
71```
72
73## Handle Color Downsampling Explicitly
74
75**Breaking:** `WithColorProfile()` has been removed. Use Lip Gloss for color adaptation:
76
77```diff
78-import "github.com/muesli/termenv"
79-
80-r, _ := glamour.NewTermRenderer(
81-    glamour.WithColorProfile(termenv.TrueColor),
82-)
83-out, _ := r.Render(markdown)
84-fmt.Print(out)
85+import "charm.land/lipgloss/v2"
86+
87+r, _ := glamour.NewTermRenderer(
88+    glamour.WithWordWrap(80),
89+)
90+out, _ := r.Render(markdown)
91+
92+// Lip Gloss handles color downsampling based on terminal capabilities
93+lipgloss.Print(out)
94```
95
96Why the change? Glamour is now pure — it always produces the same output for the same input. This makes it more predictable and testable. Lip Gloss handles the terminal-specific color adaptation when you're ready to display the output.
97
98If you don't need color adaptation (e.g., you know you're always outputting TrueColor):
99
100```go
101r, _ := glamour.NewTermRenderer(glamour.WithWordWrap(80))
102out, _ := r.Render(markdown)
103fmt.Print(out)  // Direct output, no downsampling
104```
105
106## Remove Overline Styles
107
108**Breaking:** The `Overlined` field has been removed from style configurations.
109
110If you have custom styles using `Overlined`:
111
112```diff
113 StylePrimitive: ansi.StylePrimitive{
114     Bold:      &trueBool,
115     Underline: &trueBool,
116-    Overlined: &trueBool,
117 }
118```
119
120Overline was rarely supported across terminals and not widely used. If you need similar visual separation, consider alternatives like underline, bold, inverse, or background colors.
121
122## Update Custom Style Definitions
123
124If you maintain custom `StyleConfig` definitions, update the import paths:
125
126```diff
127-import "github.com/charmbracelet/glamour/ansi"
128+import "charm.land/glamour/v2/ansi"
129
130 var myStyle = &ansi.StyleConfig{
131     // Your custom style definition
132     Document: ansi.StyleBlock{
133         StylePrimitive: ansi.StylePrimitive{
134             Color: stringPtr("#E6DB74"),
135         },
136     },
137 }
138```
139
140The structure is the same; only the import path changes.
141
142## Verify Custom Writers (Advanced)
143
144If you implemented custom margin or padding writers using `ansi.MarginWriter`:
145
1461. Ensure you call `.Close()` on all writer instances
1472. The new `IndentWriter` and `PaddingWriter` types are available for custom use
148
149```go
150import "charm.land/glamour/v2/ansi"
151
152mw := ansi.NewMarginWriter(ctx, w, style)
153defer mw.Close()  // Important: always close writers now
154
155// Write your content
156io.WriteString(mw, content)
157```
158
159This improves memory management and prevents resource leaks.
160
161## Example Migration
162
163Here's a complete before/after example:
164
165### Before (v1)
166
167```go
168package main
169
170import (
171    "fmt"
172    "github.com/charmbracelet/glamour"
173    "github.com/muesli/termenv"
174)
175
176func main() {
177    md := `# Hello World
178
179This is **Glamour v1**!
180`
181    
182    r, _ := glamour.NewTermRenderer(
183        glamour.WithAutoStyle(),
184        glamour.WithColorProfile(termenv.TrueColor),
185        glamour.WithWordWrap(80),
186    )
187    
188    out, _ := r.Render(md)
189    fmt.Print(out)
190}
191```
192
193### After (v2)
194
195```go
196package main
197
198import (
199    "fmt"
200    "charm.land/glamour/v2"
201    "charm.land/lipgloss/v2"
202)
203
204func main() {
205    md := `# Hello World
206
207This is **Glamour v2**!
208`
209    
210    r, _ := glamour.NewTermRenderer(
211        glamour.WithStylePath("dark"),  // or omit for default
212        glamour.WithWordWrap(80),
213    )
214    
215    out, _ := r.Render(md)
216    lipgloss.Print(out)  // Handles color downsampling
217}
218```
219
220## Testing Your Migration
221
222After making changes:
223
2241. **Run your tests** — Ensure all tests pass with the new version
2252. **Visual check** — Render sample markdown and verify output looks correct
2263. **Check wrapping** — Pay special attention to text wrapping if you have CJK or emoji content (it should be better now!)
2274. **Test hyperlinks** — If you use autolinks, verify they render correctly
228
229## Common Issues
230
231### "cannot find package"
232
233Make sure you've updated your `go.mod`:
234
235```bash
236go get charm.land/glamour/v2
237```
238
239And that all imports use the new path with `/v2`.
240
241### Colors look wrong
242
243If colors aren't displaying correctly, make sure you're using `lipgloss.Print()` instead of `fmt.Print()`:
244
245```go
246out, _ := r.Render(markdown)
247lipgloss.Print(out)  // Not fmt.Print(out)
248```
249
250### Text wrapping issues
251
252Glamour v2 has improved text wrapping, especially for CJK characters and emojis. If you're seeing wrapping issues, it's likely a regression. Please [open an issue](https://github.com/charmbracelet/glamour/issues)!
253
254## Need Help?
255
256If you run into issues during migration:
257
258- Check the [examples directory](https://github.com/charmbracelet/glamour/tree/main/examples) for working code
259- Review [What's New](WHATS_NEW.md) for detailed feature changes
260- Join us on [Discord](https://charm.sh/chat)
261- Open an issue on [GitHub](https://github.com/charmbracelet/glamour/issues)
262
263## Feedback
264
265Migrated successfully? Having trouble? We'd love to hear about it!
266
267- [Discord](https://charm.sh/chat)
268- [The Fediverse](https://mastodon.social/@charmcli)
269- [Twitter](https://twitter.com/charmcli)
270
271---
272
273Welcome to Glamour v2! 💄
274
275Part of [Charm](https://charm.sh).
276
277<a href="https://charm.sh/"><img alt="The Charm logo" src="https://stuff.charm.sh/charm-badge.jpg" width="400"></a>
278
279Charm热爱开源 • Charm loves open source