mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
chore: update parser tests
This commit is contained in:
@@ -42,7 +42,7 @@ func (p *BlockquoteParser) Parse(tokens []*tokenizer.Token) (ast.Node, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
contentTokens := tokens[2:size]
|
contentTokens := tokens[2:size]
|
||||||
children, err := ParseInline(contentTokens)
|
children, err := ParseBlockWithParsers(contentTokens, []BlockParser{NewParagraphParser(), NewLineBreakParser()})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -18,8 +18,12 @@ func TestBlockquoteParser(t *testing.T) {
|
|||||||
text: "> Hello world",
|
text: "> Hello world",
|
||||||
blockquote: &ast.Blockquote{
|
blockquote: &ast.Blockquote{
|
||||||
Children: []ast.Node{
|
Children: []ast.Node{
|
||||||
&ast.Text{
|
&ast.Paragraph{
|
||||||
Content: "Hello world",
|
Children: []ast.Node{
|
||||||
|
&ast.Text{
|
||||||
|
Content: "Hello world",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -28,10 +32,13 @@ func TestBlockquoteParser(t *testing.T) {
|
|||||||
text: "> Hello\nworld",
|
text: "> Hello\nworld",
|
||||||
blockquote: &ast.Blockquote{
|
blockquote: &ast.Blockquote{
|
||||||
Children: []ast.Node{
|
Children: []ast.Node{
|
||||||
&ast.Text{
|
&ast.Paragraph{
|
||||||
Content: "Hello",
|
Children: []ast.Node{
|
||||||
|
&ast.Text{
|
||||||
|
Content: "Hello",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
&ast.LineBreak{},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@@ -14,30 +14,27 @@ func NewHeadingParser() *HeadingParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (*HeadingParser) Match(tokens []*tokenizer.Token) (int, bool) {
|
func (*HeadingParser) Match(tokens []*tokenizer.Token) (int, bool) {
|
||||||
cursor := 0
|
level := 0
|
||||||
for _, token := range tokens {
|
for _, token := range tokens {
|
||||||
if token.Type == tokenizer.PoundSign {
|
if token.Type == tokenizer.PoundSign {
|
||||||
cursor++
|
level++
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(tokens) <= cursor+1 {
|
if len(tokens) <= level+1 {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
if tokens[cursor].Type != tokenizer.Space {
|
if tokens[level].Type != tokenizer.Space {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
level := cursor
|
|
||||||
if level == 0 || level > 6 {
|
if level == 0 || level > 6 {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor++
|
|
||||||
contentTokens := []*tokenizer.Token{}
|
contentTokens := []*tokenizer.Token{}
|
||||||
for _, token := range tokens[cursor:] {
|
for _, token := range tokens[level+1:] {
|
||||||
contentTokens = append(contentTokens, token)
|
contentTokens = append(contentTokens, token)
|
||||||
cursor++
|
|
||||||
if token.Type == tokenizer.Newline {
|
if token.Type == tokenizer.Newline {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -46,7 +43,7 @@ func (*HeadingParser) Match(tokens []*tokenizer.Token) (int, bool) {
|
|||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
return cursor, true
|
return len(contentTokens) + level + 1, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *HeadingParser) Parse(tokens []*tokenizer.Token) (ast.Node, error) {
|
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]
|
contentTokens := tokens[level+1 : size]
|
||||||
|
if contentTokens[len(contentTokens)-1].Type == tokenizer.Newline {
|
||||||
|
contentTokens = contentTokens[:len(contentTokens)-1]
|
||||||
|
}
|
||||||
children, err := ParseInline(contentTokens)
|
children, err := ParseInline(contentTokens)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@@ -19,7 +19,7 @@ func TestHeadingParser(t *testing.T) {
|
|||||||
heading: nil,
|
heading: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "## Hello World",
|
text: "## Hello World\n123",
|
||||||
heading: &ast.Heading{
|
heading: &ast.Heading{
|
||||||
Level: 2,
|
Level: 2,
|
||||||
Children: []ast.Node{
|
Children: []ast.Node{
|
||||||
@@ -53,7 +53,6 @@ Hello World`,
|
|||||||
&ast.Text{
|
&ast.Text{
|
||||||
Content: "123 ",
|
Content: "123 ",
|
||||||
},
|
},
|
||||||
&ast.LineBreak{},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@@ -43,8 +43,7 @@ func (p *OrderedListParser) Parse(tokens []*tokenizer.Token) (ast.Node, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
contentTokens := tokens[3:size]
|
contentTokens := tokens[3:size]
|
||||||
lastToken := contentTokens[len(contentTokens)-1]
|
if contentTokens[len(contentTokens)-1].Type == tokenizer.Newline {
|
||||||
if lastToken.Type == tokenizer.Newline {
|
|
||||||
contentTokens = contentTokens[:len(contentTokens)-1]
|
contentTokens = contentTokens[:len(contentTokens)-1]
|
||||||
}
|
}
|
||||||
children, err := ParseInline(contentTokens)
|
children, err := ParseInline(contentTokens)
|
||||||
|
@@ -39,6 +39,9 @@ func (p *ParagraphParser) Parse(tokens []*tokenizer.Token) (ast.Node, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
contentTokens := tokens[:size]
|
contentTokens := tokens[:size]
|
||||||
|
if contentTokens[len(contentTokens)-1].Type == tokenizer.Newline {
|
||||||
|
contentTokens = contentTokens[:len(contentTokens)-1]
|
||||||
|
}
|
||||||
children, err := ParseInline(contentTokens)
|
children, err := ParseInline(contentTokens)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@@ -39,7 +39,6 @@ func TestParagraphParser(t *testing.T) {
|
|||||||
&ast.Text{
|
&ast.Text{
|
||||||
Content: "Hello world!",
|
Content: "Hello world!",
|
||||||
},
|
},
|
||||||
&ast.LineBreak{},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -50,7 +49,6 @@ func TestParagraphParser(t *testing.T) {
|
|||||||
&ast.Text{
|
&ast.Text{
|
||||||
Content: "Hello world!",
|
Content: "Hello world!",
|
||||||
},
|
},
|
||||||
&ast.LineBreak{},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@@ -65,7 +65,6 @@ func TestParser(t *testing.T) {
|
|||||||
&ast.Text{
|
&ast.Text{
|
||||||
Content: "!",
|
Content: "!",
|
||||||
},
|
},
|
||||||
&ast.LineBreak{},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&ast.Paragraph{
|
&ast.Paragraph{
|
||||||
@@ -96,7 +95,6 @@ func TestParser(t *testing.T) {
|
|||||||
&ast.Text{
|
&ast.Text{
|
||||||
Content: "!",
|
Content: "!",
|
||||||
},
|
},
|
||||||
&ast.LineBreak{},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&ast.CodeBlock{
|
&ast.CodeBlock{
|
||||||
@@ -113,7 +111,6 @@ func TestParser(t *testing.T) {
|
|||||||
&ast.Text{
|
&ast.Text{
|
||||||
Content: "Hello world!",
|
Content: "Hello world!",
|
||||||
},
|
},
|
||||||
&ast.LineBreak{},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&ast.LineBreak{},
|
&ast.LineBreak{},
|
||||||
|
@@ -44,8 +44,7 @@ func (p *UnorderedListParser) Parse(tokens []*tokenizer.Token) (ast.Node, error)
|
|||||||
|
|
||||||
symbolToken := tokens[0]
|
symbolToken := tokens[0]
|
||||||
contentTokens := tokens[2:size]
|
contentTokens := tokens[2:size]
|
||||||
lastToken := contentTokens[len(contentTokens)-1]
|
if contentTokens[len(contentTokens)-1].Type == tokenizer.Newline {
|
||||||
if lastToken.Type == tokenizer.Newline {
|
|
||||||
contentTokens = contentTokens[:len(contentTokens)-1]
|
contentTokens = contentTokens[:len(contentTokens)-1]
|
||||||
}
|
}
|
||||||
children, err := ParseInline(contentTokens)
|
children, err := ParseInline(contentTokens)
|
||||||
|
@@ -24,12 +24,16 @@ func TestHTMLRender(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "> Hello\n> world!",
|
text: "> Hello\n> world!",
|
||||||
expected: `<blockquote>Hello<br>world!</blockquote>`,
|
expected: `<blockquote><p>Hello</p><p>world!</p></blockquote>`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "*Hello* world!",
|
text: "*Hello* world!",
|
||||||
expected: `<p><em>Hello</em> world!</p>`,
|
expected: `<p><em>Hello</em> world!</p>`,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
text: "Hello world!\n\nNew paragraph.",
|
||||||
|
expected: "<p>Hello world!</p><br><p>New paragraph.</p>",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
text: "**Hello** world!",
|
text: "**Hello** world!",
|
||||||
expected: `<p><strong>Hello</strong> world!</p>`,
|
expected: `<p><strong>Hello</strong> world!</p>`,
|
||||||
|
@@ -2,6 +2,7 @@ package string
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/usememos/memos/plugin/gomark/ast"
|
"github.com/usememos/memos/plugin/gomark/ast"
|
||||||
)
|
)
|
||||||
@@ -84,6 +85,7 @@ func (r *StringRender) renderLineBreak(_ *ast.LineBreak) {
|
|||||||
|
|
||||||
func (r *StringRender) renderParagraph(node *ast.Paragraph) {
|
func (r *StringRender) renderParagraph(node *ast.Paragraph) {
|
||||||
r.RenderNodes(node.Children)
|
r.RenderNodes(node.Children)
|
||||||
|
r.output.WriteString("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *StringRender) renderCodeBlock(node *ast.CodeBlock) {
|
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) {
|
func (r *StringRender) renderUnorderedList(node *ast.UnorderedList) {
|
||||||
prevSibling, nextSibling := node.PrevSibling(), node.NextSibling()
|
r.output.WriteString(node.Symbol)
|
||||||
if prevSibling == nil || prevSibling.Type() != ast.UnorderedListNode {
|
|
||||||
r.output.WriteString("\n")
|
|
||||||
}
|
|
||||||
r.output.WriteString("* ")
|
|
||||||
r.RenderNodes(node.Children)
|
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) {
|
func (r *StringRender) renderOrderedList(node *ast.OrderedList) {
|
||||||
prevSibling, nextSibling := node.PrevSibling(), node.NextSibling()
|
r.output.WriteString(fmt.Sprintf("%s. ", node.Number))
|
||||||
if prevSibling == nil || prevSibling.Type() != ast.OrderedListNode {
|
|
||||||
r.output.WriteString("\n")
|
|
||||||
}
|
|
||||||
r.output.WriteString("1. ")
|
|
||||||
r.RenderNodes(node.Children)
|
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) {
|
func (r *StringRender) renderText(node *ast.Text) {
|
||||||
|
@@ -14,17 +14,25 @@ func TestStringRender(t *testing.T) {
|
|||||||
text string
|
text string
|
||||||
expected string
|
expected string
|
||||||
}{
|
}{
|
||||||
|
{
|
||||||
|
text: "",
|
||||||
|
expected: "",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
text: "Hello world!",
|
text: "Hello world!",
|
||||||
expected: `Hello world!`,
|
expected: "Hello world!\n",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "**Hello** world!",
|
text: "**Hello** world!",
|
||||||
expected: `Hello world!`,
|
expected: "Hello world!\n",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "**[your/slash](https://example.com)** world!",
|
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",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user