Skip to content

Instantly share code, notes, and snippets.

@suzuken
Created October 17, 2019 11:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save suzuken/c1bbbfed26b5127d6d6a6867b7909085 to your computer and use it in GitHub Desktop.
Save suzuken/c1bbbfed26b5127d6d6a6867b7909085 to your computer and use it in GitHub Desktop.
package parser
import (
"bytes"
"fmt"
"strings"
)
// Parse はmarkdownをいい感じにパースして
// HTMLに変換します
func Parse(in string) (string, error) {
if strings.HasPrefix(in, "# ") {
body := strings.TrimSpace(in[2:])
return fmt.Sprintf("<h1>%s</h1>", body), nil
}
if strings.HasPrefix(in, "- ") {
var output string
lines := strings.Split(in, "\n")
for _, l := range lines {
body := strings.TrimSpace(l[2:])
output += fmt.Sprintf("<li>%s</li>", body)
}
return fmt.Sprintf("<ul>%s</ul>", output), nil
}
// table
if strings.HasPrefix(in, "| ") {
lines := strings.Split(in, "\n")
headers := make([]string, 0)
bodies := make([]string, 0)
for k, v := range lines {
if k == 0 {
h := strings.Split(v, "|")
for _, hh := range h {
if hh != "" {
headers = append(headers, hh)
}
}
continue
}
// NOTE: table head spliter
if k == 1 {
if v == "| --- | --- |" {
continue
}
return in, nil
}
// body
if strings.HasPrefix(v, "| ") {
b := strings.Split(v, "|")
for _, bb := range b {
if bb != "" {
bodies = append(bodies, bb)
}
}
}
}
var buf bytes.Buffer
buf.WriteString("<table><thead>")
buf.WriteString("<tr>")
for _, v := range headers {
buf.WriteString("<th>")
buf.WriteString(strings.TrimSpace(v))
buf.WriteString("</th>")
}
buf.WriteString("</tr>")
buf.WriteString("</thead>")
buf.WriteString("<tbody>")
buf.WriteString("<tr>")
for _, v := range bodies {
buf.WriteString("<td>")
buf.WriteString(strings.TrimSpace(v))
buf.WriteString("</td>")
}
buf.WriteString("</tr>")
buf.WriteString("</tbody>")
buf.WriteString("</table>")
// return `<table><thead><tr><th>foo</th><th>bar</th></tr></thead><tbody><tr><td>baz</td><td>bim</td></tr></tbody></table>`, nil
return buf.String(), nil
}
return in, nil
}
package parser
import "testing"
type T struct {
in, out string
}
func TestParse(t *testing.T) {
cases := []T{
{"test", "test"},
{"aaa", "aaa"},
// headings
{"#aaa", "#aaa"},
{"# aaa", "<h1>aaa</h1>"},
{"# bbb", "<h1>bbb</h1>"},
{"# ccc ", "<h1>ccc</h1>"},
// list
{"- list", "<ul><li>list</li></ul>"},
{"- aaa", "<ul><li>aaa</li></ul>"},
{"- aaa\n- bbb", "<ul><li>aaa</li><li>bbb</li></ul>"},
{"- aaa\n- bbb\n- ccc", "<ul><li>aaa</li><li>bbb</li><li>ccc</li></ul>"},
{"| foo | bar |\n", "| foo | bar |\n"},
{
"| foo | bar |\n| --- | --- |\n| baz | bim |",
`<table><thead><tr><th>foo</th><th>bar</th></tr></thead><tbody><tr><td>baz</td><td>bim</td></tr></tbody></table>`},
}
for i, v := range cases {
tt, _ := Parse(v.in)
if tt != v.out {
t.Errorf("(#%d) want %s got %s", i, v.out, tt)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment