okami.mom/glamour
git clone https://git.nkp.pet/okami.mom/glamour
c293649
main
1package ansi 2 3import ( 4"fmt" 5"io" 6"sync" 7 8"github.com/alecthomas/chroma/v2" 9"github.com/alecthomas/chroma/v2/quick" 10"github.com/alecthomas/chroma/v2/styles" 11) 12 13const ( 14// The chroma style theme name used for rendering. 15chromaStyleTheme = "charm" 16 17// The chroma formatter name used for rendering. 18chromaFormatter = "terminal256" 19) 20 21// mutex for synchronizing access to the chroma style registry. 22// Related https://github.com/alecthomas/chroma/pull/650 23var mutex = sync.Mutex {} 24 25// A CodeBlockElement is used to render code blocks. 26type CodeBlockElement struct { 27Code string 28Language string 29} 30 31func chromaStyle (style StylePrimitive )string { 32var s string 33 34if style .Color != nil { 35s = * style .Color 36 } 37if style .BackgroundColor != nil { 38if s != "" { 39s += " " 40 } 41s += "bg:" + * style .BackgroundColor 42 } 43if style .Italic != nil && * style .Italic { 44if s != "" { 45s += " " 46 } 47s += "italic" 48 } 49if style .Bold != nil && * style .Bold { 50if s != "" { 51s += " " 52 } 53s += "bold" 54 } 55if style .Underline != nil && * style .Underline { 56if s != "" { 57s += " " 58 } 59s += "underline" 60 } 61 62return s 63} 64 65// Render renders a CodeBlockElement. 66func (e * CodeBlockElement )Render (w io.Writer ,ctx RenderContext )error { 67bs := ctx .blockStack 68 69var indentation uint 70var margin uint 71formatter := chromaFormatter 72rules := ctx .options .Styles .CodeBlock 73if rules .Indent != nil { 74indentation = * rules .Indent 75 } 76if rules .Margin != nil { 77margin = * rules .Margin 78 } 79if len (ctx .options .ChromaFormatter )> 0 { 80formatter = ctx .options .ChromaFormatter 81 } 82theme := rules .Theme 83 84if rules .Chroma != nil { 85theme = chromaStyleTheme 86mutex .Lock () 87// Don't register the style if it's already registered. 88_ ,ok := styles .Registry [theme ] 89if ! ok { 90styles .Register (chroma .MustNewStyle (theme , 91 chroma.StyleEntries { 92chroma .Text :chromaStyle (rules .Chroma .Text ), 93chroma .Error :chromaStyle (rules .Chroma .Error ), 94chroma .Comment :chromaStyle (rules .Chroma .Comment ), 95chroma .CommentPreproc :chromaStyle (rules .Chroma .CommentPreproc ), 96chroma .Keyword :chromaStyle (rules .Chroma .Keyword ), 97chroma .KeywordReserved :chromaStyle (rules .Chroma .KeywordReserved ), 98chroma .KeywordNamespace :chromaStyle (rules .Chroma .KeywordNamespace ), 99chroma .KeywordType :chromaStyle (rules .Chroma .KeywordType ), 100chroma .Operator :chromaStyle (rules .Chroma .Operator ), 101chroma .Punctuation :chromaStyle (rules .Chroma .Punctuation ), 102chroma .Name :chromaStyle (rules .Chroma .Name ), 103chroma .NameBuiltin :chromaStyle (rules .Chroma .NameBuiltin ), 104chroma .NameTag :chromaStyle (rules .Chroma .NameTag ), 105chroma .NameAttribute :chromaStyle (rules .Chroma .NameAttribute ), 106chroma .NameClass :chromaStyle (rules .Chroma .NameClass ), 107chroma .NameConstant :chromaStyle (rules .Chroma .NameConstant ), 108chroma .NameDecorator :chromaStyle (rules .Chroma .NameDecorator ), 109chroma .NameException :chromaStyle (rules .Chroma .NameException ), 110chroma .NameFunction :chromaStyle (rules .Chroma .NameFunction ), 111chroma .NameOther :chromaStyle (rules .Chroma .NameOther ), 112chroma .Literal :chromaStyle (rules .Chroma .Literal ), 113chroma .LiteralNumber :chromaStyle (rules .Chroma .LiteralNumber ), 114chroma .LiteralDate :chromaStyle (rules .Chroma .LiteralDate ), 115chroma .LiteralString :chromaStyle (rules .Chroma .LiteralString ), 116chroma .LiteralStringEscape :chromaStyle (rules .Chroma .LiteralStringEscape ), 117chroma .GenericDeleted :chromaStyle (rules .Chroma .GenericDeleted ), 118chroma .GenericEmph :chromaStyle (rules .Chroma .GenericEmph ), 119chroma .GenericInserted :chromaStyle (rules .Chroma .GenericInserted ), 120chroma .GenericStrong :chromaStyle (rules .Chroma .GenericStrong ), 121chroma .GenericSubheading :chromaStyle (rules .Chroma .GenericSubheading ), 122chroma .Background :chromaStyle (rules .Chroma .Background ), 123 })) 124 } 125mutex .Unlock () 126 } 127 128iw := NewIndentWriter (w ,int (indentation + margin ),func (_ io.Writer ) { 129_ ,_ = renderText (w ,bs .Current ().Style .StylePrimitive ," " ) 130 }) 131defer iw .Close ()//nolint:errcheck 132 133if len (theme )> 0 { 134_ ,_ = renderText (iw ,bs .Current ().Style .StylePrimitive ,rules .BlockPrefix ) 135 136err := quick .Highlight (iw ,e .Code ,e .Language ,formatter ,theme ) 137if err != nil { 138return fmt .Errorf ("glamour: error highlighting code: %w" ,err ) 139 } 140_ ,_ = renderText (iw ,bs .Current ().Style .StylePrimitive ,rules .BlockSuffix ) 141return nil 142 } 143 144// fallback rendering 145el := & BaseElement { 146Token :e .Code , 147Style :rules .StylePrimitive , 148 } 149 150return el .Render (iw ,ctx ) 151}