Repository: alecthomas/chroma
Pull request #325 (2020-01-09 21:20:05)

Consider baseLineNumber when calculating the column width
Hey! Thanks for chroma! I'm using it with Hugo.

This PR solves a small issue with the line numbering indentation. `baseLineNumber` is not considered in the calculation; thus, the result is not aligned in situations like the following:

![chroma-before](https://user-images.githubusercontent.com/2112697/72094994-df30c080-3317-11ea-911e-fd5db931bd00.png)

After the fix, it works as expected:

![chroma-after](https://user-images.githubusercontent.com/2112697/72095048-012a4300-3318-11ea-990f-78cfe0a954bc.png)

Please, let me know if there is any aspect of the CL you'd like me to change or improve, and I'll be happy to do so.

P.S.: It still doesn't work for a negative `baseLineNumber`. I have the solution below – and more tests – but I'm not sure whether the added complexity is worth the rarest of usages. Please LMK what you think.

```diff
diff --git a/formatters/html/html.go b/formatters/html/html.go
index f0ef44a..5b2da5a 100644
--- a/formatters/html/html.go
+++ b/formatters/html/html.go
@@ -189,6 +189,9 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
 
 	lines := chroma.SplitTokensIntoLines(tokens)
 	lineDigits := len(fmt.Sprintf("%d", f.baseLineNumber+len(lines)-1))
+	if f.baseLineNumber < 0 && lineDigits < len(fmt.Sprintf("%d", f.baseLineNumber)) {
+		lineDigits = len(fmt.Sprintf("%d", f.baseLineNumber))
+	}
 	highlightIndex := 0
 
 	if wrapInTable {
```

alecthomas: Nice!

Patch:
diff --git a/formatters/html/html.go b/formatters/html/html.go
index d3fef2e..f0ef44a 100644
--- a/formatters/html/html.go
+++ b/formatters/html/html.go
@@ -188,7 +188,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
 	wrapInTable := f.lineNumbers && f.lineNumbersInTable
 
 	lines := chroma.SplitTokensIntoLines(tokens)
-	lineDigits := len(fmt.Sprintf("%d", len(lines)))
+	lineDigits := len(fmt.Sprintf("%d", f.baseLineNumber+len(lines)-1))
 	highlightIndex := 0
 
 	if wrapInTable {


Test patch:
diff --git a/formatters/html/html_test.go b/formatters/html/html_test.go
index 5558b33..cd9ea98 100644
--- a/formatters/html/html_test.go
+++ b/formatters/html/html_test.go
@@ -108,6 +108,51 @@ func TestTableLineNumberNewlines(t *testing.T) {
 </span>`)
 }
 
+func TestTableLineNumberSpacing(t *testing.T) {
+	testCases := []struct {
+		baseLineNumber int
+		expectedBuf    string
+	}{{
+		7,
+		`<span class="lnt"> 7
+</span><span class="lnt"> 8
+</span><span class="lnt"> 9
+</span><span class="lnt">10
+</span><span class="lnt">11
+</span>`,
+	}, {
+		6,
+		`<span class="lnt"> 6
+</span><span class="lnt"> 7
+</span><span class="lnt"> 8
+</span><span class="lnt"> 9
+</span><span class="lnt">10
+</span>`,
+	}, {
+		5,
+		`<span class="lnt">5
+</span><span class="lnt">6
+</span><span class="lnt">7
+</span><span class="lnt">8
+</span><span class="lnt">9
+</span>`,
+	}}
+	for i, testCase := range testCases {
+		f := New(
+			WithClasses(true),
+			WithLineNumbers(true),
+			LineNumbersInTable(true),
+			BaseLineNumber(testCase.baseLineNumber),
+		)
+		it, err := lexers.Get("go").Tokenise(nil, "package main\nfunc main()\n{\nprintln(`hello world`)\n}\n")
+		assert.NoError(t, err)
+		var buf bytes.Buffer
+		err = f.Format(&buf, styles.Fallback, it)
+		assert.NoError(t, err, "Test Case %d", i)
+		assert.Contains(t, buf.String(), testCase.expectedBuf, "Test Case %d", i)
+	}
+}
+
 func TestWithPreWrapper(t *testing.T) {
 	wrapper := preWrapper{
 		start: func(code bool, styleAttr string) string {