mirror of
https://github.com/charmbracelet/glow.git
synced 2026-08-09 09:49:09 +02:00
Load style from json
This commit is contained in:
parent
f3c759655a
commit
a89ebe80b5
3 changed files with 181 additions and 68 deletions
10
cmd/gold/dark.json
Normal file
10
cmd/gold/dark.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"link": {
|
||||
"color": "123",
|
||||
"underline": true
|
||||
},
|
||||
"heading": {
|
||||
"bold": true,
|
||||
"inverse": true
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/magicnumbers/gold"
|
||||
bf "gopkg.in/russross/blackfriday.v2"
|
||||
|
|
@ -22,7 +24,13 @@ This is a test yo.
|
|||
`
|
||||
|
||||
func main() {
|
||||
r := gold.TermRenderer{}
|
||||
out := bf.Run([]byte(tmd), bf.WithRenderer(&r))
|
||||
s := flag.String("s", "", "style json path")
|
||||
flag.Parse()
|
||||
r, err := gold.NewTermRenderer(*s)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
out := bf.Run([]byte(tmd), bf.WithRenderer(r))
|
||||
fmt.Println(string(out))
|
||||
}
|
||||
|
|
|
|||
229
gold.go
229
gold.go
|
|
@ -1,8 +1,11 @@
|
|||
package gold
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
|
@ -26,134 +29,171 @@ const (
|
|||
Blink
|
||||
)
|
||||
|
||||
type TermRenderer struct {
|
||||
style map[bf.NodeType]map[RuleKey]string
|
||||
type ElementStyle struct {
|
||||
Color string `json:"color"`
|
||||
BackgroundColor string `json:"background_color"`
|
||||
Underline bool `json:"underline"`
|
||||
Bold bool `json:"bold"`
|
||||
Italic bool `json:"italic"`
|
||||
CrossedOut bool `json:"crossed_out"`
|
||||
Faint bool `json:"faint"`
|
||||
Conceal bool `json:"conceal"`
|
||||
Overlined bool `json:"overlined"`
|
||||
Inverse bool `json:"inverse"`
|
||||
Blink bool `json:"blink"`
|
||||
}
|
||||
|
||||
func BaseString(node *bf.Node) string {
|
||||
type Element struct {
|
||||
BaseString string
|
||||
}
|
||||
|
||||
type TermRenderer struct {
|
||||
style map[bf.NodeType]*ElementStyle
|
||||
}
|
||||
|
||||
func NewElement(node *bf.Node) Element {
|
||||
switch node.Type {
|
||||
case bf.Document:
|
||||
return ""
|
||||
return Element{""}
|
||||
case bf.BlockQuote:
|
||||
return fmt.Sprintf("```\n%s\n```", string(node.Literal))
|
||||
return Element{fmt.Sprintf("```\n%s\n```", string(node.Literal))}
|
||||
case bf.List:
|
||||
return ""
|
||||
return Element{""}
|
||||
case bf.Item:
|
||||
return fmt.Sprintf("* %s", string(node.Literal))
|
||||
return Element{fmt.Sprintf("* %s", string(node.Literal))}
|
||||
case bf.Paragraph:
|
||||
if node.Prev != nil && node.Prev.Type != bf.Link {
|
||||
return "\n"
|
||||
return Element{"\n"}
|
||||
} else {
|
||||
return ""
|
||||
return Element{""}
|
||||
}
|
||||
case bf.Heading:
|
||||
return fmt.Sprintf("%s ", strings.Repeat("#", node.HeadingData.Level))
|
||||
return Element{fmt.Sprintf("%s ", strings.Repeat("#", node.HeadingData.Level))}
|
||||
case bf.HorizontalRule:
|
||||
return "---\n"
|
||||
return Element{"---\n"}
|
||||
case bf.Emph:
|
||||
return fmt.Sprintf("%s\n", string(node.Literal))
|
||||
return Element{fmt.Sprintf("%s\n", string(node.Literal))}
|
||||
case bf.Strong:
|
||||
return fmt.Sprintf("%s\n", string(node.Literal))
|
||||
return Element{fmt.Sprintf("%s\n", string(node.Literal))}
|
||||
case bf.Del:
|
||||
return fmt.Sprintf("%s\n", string(node.Literal))
|
||||
return Element{fmt.Sprintf("%s\n", string(node.Literal))}
|
||||
case bf.Link:
|
||||
return fmt.Sprintf("[%s](%s)\n", string(node.LastChild.Literal), string(node.LinkData.Destination))
|
||||
return Element{fmt.Sprintf("[%s](%s)\n", string(node.LastChild.Literal), string(node.LinkData.Destination))}
|
||||
case bf.Image:
|
||||
return fmt.Sprintf("%s\n", string(node.Literal))
|
||||
return Element{fmt.Sprintf("%s\n", string(node.Literal))}
|
||||
case bf.Text:
|
||||
if node.Parent != nil && node.Parent.Type != bf.Link {
|
||||
return fmt.Sprintf("%s\n", string(node.Literal))
|
||||
return Element{fmt.Sprintf("%s\n", string(node.Literal))}
|
||||
} else {
|
||||
return ""
|
||||
return Element{""}
|
||||
}
|
||||
case bf.HTMLBlock:
|
||||
return fmt.Sprintf("%s\n", string(node.Literal))
|
||||
return Element{fmt.Sprintf("%s\n", string(node.Literal))}
|
||||
case bf.CodeBlock:
|
||||
return fmt.Sprintf("%s\n", string(node.Literal))
|
||||
return Element{fmt.Sprintf("%s\n", string(node.Literal))}
|
||||
case bf.Softbreak:
|
||||
return fmt.Sprintf("%s\n", string(node.Literal))
|
||||
return Element{fmt.Sprintf("%s\n", string(node.Literal))}
|
||||
case bf.Hardbreak:
|
||||
return fmt.Sprintf("%s\n", string(node.Literal))
|
||||
return Element{fmt.Sprintf("%s\n", string(node.Literal))}
|
||||
case bf.Code:
|
||||
return fmt.Sprintf("%s\n", string(node.Literal))
|
||||
return Element{fmt.Sprintf("%s\n", string(node.Literal))}
|
||||
case bf.HTMLSpan:
|
||||
return fmt.Sprintf("%s\n", string(node.Literal))
|
||||
return Element{fmt.Sprintf("%s\n", string(node.Literal))}
|
||||
case bf.Table:
|
||||
return fmt.Sprintf("%s\n", string(node.Literal))
|
||||
return Element{fmt.Sprintf("%s\n", string(node.Literal))}
|
||||
case bf.TableCell:
|
||||
return fmt.Sprintf("%s\n", string(node.Literal))
|
||||
return Element{fmt.Sprintf("%s\n", string(node.Literal))}
|
||||
case bf.TableHead:
|
||||
return fmt.Sprintf("%s\n", string(node.Literal))
|
||||
return Element{fmt.Sprintf("%s\n", string(node.Literal))}
|
||||
case bf.TableBody:
|
||||
return fmt.Sprintf("%s\n", string(node.Literal))
|
||||
return Element{fmt.Sprintf("%s\n", string(node.Literal))}
|
||||
case bf.TableRow:
|
||||
return fmt.Sprintf("%s\n", string(node.Literal))
|
||||
return Element{fmt.Sprintf("%s\n", string(node.Literal))}
|
||||
default:
|
||||
return ""
|
||||
return Element{""}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func NewTermRenderer(stylePath string) (*TermRenderer, error) {
|
||||
if stylePath == "" {
|
||||
return NewTermRendererFromBytes([]byte("{}"))
|
||||
}
|
||||
f, err := os.Open(stylePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
b, _ := ioutil.ReadAll(f)
|
||||
return NewTermRendererFromBytes(b)
|
||||
}
|
||||
|
||||
func NewTermRendererFromBytes(b []byte) (*TermRenderer, error) {
|
||||
e := make(map[string]*ElementStyle, 0)
|
||||
err := json.Unmarshal(b, &e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tr := &TermRenderer{}
|
||||
tr.style = make(map[bf.NodeType]*ElementStyle)
|
||||
|
||||
for k, v := range e {
|
||||
t, err := keyToType(k)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
}
|
||||
tr.style[t] = v
|
||||
}
|
||||
return tr, nil
|
||||
}
|
||||
|
||||
func (tr *TermRenderer) RenderNode(w io.Writer, node *bf.Node, entering bool) bf.WalkStatus {
|
||||
if !entering {
|
||||
return bf.GoToNext
|
||||
}
|
||||
text := BaseString(node)
|
||||
if text == "" {
|
||||
el := NewElement(node)
|
||||
if el.BaseString == "" {
|
||||
return bf.GoToNext
|
||||
}
|
||||
rules := tr.style[node.Type]
|
||||
if len(rules) == 0 {
|
||||
fmt.Fprintf(w, "%s", text)
|
||||
if rules == nil {
|
||||
fmt.Fprintf(w, "%s", el.BaseString)
|
||||
return bf.GoToNext
|
||||
}
|
||||
out := aurora.Reset(text)
|
||||
if r, ok := rules[Color]; ok {
|
||||
i, err := strconv.Atoi(r)
|
||||
out := aurora.Reset(el.BaseString)
|
||||
if rules.Color != "" {
|
||||
i, err := strconv.Atoi(rules.Color)
|
||||
if err == nil && i >= 0 && i <= 255 {
|
||||
out = out.Index(uint8(i))
|
||||
}
|
||||
}
|
||||
if r, ok := rules[BackgroundColor]; ok {
|
||||
i, err := strconv.Atoi(r)
|
||||
if rules.BackgroundColor != "" {
|
||||
i, err := strconv.Atoi(rules.BackgroundColor)
|
||||
if err == nil && i >= 0 && i <= 255 {
|
||||
out = out.Index(uint8(i))
|
||||
}
|
||||
}
|
||||
if r, ok := rules[Underline]; ok {
|
||||
if r == "true" {
|
||||
out = out.Underline()
|
||||
}
|
||||
if rules.Underline {
|
||||
out = out.Underline()
|
||||
}
|
||||
if r, ok := rules[Bold]; ok {
|
||||
if r == "true" {
|
||||
out = out.Bold()
|
||||
}
|
||||
if rules.Bold {
|
||||
out = out.Bold()
|
||||
}
|
||||
if r, ok := rules[Italic]; ok {
|
||||
if r == "true" {
|
||||
out = out.Italic()
|
||||
}
|
||||
if rules.Italic {
|
||||
out = out.Italic()
|
||||
}
|
||||
if r, ok := rules[CrossedOut]; ok {
|
||||
if r == "true" {
|
||||
out = out.CrossedOut()
|
||||
}
|
||||
if rules.CrossedOut {
|
||||
out = out.CrossedOut()
|
||||
}
|
||||
if r, ok := rules[Overlined]; ok {
|
||||
if r == "true" {
|
||||
out = out.Overlined()
|
||||
}
|
||||
if rules.Overlined {
|
||||
out = out.Overlined()
|
||||
}
|
||||
if r, ok := rules[Inverse]; ok {
|
||||
if r == "true" {
|
||||
out = out.Reverse()
|
||||
}
|
||||
if rules.Inverse {
|
||||
out = out.Reverse()
|
||||
}
|
||||
if r, ok := rules[Blink]; ok {
|
||||
if r == "true" {
|
||||
out = out.Blink()
|
||||
}
|
||||
if rules.Blink {
|
||||
out = out.Blink()
|
||||
}
|
||||
w.Write([]byte(aurora.Sprintf("%s", out)))
|
||||
return bf.GoToNext
|
||||
|
|
@ -164,3 +204,58 @@ func (tr *TermRenderer) RenderHeader(w io.Writer, ast *bf.Node) {
|
|||
|
||||
func (tr *TermRenderer) RenderFooter(w io.Writer, ast *bf.Node) {
|
||||
}
|
||||
|
||||
func keyToType(key string) (bf.NodeType, error) {
|
||||
switch key {
|
||||
case "document":
|
||||
return bf.Document, nil
|
||||
case "block_quote":
|
||||
return bf.BlockQuote, nil
|
||||
case "list":
|
||||
return bf.List, nil
|
||||
case "item":
|
||||
return bf.Item, nil
|
||||
case "paragraph":
|
||||
return bf.Paragraph, nil
|
||||
case "heading":
|
||||
return bf.Heading, nil
|
||||
case "hr":
|
||||
return bf.HorizontalRule, nil
|
||||
case "emph":
|
||||
return bf.Emph, nil
|
||||
case "strong":
|
||||
return bf.Strong, nil
|
||||
case "del":
|
||||
return bf.Del, nil
|
||||
case "link":
|
||||
return bf.Link, nil
|
||||
case "image":
|
||||
return bf.Image, nil
|
||||
case "text":
|
||||
return bf.Text, nil
|
||||
case "html_block":
|
||||
return bf.HTMLBlock, nil
|
||||
case "code_block":
|
||||
return bf.CodeBlock, nil
|
||||
case "softbreak":
|
||||
return bf.Softbreak, nil
|
||||
case "hardbreak":
|
||||
return bf.Hardbreak, nil
|
||||
case "code":
|
||||
return bf.Code, nil
|
||||
case "html_span":
|
||||
return bf.HTMLSpan, nil
|
||||
case "table":
|
||||
return bf.Table, nil
|
||||
case "table_cel":
|
||||
return bf.TableCell, nil
|
||||
case "table_head":
|
||||
return bf.TableHead, nil
|
||||
case "table_body":
|
||||
return bf.TableBody, nil
|
||||
case "table_row":
|
||||
return bf.TableRow, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("Invalid element type: %s", key)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue