From cc53faa932437033e6475ff4a248dd8ccf532375 Mon Sep 17 00:00:00 2001
From: Alec Thomas <alec@swapoff.org>
Date: Mon, 13 Apr 2020 07:36:37 +1000
Subject: [PATCH] Add option to preserve all HTML classes.

Fixes #346.
---
 cmd/chroma/main.go      | 8 +++++++-
 formatters/html/html.go | 6 +++++-
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/cmd/chroma/main.go b/cmd/chroma/main.go
index 8bea178..038f8e3 100644
--- a/cmd/chroma/main.go
+++ b/cmd/chroma/main.go
@@ -53,6 +53,7 @@ command, for Go.
 		HTML                      bool   `help:"Enable HTML mode (equivalent to '--formatter html')."`
 		HTMLPrefix                string `help:"HTML CSS class prefix." placeholder:"PREFIX"`
 		HTMLStyles                bool   `help:"Output HTML CSS styles."`
+		HTMLAllStyles             bool   `help:"Output all HTML CSS styles, including redundant ones."`
 		HTMLOnly                  bool   `help:"Output HTML fragment."`
 		HTMLInlineStyles          bool   `help:"Output HTML with inline styles (no classes)."`
 		HTMLTabWidth              int    `help:"Set the HTML tab width." default:"8"`
@@ -139,7 +140,11 @@ func main() {
 
 	// Dump styles.
 	if cli.HTMLStyles {
-		formatter := html.New(html.WithClasses(true))
+		options := []html.Option{html.WithClasses(true)}
+		if cli.HTMLAllStyles {
+			options = append(options, html.WithAllClasses(true))
+		}
+		formatter := html.New(options...)
 		err = formatter.WriteCSS(w, style)
 		ctx.FatalIfErrorf(err)
 		return
@@ -170,6 +175,7 @@ func configureHTMLFormatter(ctx *kong.Context) {
 		html.TabWidth(cli.HTMLTabWidth),
 		html.BaseLineNumber(cli.HTMLBaseLine),
 		html.ClassPrefix(cli.HTMLPrefix),
+		html.WithAllClasses(cli.HTMLAllStyles),
 		html.WithClasses(!cli.HTMLInlineStyles),
 		html.Standalone(!cli.HTMLOnly),
 		html.WithLineNumbers(cli.HTMLLines),
diff --git a/formatters/html/html.go b/formatters/html/html.go
index f0ef44a..0bdc1e5 100644
--- a/formatters/html/html.go
+++ b/formatters/html/html.go
@@ -22,6 +22,9 @@ func ClassPrefix(prefix string) Option { return func(f *Formatter) { f.prefix =
 // WithClasses emits HTML using CSS classes, rather than inline styles.
 func WithClasses(b bool) Option { return func(f *Formatter) { f.Classes = b } }
 
+// WithAllClasses disables an optimisation that omits redundant CSS classes.
+func WithAllClasses(b bool) Option { return func(f *Formatter) { f.allClasses = b } }
+
 // TabWidth sets the number of characters for a tab. Defaults to 8.
 func TabWidth(width int) Option { return func(f *Formatter) { f.tabWidth = width } }
 
@@ -141,6 +144,7 @@ type Formatter struct {
 	standalone          bool
 	prefix              string
 	Classes             bool // Exported field to detect when classes are being used
+	allClasses          bool
 	preWrapper          PreWrapper
 	tabWidth            int
 	lineNumbers         bool
@@ -379,7 +383,7 @@ func (f *Formatter) styleToCSS(style *chroma.Style) map[chroma.TokenType]string
 		if t != chroma.Background {
 			entry = entry.Sub(bg)
 		}
-		if entry.IsZero() {
+		if !f.allClasses && entry.IsZero() {
 			continue
 		}
 		classes[t] = StyleEntryToCSS(entry)