66
|
1 # bfchroma
|
|
2
|
|
3 [](https://forthebadge.com)[](https://forthebadge.com)
|
|
4
|
|
5 [](https://goreportcard.com/report/github.com/Depado/bfchroma)
|
|
6 [](https://drone.depa.do/Depado/bfchroma)
|
|
7 [](https://codecov.io/gh/Depado/bfchroma)
|
|
8 [](https://github.com/Depado/bfchroma/blob/master/LICENSE)
|
|
9 [](https://godoc.org/github.com/Depado/bfchroma)
|
|
10 [](https://sourcegraph.com/github.com/Depado/bfchroma?badge)
|
|
11 [](https://saythanks.io/to/Depado)
|
|
12
|
|
13
|
|
14 Integrating [Chroma](https://github.com/alecthomas/chroma) syntax highlighter as
|
|
15 a [Blackfriday](https://github.com/russross/blackfriday) renderer.
|
|
16
|
|
17 ## Install and prerequisites
|
|
18
|
|
19 This project requires and uses the `v2` version of
|
|
20 [Blackfriday](https://github.com/russross/blackfriday/tree/v2).
|
|
21
|
|
22 ```
|
|
23 $ go get github.com/Depado/bfchroma
|
|
24 ```
|
|
25
|
|
26 ## Features
|
|
27
|
|
28 This renderer integrates chroma to highlight code with triple backtick notation.
|
|
29 It will try to use the given language when available otherwise it will try to
|
|
30 detect the language. If none of these two method works it will fallback to sane
|
|
31 defaults.
|
|
32
|
|
33 ## Usage
|
|
34
|
|
35 bfchroma uses the functional options approach so you can customize the behavior
|
|
36 of the renderer. It uses sane defaults when no option is passed so you can use
|
|
37 the renderer simply by doing so :
|
|
38
|
|
39 ```go
|
|
40 html := bf.Run([]byte(md), bf.WithRenderer(bfchroma.NewRenderer()))
|
|
41 ```
|
|
42
|
|
43 ### Options
|
|
44
|
|
45 - `Style(s string)`
|
|
46 Define the style used by chroma for the rendering. The full list can be found [here](https://github.com/alecthomas/chroma/tree/master/styles)
|
|
47 - `ChromaStyle(*chroma.Style)`
|
|
48 This option can be used to passe directly a `*chroma.Style` instead of the
|
|
49 string representing the style as with the `Style(string)` option.
|
|
50 - `WithoutAutodetect()`
|
|
51 By default when no language information is written in the code block, this
|
|
52 renderer will try to auto-detect the used language. This option disables
|
|
53 this behavior and will fallback to a sane default when no language
|
|
54 information is available.
|
|
55 - `EmbedCSS()`
|
|
56 This option will embed CSS needed for chroma's `html.WithClasses()` at the beginning of blackfriday document.
|
|
57 CSS can also be extracted separately by calling `Renderer`'s.`ChromaCSS(w)` method, which will return styleshet for currently set style
|
|
58 - `Extend(bf.Renderer)`
|
|
59 This option allows to define the base blackfriday that will be extended.
|
|
60 - `ChromaOptions(...html.Option)`
|
|
61 This option allows you to pass Chroma's html options in the renderer. Such
|
|
62 options can be found [here](https://github.com/alecthomas/chroma#the-html-formatter).
|
|
63
|
|
64 ### Option examples
|
|
65
|
|
66 Disabling language auto-detection and displaying line numbers
|
|
67
|
|
68 ```go
|
|
69 r := bfchroma.NewRenderer(
|
|
70 bfchroma.WithoutAutodetect(),
|
|
71 bfchroma.ChromaOptions(html.WithLineNumbers()),
|
|
72 )
|
|
73 ```
|
|
74
|
|
75 Extend a blackfriday renderer
|
|
76
|
|
77 ```go
|
|
78 b := bf.NewHTMLRenderer(bf.HTMLRendererParameters{
|
|
79 Flags: bf.CommonHTMLFlags,
|
|
80 })
|
|
81
|
|
82 r := bfchroma.NewRenderer(bfchroma.Extend(b))
|
|
83 ```
|
|
84
|
|
85 Use a different style
|
|
86
|
|
87 ```go
|
|
88 r := bfchroma.NewRenderer(bfchroma.Style("dracula"))
|
|
89 // Or
|
|
90 r = bfchroma.NewRenderer(bfchroma.ChromaStyle(styles.Dracula))
|
|
91 ```
|
|
92
|
|
93
|
|
94
|
|
95 ## Examples
|
|
96
|
|
97 ```go
|
|
98 package main
|
|
99
|
|
100 import (
|
|
101 "fmt"
|
|
102
|
|
103 "github.com/Depado/bfchroma"
|
|
104
|
|
105 bf "github.com/russross/blackfriday/v2"
|
|
106 )
|
|
107
|
|
108 var md = "This is some sample code.\n\n```go\n" +
|
|
109 `func main() {
|
|
110 fmt.Println("Hi")
|
|
111 }
|
|
112 ` + "```"
|
|
113
|
|
114 func main() {
|
|
115 html := bf.Run([]byte(md), bf.WithRenderer(bfchroma.NewRenderer()))
|
|
116 fmt.Println(string(html))
|
|
117 }
|
|
118 ```
|
|
119
|
|
120
|
|
121 Will output :
|
|
122
|
|
123 ```html
|
|
124 <p>This is some sample code.</p>
|
|
125 <pre style="color:#f8f8f2;background-color:#272822"><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
|
|
126 <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">"Hi"</span>)
|
|
127 }
|
|
128 </pre>
|
|
129 ```
|
|
130
|
|
131 ## Real-life example
|
|
132
|
|
133 In [smallblog](https://github.com/Depado/smallblog) I'm using bfchroma to render
|
|
134 my articles. It's using a combination of both bfchroma's options and blackfriday
|
|
135 extensions and flags.
|
|
136
|
|
137 ```go
|
|
138 package main
|
|
139
|
|
140 import (
|
|
141 "github.com/Depado/bfchroma"
|
|
142 "github.com/alecthomas/chroma/formatters/html"
|
|
143 bf "github.com/russross/blackfriday/v2"
|
|
144 )
|
|
145
|
|
146 // Defines the extensions that are used
|
|
147 var exts = bf.NoIntraEmphasis | bf.Tables | bf.FencedCode | bf.Autolink |
|
|
148 bf.Strikethrough | bf.SpaceHeadings | bf.BackslashLineBreak |
|
|
149 bf.DefinitionLists | bf.Footnotes
|
|
150
|
|
151 // Defines the HTML rendering flags that are used
|
|
152 var flags = bf.UseXHTML | bf.Smartypants | bf.SmartypantsFractions |
|
|
153 bf.SmartypantsDashes | bf.SmartypantsLatexDashes | bf.TOC
|
|
154
|
|
155 // render will take a []byte input and will render it using a new renderer each
|
|
156 // time because reusing the same can mess with TOC and header IDs
|
|
157 func render(input []byte) []byte {
|
|
158 return bf.Run(
|
|
159 input,
|
|
160 bf.WithRenderer(
|
|
161 bfchroma.NewRenderer(
|
|
162 bfchroma.WithoutAutodetect(),
|
|
163 bfchroma.ChromaOptions(
|
|
164 html.WithLineNumbers(),
|
|
165 ),
|
|
166 bfchroma.Extend(
|
|
167 bf.NewHTMLRenderer(bf.HTMLRendererParameters{
|
|
168 Flags: flags,
|
|
169 }),
|
|
170 ),
|
|
171 ),
|
|
172 ),
|
|
173 bf.WithExtensions(exts),
|
|
174 )
|
|
175 }
|
|
176 ```
|
|
177
|
|
178 ## Classes
|
|
179
|
|
180 If you have loads of code in your markdown, you might want to consider using
|
|
181 `html.WithClasses()` in your `bfchroma.ChromaOptions()`. The CSS of the style
|
|
182 you chose can then be accessed like this :
|
|
183
|
|
184 ```go
|
|
185 r := bfchroma.NewRenderer(
|
|
186 bfchroma.WithoutAutodetect(),
|
|
187 bfchroma.Extend(
|
|
188 bf.NewHTMLRenderer(bf.HTMLRendererParameters{Flags: flags}),
|
|
189 ),
|
|
190 bfchroma.Style("monokai"),
|
|
191 bfchroma.ChromaOptions(html.WithClasses()),
|
|
192 )
|
|
193
|
|
194 var css template.CSS
|
|
195
|
|
196 b := new(bytes.Buffer)
|
|
197 if err := r.ChromaCSS(b); err != nil {
|
|
198 logrus.WithError(err).Warning("Couldn't write CSS")
|
|
199 }
|
|
200 css = template.CSS(b.String())
|
|
201
|
|
202 bf.Run(input, bf.WithRenderer(r), bf.WithExtensions(exts))
|
|
203 ```
|
|
204
|
|
205 This way, you can pass your `css` var to any template and render it along the
|
|
206 rendered markdown.
|