99 "bytes"
1010 "fmt"
1111 gohtml "html"
12+ "html/template"
1213 "io"
1314 "path/filepath"
1415 "strings"
@@ -135,12 +136,26 @@ func CodeFromLexer(lexer chroma.Lexer, code string) string {
135136 return strings .TrimSuffix (htmlbuf .String (), "\n " )
136137}
137138
139+ type ContentLines struct {
140+ HTMLLines []template.HTML
141+ HasLastEOL bool
142+ LexerName string
143+ }
144+
145+ func (cl * ContentLines ) ShouldShowIncompleteMark (idx int ) bool {
146+ return ! cl .HasLastEOL && idx == len (cl .HTMLLines )- 1
147+ }
148+
149+ func hasLastEOL (code []byte ) bool {
150+ return len (code ) != 0 && code [len (code )- 1 ] == '\n'
151+ }
152+
138153// File returns a slice of chroma syntax highlighted HTML lines of code and the matched lexer name
139- func File (fileName , language string , code []byte ) ([] string , string , error ) {
154+ func File (fileName , language string , code []byte ) (* ContentLines , error ) {
140155 NewContext ()
141156
142157 if len (code ) > sizeLimit {
143- return PlainText (code ), "" , nil
158+ return PlainText (code ), nil
144159 }
145160
146161 formatter := html .New (html .WithClasses (true ),
@@ -177,30 +192,30 @@ func File(fileName, language string, code []byte) ([]string, string, error) {
177192
178193 iterator , err := lexer .Tokenise (nil , string (code ))
179194 if err != nil {
180- return nil , "" , fmt .Errorf ("can't tokenize code: %w" , err )
195+ return nil , fmt .Errorf ("can't tokenize code: %w" , err )
181196 }
182197
183198 tokensLines := chroma .SplitTokensIntoLines (iterator .Tokens ())
184199 htmlBuf := & bytes.Buffer {}
185200
186- lines := make ([]string , 0 , len (tokensLines ))
201+ lines := make ([]template. HTML , 0 , len (tokensLines ))
187202 for _ , tokens := range tokensLines {
188203 iterator = chroma .Literator (tokens ... )
189204 err = formatter .Format (htmlBuf , githubStyles , iterator )
190205 if err != nil {
191- return nil , "" , fmt .Errorf ("can't format code: %w" , err )
206+ return nil , fmt .Errorf ("can't format code: %w" , err )
192207 }
193- lines = append (lines , htmlBuf .String ())
208+ lines = append (lines , template . HTML ( htmlBuf .String () ))
194209 htmlBuf .Reset ()
195210 }
196211
197- return lines , lexerName , nil
212+ return & ContentLines { HTMLLines : lines , HasLastEOL : hasLastEOL ( code ), LexerName : lexerName } , nil
198213}
199214
200215// PlainText returns non-highlighted HTML for code
201- func PlainText (code []byte ) [] string {
216+ func PlainText (code []byte ) * ContentLines {
202217 r := bufio .NewReader (bytes .NewReader (code ))
203- m := make ([]string , 0 , bytes .Count (code , []byte {'\n' })+ 1 )
218+ m := make ([]template. HTML , 0 , bytes .Count (code , []byte {'\n' })+ 1 )
204219 for {
205220 content , err := r .ReadString ('\n' )
206221 if err != nil && err != io .EOF {
@@ -210,10 +225,9 @@ func PlainText(code []byte) []string {
210225 if content == "" && err == io .EOF {
211226 break
212227 }
213- s := gohtml .EscapeString (content )
214- m = append (m , s )
228+ m = append (m , template .HTML (gohtml .EscapeString (content )))
215229 }
216- return m
230+ return & ContentLines { HTMLLines : m , HasLastEOL : hasLastEOL ( code )}
217231}
218232
219233func formatLexerName (name string ) string {
0 commit comments