wiki/render.go

172 lines
3.7 KiB
Go

package main
import (
"bytes"
"encoding/json"
"fmt"
)
type Block struct {
Type string
Data json.RawMessage
}
type Paragraph struct {
Text string
}
type Code struct {
Code string
}
type List struct {
Style string
Items []string
}
type Header struct {
Level int
Text string
}
type ChecklistItem struct {
Text string
Checked bool
}
type Checklist struct {
Style string
Items []ChecklistItem
}
type Link struct {
Link string
Meta LinkResponseMeta
}
type Table struct {
Content [][]string
}
type Document struct {
Time int64
Version string
Blocks []Block
}
func renderJSON(text string) (string, error) {
var data Document
err := json.Unmarshal([]byte(text), &data)
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, &para)
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)
}
return buf.String(), nil
}