Skip to content

Instantly share code, notes, and snippets.

@depado
Created October 5, 2017 10:40
Show Gist options
  • Save depado/359e425bb7b188fd2f642eebd23b9222 to your computer and use it in GitHub Desktop.
Save depado/359e425bb7b188fd2f642eebd23b9222 to your computer and use it in GitHub Desktop.
Integrating Chroma in Blackfriday
package main
import (
"fmt"
"io"
"github.com/alecthomas/chroma"
"github.com/alecthomas/chroma/formatters/html"
"github.com/alecthomas/chroma/lexers"
"github.com/alecthomas/chroma/styles"
bf "gopkg.in/russross/blackfriday.v2"
)
var md = "This is some sample code.\n\n```go\n" +
`func main() {
fmt.Println("Hi")
}
` + "```"
func renderWithChroma(w io.Writer, text []byte, data bf.CodeBlockData) error {
var lexer chroma.Lexer
if len(data.Info) > 0 {
lexer = lexers.Get(string(data.Info))
} else {
lexer = lexers.Analyse(string(text))
}
if lexer == nil {
lexer = lexers.Fallback
}
style := styles.Get("monokai")
if style == nil {
style = styles.Fallback
}
formatter := html.New()
iterator, err := lexer.Tokenise(nil, string(text))
if err != nil {
return err
}
return formatter.Format(w, style, iterator)
}
type chromaRenderer struct {
defR *bf.HTMLRenderer
}
func (r *chromaRenderer) RenderNode(w io.Writer, node *bf.Node, entering bool) bf.WalkStatus {
switch node.Type {
case bf.CodeBlock:
if err := renderWithChroma(w, node.Literal, node.CodeBlockData); err != nil {
return r.defR.RenderNode(w, node, entering)
}
return bf.SkipChildren
default:
return r.defR.RenderNode(w, node, entering)
}
}
func (r *chromaRenderer) RenderHeader(w io.Writer, ast *bf.Node) {
r.defR.RenderHeader(w, ast)
}
func (r *chromaRenderer) RenderFooter(w io.Writer, ast *bf.Node) {
r.defR.RenderFooter(w, ast)
}
func main() {
r := chromaRenderer{
defR: bf.NewHTMLRenderer(bf.HTMLRendererParameters{
Flags: bf.CommonHTMLFlags,
}),
}
html := bf.Run([]byte(md), bf.WithRenderer(&r))
fmt.Println(string(html))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment