chore: implement html renderer

This commit is contained in:
Steven 2023-12-14 00:04:20 +08:00
parent 43ef9eaced
commit 5266a62685
5 changed files with 103 additions and 12 deletions

View file

@ -17,17 +17,18 @@ func NewParagraphParser() *ParagraphParser {
func (*ParagraphParser) Match(tokens []*tokenizer.Token) (int, bool) {
contentTokens := []*tokenizer.Token{}
cursor := 0
for ; cursor < len(tokens); cursor++ {
token := tokens[cursor]
for _, token := range tokens {
contentTokens = append(contentTokens, token)
if token.Type == tokenizer.Newline {
break
}
contentTokens = append(contentTokens, token)
}
if len(contentTokens) == 0 {
return 0, false
}
if len(contentTokens) == 1 && contentTokens[0].Type == tokenizer.Newline {
return 0, false
}
return len(contentTokens), true
}

View file

@ -18,6 +18,10 @@ func TestParagraphParser(t *testing.T) {
text: "",
paragraph: nil,
},
{
text: "\n",
paragraph: nil,
},
{
text: "Hello world!",
paragraph: &ast.Paragraph{
@ -28,6 +32,28 @@ func TestParagraphParser(t *testing.T) {
},
},
},
{
text: "Hello world!\n",
paragraph: &ast.Paragraph{
Children: []ast.Node{
&ast.Text{
Content: "Hello world!",
},
&ast.LineBreak{},
},
},
},
{
text: "Hello world!\n\nNew paragraph.",
paragraph: &ast.Paragraph{
Children: []ast.Node{
&ast.Text{
Content: "Hello world!",
},
&ast.LineBreak{},
},
},
},
}
for _, test := range tests {

View file

@ -57,9 +57,9 @@ func TestParser(t *testing.T) {
&ast.Text{
Content: "!",
},
&ast.LineBreak{},
},
},
&ast.LineBreak{},
&ast.Paragraph{
Children: []ast.Node{
&ast.Text{
@ -84,15 +84,36 @@ func TestParser(t *testing.T) {
&ast.Text{
Content: "!",
},
&ast.LineBreak{},
},
},
&ast.LineBreak{},
&ast.CodeBlock{
Language: "javascript",
Content: "console.log(\"Hello world!\");",
},
},
},
{
text: "Hello world!\n\nNew paragraph.",
nodes: []ast.Node{
&ast.Paragraph{
Children: []ast.Node{
&ast.Text{
Content: "Hello world!",
},
&ast.LineBreak{},
},
},
&ast.LineBreak{},
&ast.Paragraph{
Children: []ast.Node{
&ast.Text{
Content: "New paragraph.",
},
},
},
},
},
}
for _, test := range tests {

View file

@ -11,17 +11,17 @@ import (
// nolint
type HTMLRenderer struct {
output *bytes.Buffer
context *renderContext
context *RendererContext
}
type renderContext struct {
type RendererContext struct {
}
// NewHTMLRenderer creates a new HTMLRenderer.
func NewHTMLRenderer() *HTMLRenderer {
return &HTMLRenderer{
output: new(bytes.Buffer),
context: &renderContext{},
context: &RendererContext{},
}
}
@ -57,6 +57,43 @@ func (r *HTMLRenderer) RenderNode(node ast.Node) {
if prevSibling == nil || prevSibling.Type() != ast.NodeTypeBlockquote {
r.output.WriteString("</blockquote>")
}
case *ast.BoldItalic:
r.output.WriteString("<strong><em>")
r.output.WriteString(n.Content)
r.output.WriteString("</em></strong>")
case *ast.Bold:
r.output.WriteString("<strong>")
r.output.WriteString(n.Content)
r.output.WriteString("</strong>")
case *ast.Italic:
r.output.WriteString("<em>")
r.output.WriteString(n.Content)
r.output.WriteString("</em>")
case *ast.Code:
r.output.WriteString("<code>")
r.output.WriteString(n.Content)
r.output.WriteString("</code>")
case *ast.Link:
r.output.WriteString(`<a href="`)
r.output.WriteString(n.URL)
r.output.WriteString(`">`)
r.output.WriteString(n.Text)
r.output.WriteString("</a>")
case *ast.Image:
r.output.WriteString(`<img src="`)
r.output.WriteString(n.URL)
r.output.WriteString(`" alt="`)
r.output.WriteString(n.AltText)
r.output.WriteString(`" />`)
case *ast.Tag:
r.output.WriteString(`<span>`)
r.output.WriteString(`# `)
r.output.WriteString(n.Content)
r.output.WriteString(`</span>`)
case *ast.Strikethrough:
r.output.WriteString(`<del>`)
r.output.WriteString(n.Content)
r.output.WriteString(`</del>`)
case *ast.Text:
r.output.WriteString(n.Content)
default:

View file

@ -22,6 +22,14 @@ func TestHTMLRenderer(t *testing.T) {
text: "> Hello\n> world!",
expected: `<blockquote>Hello<br>world!</blockquote>`,
},
{
text: "*Hello* world!",
expected: `<p><em>Hello</em> world!</p>`,
},
{
text: "**Hello** world!",
expected: `<p><strong>Hello</strong> world!</p>`,
},
}
for _, test := range tests {
@ -29,8 +37,6 @@ func TestHTMLRenderer(t *testing.T) {
nodes, err := parser.Parse(tokens)
require.NoError(t, err)
actual := NewHTMLRenderer().Render(nodes)
if actual != test.expected {
t.Errorf("expected: %s, actual: %s", test.expected, actual)
}
require.Equal(t, test.expected, actual)
}
}