Skip to content

Commit e9ffd5a

Browse files
authored
fix: don't emit empty tail tokens (#1121)
When tokens are split into lines, tokens that end with a newline are emitted again as an empty token, which is confusing and doesn't have any benefit. This conversion shouldn't emit a empty tail token. Adds a test. I noticed this issue by a CI failure for the output of a Go program that was changed because of d0ad679 and the new output contained a empty whitespace token at the beginning of most lines.
1 parent 4e1403e commit e9ffd5a

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

formatters/html/html_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,48 @@ func TestSplitTokensIntoLines(t *testing.T) {
4949
}
5050
actual := chroma.SplitTokensIntoLines(in)
5151
assert.Equal(t, expected, actual)
52+
53+
in = []chroma.Token{
54+
{Value: "func", Type: chroma.KeywordDeclaration},
55+
{Value: " ", Type: chroma.TextWhitespace},
56+
{Value: "main", Type: chroma.NameFunction},
57+
{Value: "()", Type: chroma.Punctuation},
58+
{Value: " ", Type: chroma.TextWhitespace},
59+
{Value: "{", Type: chroma.Punctuation},
60+
{Value: "\n\t", Type: chroma.TextWhitespace},
61+
{Value: "println", Type: chroma.NameBuiltin},
62+
{Value: "(", Type: chroma.Punctuation},
63+
{Value: `"mark this"`, Type: chroma.LiteralString},
64+
{Value: ")", Type: chroma.Punctuation},
65+
{Value: "\n", Type: chroma.TextWhitespace},
66+
{Value: "}", Type: chroma.Punctuation},
67+
{Value: "\n", Type: chroma.TextWhitespace},
68+
}
69+
expected = [][]chroma.Token{
70+
{
71+
{Type: chroma.KeywordDeclaration, Value: "func"},
72+
{Type: chroma.TextWhitespace, Value: " "},
73+
{Type: chroma.NameFunction, Value: "main"},
74+
{Type: chroma.Punctuation, Value: "()"},
75+
{Type: chroma.TextWhitespace, Value: " "},
76+
{Type: chroma.Punctuation, Value: "{"},
77+
{Type: chroma.TextWhitespace, Value: "\n"},
78+
},
79+
{
80+
{Type: chroma.TextWhitespace, Value: "\t"},
81+
{Type: chroma.NameBuiltin, Value: "println"},
82+
{Type: chroma.Punctuation, Value: "("},
83+
{Type: chroma.LiteralString, Value: `"mark this"`},
84+
{Type: chroma.Punctuation, Value: ")"},
85+
{Type: chroma.TextWhitespace, Value: "\n"},
86+
},
87+
{
88+
{Type: chroma.Punctuation, Value: "}"},
89+
{Type: chroma.TextWhitespace, Value: "\n"},
90+
},
91+
}
92+
actual = chroma.SplitTokensIntoLines(in)
93+
assert.Equal(t, expected, actual)
5294
}
5395

5496
func TestFormatterStyleToCSS(t *testing.T) {

iterator.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ func Literator(tokens ...Token) Iterator {
5858
// SplitTokensIntoLines splits tokens containing newlines in two.
5959
func SplitTokensIntoLines(tokens []Token) (out [][]Token) {
6060
var line []Token // nolint: prealloc
61+
tokenLoop:
6162
for _, token := range tokens {
6263
for strings.Contains(token.Value, "\n") {
6364
parts := strings.SplitAfterN(token.Value, "\n", 2)
@@ -70,6 +71,11 @@ func SplitTokensIntoLines(tokens []Token) (out [][]Token) {
7071
line = append(line, clone)
7172
out = append(out, line)
7273
line = nil
74+
75+
// If the tail token is empty, don't emit it.
76+
if len(token.Value) == 0 {
77+
continue tokenLoop
78+
}
7379
}
7480
line = append(line, token)
7581
}
@@ -83,5 +89,5 @@ func SplitTokensIntoLines(tokens []Token) (out [][]Token) {
8389
out = out[:len(out)-1]
8490
}
8591
}
86-
return
92+
return out
8793
}

0 commit comments

Comments
 (0)