From 8d4e3f0692f80267a1896eb53455c024865c729b Mon Sep 17 00:00:00 2001 From: Christian Muehlhaeuser Date: Mon, 10 Feb 2020 13:53:56 +0100 Subject: [PATCH] Use TrueColor color profile as default Users can override the desired profile by calling WithColorProfile. --- ansi/baseelement.go | 14 +++++++------- ansi/blockelement.go | 8 ++++---- ansi/codeblock.go | 6 +++--- ansi/context.go | 13 +++++-------- ansi/heading.go | 12 ++++++------ ansi/margin.go | 4 ++-- ansi/paragraph.go | 8 ++++---- ansi/renderer.go | 8 +++++--- ansi/renderer_test.go | 7 +++++-- ansi/stylewriter.go | 2 +- ansi/table.go | 10 +++++----- glamour.go | 13 ++++++++++++- 12 files changed, 59 insertions(+), 46 deletions(-) diff --git a/ansi/baseelement.go b/ansi/baseelement.go index 470eb7b..c4a388e 100644 --- a/ansi/baseelement.go +++ b/ansi/baseelement.go @@ -73,22 +73,22 @@ func renderText(w io.Writer, p termenv.Profile, rules StylePrimitive, s string) func (e *BaseElement) Render(w io.Writer, ctx RenderContext) error { bs := ctx.blockStack - renderText(w, ctx.colorProfile, bs.Current().Style.StylePrimitive, e.Prefix) + renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, e.Prefix) defer func() { - renderText(w, ctx.colorProfile, bs.Current().Style.StylePrimitive, e.Suffix) + renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, e.Suffix) }() rules := bs.With(e.Style) // render unstyled prefix/suffix - renderText(w, ctx.colorProfile, bs.Current().Style.StylePrimitive, rules.BlockPrefix) + renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.BlockPrefix) defer func() { - renderText(w, ctx.colorProfile, bs.Current().Style.StylePrimitive, rules.BlockSuffix) + renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.BlockSuffix) }() // render styled prefix/suffix - renderText(w, ctx.colorProfile, rules, rules.Prefix) + renderText(w, ctx.options.ColorProfile, rules, rules.Prefix) defer func() { - renderText(w, ctx.colorProfile, rules, rules.Suffix) + renderText(w, ctx.options.ColorProfile, rules, rules.Suffix) }() s := e.Token @@ -99,6 +99,6 @@ func (e *BaseElement) Render(w io.Writer, ctx RenderContext) error { return err } } - renderText(w, ctx.colorProfile, rules, s) + renderText(w, ctx.options.ColorProfile, rules, s) return nil } diff --git a/ansi/blockelement.go b/ansi/blockelement.go index 5809ca1..893f9e5 100644 --- a/ansi/blockelement.go +++ b/ansi/blockelement.go @@ -21,8 +21,8 @@ func (e *BlockElement) Render(w io.Writer, ctx RenderContext) error { bs := ctx.blockStack bs.Push(*e) - renderText(w, ctx.colorProfile, bs.Parent().Style.StylePrimitive, e.Style.BlockPrefix) - renderText(bs.Current().Block, ctx.colorProfile, bs.Current().Style.StylePrimitive, e.Style.Prefix) + renderText(w, ctx.options.ColorProfile, bs.Parent().Style.StylePrimitive, e.Style.BlockPrefix) + renderText(bs.Current().Block, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, e.Style.Prefix) return nil } @@ -50,8 +50,8 @@ func (e *BlockElement) Finish(w io.Writer, ctx RenderContext) error { } } - renderText(w, ctx.colorProfile, bs.Current().Style.StylePrimitive, e.Style.Suffix) - renderText(w, ctx.colorProfile, bs.Parent().Style.StylePrimitive, e.Style.BlockSuffix) + renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, e.Style.Suffix) + renderText(w, ctx.options.ColorProfile, bs.Parent().Style.StylePrimitive, e.Style.BlockSuffix) bs.Current().Block.Reset() bs.Pop() diff --git a/ansi/codeblock.go b/ansi/codeblock.go index 907893a..72d8615 100644 --- a/ansi/codeblock.go +++ b/ansi/codeblock.go @@ -102,16 +102,16 @@ func (e *CodeBlockElement) Render(w io.Writer, ctx RenderContext) error { } iw := indent.NewWriterPipe(w, indentation+margin, func(wr io.Writer) { - renderText(w, ctx.colorProfile, bs.Current().Style.StylePrimitive, " ") + renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, " ") }) if len(theme) > 0 { - renderText(iw, ctx.colorProfile, bs.Current().Style.StylePrimitive, rules.BlockPrefix) + renderText(iw, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.BlockPrefix) err := quick.Highlight(iw, e.Code, e.Language, "terminal256", theme) if err != nil { return err } - renderText(iw, ctx.colorProfile, bs.Current().Style.StylePrimitive, rules.BlockSuffix) + renderText(iw, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.BlockSuffix) return nil } diff --git a/ansi/context.go b/ansi/context.go index 3b6c197..ee3c2eb 100644 --- a/ansi/context.go +++ b/ansi/context.go @@ -5,7 +5,6 @@ import ( "strings" "github.com/microcosm-cc/bluemonday" - "github.com/muesli/termenv" ) // RenderContext holds the current rendering options and state. @@ -15,18 +14,16 @@ type RenderContext struct { blockStack *BlockStack table *TableElement - stripper *bluemonday.Policy - colorProfile termenv.Profile + stripper *bluemonday.Policy } // NewRenderContext returns a new RenderContext. func NewRenderContext(options Options) RenderContext { return RenderContext{ - options: options, - blockStack: &BlockStack{}, - table: &TableElement{}, - stripper: bluemonday.StrictPolicy(), - colorProfile: termenv.ColorProfile(), + options: options, + blockStack: &BlockStack{}, + table: &TableElement{}, + stripper: bluemonday.StrictPolicy(), } } diff --git a/ansi/heading.go b/ansi/heading.go index fc83a7b..e7ff939 100644 --- a/ansi/heading.go +++ b/ansi/heading.go @@ -34,7 +34,7 @@ func (e *HeadingElement) Render(w io.Writer, ctx RenderContext) error { } if !e.First { - renderText(w, ctx.colorProfile, bs.Current().Style.StylePrimitive, "\n") + renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, "\n") } be := BlockElement{ @@ -43,8 +43,8 @@ func (e *HeadingElement) Render(w io.Writer, ctx RenderContext) error { } bs.Push(be) - renderText(w, ctx.colorProfile, bs.Parent().Style.StylePrimitive, rules.BlockPrefix) - renderText(bs.Current().Block, ctx.colorProfile, bs.Current().Style.StylePrimitive, rules.Prefix) + renderText(w, ctx.options.ColorProfile, bs.Parent().Style.StylePrimitive, rules.BlockPrefix) + renderText(bs.Current().Block, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.Prefix) return nil } @@ -62,7 +62,7 @@ func (e *HeadingElement) Finish(w io.Writer, ctx RenderContext) error { } iw := indent.NewWriterPipe(w, indentation+margin, func(wr io.Writer) { - renderText(w, ctx.colorProfile, bs.Parent().Style.StylePrimitive, " ") + renderText(w, ctx.options.ColorProfile, bs.Parent().Style.StylePrimitive, " ") }) flow := wordwrap.NewWriter(int(bs.Width(ctx) - indentation - margin*2)) @@ -77,8 +77,8 @@ func (e *HeadingElement) Finish(w io.Writer, ctx RenderContext) error { return err } - renderText(w, ctx.colorProfile, bs.Current().Style.StylePrimitive, rules.Suffix) - renderText(w, ctx.colorProfile, bs.Parent().Style.StylePrimitive, rules.BlockSuffix) + renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.Suffix) + renderText(w, ctx.options.ColorProfile, bs.Parent().Style.StylePrimitive, rules.BlockSuffix) bs.Current().Block.Reset() bs.Pop() diff --git a/ansi/margin.go b/ansi/margin.go index 17519cf..e039783 100644 --- a/ansi/margin.go +++ b/ansi/margin.go @@ -29,7 +29,7 @@ func NewMarginWriter(ctx RenderContext, w io.Writer, rules StyleBlock) *MarginWr } pw := padding.NewWriterPipe(w, bs.Width(ctx), func(wr io.Writer) { - renderText(w, ctx.colorProfile, rules.StylePrimitive, " ") + renderText(w, ctx.options.ColorProfile, rules.StylePrimitive, " ") }) ic := " " @@ -37,7 +37,7 @@ func NewMarginWriter(ctx RenderContext, w io.Writer, rules StyleBlock) *MarginWr ic = *rules.IndentToken } iw := indent.NewWriterPipe(pw, indentation+margin, func(wr io.Writer) { - renderText(w, ctx.colorProfile, bs.Parent().Style.StylePrimitive, ic) + renderText(w, ctx.options.ColorProfile, bs.Parent().Style.StylePrimitive, ic) }) return &MarginWriter{ diff --git a/ansi/paragraph.go b/ansi/paragraph.go index 2c34a04..71e0725 100644 --- a/ansi/paragraph.go +++ b/ansi/paragraph.go @@ -26,8 +26,8 @@ func (e *ParagraphElement) Render(w io.Writer, ctx RenderContext) error { } bs.Push(be) - renderText(w, ctx.colorProfile, bs.Parent().Style.StylePrimitive, rules.BlockPrefix) - renderText(bs.Current().Block, ctx.colorProfile, bs.Current().Style.StylePrimitive, rules.Prefix) + renderText(w, ctx.options.ColorProfile, bs.Parent().Style.StylePrimitive, rules.BlockPrefix) + renderText(bs.Current().Block, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.Prefix) return nil } @@ -49,8 +49,8 @@ func (e *ParagraphElement) Finish(w io.Writer, ctx RenderContext) error { _, _ = mw.Write([]byte("\n")) } - renderText(w, ctx.colorProfile, bs.Current().Style.StylePrimitive, rules.Suffix) - renderText(w, ctx.colorProfile, bs.Parent().Style.StylePrimitive, rules.BlockSuffix) + renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.Suffix) + renderText(w, ctx.options.ColorProfile, bs.Parent().Style.StylePrimitive, rules.BlockSuffix) bs.Current().Block.Reset() bs.Pop() diff --git a/ansi/renderer.go b/ansi/renderer.go index ea4576d..3604914 100644 --- a/ansi/renderer.go +++ b/ansi/renderer.go @@ -5,6 +5,7 @@ import ( "net/url" "strings" + "github.com/muesli/termenv" "github.com/yuin/goldmark/ast" astext "github.com/yuin/goldmark/extension/ast" "github.com/yuin/goldmark/renderer" @@ -13,9 +14,10 @@ import ( // Options is used to configure an ANSIRenderer. type Options struct { - BaseURL string - WordWrap int - Styles StyleConfig + BaseURL string + WordWrap int + ColorProfile termenv.Profile + Styles StyleConfig } // ANSIRenderer renders markdown content as ANSI escaped sequences. diff --git a/ansi/renderer_test.go b/ansi/renderer_test.go index 39adcb8..8cf8eab 100644 --- a/ansi/renderer_test.go +++ b/ansi/renderer_test.go @@ -8,6 +8,7 @@ import ( "strings" "testing" + "github.com/muesli/termenv" "github.com/yuin/goldmark" "github.com/yuin/goldmark/extension" "github.com/yuin/goldmark/parser" @@ -43,7 +44,8 @@ func TestRenderer(t *testing.T) { } options := Options{ - WordWrap: 80, + WordWrap: 80, + ColorProfile: termenv.TrueColor, } err = json.Unmarshal(b, &options.Styles) if err != nil { @@ -113,7 +115,8 @@ func TestRendererIssues(t *testing.T) { } options := Options{ - WordWrap: 80, + WordWrap: 80, + ColorProfile: termenv.TrueColor, } err = json.Unmarshal(b, &options.Styles) if err != nil { diff --git a/ansi/stylewriter.go b/ansi/stylewriter.go index 69a934c..28c01e0 100644 --- a/ansi/stylewriter.go +++ b/ansi/stylewriter.go @@ -28,6 +28,6 @@ func (w *StyleWriter) Write(b []byte) (int, error) { // Close must be called when you're finished writing to a StyleWriter. func (w *StyleWriter) Close() error { - renderText(w.w, w.ctx.colorProfile, w.rules, w.buf.String()) + renderText(w.w, w.ctx.options.ColorProfile, w.rules, w.buf.String()) return nil } diff --git a/ansi/table.go b/ansi/table.go index 6b83842..9432f00 100644 --- a/ansi/table.go +++ b/ansi/table.go @@ -43,14 +43,14 @@ func (e *TableElement) Render(w io.Writer, ctx RenderContext) error { } iw := indent.NewWriterPipe(w, indentation+margin, func(wr io.Writer) { - renderText(w, ctx.colorProfile, bs.Current().Style.StylePrimitive, " ") + renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, " ") }) style := bs.With(rules.StylePrimitive) ctx.table.styleWriter = NewStyleWriter(ctx, iw, style) - renderText(w, ctx.colorProfile, bs.Current().Style.StylePrimitive, rules.BlockPrefix) - renderText(ctx.table.styleWriter, ctx.colorProfile, style, rules.Prefix) + renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.BlockPrefix) + renderText(ctx.table.styleWriter, ctx.options.ColorProfile, style, rules.Prefix) ctx.table.writer = tablewriter.NewWriter(ctx.table.styleWriter) return nil } @@ -72,8 +72,8 @@ func (e *TableElement) Finish(w io.Writer, ctx RenderContext) error { ctx.table.writer.Render() ctx.table.writer = nil - renderText(ctx.table.styleWriter, ctx.colorProfile, ctx.blockStack.With(rules.StylePrimitive), rules.Suffix) - renderText(ctx.table.styleWriter, ctx.colorProfile, ctx.blockStack.Current().Style.StylePrimitive, rules.BlockSuffix) + renderText(ctx.table.styleWriter, ctx.options.ColorProfile, ctx.blockStack.With(rules.StylePrimitive), rules.Suffix) + renderText(ctx.table.styleWriter, ctx.options.ColorProfile, ctx.blockStack.Current().Style.StylePrimitive, rules.BlockSuffix) return ctx.table.styleWriter.Close() } diff --git a/glamour.go b/glamour.go index 376278d..d151aa5 100644 --- a/glamour.go +++ b/glamour.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "os" + "github.com/muesli/termenv" "github.com/yuin/goldmark" "github.com/yuin/goldmark/extension" "github.com/yuin/goldmark/parser" @@ -60,7 +61,8 @@ func NewTermRenderer(options ...TermRendererOption) (*TermRenderer, error) { ), ), ansiOptions: ansi.Options{ - WordWrap: 80, + WordWrap: 80, + ColorProfile: termenv.TrueColor, }, } for _, o := range options { @@ -87,6 +89,15 @@ func WithBaseURL(baseURL string) TermRendererOption { } } +// WithColorProfile sets the TermRenderer's color profile +// (TrueColor / ANSI256 / ANSI). +func WithColorProfile(profile termenv.Profile) TermRendererOption { + return func(tr *TermRenderer) error { + tr.ansiOptions.ColorProfile = profile + return nil + } +} + // WithStandardStyle sets a TermRenderer's styles with a standard (builtin) // style. func WithStandardStyle(style string) TermRendererOption {