summaryrefslogtreecommitdiffstats
path: root/helpers/pygments_test.go
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2017-09-25 08:59:02 +0200
committerGitHub <noreply@github.com>2017-09-25 08:59:02 +0200
commitfb33d8286d78a78a74deb44355b621852a1c4033 (patch)
treea726e33fbaa0ca7a315a2e12021306fd5b27690e /helpers/pygments_test.go
parent81ed564793609a32be20a569cc15da2cc02dd734 (diff)
Use Chroma as new default syntax highlighter
If you want to use Pygments, set `pygmentsUseClassic=true` in your site config. Fixes #3888
Diffstat (limited to 'helpers/pygments_test.go')
-rw-r--r--helpers/pygments_test.go201
1 files changed, 199 insertions, 2 deletions
diff --git a/helpers/pygments_test.go b/helpers/pygments_test.go
index 1fce17859..ee8076c71 100644
--- a/helpers/pygments_test.go
+++ b/helpers/pygments_test.go
@@ -14,12 +14,19 @@
package helpers
import (
+ "fmt"
+ "reflect"
"testing"
+ "github.com/alecthomas/chroma/formatters/html"
+
"github.com/spf13/viper"
+ "github.com/stretchr/testify/require"
)
func TestParsePygmentsArgs(t *testing.T) {
+ assert := require.New(t)
+
for i, this := range []struct {
in string
pygmentsStyle string
@@ -38,8 +45,10 @@ func TestParsePygmentsArgs(t *testing.T) {
v := viper.New()
v.Set("pygmentsStyle", this.pygmentsStyle)
v.Set("pygmentsUseClasses", this.pygmentsUseClasses)
+ spec, err := NewContentSpec(v)
+ assert.NoError(err)
- result1, err := parsePygmentsOpts(v, this.in)
+ result1, err := spec.createPygmentsOptionsString(this.in)
if b, ok := this.expect1.(bool); ok && !b {
if err == nil {
t.Errorf("[%d] parsePygmentArgs didn't return an expected error", i)
@@ -58,6 +67,8 @@ func TestParsePygmentsArgs(t *testing.T) {
}
func TestParseDefaultPygmentsArgs(t *testing.T) {
+ assert := require.New(t)
+
expect := "encoding=utf8,noclasses=false,style=foo"
for i, this := range []struct {
@@ -83,7 +94,10 @@ func TestParseDefaultPygmentsArgs(t *testing.T) {
v.Set("pygmentsUseClasses", b)
}
- result, err := parsePygmentsOpts(v, this.in)
+ spec, err := NewContentSpec(v)
+ assert.NoError(err)
+
+ result, err := spec.createPygmentsOptionsString(this.in)
if err != nil {
t.Errorf("[%d] parsePygmentArgs failed: %s", i, err)
continue
@@ -93,3 +107,186 @@ func TestParseDefaultPygmentsArgs(t *testing.T) {
}
}
}
+
+type chromaInfo struct {
+ classes bool
+ lineNumbers bool
+ highlightRangesLen int
+ highlightRangesStr string
+ baseLineNumber int
+}
+
+func formatterChromaInfo(f *html.Formatter) chromaInfo {
+ v := reflect.ValueOf(f).Elem()
+ c := chromaInfo{}
+ // Hack:
+ c.classes = v.FieldByName("classes").Bool()
+ c.lineNumbers = v.FieldByName("lineNumbers").Bool()
+ c.baseLineNumber = int(v.FieldByName("baseLineNumber").Int())
+ vv := v.FieldByName("highlightRanges")
+ c.highlightRangesLen = vv.Len()
+ c.highlightRangesStr = fmt.Sprint(vv)
+
+ return c
+}
+
+func TestChromaHTMLHighlight(t *testing.T) {
+ assert := require.New(t)
+
+ v := viper.New()
+ v.Set("pygmentsUseClasses", true)
+ spec, err := NewContentSpec(v)
+ assert.NoError(err)
+
+ result, err := spec.Highlight(`echo "Hello"`, "bash", "")
+ assert.NoError(err)
+
+ assert.Contains(result, `<code class="language-bash" data-lang="bash"><span class="s7d2">echo</span> <span class="sc1c">&#34;Hello&#34;</span></code>`)
+
+}
+
+func TestChromaHTMLFormatterFromOptions(t *testing.T) {
+ assert := require.New(t)
+
+ for i, this := range []struct {
+ in string
+ pygmentsStyle interface{}
+ pygmentsUseClasses interface{}
+ pygmentsOptions string
+ assert func(c chromaInfo)
+ }{
+ {"", "monokai", true, "style=manni,noclasses=true", func(c chromaInfo) {
+ assert.True(c.classes)
+ assert.False(c.lineNumbers)
+ assert.Equal(0, c.highlightRangesLen)
+
+ }},
+ {"", nil, nil, "style=monokai,noclasses=false", func(c chromaInfo) {
+ assert.True(c.classes)
+ }},
+ {"linenos=sure,hl_lines=1 2 3", nil, nil, "style=monokai,noclasses=false", func(c chromaInfo) {
+ assert.True(c.classes)
+ assert.True(c.lineNumbers)
+ assert.Equal(3, c.highlightRangesLen)
+ assert.Equal("[[1 1] [2 2] [3 3]]", c.highlightRangesStr)
+ assert.Equal(1, c.baseLineNumber)
+ }},
+ {"linenos=sure,hl_lines=1,linenostart=4", nil, nil, "style=monokai,noclasses=false", func(c chromaInfo) {
+ assert.True(c.classes)
+ assert.True(c.lineNumbers)
+ assert.Equal(1, c.highlightRangesLen)
+ // This compansates for https://github.com/alecthomas/chroma/issues/30
+ assert.Equal("[[4 4]]", c.highlightRangesStr)
+ assert.Equal(4, c.baseLineNumber)
+ }},
+ {"style=monokai,noclasses=false", nil, nil, "style=manni,noclasses=true", func(c chromaInfo) {
+ assert.True(c.classes)
+ }},
+ {"style=monokai,noclasses=true", "friendly", false, "style=manni,noclasses=false", func(c chromaInfo) {
+ assert.False(c.classes)
+ }},
+ } {
+ v := viper.New()
+
+ v.Set("pygmentsOptions", this.pygmentsOptions)
+
+ if s, ok := this.pygmentsStyle.(string); ok {
+ v.Set("pygmentsStyle", s)
+ }
+
+ if b, ok := this.pygmentsUseClasses.(bool); ok {
+ v.Set("pygmentsUseClasses", b)
+ }
+
+ spec, err := NewContentSpec(v)
+ assert.NoError(err)
+
+ opts, err := spec.parsePygmentsOpts(this.in)
+ if err != nil {
+ t.Fatalf("[%d] parsePygmentsOpts failed: %s", i, err)
+ }
+
+ chromaFormatter, err := spec.chromaFormatterFromOptions(opts)
+ if err != nil {
+ t.Fatalf("[%d] chromaFormatterFromOptions failed: %s", i, err)
+ }
+
+ this.assert(formatterChromaInfo(chromaFormatter.(*html.Formatter)))
+ }
+}
+
+func TestHlLinesToRanges(t *testing.T) {
+ var zero [][2]int
+
+ for _, this := range []struct {
+ in string
+ startLine int
+ expected interface{}
+ }{
+ {"", 1, zero},
+ {"1 4", 1, [][2]int{[2]int{1, 1}, [2]int{4, 4}}},
+ {"1 4", 2, [][2]int{[2]int{2, 2}, [2]int{5, 5}}},
+ {"1-4 5-8", 1, [][2]int{[2]int{1, 4}, [2]int{5, 8}}},
+ {" 1 4 ", 1, [][2]int{[2]int{1, 1}, [2]int{4, 4}}},
+ {"1-4 5-8 ", 1, [][2]int{[2]int{1, 4}, [2]int{5, 8}}},
+ {"1-4 5", 1, [][2]int{[2]int{1, 4}, [2]int{5, 5}}},
+ {"4 5-9", 1, [][2]int{[2]int{4, 4}, [2]int{5, 9}}},
+ {" 1 -4 5 - 8 ", 1, true},
+ {"a b", 1, true},
+ } {
+ got, err := hlLinesToRanges(this.startLine, this.in)
+
+ if expectErr, ok := this.expected.(bool); ok && expectErr {
+ if err == nil {
+ t.Fatal("No error")
+ }
+ } else if err != nil {
+ t.Fatalf("Got error: %s", err)
+ } else if !reflect.DeepEqual(this.expected, got) {
+ t.Fatalf("Expected\n%v but got\n%v", this.expected, got)
+ }
+ }
+}
+
+func BenchmarkChromaHighlight(b *testing.B) {
+ assert := require.New(b)
+ v := viper.New()
+
+ v.Set("pygmentsstyle", "trac")
+ v.Set("pygmentsuseclasses", false)
+ v.Set("pygmentsuseclassic", false)
+
+ code := `// GetTitleFunc returns a func that can be used to transform a string to
+// title case.
+//
+// The supported styles are
+//
+// - "Go" (strings.Title)
+// - "AP" (see https://www.apstylebook.com/)
+// - "Chicago" (see http://www.chicagomanualofstyle.org/home.html)
+//
+// If an unknown or empty style is provided, AP style is what you get.
+func GetTitleFunc(style string) func(s string) string {
+ switch strings.ToLower(style) {
+ case "go":
+ return strings.Title
+ case "chicago":
+ tc := transform.NewTitleConverter(transform.ChicagoStyle)
+ return tc.Title
+ default:
+ tc := transform.NewTitleConverter(transform.APStyle)
+ return tc.Title
+ }
+}
+`
+
+ spec, err := NewContentSpec(v)
+ assert.NoError(err)
+
+ for i := 0; i < b.N; i++ {
+ _, err := spec.Highlight(code, "go", "linenos=inline,hl_lines=8 15-17")
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}