source: code/trunk/vendor/github.com/Depado/bfchroma/v2/renderer.go@ 67

Last change on this file since 67 was 67, checked in by Izuru Yakumo, 23 months ago

Use vendored modules

Signed-off-by: Izuru Yakumo <yakumo.izuru@…>

File size: 4.0 KB
Line 
1// Package bfchroma provides an easy and extensible blackfriday renderer that
2// uses the chroma syntax highlighter to render code blocks.
3package bfchroma
4
5import (
6 "io"
7
8 "github.com/alecthomas/chroma/v2"
9 "github.com/alecthomas/chroma/v2/formatters/html"
10 "github.com/alecthomas/chroma/v2/lexers"
11 "github.com/alecthomas/chroma/v2/styles"
12 bf "github.com/russross/blackfriday/v2"
13)
14
15// Option defines the functional option type
16type Option func(r *Renderer)
17
18// Style is a function option allowing to set the style used by chroma
19// Default : "monokai"
20func Style(s string) Option {
21 return func(r *Renderer) {
22 r.Style = styles.Get(s)
23 }
24}
25
26// ChromaStyle is an option to directly set the style of the renderer using a
27// chroma style instead of a string
28func ChromaStyle(s *chroma.Style) Option {
29 return func(r *Renderer) {
30 r.Style = s
31 }
32}
33
34// WithoutAutodetect disables chroma's language detection when no codeblock
35// extra information is given. It will fallback to a sane default instead of
36// trying to detect the language.
37func WithoutAutodetect() Option {
38 return func(r *Renderer) {
39 r.Autodetect = false
40 }
41}
42
43// EmbedCSS will embed CSS needed for html.WithClasses() in beginning of the document
44func EmbedCSS() Option {
45 return func(r *Renderer) {
46 r.embedCSS = true
47 }
48}
49
50// ChromaOptions allows to pass Chroma html.Option such as Standalone()
51// WithClasses(), ClassPrefix(prefix)...
52func ChromaOptions(options ...html.Option) Option {
53 return func(r *Renderer) {
54 r.ChromaOptions = options
55 }
56}
57
58// Extend allows to specify the blackfriday renderer which is extended
59func Extend(br bf.Renderer) Option {
60 return func(r *Renderer) {
61 r.Base = br
62 }
63}
64
65// NewRenderer will return a new bfchroma renderer with sane defaults
66func NewRenderer(options ...Option) *Renderer {
67 r := &Renderer{
68 Base: bf.NewHTMLRenderer(bf.HTMLRendererParameters{
69 Flags: bf.CommonHTMLFlags,
70 }),
71 Style: styles.Monokai,
72 Autodetect: true,
73 }
74 for _, option := range options {
75 option(r)
76 }
77 r.Formatter = html.New(r.ChromaOptions...)
78 return r
79}
80
81// RenderWithChroma will render the given text to the w io.Writer
82func (r *Renderer) RenderWithChroma(w io.Writer, text []byte, data bf.CodeBlockData) error {
83 var lexer chroma.Lexer
84
85 // Determining the lexer to use
86 if len(data.Info) > 0 {
87 lexer = lexers.Get(string(data.Info))
88 } else if r.Autodetect {
89 lexer = lexers.Analyse(string(text))
90 }
91 if lexer == nil {
92 lexer = lexers.Fallback
93 }
94
95 // Tokenize the code
96 iterator, err := lexer.Tokenise(nil, string(text))
97 if err != nil {
98 return err
99 }
100 return r.Formatter.Format(w, r.Style, iterator)
101}
102
103// Renderer is a custom Blackfriday renderer that uses the capabilities of
104// chroma to highlight code with triple backtick notation
105type Renderer struct {
106 Base bf.Renderer
107 Autodetect bool
108 ChromaOptions []html.Option
109 Style *chroma.Style
110 Formatter *html.Formatter
111 embedCSS bool
112}
113
114// RenderNode satisfies the Renderer interface
115func (r *Renderer) RenderNode(w io.Writer, node *bf.Node, entering bool) bf.WalkStatus {
116 switch node.Type {
117 case bf.Document:
118 if entering && r.embedCSS {
119 w.Write([]byte("<style>")) // nolint: errcheck
120 r.Formatter.WriteCSS(w, r.Style) // nolint: errcheck
121 w.Write([]byte("</style>")) // nolint: errcheck
122 }
123 return r.Base.RenderNode(w, node, entering)
124 case bf.CodeBlock:
125 if err := r.RenderWithChroma(w, node.Literal, node.CodeBlockData); err != nil {
126 return r.Base.RenderNode(w, node, entering)
127 }
128 return bf.SkipChildren
129 default:
130 return r.Base.RenderNode(w, node, entering)
131 }
132}
133
134// RenderHeader satisfies the Renderer interface
135func (r *Renderer) RenderHeader(w io.Writer, ast *bf.Node) {
136 r.Base.RenderHeader(w, ast)
137}
138
139// RenderFooter satisfies the Renderer interface
140func (r *Renderer) RenderFooter(w io.Writer, ast *bf.Node) {
141 r.Base.RenderFooter(w, ast)
142}
143
144// ChromaCSS returns CSS used with chroma's html.WithClasses() option
145func (r *Renderer) ChromaCSS(w io.Writer) error {
146 return r.Formatter.WriteCSS(w, r.Style)
147}
Note: See TracBrowser for help on using the repository browser.