From eb3a072bcf3ec3f9de126e5b644bf5a0e78b32c1 Mon Sep 17 00:00:00 2001 From: Peter Stuifzand Date: Sun, 25 Aug 2019 15:40:56 +0200 Subject: [PATCH] Refactor renderer --- render.go | 266 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 160 insertions(+), 106 deletions(-) diff --git a/render.go b/render.go index 2f9f185..0c4e5b6 100644 --- a/render.go +++ b/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("") - for _, row := range table.Content { - buf.WriteString("") - for _, col := range row { - buf.WriteString("") - } - buf.WriteString("") - } - buf.WriteString("
") - buf.WriteString(col) - buf.WriteString("
") - 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, `%s`, 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("
  • ") - buf.WriteString(item) - buf.WriteString("
  • ") - } - 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, "%s", 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("

    ") - buf.WriteString(para.Text) - buf.WriteString("

    ") - 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("
    ")
    -			buf.WriteString(code.Code)
    -			buf.WriteString("
    ") - 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("

    ") - - buf.WriteString(``) - if item.Checked { - buf.WriteString(` `) - buf.WriteString(` `) - buf.WriteString(` `) - buf.WriteString(` `) - } - buf.WriteString(``) - buf.WriteString(item.Text) - buf.WriteString("

    ") - } - 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(`
    `) + for _, item := range checklist.Items { + buf.WriteString(`
    `) + + buf.WriteString(``) + if item.Checked { + buf.WriteString(``) + } + buf.WriteString(``) + buf.WriteString(`
    `) + buf.WriteString(item.Text) + buf.WriteString("
    ") + buf.WriteString("
    ") + } + buf.WriteString("
    ") + _, err := buf.WriteTo(w) + return err +} + +func (code *Code) Render(w io.Writer) error { + var buf bytes.Buffer + buf.WriteString("
    ")
    +	buf.WriteString(code.Code)
    +	buf.WriteString("
    ") + _, err := buf.WriteTo(w) + return err +} + +func (link *Link) Render(w io.Writer) error { + // TODO(peter): improve link rendering + _, err := fmt.Fprintf(w, `%s`, link.Link, link.Meta.Title) + return err +} + +func (table *Table) Render(w io.Writer) error { + var buf bytes.Buffer + buf.WriteString("") + for _, row := range table.Content { + buf.WriteString("") + for _, col := range row { + buf.WriteString("") + } + buf.WriteString("") + } + buf.WriteString("
    ") + buf.WriteString(col) + buf.WriteString("
    ") + _, 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("
  • ") + buf.WriteString(item) + buf.WriteString("
  • ") + } + buf.WriteString("") + + _, err := buf.WriteTo(w) + return err +} + +func (header *Header) Render(w io.Writer) error { + _, err := fmt.Fprintf(w, "%s", header.Level, header.Text, header.Level) + return err +} + +func (para Paragraph) Render(w io.Writer) error { + var buf bytes.Buffer + buf.WriteString("

    ") + buf.WriteString(para.Text) + buf.WriteString("

    ") + _, err := buf.WriteTo(w) + return err +}