-
Notifications
You must be signed in to change notification settings - Fork 167
/
codeblock.go
125 lines (112 loc) Β· 4.01 KB
/
codeblock.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package ansi
import (
"io"
"github.com/alecthomas/chroma"
"github.com/alecthomas/chroma/quick"
"github.com/alecthomas/chroma/styles"
"github.com/muesli/reflow/indent"
)
// A CodeBlockElement is used to render code blocks.
type CodeBlockElement struct {
Code string
Language string
}
func chromaStyle(style StylePrimitive) string {
var s string
if style.Color != nil {
s = *style.Color
}
if style.BackgroundColor != nil {
if s != "" {
s += " "
}
s += "bg:" + *style.BackgroundColor
}
if style.Italic != nil && *style.Italic {
if s != "" {
s += " "
}
s += "italic"
}
if style.Bold != nil && *style.Bold {
if s != "" {
s += " "
}
s += "bold"
}
if style.Underline != nil && *style.Underline {
if s != "" {
s += " "
}
s += "underline"
}
return s
}
func (e *CodeBlockElement) Render(w io.Writer, ctx RenderContext) error {
bs := ctx.blockStack
var indentation uint
var margin uint
rules := ctx.options.Styles.CodeBlock
if rules.Indent != nil {
indentation = *rules.Indent
}
if rules.Margin != nil {
margin = *rules.Margin
}
theme := rules.Theme
if rules.Chroma != nil && ctx.options.ColorProfile > 1 {
theme = "charm"
styles.Register(chroma.MustNewStyle("charm",
chroma.StyleEntries{
chroma.Text: chromaStyle(rules.Chroma.Text),
chroma.Error: chromaStyle(rules.Chroma.Error),
chroma.Comment: chromaStyle(rules.Chroma.Comment),
chroma.CommentPreproc: chromaStyle(rules.Chroma.CommentPreproc),
chroma.Keyword: chromaStyle(rules.Chroma.Keyword),
chroma.KeywordReserved: chromaStyle(rules.Chroma.KeywordReserved),
chroma.KeywordNamespace: chromaStyle(rules.Chroma.KeywordNamespace),
chroma.KeywordType: chromaStyle(rules.Chroma.KeywordType),
chroma.Operator: chromaStyle(rules.Chroma.Operator),
chroma.Punctuation: chromaStyle(rules.Chroma.Punctuation),
chroma.Name: chromaStyle(rules.Chroma.Name),
chroma.NameBuiltin: chromaStyle(rules.Chroma.NameBuiltin),
chroma.NameTag: chromaStyle(rules.Chroma.NameTag),
chroma.NameAttribute: chromaStyle(rules.Chroma.NameAttribute),
chroma.NameClass: chromaStyle(rules.Chroma.NameClass),
chroma.NameConstant: chromaStyle(rules.Chroma.NameConstant),
chroma.NameDecorator: chromaStyle(rules.Chroma.NameDecorator),
chroma.NameException: chromaStyle(rules.Chroma.NameException),
chroma.NameFunction: chromaStyle(rules.Chroma.NameFunction),
chroma.NameOther: chromaStyle(rules.Chroma.NameOther),
chroma.Literal: chromaStyle(rules.Chroma.Literal),
chroma.LiteralNumber: chromaStyle(rules.Chroma.LiteralNumber),
chroma.LiteralDate: chromaStyle(rules.Chroma.LiteralDate),
chroma.LiteralString: chromaStyle(rules.Chroma.LiteralString),
chroma.LiteralStringEscape: chromaStyle(rules.Chroma.LiteralStringEscape),
chroma.GenericDeleted: chromaStyle(rules.Chroma.GenericDeleted),
chroma.GenericEmph: chromaStyle(rules.Chroma.GenericEmph),
chroma.GenericInserted: chromaStyle(rules.Chroma.GenericInserted),
chroma.GenericStrong: chromaStyle(rules.Chroma.GenericStrong),
chroma.GenericSubheading: chromaStyle(rules.Chroma.GenericSubheading),
chroma.Background: chromaStyle(rules.Chroma.Background),
}))
}
iw := indent.NewWriterPipe(w, indentation+margin, func(wr io.Writer) {
renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, " ")
})
if len(theme) > 0 {
renderText(iw, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.BlockPrefix)
err := quick.Highlight(iw, e.Code, e.Language, "terminal256", theme)
if err != nil {
return err
}
renderText(iw, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.BlockSuffix)
return nil
}
// fallback rendering
el := &BaseElement{
Token: e.Code,
Style: rules.StylePrimitive,
}
return el.Render(iw, ctx)
}