diff --git a/plugin/gomark/parser/blockquote.go b/plugin/gomark/parser/blockquote.go index 240c0de2..479c7ace 100644 --- a/plugin/gomark/parser/blockquote.go +++ b/plugin/gomark/parser/blockquote.go @@ -42,7 +42,7 @@ func (p *BlockquoteParser) Parse(tokens []*tokenizer.Token) (ast.Node, error) { } contentTokens := tokens[2:size] - children, err := ParseInline(contentTokens) + children, err := ParseBlockWithParsers(contentTokens, []BlockParser{NewParagraphParser(), NewLineBreakParser()}) if err != nil { return nil, err } diff --git a/plugin/gomark/parser/blockquote_test.go b/plugin/gomark/parser/blockquote_test.go index c3d5a049..c7568074 100644 --- a/plugin/gomark/parser/blockquote_test.go +++ b/plugin/gomark/parser/blockquote_test.go @@ -18,8 +18,12 @@ func TestBlockquoteParser(t *testing.T) { text: "> Hello world", blockquote: &ast.Blockquote{ Children: []ast.Node{ - &ast.Text{ - Content: "Hello world", + &ast.Paragraph{ + Children: []ast.Node{ + &ast.Text{ + Content: "Hello world", + }, + }, }, }, }, @@ -28,10 +32,13 @@ func TestBlockquoteParser(t *testing.T) { text: "> Hello\nworld", blockquote: &ast.Blockquote{ Children: []ast.Node{ - &ast.Text{ - Content: "Hello", + &ast.Paragraph{ + Children: []ast.Node{ + &ast.Text{ + Content: "Hello", + }, + }, }, - &ast.LineBreak{}, }, }, }, diff --git a/plugin/gomark/parser/heading.go b/plugin/gomark/parser/heading.go index bd79f146..9e6754a0 100644 --- a/plugin/gomark/parser/heading.go +++ b/plugin/gomark/parser/heading.go @@ -14,30 +14,27 @@ func NewHeadingParser() *HeadingParser { } func (*HeadingParser) Match(tokens []*tokenizer.Token) (int, bool) { - cursor := 0 + level := 0 for _, token := range tokens { if token.Type == tokenizer.PoundSign { - cursor++ + level++ } else { break } } - if len(tokens) <= cursor+1 { + if len(tokens) <= level+1 { return 0, false } - if tokens[cursor].Type != tokenizer.Space { + if tokens[level].Type != tokenizer.Space { return 0, false } - level := cursor if level == 0 || level > 6 { return 0, false } - cursor++ contentTokens := []*tokenizer.Token{} - for _, token := range tokens[cursor:] { + for _, token := range tokens[level+1:] { contentTokens = append(contentTokens, token) - cursor++ if token.Type == tokenizer.Newline { break } @@ -46,7 +43,7 @@ func (*HeadingParser) Match(tokens []*tokenizer.Token) (int, bool) { return 0, false } - return cursor, true + return len(contentTokens) + level + 1, true } func (p *HeadingParser) Parse(tokens []*tokenizer.Token) (ast.Node, error) { @@ -65,6 +62,9 @@ func (p *HeadingParser) Parse(tokens []*tokenizer.Token) (ast.Node, error) { } contentTokens := tokens[level+1 : size] + if contentTokens[len(contentTokens)-1].Type == tokenizer.Newline { + contentTokens = contentTokens[:len(contentTokens)-1] + } children, err := ParseInline(contentTokens) if err != nil { return nil, err diff --git a/plugin/gomark/parser/heading_test.go b/plugin/gomark/parser/heading_test.go index 43c48df7..a68bb460 100644 --- a/plugin/gomark/parser/heading_test.go +++ b/plugin/gomark/parser/heading_test.go @@ -19,7 +19,7 @@ func TestHeadingParser(t *testing.T) { heading: nil, }, { - text: "## Hello World", + text: "## Hello World\n123", heading: &ast.Heading{ Level: 2, Children: []ast.Node{ @@ -53,7 +53,6 @@ Hello World`, &ast.Text{ Content: "123 ", }, - &ast.LineBreak{}, }, }, }, diff --git a/plugin/gomark/parser/ordered_list.go b/plugin/gomark/parser/ordered_list.go index b4c2f151..d0d4343a 100644 --- a/plugin/gomark/parser/ordered_list.go +++ b/plugin/gomark/parser/ordered_list.go @@ -43,8 +43,7 @@ func (p *OrderedListParser) Parse(tokens []*tokenizer.Token) (ast.Node, error) { } contentTokens := tokens[3:size] - lastToken := contentTokens[len(contentTokens)-1] - if lastToken.Type == tokenizer.Newline { + if contentTokens[len(contentTokens)-1].Type == tokenizer.Newline { contentTokens = contentTokens[:len(contentTokens)-1] } children, err := ParseInline(contentTokens) diff --git a/plugin/gomark/parser/paragraph.go b/plugin/gomark/parser/paragraph.go index c5edeb16..8ac5a5a1 100644 --- a/plugin/gomark/parser/paragraph.go +++ b/plugin/gomark/parser/paragraph.go @@ -39,6 +39,9 @@ func (p *ParagraphParser) Parse(tokens []*tokenizer.Token) (ast.Node, error) { } contentTokens := tokens[:size] + if contentTokens[len(contentTokens)-1].Type == tokenizer.Newline { + contentTokens = contentTokens[:len(contentTokens)-1] + } children, err := ParseInline(contentTokens) if err != nil { return nil, err diff --git a/plugin/gomark/parser/paragraph_test.go b/plugin/gomark/parser/paragraph_test.go index e2f50249..cf154dd2 100644 --- a/plugin/gomark/parser/paragraph_test.go +++ b/plugin/gomark/parser/paragraph_test.go @@ -39,7 +39,6 @@ func TestParagraphParser(t *testing.T) { &ast.Text{ Content: "Hello world!", }, - &ast.LineBreak{}, }, }, }, @@ -50,7 +49,6 @@ func TestParagraphParser(t *testing.T) { &ast.Text{ Content: "Hello world!", }, - &ast.LineBreak{}, }, }, }, diff --git a/plugin/gomark/parser/parser_test.go b/plugin/gomark/parser/parser_test.go index 33e14ed2..602d09bc 100644 --- a/plugin/gomark/parser/parser_test.go +++ b/plugin/gomark/parser/parser_test.go @@ -65,7 +65,6 @@ func TestParser(t *testing.T) { &ast.Text{ Content: "!", }, - &ast.LineBreak{}, }, }, &ast.Paragraph{ @@ -96,7 +95,6 @@ func TestParser(t *testing.T) { &ast.Text{ Content: "!", }, - &ast.LineBreak{}, }, }, &ast.CodeBlock{ @@ -113,7 +111,6 @@ func TestParser(t *testing.T) { &ast.Text{ Content: "Hello world!", }, - &ast.LineBreak{}, }, }, &ast.LineBreak{}, diff --git a/plugin/gomark/parser/unordered_list.go b/plugin/gomark/parser/unordered_list.go index b98ca9c6..95e02cfd 100644 --- a/plugin/gomark/parser/unordered_list.go +++ b/plugin/gomark/parser/unordered_list.go @@ -44,8 +44,7 @@ func (p *UnorderedListParser) Parse(tokens []*tokenizer.Token) (ast.Node, error) symbolToken := tokens[0] contentTokens := tokens[2:size] - lastToken := contentTokens[len(contentTokens)-1] - if lastToken.Type == tokenizer.Newline { + if contentTokens[len(contentTokens)-1].Type == tokenizer.Newline { contentTokens = contentTokens[:len(contentTokens)-1] } children, err := ParseInline(contentTokens) diff --git a/plugin/gomark/render/html/html_test.go b/plugin/gomark/render/html/html_test.go index d7a3409e..fb6499a5 100644 --- a/plugin/gomark/render/html/html_test.go +++ b/plugin/gomark/render/html/html_test.go @@ -24,12 +24,16 @@ func TestHTMLRender(t *testing.T) { }, { text: "> Hello\n> world!", - expected: `
Hello`, + expected: `
world!
`, }, { text: "*Hello* world!", expected: `Hello
world!
Hello world!
`, }, + { + text: "Hello world!\n\nNew paragraph.", + expected: "Hello world!
New paragraph.
", + }, { text: "**Hello** world!", expected: `Hello world!
`, diff --git a/plugin/gomark/render/string/string.go b/plugin/gomark/render/string/string.go index e4d65cbf..f8a5dab0 100644 --- a/plugin/gomark/render/string/string.go +++ b/plugin/gomark/render/string/string.go @@ -2,6 +2,7 @@ package string import ( "bytes" + "fmt" "github.com/usememos/memos/plugin/gomark/ast" ) @@ -84,6 +85,7 @@ func (r *StringRender) renderLineBreak(_ *ast.LineBreak) { func (r *StringRender) renderParagraph(node *ast.Paragraph) { r.RenderNodes(node.Children) + r.output.WriteString("\n") } func (r *StringRender) renderCodeBlock(node *ast.CodeBlock) { @@ -106,27 +108,15 @@ func (r *StringRender) renderBlockquote(node *ast.Blockquote) { } func (r *StringRender) renderUnorderedList(node *ast.UnorderedList) { - prevSibling, nextSibling := node.PrevSibling(), node.NextSibling() - if prevSibling == nil || prevSibling.Type() != ast.UnorderedListNode { - r.output.WriteString("\n") - } - r.output.WriteString("* ") + r.output.WriteString(node.Symbol) r.RenderNodes(node.Children) - if nextSibling == nil || nextSibling.Type() != ast.UnorderedListNode { - r.output.WriteString("\n") - } + r.output.WriteString("\n") } func (r *StringRender) renderOrderedList(node *ast.OrderedList) { - prevSibling, nextSibling := node.PrevSibling(), node.NextSibling() - if prevSibling == nil || prevSibling.Type() != ast.OrderedListNode { - r.output.WriteString("\n") - } - r.output.WriteString("1. ") + r.output.WriteString(fmt.Sprintf("%s. ", node.Number)) r.RenderNodes(node.Children) - if nextSibling == nil || nextSibling.Type() != ast.OrderedListNode { - r.output.WriteString("\n") - } + r.output.WriteString("\n") } func (r *StringRender) renderText(node *ast.Text) { diff --git a/plugin/gomark/render/string/string_test.go b/plugin/gomark/render/string/string_test.go index 28971bbd..c6569068 100644 --- a/plugin/gomark/render/string/string_test.go +++ b/plugin/gomark/render/string/string_test.go @@ -14,17 +14,25 @@ func TestStringRender(t *testing.T) { text string expected string }{ + { + text: "", + expected: "", + }, { text: "Hello world!", - expected: `Hello world!`, + expected: "Hello world!\n", }, { text: "**Hello** world!", - expected: `Hello world!`, + expected: "Hello world!\n", }, { text: "**[your/slash](https://example.com)** world!", - expected: `your/slash world!`, + expected: "your/slash world!\n", + }, + { + text: "Test\n1. Hello\n2. World", + expected: "Test\n1. Hello\n2. World\n", }, }