Glamour

repository·main·Indexed 25 days ago

https://github.com/charmbracelet/glamour

A stylesheet-based markdown renderer for CLI applications that converts markdown documents into ANSI-compatible terminal output. It supports customizable styles, built-in themes like Dark, Light, Dracula, and Tokyo Night, and integrates with Lip Gloss for color downsampling and Chroma for code block syntax highlighting.

Tokens
3.2K
Snippets
6
Records
17
Agent score
86%

What's inside glamour

  1. Migrate from Glamour v1 to v2

    main

    To upgrade to Glamour v2, you must update your import paths, dependencies, and handle several breaking changes regarding style detection and color downsampling.

    1. Update Import Paths

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

    • charm.land/glamour/v2
    • charm.land/glamour/v2/ansi
    • charm.land/glamour/v2/styles

    2. Update Dependencies

    Run the following commands to update your project:

    go get charm.land/glamour/v2@latest

    If you require color downsampling (recommended for most apps), also install Lip Gloss v2:

    go get charm.land/lipgloss/v2@latest

    3. Handle Style Selection

    WithAutoStyle() has been removed. The default style is now "dark". To specify a style, use WithStylePath(path). Built-in styles include "pink", "dracula", "tokyo-night", and "ascii".

    To detect the terminal background manually and select a style, use lipgloss.HasDarkBackground():

    import "charm.land/lipgloss/v2"
    
    isDark := lipgloss.HasDarkBackground()
    style := "dark"
    if !isDark {
        style = "light"
    }
    r, _ := glamour.NewTermRenderer(glamour.WithStylePath(style))

    4. Handle Color Downsampling

    WithColorProfile() has been removed. Glamour v2 is now pure and always produces the same output for the same input. To handle terminal-specific color adaptation (downsampling), use lipgloss.Print() instead of fmt.Print().

    import "charm.land/lipgloss/v2"
    
    r, _ := glamour.NewTermRenderer(glamour.WithWordWrap(80))
    out, _ := r.Render(markdown)
    
    // Use lipgloss.Print to handle color adaptation
    lipgloss.Print(out)

    5. Remove Overline Styles

    The Overlined field has been removed from ansi.StylePrimitive. If you have custom styles, remove this field and use alternatives like Underline, Bold, or background colors.

    6. Verify Custom Writers

    If you use ansi.MarginWriter, you must now call .Close() on all writer instances to prevent resource leaks.

    import "charm.land/glamour/v2/ansi"
    
    mw := ansi.NewMarginWriter(ctx, w, style)
    defer mw.Close()
    package main
    
    import (
        "charm.land/glamour/v2"
        "charm.land/lipgloss/v2"
    )
    
    func main() {
        md := `# Hello World
    
    This is **Glamour v2**!
    `
        
        r, _ := glamour.NewTermRenderer(
            glamour.WithStylePath("dark"),
            glamour.WithWordWrap(80),
        )
        
        out, _ := r.Render(md)
        lipgloss.Print(out)
    }
  2. Perform color downsampling with Lip Gloss

    main

    Glamour is designed to be pure and does not automatically detect terminal color capabilities. To ensure colors are downsampled correctly for the user's terminal, pass the rendered output through lipgloss.Print.

    import (
        "charm.land/glamour/v2"
        "charm.land/lipgloss/v2"
    )
    
    r, _ := glamour.NewTermRenderer(
        // wrap output at specific width (default is 80)
        glamour.WithWordWrap(40),
    )
    
    out, err := r.Render(in)
    if err != nil {
        // handle error
    }
    
    // downsample colors based on terminal capabilities.
    lipgloss.Print(out)
  3. Configure styles via environment variables

    main

    You can control which stylesheet is used by setting the GLAMOUR_STYLE environment variable. This variable can point to a built-in style name or a file location for a custom style.

    Ways to apply this:

    1. Use glamour.Render(inputText, "desiredStyle") for direct style selection.
    2. Use glamour.RenderWithEnvironmentConfig(inputText) to respect the GLAMOUR_STYLE environment variable.
    3. Pass glamour.WithEnvironmentConfig() to a custom renderer created via glamour.NewTermRenderer to respect the GLAMOUR_STYLE environment variable.
  4. Configure Task List Styles

    main

    The task element allows you to customize the prefixes used for finished and unfinished tasks in Markdown.

    AttributeValueDescription
    tickedstringPrefix for finished tasks
    untickedstringPrefix for unfinished tasks
    "task": {
        "ticked": "✓ ",
        "unticked": "✗ "
    }
  5. Troubleshoot Glamour v2 Migration Issues

    main

    "cannot find package"

    Ensure you have updated your go.mod and that all imports use the new path with /v2:

    go get charm.land/glamour/v2

    "Colors look wrong"

    If colors are not displaying correctly, ensure you are using lipgloss.Print() instead of fmt.Print() to handle color downsampling:

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

    "Text wrapping issues"

    Glamour v2 includes improved text wrapping for CJK characters and emojis. If you encounter wrapping regressions, please open an issue on GitHub.

  6. Render Markdown with a default style

    main

    Use glamour.Render to quickly render markdown text using one of the built-in styles (e.g., "dark"). This is the simplest way to get ANSI-compatible markdown output.

    import "charm.land/glamour/v2"
    
    in := `# Hello World
    
    This is a simple example of Markdown rendering with Glamour!
    Check out the [other examples](https://github.com/charmbracelet/glamour/tree/main/examples) too.
    
    Bye!
    `
    
    out, err := glamour.Render(in, "dark")
    fmt.Print(out)
  7. Create a custom TermRenderer

    main

    For more control, use glamour.NewTermRenderer to create a renderer instance. This allows you to pass configuration options like glamour.WithWordWrap to control output behavior, such as the line wrap width.

    import "charm.land/glamour/v2"
    
    r, _ := glamour.NewTermRenderer(
        // wrap output at specific width (default is 80)
        glamour.WithWordWrap(40),
    )
    
    out, err := r.Render(in)
    fmt.Print(out)
  8. Configure Block Element Styles

    main

    Block elements (like document, paragraph, heading, block_quote, list, code_block, and table) wrap other elements. They support the following style attributes:

    AttributeValueDescription
    block_prefixstringPrinted before the block's first element (in parent's style)
    block_suffixstringPrinted after the block's last element (in parent's style)
    prefixstringPrinted before the block's first element
    suffixstringPrinted after the block's last element
    indentnumberSpecifies the indentation of the block
    indent_tokenstringSpecifies the indentation format
    marginnumberSpecifies the margin around the block
    colorcolorDefines the default text color for the block
    background_colorcolorDefines the default background color for the block

    Elements inside a block inherit the following settings from the parent block:

    AttributeValueDescription
    colorcolorDefines the default text color
    background_colorcolorDefines the default background color
    boldboolIncreases text intensity
    faintboolDecreases text intensity
    italicboolPrints the text in italic
    crossed_outboolEnables strikethrough
    underlineboolEnables underline
    overlinedboolEnables overline
    blinkboolEnables blinking text
    concealboolConceals / hides the text
    inverseboolSwaps fore- & background colors
  9. Configure Inline Element Styles

    main

    Inline elements (like text, link, code, emph, strong, etc.) support the following style attributes:

    AttributeValueDescription
    block_prefixstringPrinted before the element (in parent's style)
    block_suffixstringPrinted after the element (in parent's style)
    prefixstringPrinted before the element
    suffixstringPrinted after the element
    colorcolorDefines the default text color
    background_colorcolorDefines the default background color
    boldboolIncreases text intensity
    faintboolDecreases text intensity
    italicboolPrints the text in italic
    crossed_outboolEnables strikethrough
    underlineboolEnables underline
    overlinedboolEnables overline
    blinkboolEnables blinking text
    concealboolConceals / hides the text
    inverseboolSwaps fore- & background colors