Refactor renderer
This commit is contained in:
parent
b7eaf1cc5c
commit
eb3a072bcf
266
render.go
266
render.go
|
@ -4,11 +4,18 @@ import (
|
|||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
type Renderer interface {
|
||||
Render(w io.Writer) error
|
||||
}
|
||||
|
||||
type Block struct {
|
||||
Type string
|
||||
Data json.RawMessage
|
||||
|
||||
renderer Renderer
|
||||
}
|
||||
|
||||
type Paragraph struct {
|
||||
|
@ -54,118 +61,165 @@ type Document struct {
|
|||
Blocks []Block
|
||||
}
|
||||
|
||||
func (block Block) getType() (Renderer, error) {
|
||||
switch block.Type {
|
||||
case "table":
|
||||
return &Table{}, nil
|
||||
case "link":
|
||||
return &Link{}, nil
|
||||
case "list":
|
||||
return &List{}, nil
|
||||
case "header":
|
||||
return &Header{}, nil
|
||||
case "paragraph":
|
||||
return &Paragraph{}, nil
|
||||
case "code":
|
||||
return &Code{}, nil
|
||||
case "checklist":
|
||||
return &Checklist{}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown type: %s", block.Type)
|
||||
}
|
||||
}
|
||||
|
||||
func (block Block) load() (Renderer, error) {
|
||||
if block.renderer != nil {
|
||||
return block.renderer, nil
|
||||
}
|
||||
renderer, err := block.getType()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(block.Data, renderer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
block.renderer = renderer
|
||||
|
||||
return renderer, nil
|
||||
}
|
||||
|
||||
func (document *Document) Render(w io.Writer) error {
|
||||
var buf bytes.Buffer
|
||||
for _, block := range document.Blocks {
|
||||
renderer, err := block.load()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = renderer.Render(&buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err := buf.WriteTo(w)
|
||||
return err
|
||||
}
|
||||
|
||||
func renderJSON(text string) (string, error) {
|
||||
var data Document
|
||||
err := json.Unmarshal([]byte(text), &data)
|
||||
var document Document
|
||||
err := json.Unmarshal([]byte(text), &document)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
||||
for _, block := range data.Blocks {
|
||||
switch block.Type {
|
||||
case "table":
|
||||
var table Table
|
||||
err = json.Unmarshal(block.Data, &table)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error while parsing %s: %s", block.Type, err.Error())
|
||||
}
|
||||
|
||||
buf.WriteString("<table class='table'>")
|
||||
for _, row := range table.Content {
|
||||
buf.WriteString("<tr>")
|
||||
for _, col := range row {
|
||||
buf.WriteString("<td>")
|
||||
buf.WriteString(col)
|
||||
buf.WriteString("</td>")
|
||||
}
|
||||
buf.WriteString("</tr>")
|
||||
}
|
||||
buf.WriteString("</table>")
|
||||
break
|
||||
case "link":
|
||||
// TODO(peter): improve link rendering
|
||||
var link Link
|
||||
err = json.Unmarshal(block.Data, &link)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error while parsing %s: %s", block.Type, err.Error())
|
||||
}
|
||||
fmt.Fprintf(&buf, `<a href=%q>%s</a>`, link.Link, link.Meta.Title)
|
||||
case "list":
|
||||
var list List
|
||||
err = json.Unmarshal(block.Data, &list)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error while parsing %s: %s", block.Type, err.Error())
|
||||
}
|
||||
var tag string
|
||||
if list.Style == "ordered" {
|
||||
tag = "ol"
|
||||
} else {
|
||||
tag = "ul"
|
||||
}
|
||||
buf.WriteString("<")
|
||||
buf.WriteString(tag)
|
||||
buf.WriteString(">")
|
||||
for _, item := range list.Items {
|
||||
buf.WriteString("<li>")
|
||||
buf.WriteString(item)
|
||||
buf.WriteString("</li>")
|
||||
}
|
||||
buf.WriteString("</")
|
||||
buf.WriteString(tag)
|
||||
buf.WriteString(">")
|
||||
case "header":
|
||||
var header Header
|
||||
err = json.Unmarshal(block.Data, &header)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error while parsing %s: %s", block.Type, err.Error())
|
||||
}
|
||||
fmt.Fprintf(&buf, "<h%d>%s</h%d>", header.Level, header.Text, header.Level)
|
||||
case "paragraph":
|
||||
var para Paragraph
|
||||
err = json.Unmarshal(block.Data, ¶)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error while parsing %s: %s", block.Type, err.Error())
|
||||
}
|
||||
buf.WriteString("<p>")
|
||||
buf.WriteString(para.Text)
|
||||
buf.WriteString("</p>")
|
||||
case "code":
|
||||
var code Code
|
||||
err = json.Unmarshal(block.Data, &code)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error while parsing %s: %s", block.Type, err.Error())
|
||||
}
|
||||
buf.WriteString("<pre>")
|
||||
buf.WriteString(code.Code)
|
||||
buf.WriteString("</pre>")
|
||||
case "checklist":
|
||||
var checklist Checklist
|
||||
err = json.Unmarshal(block.Data, &checklist)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error while parsing %s: %s", block.Type, err.Error())
|
||||
}
|
||||
for _, item := range checklist.Items {
|
||||
buf.WriteString("<p>")
|
||||
|
||||
buf.WriteString(`<span class="icon is-medium">`)
|
||||
if item.Checked {
|
||||
buf.WriteString(` <span class="fa-stack">`)
|
||||
buf.WriteString(` <i class="fa fa-circle fa-stack-2x has-text-success"></i>`)
|
||||
buf.WriteString(` <i class="fa fa-check fa-stack-1x fa-inverse"></i>`)
|
||||
buf.WriteString(` </span>`)
|
||||
}
|
||||
buf.WriteString(`</span>`)
|
||||
buf.WriteString(item.Text)
|
||||
buf.WriteString("</p>")
|
||||
}
|
||||
default:
|
||||
return "", fmt.Errorf("unknown type: %s", block.Type)
|
||||
}
|
||||
|
||||
fmt.Fprintln(&buf)
|
||||
err = document.Render(&buf)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
func (checklist *Checklist) Render(w io.Writer) error {
|
||||
var buf bytes.Buffer
|
||||
|
||||
buf.WriteString(`<div class="checklist">`)
|
||||
for _, item := range checklist.Items {
|
||||
buf.WriteString(`<div class="checklist--item">`)
|
||||
|
||||
buf.WriteString(`<span class="icon is-medium">`)
|
||||
if item.Checked {
|
||||
buf.WriteString(`<i class="fa fa-check-circle has-text-success"></i>`)
|
||||
}
|
||||
buf.WriteString(`</span>`)
|
||||
buf.WriteString(`<div class="checklist--item-text">`)
|
||||
buf.WriteString(item.Text)
|
||||
buf.WriteString("</div>")
|
||||
buf.WriteString("</div>")
|
||||
}
|
||||
buf.WriteString("</div>")
|
||||
_, err := buf.WriteTo(w)
|
||||
return err
|
||||
}
|
||||
|
||||
func (code *Code) Render(w io.Writer) error {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString("<pre>")
|
||||
buf.WriteString(code.Code)
|
||||
buf.WriteString("</pre>")
|
||||
_, err := buf.WriteTo(w)
|
||||
return err
|
||||
}
|
||||
|
||||
func (link *Link) Render(w io.Writer) error {
|
||||
// TODO(peter): improve link rendering
|
||||
_, err := fmt.Fprintf(w, `<a href=%q>%s</a>`, link.Link, link.Meta.Title)
|
||||
return err
|
||||
}
|
||||
|
||||
func (table *Table) Render(w io.Writer) error {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString("<table class='table'>")
|
||||
for _, row := range table.Content {
|
||||
buf.WriteString("<tr>")
|
||||
for _, col := range row {
|
||||
buf.WriteString("<td>")
|
||||
buf.WriteString(col)
|
||||
buf.WriteString("</td>")
|
||||
}
|
||||
buf.WriteString("</tr>")
|
||||
}
|
||||
buf.WriteString("</table>")
|
||||
_, err := buf.WriteTo(w)
|
||||
return err
|
||||
}
|
||||
func (list *List) Render(w io.Writer) error {
|
||||
var buf bytes.Buffer
|
||||
|
||||
var tag string
|
||||
if list.Style == "ordered" {
|
||||
tag = "ol"
|
||||
} else {
|
||||
tag = "ul"
|
||||
}
|
||||
buf.WriteString("<")
|
||||
buf.WriteString(tag)
|
||||
buf.WriteString(">")
|
||||
for _, item := range list.Items {
|
||||
buf.WriteString("<li>")
|
||||
buf.WriteString(item)
|
||||
buf.WriteString("</li>")
|
||||
}
|
||||
buf.WriteString("</")
|
||||
buf.WriteString(tag)
|
||||
buf.WriteString(">")
|
||||
|
||||
_, err := buf.WriteTo(w)
|
||||
return err
|
||||
}
|
||||
|
||||
func (header *Header) Render(w io.Writer) error {
|
||||
_, err := fmt.Fprintf(w, "<h%d>%s</h%d>", header.Level, header.Text, header.Level)
|
||||
return err
|
||||
}
|
||||
|
||||
func (para Paragraph) Render(w io.Writer) error {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString("<p>")
|
||||
buf.WriteString(para.Text)
|
||||
buf.WriteString("</p>")
|
||||
_, err := buf.WriteTo(w)
|
||||
return err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user