Use ElementStyle as a value instead of pointer, so we can drop all the annoying nil checks

This commit is contained in:
Christian Muehlhaeuser
2019-12-05 18:05:29 +01:00
parent 556c490ac4
commit 78e36a02d0
11 changed files with 147 additions and 176 deletions
+16 -17
View File
@@ -16,27 +16,27 @@ type BaseElement struct {
Token string Token string
Prefix string Prefix string
Suffix string Suffix string
Style *ElementStyle Style ElementStyle
} }
func color(c string) (uint8, error) { func color(c *string) (uint8, error) {
if len(c) == 0 { if c == nil || len(*c) == 0 {
return 0, errors.New("Invalid color") return 0, errors.New("Invalid color")
} }
if c[0] == '#' { if (*c)[0] == '#' {
i, err := hexToANSIColor(c) i, err := hexToANSIColor(*c)
return uint8(i), err return uint8(i), err
} }
i, err := strconv.Atoi(c) i, err := strconv.Atoi(*c)
return uint8(i), err return uint8(i), err
} }
func colorSeq(c string) (string, error) { func colorSeq(c *string) (string, error) {
if len(c) == 0 { if c == nil || len(*c) == 0 {
return "", errors.New("Invalid color") return "", errors.New("Invalid color")
} }
col, err := colorful.Hex(c) col, err := colorful.Hex(*c)
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -44,13 +44,13 @@ func colorSeq(c string) (string, error) {
return fmt.Sprintf("%d;%d;%dm", uint8(col.R*255), uint8(col.G*255), uint8(col.B*255)), nil return fmt.Sprintf("%d;%d;%dm", uint8(col.R*255), uint8(col.G*255), uint8(col.B*255)), nil
} }
func renderText(w io.Writer, rules *ElementStyle, s string) { func renderText(w io.Writer, rules ElementStyle, s string) {
if len(s) == 0 { if len(s) == 0 {
return return
} }
// FIXME: ugly true-color ANSI support hack // FIXME: ugly true-color ANSI support hack
if rules != nil && os.Getenv("COLORTERM") == "truecolor" { if os.Getenv("COLORTERM") == "truecolor" {
bg, err := colorSeq(rules.BackgroundColor) bg, err := colorSeq(rules.BackgroundColor)
if err == nil { if err == nil {
s = "\x1b[48;2;" + bg + s s = "\x1b[48;2;" + bg + s
@@ -63,16 +63,18 @@ func renderText(w io.Writer, rules *ElementStyle, s string) {
out := aurora.Reset(s) out := aurora.Reset(s)
if rules != nil { if rules.Color != nil {
i, err := color(rules.Color) i, err := color(rules.Color)
if err == nil { if err == nil {
out = out.Index(i) out = out.Index(i)
} }
i, err = color(rules.BackgroundColor) }
if rules.BackgroundColor != nil {
i, err := color(rules.BackgroundColor)
if err == nil { if err == nil {
out = out.BgIndex(i) out = out.BgIndex(i)
} }
}
if rules.Underline != nil && *rules.Underline { if rules.Underline != nil && *rules.Underline {
out = out.Underline() out = out.Underline()
} }
@@ -94,7 +96,6 @@ func renderText(w io.Writer, rules *ElementStyle, s string) {
if rules.Blink != nil && *rules.Blink { if rules.Blink != nil && *rules.Blink {
out = out.Blink() out = out.Blink()
} }
}
_, _ = w.Write([]byte(out.String())) _, _ = w.Write([]byte(out.String()))
} }
@@ -106,12 +107,10 @@ func (e *BaseElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) error
}() }()
rules := tr.blockStack.With(e.Style) rules := tr.blockStack.With(e.Style)
if rules != nil {
renderText(w, rules, rules.Prefix) renderText(w, rules, rules.Prefix)
defer func() { defer func() {
renderText(w, rules, rules.Suffix) renderText(w, rules, rules.Suffix)
}() }()
}
renderText(w, rules, e.Token) renderText(w, rules, e.Token)
return nil return nil
+4 -4
View File
@@ -6,7 +6,7 @@ import (
type BlockElement struct { type BlockElement struct {
Block *bytes.Buffer Block *bytes.Buffer
Style *ElementStyle Style ElementStyle
} }
type BlockStack []BlockElement type BlockStack []BlockElement
@@ -29,7 +29,7 @@ func (s BlockStack) Indent() uint {
var i uint var i uint
for _, v := range s { for _, v := range s {
if v.Style == nil || v.Style.Indent == nil { if v.Style.Indent == nil {
continue continue
} }
i += *v.Style.Indent i += *v.Style.Indent
@@ -42,7 +42,7 @@ func (s BlockStack) Margin() uint {
var i uint var i uint
for _, v := range s { for _, v := range s {
if v.Style == nil || v.Style.Margin == nil { if v.Style.Margin == nil {
continue continue
} }
i += *v.Style.Margin i += *v.Style.Margin
@@ -69,6 +69,6 @@ func (s BlockStack) Current() BlockElement {
return s[len(s)-1] return s[len(s)-1]
} }
func (s BlockStack) With(child *ElementStyle) *ElementStyle { func (s BlockStack) With(child ElementStyle) ElementStyle {
return cascadeStyle(s.Current().Style, child, true) return cascadeStyle(s.Current().Style, child, true)
} }
+1 -4
View File
@@ -13,19 +13,16 @@ type CodeBlockElement struct {
} }
func (e *CodeBlockElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) error { func (e *CodeBlockElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) error {
var theme string
var indent uint var indent uint
var margin uint var margin uint
rules := tr.style[CodeBlock] rules := tr.style[CodeBlock]
if rules != nil {
if rules.Indent != nil { if rules.Indent != nil {
indent = *rules.Indent indent = *rules.Indent
} }
if rules.Margin != nil { if rules.Margin != nil {
margin = *rules.Margin margin = *rules.Margin
} }
theme = rules.Theme theme := rules.Theme
}
iw := &IndentWriter{ iw := &IndentWriter{
Indent: indent + margin, Indent: indent + margin,
+2 -6
View File
@@ -18,26 +18,22 @@ func (e *DocumentElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) e
} }
tr.blockStack.Push(be) tr.blockStack.Push(be)
if rules != nil {
renderText(tr.blockStack.Current().Block, rules, rules.Prefix) renderText(tr.blockStack.Current().Block, rules, rules.Prefix)
}
return nil return nil
} }
func (e *DocumentElement) Finish(w io.Writer, node *bf.Node, tr *TermRenderer) error { func (e *DocumentElement) Finish(w io.Writer, node *bf.Node, tr *TermRenderer) error {
var indent uint var indent uint
var margin uint var margin uint
var suffix string
rules := tr.style[Document] rules := tr.style[Document]
if rules != nil {
if rules.Indent != nil { if rules.Indent != nil {
indent = *rules.Indent indent = *rules.Indent
} }
if rules.Margin != nil { if rules.Margin != nil {
margin = *rules.Margin margin = *rules.Margin
} }
suffix = rules.Suffix suffix := rules.Suffix
}
pw := &PaddingWriter{ pw := &PaddingWriter{
Padding: uint(tr.WordWrap) - margin, Padding: uint(tr.WordWrap) - margin,
PadFunc: func(wr io.Writer) { PadFunc: func(wr io.Writer) {
+3 -3
View File
@@ -21,7 +21,7 @@ type TermRenderer struct {
BaseURL string BaseURL string
WordWrap int WordWrap int
style map[StyleType]*ElementStyle style map[StyleType]ElementStyle
blockStack BlockStack blockStack BlockStack
table TableElement table TableElement
} }
@@ -56,13 +56,13 @@ func NewTermRenderer(stylePath string) (*TermRenderer, error) {
} }
func NewTermRendererFromBytes(b []byte) (*TermRenderer, error) { func NewTermRendererFromBytes(b []byte) (*TermRenderer, error) {
e := make(map[string]*ElementStyle) e := make(map[string]ElementStyle)
err := json.Unmarshal(b, &e) err := json.Unmarshal(b, &e)
if err != nil { if err != nil {
return nil, err return nil, err
} }
tr := &TermRenderer{} tr := &TermRenderer{}
tr.style = make(map[StyleType]*ElementStyle) tr.style = make(map[StyleType]ElementStyle)
for k, v := range e { for k, v := range e {
t, err := keyToType(k) t, err := keyToType(k)
-2
View File
@@ -32,14 +32,12 @@ func (e *HeadingElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) er
rules = cascadeStyles(false, rules, tr.style[H6]) rules = cascadeStyles(false, rules, tr.style[H6])
} }
if rules != nil {
if rules.Indent != nil { if rules.Indent != nil {
indent = *rules.Indent indent = *rules.Indent
} }
if rules.Margin != nil { if rules.Margin != nil {
margin = *rules.Margin margin = *rules.Margin
} }
}
iw := &IndentWriter{ iw := &IndentWriter{
Indent: indent + margin, Indent: indent + margin,
+2 -2
View File
@@ -35,8 +35,8 @@ func (e *LinkElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) error
} }
if len(node.LinkData.Destination) > 0 { if len(node.LinkData.Destination) > 0 {
style := *tr.style[Link]
pre := " " pre := " "
style := tr.style[Link]
if !textRendered { if !textRendered {
pre = "" pre = ""
style.Prefix = "" style.Prefix = ""
@@ -46,7 +46,7 @@ func (e *LinkElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) error
el := &BaseElement{ el := &BaseElement{
Token: resolveRelativeURL(tr.BaseURL, string(node.LinkData.Destination)), Token: resolveRelativeURL(tr.BaseURL, string(node.LinkData.Destination)),
Prefix: pre, Prefix: pre,
Style: &style, Style: style,
} }
err := el.Render(w, node, tr) err := el.Render(w, node, tr)
if err != nil { if err != nil {
+1 -4
View File
@@ -29,17 +29,14 @@ func (e *ListElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) error
func (e *ListElement) Finish(w io.Writer, node *bf.Node, tr *TermRenderer) error { func (e *ListElement) Finish(w io.Writer, node *bf.Node, tr *TermRenderer) error {
var indent uint var indent uint
var margin uint var margin uint
var suffix string
rules := tr.blockStack.Current().Style rules := tr.blockStack.Current().Style
if rules != nil {
if rules.Indent != nil { if rules.Indent != nil {
indent = *rules.Indent indent = *rules.Indent
} }
if rules.Margin != nil { if rules.Margin != nil {
margin = *rules.Margin margin = *rules.Margin
} }
suffix = rules.Suffix suffix := rules.Suffix
}
renderText(tr.blockStack.Current().Block, rules, suffix) renderText(tr.blockStack.Current().Block, rules, suffix)
pw := &PaddingWriter{ pw := &PaddingWriter{
+2 -7
View File
@@ -13,7 +13,7 @@ type ParagraphElement struct {
} }
func (e *ParagraphElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) error { func (e *ParagraphElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) error {
var rules *ElementStyle var rules ElementStyle
if node.Parent != nil && node.Parent.Type == bf.Item { if node.Parent != nil && node.Parent.Type == bf.Item {
// list item // list item
rules = tr.style[List] rules = tr.style[List]
@@ -27,31 +27,26 @@ func (e *ParagraphElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer)
tr.blockStack.Push(be) tr.blockStack.Push(be)
} }
if rules != nil {
renderText(w, tr.blockStack.Current().Style, rules.Prefix) renderText(w, tr.blockStack.Current().Style, rules.Prefix)
}
return nil return nil
} }
func (e *ParagraphElement) Finish(w io.Writer, node *bf.Node, tr *TermRenderer) error { func (e *ParagraphElement) Finish(w io.Writer, node *bf.Node, tr *TermRenderer) error {
var indent uint var indent uint
var margin uint var margin uint
var suffix string
rules := tr.blockStack.Current().Style rules := tr.blockStack.Current().Style
if node.Parent != nil && node.Parent.Type == bf.Item { if node.Parent != nil && node.Parent.Type == bf.Item {
// remove indent & margin for list items // remove indent & margin for list items
rules = tr.blockStack.Current().Style rules = tr.blockStack.Current().Style
} }
if rules != nil {
if rules.Indent != nil { if rules.Indent != nil {
indent = *rules.Indent indent = *rules.Indent
} }
if rules.Margin != nil { if rules.Margin != nil {
margin = *rules.Margin margin = *rules.Margin
} }
suffix = rules.Suffix suffix := rules.Suffix
}
renderText(tr.blockStack.Current().Block, rules, suffix) renderText(tr.blockStack.Current().Block, rules, suffix)
pw := &PaddingWriter{ pw := &PaddingWriter{
+9 -19
View File
@@ -45,8 +45,8 @@ const (
) )
type ElementStyle struct { type ElementStyle struct {
Color string `json:"color"` Color *string `json:"color"`
BackgroundColor string `json:"background_color"` BackgroundColor *string `json:"background_color"`
Underline *bool `json:"underline"` Underline *bool `json:"underline"`
Bold *bool `json:"bold"` Bold *bool `json:"bold"`
Italic *bool `json:"italic"` Italic *bool `json:"italic"`
@@ -63,8 +63,8 @@ type ElementStyle struct {
Suffix string `json:"suffix"` Suffix string `json:"suffix"`
} }
func cascadeStyles(onlyColors bool, s ...*ElementStyle) *ElementStyle { func cascadeStyles(onlyColors bool, s ...ElementStyle) ElementStyle {
var r *ElementStyle var r ElementStyle
for _, v := range s { for _, v := range s {
r = cascadeStyle(r, v, onlyColors) r = cascadeStyle(r, v, onlyColors)
@@ -72,15 +72,8 @@ func cascadeStyles(onlyColors bool, s ...*ElementStyle) *ElementStyle {
return r return r
} }
func cascadeStyle(parent *ElementStyle, child *ElementStyle, onlyColors bool) *ElementStyle { func cascadeStyle(parent ElementStyle, child ElementStyle, onlyColors bool) ElementStyle {
if parent == nil { s := child
return child
}
s := ElementStyle{}
if child != nil {
s = *child
}
s.Color = parent.Color s.Color = parent.Color
s.BackgroundColor = parent.BackgroundColor s.BackgroundColor = parent.BackgroundColor
@@ -99,14 +92,12 @@ func cascadeStyle(parent *ElementStyle, child *ElementStyle, onlyColors bool) *E
s.Blink = parent.Blink s.Blink = parent.Blink
} }
if child != nil { if child.Color != nil {
if child.Color != "" {
s.Color = child.Color s.Color = child.Color
} }
if child.BackgroundColor != "" { if child.BackgroundColor != nil {
s.BackgroundColor = child.BackgroundColor s.BackgroundColor = child.BackgroundColor
} }
if child.Indent != nil { if child.Indent != nil {
s.Indent = child.Indent s.Indent = child.Indent
} }
@@ -140,9 +131,8 @@ func cascadeStyle(parent *ElementStyle, child *ElementStyle, onlyColors bool) *E
if child.Blink != nil { if child.Blink != nil {
s.Blink = child.Blink s.Blink = child.Blink
} }
}
return &s return s
} }
func hexToANSIColor(h string) (int, error) { func hexToANSIColor(h string) (int, error) {
+1 -2
View File
@@ -26,14 +26,13 @@ func (e *TableElement) Render(w io.Writer, node *bf.Node, tr *TermRenderer) erro
var indent uint var indent uint
var margin uint var margin uint
rules := tr.style[Table] rules := tr.style[Table]
if rules != nil {
if rules.Indent != nil { if rules.Indent != nil {
indent = *rules.Indent indent = *rules.Indent
} }
if rules.Margin != nil { if rules.Margin != nil {
margin = *rules.Margin margin = *rules.Margin
} }
}
iw := &IndentWriter{ iw := &IndentWriter{
Indent: indent + margin, Indent: indent + margin,
IndentFunc: func(wr io.Writer) { IndentFunc: func(wr io.Writer) {