diff --git a/formatters/html/html.go b/formatters/html/html.go index d963b28..2a921ab 100644 --- a/formatters/html/html.go +++ b/formatters/html/html.go @@ -99,34 +99,10 @@ func (f *Formatter) Format(w io.Writer, style *chroma.Style, iterator chroma.Ite return f.writeHTML(w, style, iterator.Tokens()) } -// Ensure that style entries exist for highlighting, etc. -func (f *Formatter) restyle(style *chroma.Style) (*chroma.Style, error) { - builder := style.Builder() - bg := builder.Get(chroma.Background) - // If we don't have a line highlight colour, make one that is 10% brighter/darker than the background. - if !style.Has(chroma.LineHighlight) { - highlight := chroma.StyleEntry{Background: bg.Background} - highlight.Background = highlight.Background.BrightenOrDarken(0.1) - builder.AddEntry(chroma.LineHighlight, highlight) - } - // If we don't have line numbers, use the text colour but 20% brighter/darker - if !style.Has(chroma.LineNumbers) { - text := chroma.StyleEntry{Colour: bg.Colour} - text.Colour = text.Colour.BrightenOrDarken(0.5) - builder.AddEntry(chroma.LineNumbers, text) - builder.AddEntry(chroma.LineNumbersTable, text) - } - return builder.Build() -} - // We deliberately don't use html/template here because it is two orders of magnitude slower (benchmarked). // // OTOH we need to be super careful about correct escaping... func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.Token) (err error) { // nolint: gocyclo - style, err = f.restyle(style) - if err != nil { - return err - } css := f.styleToCSS(style) if !f.Classes { for t, style := range css { diff --git a/style.go b/style.go index c768293..a638f6a 100644 --- a/style.go +++ b/style.go @@ -247,15 +247,7 @@ func (s *Style) Builder() *StyleBuilder { // // This is distinct from Get() which will merge parent tokens. func (s *Style) Has(ttype TokenType) bool { - return !s.get(ttype).IsZero() -} - -func (s *Style) get(ttype TokenType) StyleEntry { - out := s.entries[ttype] - if out.IsZero() && s.parent != nil { - return s.parent.get(ttype) - } - return out + return !s.get(ttype).IsZero() || s.synthesisable(ttype) } // Get a style entry. Will try sub-category or category if an exact match is not found, and @@ -268,6 +260,38 @@ func (s *Style) Get(ttype TokenType) StyleEntry { s.get(ttype.SubCategory())) } +func (s *Style) get(ttype TokenType) StyleEntry { + out := s.entries[ttype] + if out.IsZero() && s.synthesisable(ttype) { + out = s.synthesise(ttype) + } + if out.IsZero() && s.parent != nil { + return s.parent.get(ttype) + } + return out +} + +func (s *Style) synthesise(ttype TokenType) StyleEntry { + bg := s.get(Background) + text := StyleEntry{Colour: bg.Colour} + text.Colour = text.Colour.BrightenOrDarken(0.5) + + switch ttype { + // If we don't have a line highlight colour, make one that is 10% brighter/darker than the background. + case LineHighlight: + return StyleEntry{Background: bg.Background.BrightenOrDarken(0.1)} + + // If we don't have line numbers, use the text colour but 20% brighter/darker + case LineNumbers, LineNumbersTable: + return text + } + return StyleEntry{} +} + +func (s *Style) synthesisable(ttype TokenType) bool { + return ttype == LineHighlight || ttype == LineNumbers || ttype == LineNumbersTable +} + // ParseStyleEntry parses a Pygments style entry. func ParseStyleEntry(entry string) (StyleEntry, error) { // nolint: gocyclo out := StyleEntry{} diff --git a/style_test.go b/style_test.go index f3b5f60..fca55b4 100644 --- a/style_test.go +++ b/style_test.go @@ -35,3 +35,16 @@ func TestStyleClone(t *testing.T) { assert.Equal(t, "#00ff00 bg:#ffffff", clone.Get(Comment).String()) assert.Equal(t, "bg:#ffffff", parent.Get(Comment).String()) } + +func TestSynthesisedStyleEntries(t *testing.T) { + style, err := NewStyle("test", StyleEntries{ + Background: "bg:#ffffff", + }) + assert.NoError(t, err) + assert.True(t, style.Has(LineHighlight)) + assert.True(t, style.Has(LineNumbersTable)) + assert.True(t, style.Has(LineNumbers)) + assert.Equal(t, "bg:#e5e5e5", style.Get(LineHighlight).String()) + assert.Equal(t, "#7f7f7f bg:#ffffff", style.Get(LineNumbers).String()) + assert.Equal(t, "#7f7f7f bg:#ffffff", style.Get(LineNumbersTable).String()) +}