From b4ff505cfe97b7a21744abe0b8ab7903bc3e077c Mon Sep 17 00:00:00 2001 From: Steven Date: Tue, 17 Sep 2024 18:05:49 +0800 Subject: [PATCH] refactor: list node --- ast/ast.go | 59 ++------ ast/block.go | 59 ++++++-- ast/utils.go | 23 --- parser/horizontal_rule_test.go | 51 ------- .../{ordered_list.go => ordered_list_item.go} | 10 +- parser/parser.go | 78 +++++++--- parser/{task_list.go => task_list_item.go} | 10 +- parser/{ => tests}/auto_link_test.go | 16 +-- parser/{ => tests}/blockquote_test.go | 24 ++-- parser/{ => tests}/bold_italic_test.go | 29 ++-- parser/{ => tests}/bold_test.go | 23 ++- parser/{ => tests}/code_block_test.go | 33 +++-- parser/{ => tests}/code_test.go | 17 ++- parser/{ => tests}/embedded_content_test.go | 31 ++-- parser/{ => tests}/escaping_character_test.go | 9 +- parser/{ => tests}/heading_test.go | 29 ++-- parser/{ => tests}/highlight_test.go | 17 ++- parser/tests/horizontal_rule_test.go | 50 +++++++ parser/{ => tests}/html_element_test.go | 18 +-- parser/{ => tests}/image_test.go | 25 ++-- parser/{ => tests}/italic_test.go | 23 ++- parser/{ => tests}/link_test.go | 21 ++- parser/{ => tests}/math_block_test.go | 15 +- parser/{ => tests}/math_test.go | 12 +- .../ordered_list_item_test.go} | 16 +-- parser/{ => tests}/paragraph_test.go | 27 ++-- parser/{ => tests}/parser_test.go | 133 +++++++++++++----- parser/{ => tests}/referenced_content_test.go | 27 ++-- parser/{ => tests}/spoiler_test.go | 18 +-- parser/{ => tests}/strikethrough_test.go | 22 +-- parser/{ => tests}/subscript_test.go | 22 +-- parser/{ => tests}/superscript_test.go | 23 ++- parser/{ => tests}/table_test.go | 17 ++- parser/{ => tests}/tag_test.go | 19 ++- .../task_list_item_test.go} | 20 ++- .../unordered_list_item_test.go} | 14 +- parser/tokenizer/tokenizer_test.go | 32 ++++- ...ordered_list.go => unordered_list_item.go} | 10 +- renderer/html/html.go | 49 +++---- renderer/html/html_test.go | 8 +- renderer/string/string.go | 29 ++-- renderer/string/string_test.go | 2 +- restore/restore.go | 3 - 43 files changed, 626 insertions(+), 547 deletions(-) delete mode 100644 ast/utils.go delete mode 100644 parser/horizontal_rule_test.go rename parser/{ordered_list.go => ordered_list_item.go} (77%) rename parser/{task_list.go => task_list_item.go} (85%) rename parser/{ => tests}/auto_link_test.go (66%) rename parser/{ => tests}/blockquote_test.go (76%) rename parser/{ => tests}/bold_italic_test.go (50%) rename parser/{ => tests}/bold_test.go (69%) rename parser/{ => tests}/code_block_test.go (56%) rename parser/{ => tests}/code_test.go (63%) rename parser/{ => tests}/embedded_content_test.go (58%) rename parser/{ => tests}/escaping_character_test.go (66%) rename parser/{ => tests}/heading_test.go (70%) rename parser/{ => tests}/highlight_test.go (63%) create mode 100644 parser/tests/horizontal_rule_test.go rename parser/{ => tests}/html_element_test.go (52%) rename parser/{ => tests}/image_test.go (57%) rename parser/{ => tests}/italic_test.go (60%) rename parser/{ => tests}/link_test.go (71%) rename parser/{ => tests}/math_block_test.go (62%) rename parser/{ => tests}/math_test.go (63%) rename parser/{ordered_list_test.go => tests/ordered_list_item_test.go} (73%) rename parser/{ => tests}/paragraph_test.go (63%) rename parser/{ => tests}/parser_test.go (67%) rename parser/{ => tests}/referenced_content_test.go (59%) rename parser/{ => tests}/spoiler_test.go (54%) rename parser/{ => tests}/strikethrough_test.go (53%) rename parser/{ => tests}/subscript_test.go (55%) rename parser/{ => tests}/superscript_test.go (54%) rename parser/{ => tests}/table_test.go (85%) rename parser/{ => tests}/tag_test.go (64%) rename parser/{task_list_test.go => tests/task_list_item_test.go} (71%) rename parser/{unordered_list_test.go => tests/unordered_list_item_test.go} (70%) rename parser/{unordered_list.go => unordered_list_item.go} (77%) diff --git a/ast/ast.go b/ast/ast.go index f5bb4d2..c0ec0ce 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -4,18 +4,20 @@ type NodeType string // Block nodes. const ( - LineBreakNode NodeType = "LINE_BREAK" - ParagraphNode NodeType = "PARAGRAPH" - CodeBlockNode NodeType = "CODE_BLOCK" - HeadingNode NodeType = "HEADING" - HorizontalRuleNode NodeType = "HORIZONTAL_RULE" - BlockquoteNode NodeType = "BLOCKQUOTE" - OrderedListNode NodeType = "ORDERED_LIST" - UnorderedListNode NodeType = "UNORDERED_LIST" - TaskListNode NodeType = "TASK_LIST" - MathBlockNode NodeType = "MATH_BLOCK" - TableNode NodeType = "TABLE" - EmbeddedContentNode NodeType = "EMBEDDED_CONTENT" + LineBreakNode NodeType = "LINE_BREAK" + ParagraphNode NodeType = "PARAGRAPH" + CodeBlockNode NodeType = "CODE_BLOCK" + HeadingNode NodeType = "HEADING" + HorizontalRuleNode NodeType = "HORIZONTAL_RULE" + BlockquoteNode NodeType = "BLOCKQUOTE" + ListNode NodeType = "LIST" + ListItemNode NodeType = "LIST_ITEM" + OrderedListItemNode NodeType = "ORDERED_LIST_ITEM" + UnorderedListItemNode NodeType = "UNORDERED_LIST_ITEM" + TaskListItemNode NodeType = "TASK_LIST_ITEM" + MathBlockNode NodeType = "MATH_BLOCK" + TableNode NodeType = "TABLE" + EmbeddedContentNode NodeType = "EMBEDDED_CONTENT" ) // Inline nodes. @@ -46,45 +48,14 @@ type Node interface { // Restore returns a string representation of this node. Restore() string - - // PrevSibling returns a previous sibling node of this node. - PrevSibling() Node - - // NextSibling returns a next sibling node of this node. - NextSibling() Node - - // SetPrevSibling sets a previous sibling node to this node. - SetPrevSibling(Node) - - // SetNextSibling sets a next sibling node to this node. - SetNextSibling(Node) } type BaseNode struct { - prevSibling Node - - nextSibling Node -} - -func (n *BaseNode) PrevSibling() Node { - return n.prevSibling -} - -func (n *BaseNode) NextSibling() Node { - return n.nextSibling -} - -func (n *BaseNode) SetPrevSibling(node Node) { - n.prevSibling = node -} - -func (n *BaseNode) SetNextSibling(node Node) { - n.nextSibling = node } func IsBlockNode(node Node) bool { switch node.Type() { - case ParagraphNode, CodeBlockNode, HeadingNode, HorizontalRuleNode, BlockquoteNode, OrderedListNode, UnorderedListNode, TaskListNode, MathBlockNode, TableNode, EmbeddedContentNode: + case ParagraphNode, CodeBlockNode, HeadingNode, HorizontalRuleNode, BlockquoteNode, ListNode, ListItemNode, OrderedListItemNode, UnorderedListItemNode, TaskListItemNode, TableNode, EmbeddedContentNode: return true default: return false diff --git a/ast/block.go b/ast/block.go index b33fa80..695261b 100644 --- a/ast/block.go +++ b/ast/block.go @@ -113,9 +113,40 @@ func (n *Blockquote) Restore() string { return result } -type OrderedList struct { +type List struct { BaseBlock + Children []Node +} + +func (*List) Type() NodeType { + return ListNode +} + +func (n *List) Restore() string { + var result string + for _, child := range n.Children { + result += child.Restore() + } + return result +} + +type ListItem struct { + BaseBlock +} + +func (*ListItem) Type() NodeType { + return ListItemNode +} + +func (*ListItem) Restore() string { + // Should be overridden. + return "" +} + +type OrderedListItem struct { + ListItem + // Number is the number of the list. Number string // Indent is the number of spaces. @@ -123,11 +154,11 @@ type OrderedList struct { Children []Node } -func (*OrderedList) Type() NodeType { - return OrderedListNode +func (*OrderedListItem) Type() NodeType { + return OrderedListItemNode } -func (n *OrderedList) Restore() string { +func (n *OrderedListItem) Restore() string { var result string for _, child := range n.Children { result += child.Restore() @@ -135,8 +166,8 @@ func (n *OrderedList) Restore() string { return fmt.Sprintf("%s%s. %s", strings.Repeat(" ", n.Indent), n.Number, result) } -type UnorderedList struct { - BaseBlock +type UnorderedListItem struct { + ListItem // Symbol is "*" or "-" or "+". Symbol string @@ -145,11 +176,11 @@ type UnorderedList struct { Children []Node } -func (*UnorderedList) Type() NodeType { - return UnorderedListNode +func (*UnorderedListItem) Type() NodeType { + return UnorderedListItemNode } -func (n *UnorderedList) Restore() string { +func (n *UnorderedListItem) Restore() string { var result string for _, child := range n.Children { result += child.Restore() @@ -157,8 +188,8 @@ func (n *UnorderedList) Restore() string { return fmt.Sprintf("%s%s %s", strings.Repeat(" ", n.Indent), n.Symbol, result) } -type TaskList struct { - BaseBlock +type TaskListItem struct { + ListItem // Symbol is "*" or "-" or "+". Symbol string @@ -168,11 +199,11 @@ type TaskList struct { Children []Node } -func (*TaskList) Type() NodeType { - return TaskListNode +func (*TaskListItem) Type() NodeType { + return TaskListItemNode } -func (n *TaskList) Restore() string { +func (n *TaskListItem) Restore() string { var result string for _, child := range n.Children { result += child.Restore() diff --git a/ast/utils.go b/ast/utils.go deleted file mode 100644 index a5a5fd5..0000000 --- a/ast/utils.go +++ /dev/null @@ -1,23 +0,0 @@ -package ast - -func FindPrevSiblingExceptLineBreak(node Node) Node { - if node == nil { - return nil - } - prev := node.PrevSibling() - if prev != nil && prev.Type() == LineBreakNode && prev.PrevSibling() != nil && prev.PrevSibling().Type() != LineBreakNode { - return FindPrevSiblingExceptLineBreak(prev) - } - return prev -} - -func FindNextSiblingExceptLineBreak(node Node) Node { - if node == nil { - return nil - } - next := node.NextSibling() - if next != nil && next.Type() == LineBreakNode && next.NextSibling() != nil && next.NextSibling().Type() != LineBreakNode { - return FindNextSiblingExceptLineBreak(next) - } - return next -} diff --git a/parser/horizontal_rule_test.go b/parser/horizontal_rule_test.go deleted file mode 100644 index 1754e7b..0000000 --- a/parser/horizontal_rule_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package parser - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/usememos/gomark/ast" - "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" -) - -func TestHorizontalRuleParser(t *testing.T) { - tests := []struct { - text string - horizontalRule ast.Node - }{ - { - text: "---", - horizontalRule: &ast.HorizontalRule{ - Symbol: "-", - }, - }, - { - text: "---\naaa", - horizontalRule: &ast.HorizontalRule{ - Symbol: "-", - }, - }, - { - text: "****", - horizontalRule: nil, - }, - { - text: "***", - horizontalRule: &ast.HorizontalRule{ - Symbol: "*", - }, - }, - { - text: "-*-", - horizontalRule: nil, - }, - } - - for _, test := range tests { - tokens := tokenizer.Tokenize(test.text) - node, _ := NewHorizontalRuleParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.horizontalRule}), restore.Restore([]ast.Node{node})) - } -} diff --git a/parser/ordered_list.go b/parser/ordered_list_item.go similarity index 77% rename from parser/ordered_list.go rename to parser/ordered_list_item.go index 199e4de..3c485b7 100644 --- a/parser/ordered_list.go +++ b/parser/ordered_list_item.go @@ -5,13 +5,13 @@ import ( "github.com/usememos/gomark/parser/tokenizer" ) -type OrderedListParser struct{} +type OrderedListItemParser struct{} -func NewOrderedListParser() *OrderedListParser { - return &OrderedListParser{} +func NewOrderedListItemParser() *OrderedListItemParser { + return &OrderedListItemParser{} } -func (*OrderedListParser) Match(tokens []*tokenizer.Token) (ast.Node, int) { +func (*OrderedListItemParser) Match(tokens []*tokenizer.Token) (ast.Node, int) { matchedTokens := tokenizer.GetFirstLine(tokens) indent := 0 for _, token := range matchedTokens { @@ -38,7 +38,7 @@ func (*OrderedListParser) Match(tokens []*tokenizer.Token) (ast.Node, int) { if err != nil { return nil, 0 } - return &ast.OrderedList{ + return &ast.OrderedListItem{ Number: matchedTokens[indent].Value, Indent: indent, Children: children, diff --git a/parser/parser.go b/parser/parser.go index f1b6b6f..201ca95 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -27,9 +27,9 @@ var defaultBlockParsers = []BlockParser{ NewHorizontalRuleParser(), NewHeadingParser(), NewBlockquoteParser(), - NewTaskListParser(), - NewUnorderedListParser(), - NewOrderedListParser(), + NewOrderedListItemParser(), + NewTaskListItemParser(), + NewUnorderedListItemParser(), NewMathBlockParser(), NewEmbeddedContentParser(), NewParagraphParser(), @@ -42,24 +42,18 @@ func ParseBlock(tokens []*tokenizer.Token) ([]ast.Node, error) { func ParseBlockWithParsers(tokens []*tokenizer.Token, blockParsers []BlockParser) ([]ast.Node, error) { nodes := []ast.Node{} - var prevNode ast.Node for len(tokens) > 0 { for _, blockParser := range blockParsers { node, size := blockParser.Match(tokens) if node != nil && size != 0 { // Consume matched tokens. tokens = tokens[size:] - if prevNode != nil { - prevNode.SetNextSibling(node) - node.SetPrevSibling(prevNode) - } - prevNode = node nodes = append(nodes, node) break } } } - return nodes, nil + return mergeListItemNodes(nodes), nil } var defaultInlineParsers = []InlineParser{ @@ -90,28 +84,66 @@ func ParseInline(tokens []*tokenizer.Token) ([]ast.Node, error) { func ParseInlineWithParsers(tokens []*tokenizer.Token, inlineParsers []InlineParser) ([]ast.Node, error) { nodes := []ast.Node{} - var prevNode ast.Node for len(tokens) > 0 { for _, inlineParser := range inlineParsers { node, size := inlineParser.Match(tokens) if node != nil && size != 0 { // Consume matched tokens. tokens = tokens[size:] - if prevNode != nil { - // Merge text nodes if possible. - if prevNode.Type() == ast.TextNode && node.Type() == ast.TextNode { - prevNode.(*ast.Text).Content += node.(*ast.Text).Content - break - } - - prevNode.SetNextSibling(node) - node.SetPrevSibling(prevNode) - } - prevNode = node nodes = append(nodes, node) break } } } - return nodes, nil + return mergeTextNodes(nodes), nil +} + +func mergeListItemNodes(nodes []ast.Node) []ast.Node { + if len(nodes) == 0 { + return nodes + } + result := []ast.Node{} + for i := 0; i < len(nodes); i++ { + var prevNode, prevResultNode ast.Node + if i > 0 { + prevNode = nodes[i-1] + } + if len(result) > 0 { + prevResultNode = result[len(result)-1] + } + switch nodes[i].(type) { + case *ast.OrderedListItem, *ast.UnorderedListItem, *ast.TaskListItem: + if prevResultNode == nil || prevResultNode.Type() != ast.ListNode { + prevResultNode = &ast.List{ + BaseBlock: ast.BaseBlock{}, + } + result = append(result, prevResultNode) + } + prevResultNode.(*ast.List).Children = append(prevResultNode.(*ast.List).Children, nodes[i]) + case *ast.LineBreak: + if prevResultNode != nil && prevResultNode.Type() == ast.ListNode && (prevNode == nil || prevNode.Type() != ast.LineBreakNode) { + prevResultNode.(*ast.List).Children = append(prevResultNode.(*ast.List).Children, nodes[i]) + } else { + result = append(result, nodes[i]) + } + default: + result = append(result, nodes[i]) + } + } + return result +} + +func mergeTextNodes(nodes []ast.Node) []ast.Node { + if len(nodes) == 0 { + return nodes + } + result := []ast.Node{nodes[0]} + for i := 1; i < len(nodes); i++ { + if nodes[i].Type() == ast.TextNode && result[len(result)-1].Type() == ast.TextNode { + result[len(result)-1].(*ast.Text).Content += nodes[i].(*ast.Text).Content + } else { + result = append(result, nodes[i]) + } + } + return result } diff --git a/parser/task_list.go b/parser/task_list_item.go similarity index 85% rename from parser/task_list.go rename to parser/task_list_item.go index 7d28c4a..56b515a 100644 --- a/parser/task_list.go +++ b/parser/task_list_item.go @@ -5,13 +5,13 @@ import ( "github.com/usememos/gomark/parser/tokenizer" ) -type TaskListParser struct{} +type TaskListItemParser struct{} -func NewTaskListParser() *TaskListParser { - return &TaskListParser{} +func NewTaskListItemParser() *TaskListItemParser { + return &TaskListItemParser{} } -func (*TaskListParser) Match(tokens []*tokenizer.Token) (ast.Node, int) { +func (*TaskListItemParser) Match(tokens []*tokenizer.Token) (ast.Node, int) { matchedTokens := tokenizer.GetFirstLine(tokens) indent := 0 for _, token := range matchedTokens { @@ -47,7 +47,7 @@ func (*TaskListParser) Match(tokens []*tokenizer.Token) (ast.Node, int) { if err != nil { return nil, 0 } - return &ast.TaskList{ + return &ast.TaskListItem{ Symbol: symbolToken.Type, Indent: indent, Complete: matchedTokens[indent+3].Value == "x", diff --git a/parser/auto_link_test.go b/parser/tests/auto_link_test.go similarity index 66% rename from parser/auto_link_test.go rename to parser/tests/auto_link_test.go index 14d9d0e..da33020 100644 --- a/parser/auto_link_test.go +++ b/parser/tests/auto_link_test.go @@ -1,4 +1,4 @@ -package parser +package tests import ( "testing" @@ -6,28 +6,28 @@ import ( "github.com/stretchr/testify/require" "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestAutoLinkParser(t *testing.T) { tests := []struct { text string - link ast.Node + node ast.Node }{ { text: "", - link: &ast.AutoLink{ + node: &ast.AutoLink{ URL: "https://example.com", }, }, { text: "https://example.com", - link: &ast.AutoLink{ + node: &ast.AutoLink{ URL: "https://example.com", IsRawText: true, }, @@ -36,7 +36,7 @@ func TestAutoLinkParser(t *testing.T) { for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewAutoLinkParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.link}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewAutoLinkParser().Match(tokens) + require.Equal(t, node, test.node) } } diff --git a/parser/blockquote_test.go b/parser/tests/blockquote_test.go similarity index 76% rename from parser/blockquote_test.go rename to parser/tests/blockquote_test.go index 1767071..b1077c7 100644 --- a/parser/blockquote_test.go +++ b/parser/tests/blockquote_test.go @@ -1,4 +1,4 @@ -package parser +package tests import ( "testing" @@ -6,22 +6,22 @@ import ( "github.com/stretchr/testify/require" "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestBlockquoteParser(t *testing.T) { tests := []struct { - text string - blockquote ast.Node + text string + node ast.Node }{ { - text: ">Hello world", - blockquote: nil, + text: ">Hello world", + node: nil, }, { text: "> Hello world", - blockquote: &ast.Blockquote{ + node: &ast.Blockquote{ Children: []ast.Node{ &ast.Paragraph{ Children: []ast.Node{ @@ -35,7 +35,7 @@ func TestBlockquoteParser(t *testing.T) { }, { text: "> 你好", - blockquote: &ast.Blockquote{ + node: &ast.Blockquote{ Children: []ast.Node{ &ast.Paragraph{ Children: []ast.Node{ @@ -49,7 +49,7 @@ func TestBlockquoteParser(t *testing.T) { }, { text: "> Hello\n> world", - blockquote: &ast.Blockquote{ + node: &ast.Blockquote{ Children: []ast.Node{ &ast.Paragraph{ Children: []ast.Node{ @@ -70,7 +70,7 @@ func TestBlockquoteParser(t *testing.T) { }, { text: "> Hello\n> > world", - blockquote: &ast.Blockquote{ + node: &ast.Blockquote{ Children: []ast.Node{ &ast.Paragraph{ Children: []ast.Node{ @@ -97,7 +97,7 @@ func TestBlockquoteParser(t *testing.T) { for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewBlockquoteParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.blockquote}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewBlockquoteParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/bold_italic_test.go b/parser/tests/bold_italic_test.go similarity index 50% rename from parser/bold_italic_test.go rename to parser/tests/bold_italic_test.go index b9b79e9..055bff5 100644 --- a/parser/bold_italic_test.go +++ b/parser/tests/bold_italic_test.go @@ -1,42 +1,41 @@ -package parser +package tests import ( "testing" "github.com/stretchr/testify/require" - "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestBoldItalicParser(t *testing.T) { tests := []struct { - text string - boldItalic ast.Node + text string + node ast.Node }{ { - text: "*Hello world!", - boldItalic: nil, + text: "*Hello world!", + node: nil, }, { - text: "*** Hello * *", - boldItalic: nil, + text: "*** Hello * *", + node: nil, }, { - text: "*** Hello **", - boldItalic: nil, + text: "*** Hello **", + node: nil, }, { text: "***Hello***", - boldItalic: &ast.BoldItalic{ + node: &ast.BoldItalic{ Symbol: "*", Content: "Hello", }, }, { text: "*** Hello ***", - boldItalic: &ast.BoldItalic{ + node: &ast.BoldItalic{ Symbol: "*", Content: " Hello ", }, @@ -45,7 +44,7 @@ func TestBoldItalicParser(t *testing.T) { for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewBoldItalicParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.boldItalic}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewBoldItalicParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/bold_test.go b/parser/tests/bold_test.go similarity index 69% rename from parser/bold_test.go rename to parser/tests/bold_test.go index b14a6cf..a314304 100644 --- a/parser/bold_test.go +++ b/parser/tests/bold_test.go @@ -1,31 +1,30 @@ -package parser +package tests import ( "testing" "github.com/stretchr/testify/require" - "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestBoldParser(t *testing.T) { tests := []struct { text string - bold ast.Node + node ast.Node }{ { text: "*Hello world!", - bold: nil, + node: nil, }, { text: "****", - bold: nil, + node: nil, }, { text: "**Hello**", - bold: &ast.Bold{ + node: &ast.Bold{ Symbol: "*", Children: []ast.Node{ &ast.Text{ @@ -36,7 +35,7 @@ func TestBoldParser(t *testing.T) { }, { text: "** Hello **", - bold: &ast.Bold{ + node: &ast.Bold{ Symbol: "*", Children: []ast.Node{ &ast.Text{ @@ -47,17 +46,17 @@ func TestBoldParser(t *testing.T) { }, { text: "** Hello * *", - bold: nil, + node: nil, }, { text: "* * Hello **", - bold: nil, + node: nil, }, } for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewBoldParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.bold}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewBoldParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/code_block_test.go b/parser/tests/code_block_test.go similarity index 56% rename from parser/code_block_test.go rename to parser/tests/code_block_test.go index 8c95bff..f58c9a3 100644 --- a/parser/code_block_test.go +++ b/parser/tests/code_block_test.go @@ -1,56 +1,55 @@ -package parser +package tests import ( "testing" "github.com/stretchr/testify/require" - "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestCodeBlockParser(t *testing.T) { tests := []struct { - text string - codeBlock ast.Node + text string + node ast.Node }{ { - text: "```Hello world!```", - codeBlock: nil, + text: "```Hello world!```", + node: nil, }, { text: "```\nHello\n```", - codeBlock: &ast.CodeBlock{ + node: &ast.CodeBlock{ Language: "", Content: "Hello", }, }, { text: "```\nHello world!\n```", - codeBlock: &ast.CodeBlock{ + node: &ast.CodeBlock{ Language: "", Content: "Hello world!", }, }, { text: "```java\nHello \n world!\n```", - codeBlock: &ast.CodeBlock{ + node: &ast.CodeBlock{ Language: "java", Content: "Hello \n world!", }, }, { - text: "```java\nHello \n world!\n```111", - codeBlock: nil, + text: "```java\nHello \n world!\n```111", + node: nil, }, { - text: "```java\nHello \n world!\n``` 111", - codeBlock: nil, + text: "```java\nHello \n world!\n``` 111", + node: nil, }, { text: "```java\nHello \n world!\n```\n123123", - codeBlock: &ast.CodeBlock{ + node: &ast.CodeBlock{ Language: "java", Content: "Hello \n world!", }, @@ -59,7 +58,7 @@ func TestCodeBlockParser(t *testing.T) { for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewCodeBlockParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.codeBlock}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewCodeBlockParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/code_test.go b/parser/tests/code_test.go similarity index 63% rename from parser/code_test.go rename to parser/tests/code_test.go index 0204a2e..bb90250 100644 --- a/parser/code_test.go +++ b/parser/tests/code_test.go @@ -1,39 +1,38 @@ -package parser +package tests import ( "testing" "github.com/stretchr/testify/require" - "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestCodeParser(t *testing.T) { tests := []struct { text string - code ast.Node + node ast.Node }{ { text: "`Hello world!", - code: nil, + node: nil, }, { text: "`Hello world!`", - code: &ast.Code{ + node: &ast.Code{ Content: "Hello world!", }, }, { text: "`Hello \nworld!`", - code: nil, + node: nil, }, } for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewCodeParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.code}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewCodeParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/embedded_content_test.go b/parser/tests/embedded_content_test.go similarity index 58% rename from parser/embedded_content_test.go rename to parser/tests/embedded_content_test.go index 68efabe..7638d23 100644 --- a/parser/embedded_content_test.go +++ b/parser/tests/embedded_content_test.go @@ -1,56 +1,55 @@ -package parser +package tests import ( "testing" "github.com/stretchr/testify/require" - "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestEmbeddedContentParser(t *testing.T) { tests := []struct { - text string - embeddedContent ast.Node + text string + node ast.Node }{ { - text: "![[Hello world]", - embeddedContent: nil, + text: "![[Hello world]", + node: nil, }, { text: "![[Hello world]]", - embeddedContent: &ast.EmbeddedContent{ + node: &ast.EmbeddedContent{ ResourceName: "Hello world", }, }, { text: "![[memos/1]]", - embeddedContent: &ast.EmbeddedContent{ + node: &ast.EmbeddedContent{ ResourceName: "memos/1", }, }, { - text: "![[resources/101]] \n123", - embeddedContent: nil, + text: "![[resources/101]] \n123", + node: nil, }, { text: "![[resources/101]]\n123", - embeddedContent: &ast.EmbeddedContent{ + node: &ast.EmbeddedContent{ ResourceName: "resources/101", }, }, { text: "![[resources/101?align=center]]\n123", - embeddedContent: &ast.EmbeddedContent{ + node: &ast.EmbeddedContent{ ResourceName: "resources/101", Params: "align=center", }, }, { text: "![[resources/6uxnhT98q8vN8anBbUbRGu?align=center]]", - embeddedContent: &ast.EmbeddedContent{ + node: &ast.EmbeddedContent{ ResourceName: "resources/6uxnhT98q8vN8anBbUbRGu", Params: "align=center", }, @@ -59,7 +58,7 @@ func TestEmbeddedContentParser(t *testing.T) { for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewEmbeddedContentParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.embeddedContent}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewEmbeddedContentParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/escaping_character_test.go b/parser/tests/escaping_character_test.go similarity index 66% rename from parser/escaping_character_test.go rename to parser/tests/escaping_character_test.go index e7264d3..24b31a7 100644 --- a/parser/escaping_character_test.go +++ b/parser/tests/escaping_character_test.go @@ -1,13 +1,12 @@ -package parser +package tests import ( "testing" "github.com/stretchr/testify/require" - "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestEscapingCharacterParser(t *testing.T) { @@ -25,7 +24,7 @@ func TestEscapingCharacterParser(t *testing.T) { for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewEscapingCharacterParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.node}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewEscapingCharacterParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/heading_test.go b/parser/tests/heading_test.go similarity index 70% rename from parser/heading_test.go rename to parser/tests/heading_test.go index 3636013..3b12a8f 100644 --- a/parser/heading_test.go +++ b/parser/tests/heading_test.go @@ -1,27 +1,26 @@ -package parser +package tests import ( "testing" "github.com/stretchr/testify/require" - "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestHeadingParser(t *testing.T) { tests := []struct { - text string - heading ast.Node + text string + node ast.Node }{ { - text: "*Hello world", - heading: nil, + text: "*Hello world", + node: nil, }, { text: "## Hello World\n123", - heading: &ast.Heading{ + node: &ast.Heading{ Level: 2, Children: []ast.Node{ &ast.Text{ @@ -32,7 +31,7 @@ func TestHeadingParser(t *testing.T) { }, { text: "# # Hello World", - heading: &ast.Heading{ + node: &ast.Heading{ Level: 1, Children: []ast.Node{ &ast.Text{ @@ -42,13 +41,13 @@ func TestHeadingParser(t *testing.T) { }, }, { - text: " # 123123 Hello World", - heading: nil, + text: " # 123123 Hello World", + node: nil, }, { text: `# 123 Hello World`, - heading: &ast.Heading{ + node: &ast.Heading{ Level: 1, Children: []ast.Node{ &ast.Text{ @@ -59,7 +58,7 @@ Hello World`, }, { text: "### **Hello** World", - heading: &ast.Heading{ + node: &ast.Heading{ Level: 3, Children: []ast.Node{ &ast.Bold{ @@ -80,7 +79,7 @@ Hello World`, for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewHeadingParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.heading}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewHeadingParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/highlight_test.go b/parser/tests/highlight_test.go similarity index 63% rename from parser/highlight_test.go rename to parser/tests/highlight_test.go index d585ee0..a9db81d 100644 --- a/parser/highlight_test.go +++ b/parser/tests/highlight_test.go @@ -1,33 +1,32 @@ -package parser +package tests import ( "testing" "github.com/stretchr/testify/require" - "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestHighlightParser(t *testing.T) { tests := []struct { text string - bold ast.Node + node ast.Node }{ { text: "==Hello world!", - bold: nil, + node: nil, }, { text: "==Hello==", - bold: &ast.Highlight{ + node: &ast.Highlight{ Content: "Hello", }, }, { text: "==Hello world==", - bold: &ast.Highlight{ + node: &ast.Highlight{ Content: "Hello world", }, }, @@ -35,7 +34,7 @@ func TestHighlightParser(t *testing.T) { for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewHighlightParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.bold}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewHighlightParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/tests/horizontal_rule_test.go b/parser/tests/horizontal_rule_test.go new file mode 100644 index 0000000..6858b49 --- /dev/null +++ b/parser/tests/horizontal_rule_test.go @@ -0,0 +1,50 @@ +package tests + +import ( + "testing" + + "github.com/stretchr/testify/require" + "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" + "github.com/usememos/gomark/parser/tokenizer" +) + +func TestHorizontalRuleParser(t *testing.T) { + tests := []struct { + text string + node ast.Node + }{ + { + text: "---", + node: &ast.HorizontalRule{ + Symbol: "-", + }, + }, + { + text: "---\naaa", + node: &ast.HorizontalRule{ + Symbol: "-", + }, + }, + { + text: "****", + node: nil, + }, + { + text: "***", + node: &ast.HorizontalRule{ + Symbol: "*", + }, + }, + { + text: "-*-", + node: nil, + }, + } + + for _, test := range tests { + tokens := tokenizer.Tokenize(test.text) + node, _ := parser.NewHorizontalRuleParser().Match(tokens) + require.Equal(t, test.node, node) + } +} diff --git a/parser/html_element_test.go b/parser/tests/html_element_test.go similarity index 52% rename from parser/html_element_test.go rename to parser/tests/html_element_test.go index 0ec9b0b..41a88ba 100644 --- a/parser/html_element_test.go +++ b/parser/tests/html_element_test.go @@ -1,31 +1,31 @@ -package parser +package tests import ( "testing" "github.com/stretchr/testify/require" - "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestHTMLElementParser(t *testing.T) { tests := []struct { - text string - htmlElement ast.Node + text string + node ast.Node }{ { text: "
", - htmlElement: &ast.HTMLElement{ - TagName: "br", + node: &ast.HTMLElement{ + TagName: "br", + Attributes: map[string]string{}, }, }, } for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewHTMLElementParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.htmlElement}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewHTMLElementParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/image_test.go b/parser/tests/image_test.go similarity index 57% rename from parser/image_test.go rename to parser/tests/image_test.go index 56f5e8f..c809d57 100644 --- a/parser/image_test.go +++ b/parser/tests/image_test.go @@ -1,38 +1,37 @@ -package parser +package tests import ( "testing" "github.com/stretchr/testify/require" - "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestImageParser(t *testing.T) { tests := []struct { - text string - image ast.Node + text string + node ast.Node }{ { text: "![](https://example.com)", - image: &ast.Image{ + node: &ast.Image{ AltText: "", URL: "https://example.com", }, }, { - text: "! [](https://example.com)", - image: nil, + text: "! [](https://example.com)", + node: nil, }, { - text: "![alte]( htt ps :/ /example.com)", - image: nil, + text: "![alte]( htt ps :/ /example.com)", + node: nil, }, { text: "![al te](https://example.com)", - image: &ast.Image{ + node: &ast.Image{ AltText: "al te", URL: "https://example.com", }, @@ -40,7 +39,7 @@ func TestImageParser(t *testing.T) { } for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewImageParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.image}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewImageParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/italic_test.go b/parser/tests/italic_test.go similarity index 60% rename from parser/italic_test.go rename to parser/tests/italic_test.go index 8f2172e..82ba56e 100644 --- a/parser/italic_test.go +++ b/parser/tests/italic_test.go @@ -1,41 +1,40 @@ -package parser +package tests import ( "testing" "github.com/stretchr/testify/require" - "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestItalicParser(t *testing.T) { tests := []struct { - text string - italic ast.Node + text string + node ast.Node }{ { - text: "*Hello world!", - italic: nil, + text: "*Hello world!", + node: nil, }, { text: "*Hello*", - italic: &ast.Italic{ + node: &ast.Italic{ Symbol: "*", Content: "Hello", }, }, { text: "* Hello *", - italic: &ast.Italic{ + node: &ast.Italic{ Symbol: "*", Content: " Hello ", }, }, { text: "*1* Hello * *", - italic: &ast.Italic{ + node: &ast.Italic{ Symbol: "*", Content: "1", }, @@ -44,7 +43,7 @@ func TestItalicParser(t *testing.T) { for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewItalicParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.italic}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewItalicParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/link_test.go b/parser/tests/link_test.go similarity index 71% rename from parser/link_test.go rename to parser/tests/link_test.go index cd326f8..a6fbef8 100644 --- a/parser/link_test.go +++ b/parser/tests/link_test.go @@ -1,45 +1,44 @@ -package parser +package tests import ( "testing" "github.com/stretchr/testify/require" - "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestLinkParser(t *testing.T) { tests := []struct { text string - link ast.Node + node ast.Node }{ { text: "[](https://example.com)", - link: &ast.Link{ + node: &ast.Link{ Text: "", URL: "https://example.com", }, }, { text: "! [](https://example.com)", - link: nil, + node: nil, }, { text: "[alte]( htt ps :/ /example.com)", - link: nil, + node: nil, }, { text: "[your/slash](https://example.com)", - link: &ast.Link{ + node: &ast.Link{ Text: "your/slash", URL: "https://example.com", }, }, { text: "[hello world](https://example.com)", - link: &ast.Link{ + node: &ast.Link{ Text: "hello world", URL: "https://example.com", }, @@ -47,7 +46,7 @@ func TestLinkParser(t *testing.T) { } for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewLinkParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.link}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewLinkParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/math_block_test.go b/parser/tests/math_block_test.go similarity index 62% rename from parser/math_block_test.go rename to parser/tests/math_block_test.go index 9503895..fbd809d 100644 --- a/parser/math_block_test.go +++ b/parser/tests/math_block_test.go @@ -1,36 +1,35 @@ -package parser +package tests import ( "testing" "github.com/stretchr/testify/require" - "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestMathBlockParser(t *testing.T) { tests := []struct { text string - link ast.Node + node ast.Node }{ { text: "$$\n(1+x)^2\n$$", - link: &ast.MathBlock{ + node: &ast.MathBlock{ Content: "(1+x)^2", }, }, { text: "$$\na=3\n$$", - link: &ast.MathBlock{ + node: &ast.MathBlock{ Content: "a=3", }, }, } for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewMathBlockParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.link}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewMathBlockParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/math_test.go b/parser/tests/math_test.go similarity index 63% rename from parser/math_test.go rename to parser/tests/math_test.go index 91b1bea..bd20661 100644 --- a/parser/math_test.go +++ b/parser/tests/math_test.go @@ -1,4 +1,4 @@ -package parser +package tests import ( "testing" @@ -6,25 +6,25 @@ import ( "github.com/stretchr/testify/require" "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestMathParser(t *testing.T) { tests := []struct { text string - link ast.Node + node ast.Node }{ { text: "$\\sqrt{3x-1}+(1+x)^2$", - link: &ast.Math{ + node: &ast.Math{ Content: "\\sqrt{3x-1}+(1+x)^2", }, }, } for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewMathParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.link}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewMathParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/ordered_list_test.go b/parser/tests/ordered_list_item_test.go similarity index 73% rename from parser/ordered_list_test.go rename to parser/tests/ordered_list_item_test.go index 66dbe72..55516c7 100644 --- a/parser/ordered_list_test.go +++ b/parser/tests/ordered_list_item_test.go @@ -1,4 +1,4 @@ -package parser +package tests import ( "testing" @@ -6,11 +6,11 @@ import ( "github.com/stretchr/testify/require" "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) -func TestOrderedListParser(t *testing.T) { +func TestOrderedListItemParser(t *testing.T) { tests := []struct { text string node ast.Node @@ -21,7 +21,7 @@ func TestOrderedListParser(t *testing.T) { }, { text: "1. Hello World", - node: &ast.OrderedList{ + node: &ast.OrderedListItem{ Number: "1", Children: []ast.Node{ &ast.Text{ @@ -32,7 +32,7 @@ func TestOrderedListParser(t *testing.T) { }, { text: " 1. Hello World", - node: &ast.OrderedList{ + node: &ast.OrderedListItem{ Number: "1", Indent: 2, Children: []ast.Node{ @@ -48,7 +48,7 @@ func TestOrderedListParser(t *testing.T) { }, { text: "22. Hello *World*", - node: &ast.OrderedList{ + node: &ast.OrderedListItem{ Number: "22", Children: []ast.Node{ &ast.Text{ @@ -65,7 +65,7 @@ func TestOrderedListParser(t *testing.T) { for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewOrderedListParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.node}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewOrderedListItemParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/paragraph_test.go b/parser/tests/paragraph_test.go similarity index 63% rename from parser/paragraph_test.go rename to parser/tests/paragraph_test.go index 407ab13..054d052 100644 --- a/parser/paragraph_test.go +++ b/parser/tests/paragraph_test.go @@ -1,31 +1,30 @@ -package parser +package tests import ( "testing" "github.com/stretchr/testify/require" - "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestParagraphParser(t *testing.T) { tests := []struct { - text string - paragraph ast.Node + text string + node ast.Node }{ { - text: "", - paragraph: nil, + text: "", + node: nil, }, { - text: "\n", - paragraph: nil, + text: "\n", + node: nil, }, { text: "Hello world!", - paragraph: &ast.Paragraph{ + node: &ast.Paragraph{ Children: []ast.Node{ &ast.Text{ Content: "Hello world!", @@ -35,7 +34,7 @@ func TestParagraphParser(t *testing.T) { }, { text: "Hello world!\n", - paragraph: &ast.Paragraph{ + node: &ast.Paragraph{ Children: []ast.Node{ &ast.Text{ Content: "Hello world!", @@ -45,7 +44,7 @@ func TestParagraphParser(t *testing.T) { }, { text: "Hello world!\n\nNew paragraph.", - paragraph: &ast.Paragraph{ + node: &ast.Paragraph{ Children: []ast.Node{ &ast.Text{ Content: "Hello world!", @@ -57,7 +56,7 @@ func TestParagraphParser(t *testing.T) { for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewParagraphParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.paragraph}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewParagraphParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/parser_test.go b/parser/tests/parser_test.go similarity index 67% rename from parser/parser_test.go rename to parser/tests/parser_test.go index e634a60..89bd7bb 100644 --- a/parser/parser_test.go +++ b/parser/tests/parser_test.go @@ -1,4 +1,4 @@ -package parser +package tests import ( "testing" @@ -6,8 +6,8 @@ import ( "github.com/stretchr/testify/require" "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestParser(t *testing.T) { @@ -158,21 +158,25 @@ func TestParser(t *testing.T) { { text: "1. hello\n- [ ] world", nodes: []ast.Node{ - &ast.OrderedList{ - Number: "1", + &ast.List{ Children: []ast.Node{ - &ast.Text{ - Content: "hello", + &ast.OrderedListItem{ + Number: "1", + Children: []ast.Node{ + &ast.Text{ + Content: "hello", + }, + }, }, - }, - }, - &ast.LineBreak{}, - &ast.TaskList{ - Symbol: tokenizer.Hyphen, - Complete: false, - Children: []ast.Node{ - &ast.Text{ - Content: "world", + &ast.LineBreak{}, + &ast.TaskListItem{ + Symbol: tokenizer.Hyphen, + Complete: false, + Children: []ast.Node{ + &ast.Text{ + Content: "world", + }, + }, }, }, }, @@ -181,22 +185,26 @@ func TestParser(t *testing.T) { { text: "- [ ] hello\n- [x] world", nodes: []ast.Node{ - &ast.TaskList{ - Symbol: tokenizer.Hyphen, - Complete: false, + &ast.List{ Children: []ast.Node{ - &ast.Text{ - Content: "hello", + &ast.TaskListItem{ + Symbol: tokenizer.Hyphen, + Complete: false, + Children: []ast.Node{ + &ast.Text{ + Content: "hello", + }, + }, }, - }, - }, - &ast.LineBreak{}, - &ast.TaskList{ - Symbol: tokenizer.Hyphen, - Complete: true, - Children: []ast.Node{ - &ast.Text{ - Content: "world", + &ast.LineBreak{}, + &ast.TaskListItem{ + Symbol: tokenizer.Hyphen, + Complete: true, + Children: []ast.Node{ + &ast.Text{ + Content: "world", + }, + }, }, }, }, @@ -251,7 +259,8 @@ func TestParser(t *testing.T) { Content: "world", }, &ast.HTMLElement{ - TagName: "br", + TagName: "br", + Attributes: map[string]string{}, }, }, }, @@ -266,7 +275,8 @@ func TestParser(t *testing.T) { Content: "Hello ", }, &ast.HTMLElement{ - TagName: "br", + TagName: "br", + Attributes: map[string]string{}, }, &ast.Text{ Content: " world", @@ -275,11 +285,68 @@ func TestParser(t *testing.T) { }, }, }, + { + text: "* unordered list item 1\n* unordered list item 2", + nodes: []ast.Node{ + &ast.List{ + Children: []ast.Node{ + &ast.UnorderedListItem{ + Symbol: tokenizer.Asterisk, + Children: []ast.Node{ + &ast.Text{ + Content: "unordered list item 1", + }, + }, + }, + &ast.LineBreak{}, + &ast.UnorderedListItem{ + Symbol: tokenizer.Asterisk, + Children: []ast.Node{ + &ast.Text{ + Content: "unordered list item 2", + }, + }, + }, + }, + }, + }, + }, + { + text: "* unordered list item\n\n1. ordered list item", + nodes: []ast.Node{ + &ast.List{ + Children: []ast.Node{ + &ast.UnorderedListItem{ + Symbol: tokenizer.Asterisk, + Children: []ast.Node{ + &ast.Text{ + Content: "unordered list item", + }, + }, + }, + &ast.LineBreak{}, + }, + }, + &ast.LineBreak{}, + &ast.List{ + Children: []ast.Node{ + &ast.OrderedListItem{ + Number: "1", + Children: []ast.Node{ + &ast.Text{ + Content: "ordered list item", + }, + }, + }, + }, + }, + }, + }, } for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - nodes, _ := Parse(tokens) - require.Equal(t, restore.Restore(test.nodes), restore.Restore(nodes)) + nodes, _ := parser.Parse(tokens) + require.Equal(t, test.nodes, nodes) } } diff --git a/parser/referenced_content_test.go b/parser/tests/referenced_content_test.go similarity index 59% rename from parser/referenced_content_test.go rename to parser/tests/referenced_content_test.go index 72c4237..93ee698 100644 --- a/parser/referenced_content_test.go +++ b/parser/tests/referenced_content_test.go @@ -1,52 +1,51 @@ -package parser +package tests import ( "testing" "github.com/stretchr/testify/require" - "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestReferencedContentParser(t *testing.T) { tests := []struct { - text string - referencedContent ast.Node + text string + node ast.Node }{ { - text: "[[Hello world]", - referencedContent: nil, + text: "[[Hello world]", + node: nil, }, { text: "[[Hello world]]", - referencedContent: &ast.ReferencedContent{ + node: &ast.ReferencedContent{ ResourceName: "Hello world", }, }, { text: "[[memos/1]]", - referencedContent: &ast.ReferencedContent{ + node: &ast.ReferencedContent{ ResourceName: "memos/1", }, }, { text: "[[resources/101]]111\n123", - referencedContent: &ast.ReferencedContent{ + node: &ast.ReferencedContent{ ResourceName: "resources/101", }, }, { text: "[[resources/101?align=center]]", - referencedContent: &ast.ReferencedContent{ + node: &ast.ReferencedContent{ ResourceName: "resources/101", Params: "align=center", }, }, { text: "[[resources/6uxnhT98q8vN8anBbUbRGu?align=center]]", - referencedContent: &ast.ReferencedContent{ + node: &ast.ReferencedContent{ ResourceName: "resources/6uxnhT98q8vN8anBbUbRGu", Params: "align=center", }, @@ -55,7 +54,7 @@ func TestReferencedContentParser(t *testing.T) { for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewReferencedContentParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.referencedContent}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewReferencedContentParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/spoiler_test.go b/parser/tests/spoiler_test.go similarity index 54% rename from parser/spoiler_test.go rename to parser/tests/spoiler_test.go index 661ec26..fd56619 100644 --- a/parser/spoiler_test.go +++ b/parser/tests/spoiler_test.go @@ -1,4 +1,4 @@ -package parser +package tests import ( "testing" @@ -6,22 +6,22 @@ import ( "github.com/stretchr/testify/require" "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestSpoilerParser(t *testing.T) { tests := []struct { - text string - spoiler ast.Node + text string + node ast.Node }{ { - text: "*Hello world!", - spoiler: nil, + text: "*Hello world!", + node: nil, }, { text: "||Hello||", - spoiler: &ast.Spoiler{ + node: &ast.Spoiler{ Content: "Hello", }, }, @@ -29,7 +29,7 @@ func TestSpoilerParser(t *testing.T) { for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewSpoilerParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.spoiler}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewSpoilerParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/strikethrough_test.go b/parser/tests/strikethrough_test.go similarity index 53% rename from parser/strikethrough_test.go rename to parser/tests/strikethrough_test.go index d6659d2..a42608f 100644 --- a/parser/strikethrough_test.go +++ b/parser/tests/strikethrough_test.go @@ -1,4 +1,4 @@ -package parser +package tests import ( "testing" @@ -6,34 +6,34 @@ import ( "github.com/stretchr/testify/require" "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestStrikethroughParser(t *testing.T) { tests := []struct { - text string - strikethrough ast.Node + text string + node ast.Node }{ { - text: "~~Hello world", - strikethrough: nil, + text: "~~Hello world", + node: nil, }, { text: "~~Hello~~", - strikethrough: &ast.Strikethrough{ + node: &ast.Strikethrough{ Content: "Hello", }, }, { text: "~~ Hello ~~", - strikethrough: &ast.Strikethrough{ + node: &ast.Strikethrough{ Content: " Hello ", }, }, { text: "~~1~~ Hello ~~~", - strikethrough: &ast.Strikethrough{ + node: &ast.Strikethrough{ Content: "1", }, }, @@ -41,7 +41,7 @@ func TestStrikethroughParser(t *testing.T) { for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewStrikethroughParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.strikethrough}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewStrikethroughParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/subscript_test.go b/parser/tests/subscript_test.go similarity index 55% rename from parser/subscript_test.go rename to parser/tests/subscript_test.go index 2e07926..fe2591b 100644 --- a/parser/subscript_test.go +++ b/parser/tests/subscript_test.go @@ -1,4 +1,4 @@ -package parser +package tests import ( "testing" @@ -6,34 +6,34 @@ import ( "github.com/stretchr/testify/require" "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestSubscriptParser(t *testing.T) { tests := []struct { - text string - subscript ast.Node + text string + node ast.Node }{ { - text: "~Hello world!", - subscript: nil, + text: "~Hello world!", + node: nil, }, { text: "~Hello~", - subscript: &ast.Subscript{ + node: &ast.Subscript{ Content: "Hello", }, }, { text: "~ Hello ~", - subscript: &ast.Subscript{ + node: &ast.Subscript{ Content: " Hello ", }, }, { text: "~1~ Hello ~ ~", - subscript: &ast.Subscript{ + node: &ast.Subscript{ Content: "1", }, }, @@ -41,7 +41,7 @@ func TestSubscriptParser(t *testing.T) { for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewSubscriptParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.subscript}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewSubscriptParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/superscript_test.go b/parser/tests/superscript_test.go similarity index 54% rename from parser/superscript_test.go rename to parser/tests/superscript_test.go index 3449967..56b4bf0 100644 --- a/parser/superscript_test.go +++ b/parser/tests/superscript_test.go @@ -1,39 +1,38 @@ -package parser +package tests import ( "testing" "github.com/stretchr/testify/require" - "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestSuperscriptParser(t *testing.T) { tests := []struct { - text string - superscript ast.Node + text string + node ast.Node }{ { - text: "^Hello world!", - superscript: nil, + text: "^Hello world!", + node: nil, }, { text: "^Hello^", - superscript: &ast.Superscript{ + node: &ast.Superscript{ Content: "Hello", }, }, { text: "^ Hello ^", - superscript: &ast.Superscript{ + node: &ast.Superscript{ Content: " Hello ", }, }, { text: "^1^ Hello ^ ^", - superscript: &ast.Superscript{ + node: &ast.Superscript{ Content: "1", }, }, @@ -41,7 +40,7 @@ func TestSuperscriptParser(t *testing.T) { for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewSuperscriptParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.superscript}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewSuperscriptParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/table_test.go b/parser/tests/table_test.go similarity index 85% rename from parser/table_test.go rename to parser/tests/table_test.go index 2a8faeb..da55fcd 100644 --- a/parser/table_test.go +++ b/parser/tests/table_test.go @@ -1,23 +1,22 @@ -package parser +package tests import ( "testing" "github.com/stretchr/testify/require" - "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestTableParser(t *testing.T) { tests := []struct { - text string - table ast.Node + text string + node ast.Node }{ { text: "| header |\n| --- |\n| cell |\n", - table: &ast.Table{ + node: &ast.Table{ Header: []ast.Node{ &ast.Paragraph{ Children: []ast.Node{ @@ -39,7 +38,7 @@ func TestTableParser(t *testing.T) { }, { text: "| **header1** | header2 |\n| --- | ---- |\n| cell1 | cell2 |\n| cell3 | cell4 |", - table: &ast.Table{ + node: &ast.Table{ Header: []ast.Node{ &ast.Paragraph{ Children: []ast.Node{ @@ -90,7 +89,7 @@ func TestTableParser(t *testing.T) { for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewTableParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.table}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewTableParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/tag_test.go b/parser/tests/tag_test.go similarity index 64% rename from parser/tag_test.go rename to parser/tests/tag_test.go index 0f42072..eab6cf5 100644 --- a/parser/tag_test.go +++ b/parser/tests/tag_test.go @@ -1,37 +1,36 @@ -package parser +package tests import ( "testing" "github.com/stretchr/testify/require" - "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) func TestTagParser(t *testing.T) { tests := []struct { text string - tag ast.Node + node ast.Node }{ { text: "*Hello world", - tag: nil, + node: nil, }, { text: "# Hello World", - tag: nil, + node: nil, }, { text: "#tag", - tag: &ast.Tag{ + node: &ast.Tag{ Content: "tag", }, }, { text: "#tag/subtag 123", - tag: &ast.Tag{ + node: &ast.Tag{ Content: "tag/subtag", }, }, @@ -39,7 +38,7 @@ func TestTagParser(t *testing.T) { for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewTagParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.tag}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewTagParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/task_list_test.go b/parser/tests/task_list_item_test.go similarity index 71% rename from parser/task_list_test.go rename to parser/tests/task_list_item_test.go index d555a62..02eb080 100644 --- a/parser/task_list_test.go +++ b/parser/tests/task_list_item_test.go @@ -1,16 +1,15 @@ -package parser +package tests import ( "testing" "github.com/stretchr/testify/require" - "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) -func TestTaskListParser(t *testing.T) { +func TestTaskListItemParser(t *testing.T) { tests := []struct { text string node ast.Node @@ -21,9 +20,8 @@ func TestTaskListParser(t *testing.T) { }, { text: "+ [ ] Hello World", - node: &ast.TaskList{ - Symbol: tokenizer.PlusSign, - Complete: false, + node: &ast.TaskListItem{ + Symbol: tokenizer.PlusSign, Children: []ast.Node{ &ast.Text{ Content: "Hello World", @@ -33,7 +31,7 @@ func TestTaskListParser(t *testing.T) { }, { text: " + [ ] Hello World", - node: &ast.TaskList{ + node: &ast.TaskListItem{ Symbol: tokenizer.PlusSign, Indent: 2, Complete: false, @@ -46,7 +44,7 @@ func TestTaskListParser(t *testing.T) { }, { text: "* [x] **Hello**", - node: &ast.TaskList{ + node: &ast.TaskListItem{ Symbol: tokenizer.Asterisk, Complete: true, Children: []ast.Node{ @@ -65,7 +63,7 @@ func TestTaskListParser(t *testing.T) { for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewTaskListParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.node}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewTaskListItemParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/unordered_list_test.go b/parser/tests/unordered_list_item_test.go similarity index 70% rename from parser/unordered_list_test.go rename to parser/tests/unordered_list_item_test.go index 25d937d..5c724f6 100644 --- a/parser/unordered_list_test.go +++ b/parser/tests/unordered_list_item_test.go @@ -1,4 +1,4 @@ -package parser +package tests import ( "testing" @@ -6,11 +6,11 @@ import ( "github.com/stretchr/testify/require" "github.com/usememos/gomark/ast" + "github.com/usememos/gomark/parser" "github.com/usememos/gomark/parser/tokenizer" - "github.com/usememos/gomark/restore" ) -func TestUnorderedListParser(t *testing.T) { +func TestUnorderedListItemParser(t *testing.T) { tests := []struct { text string node ast.Node @@ -21,7 +21,7 @@ func TestUnorderedListParser(t *testing.T) { }, { text: "+ Hello World", - node: &ast.UnorderedList{ + node: &ast.UnorderedListItem{ Symbol: tokenizer.PlusSign, Children: []ast.Node{ &ast.Text{ @@ -32,7 +32,7 @@ func TestUnorderedListParser(t *testing.T) { }, { text: "* **Hello**", - node: &ast.UnorderedList{ + node: &ast.UnorderedListItem{ Symbol: tokenizer.Asterisk, Children: []ast.Node{ &ast.Bold{ @@ -50,7 +50,7 @@ func TestUnorderedListParser(t *testing.T) { for _, test := range tests { tokens := tokenizer.Tokenize(test.text) - node, _ := NewUnorderedListParser().Match(tokens) - require.Equal(t, restore.Restore([]ast.Node{test.node}), restore.Restore([]ast.Node{node})) + node, _ := parser.NewUnorderedListItemParser().Match(tokens) + require.Equal(t, test.node, node) } } diff --git a/parser/tokenizer/tokenizer_test.go b/parser/tokenizer/tokenizer_test.go index 94a2bfe..72be63e 100644 --- a/parser/tokenizer/tokenizer_test.go +++ b/parser/tokenizer/tokenizer_test.go @@ -84,7 +84,6 @@ func TestSplit(t *testing.T) { sep TokenType result [][]*Token }{ - { tokens: []*Token{ { @@ -140,3 +139,34 @@ func TestSplit(t *testing.T) { } } } + +func TestGetFirstLine(t *testing.T) { + tests := []struct { + tokens []*Token + want []*Token + }{ + { + tokens: []*Token{ + { + Type: Asterisk, + Value: "hello world", + }, + { + Type: NewLine, + Value: "\n", + }, + }, + want: []*Token{ + { + Type: Asterisk, + Value: "hello world", + }, + }, + }, + } + + for _, test := range tests { + result := GetFirstLine(test.tokens) + require.Equal(t, test.want, result) + } +} diff --git a/parser/unordered_list.go b/parser/unordered_list_item.go similarity index 77% rename from parser/unordered_list.go rename to parser/unordered_list_item.go index 4b313e8..55725cb 100644 --- a/parser/unordered_list.go +++ b/parser/unordered_list_item.go @@ -5,13 +5,13 @@ import ( "github.com/usememos/gomark/parser/tokenizer" ) -type UnorderedListParser struct{} +type UnorderedListItemParser struct{} -func NewUnorderedListParser() *UnorderedListParser { - return &UnorderedListParser{} +func NewUnorderedListItemParser() *UnorderedListItemParser { + return &UnorderedListItemParser{} } -func (*UnorderedListParser) Match(tokens []*tokenizer.Token) (ast.Node, int) { +func (*UnorderedListItemParser) Match(tokens []*tokenizer.Token) (ast.Node, int) { matchedTokens := tokenizer.GetFirstLine(tokens) indent := 0 for _, token := range matchedTokens { @@ -38,7 +38,7 @@ func (*UnorderedListParser) Match(tokens []*tokenizer.Token) (ast.Node, int) { if err != nil { return nil, 0 } - return &ast.UnorderedList{ + return &ast.UnorderedListItem{ Symbol: symbolToken.Type, Indent: indent, Children: children, diff --git a/renderer/html/html.go b/renderer/html/html.go index ff0f4fd..d2d318b 100644 --- a/renderer/html/html.go +++ b/renderer/html/html.go @@ -39,12 +39,14 @@ func (r *HTMLRenderer) RenderNode(node ast.Node) { r.renderHorizontalRule(n) case *ast.Blockquote: r.renderBlockquote(n) - case *ast.UnorderedList: - r.renderUnorderedList(n) - case *ast.OrderedList: - r.renderOrderedList(n) - case *ast.TaskList: - r.renderTaskList(n) + case *ast.List: + r.renderList(n) + case *ast.UnorderedListItem: + r.renderUnorderedListItem(n) + case *ast.OrderedListItem: + r.renderOrderedListItem(n) + case *ast.TaskListItem: + r.renderTaskListItem(n) case *ast.MathBlock: r.renderMathBlock(n) case *ast.Table: @@ -149,48 +151,35 @@ func (r *HTMLRenderer) renderBlockquote(node *ast.Blockquote) { r.output.WriteString("") } -func (r *HTMLRenderer) renderUnorderedList(node *ast.UnorderedList) { - prevSibling, nextSibling := ast.FindPrevSiblingExceptLineBreak(node), ast.FindNextSiblingExceptLineBreak(node) - if prevSibling == nil || prevSibling.Type() != ast.UnorderedListNode { - r.output.WriteString("") - } } -func (r *HTMLRenderer) renderOrderedList(node *ast.OrderedList) { - prevSibling, nextSibling := ast.FindPrevSiblingExceptLineBreak(node), ast.FindNextSiblingExceptLineBreak(node) - if prevSibling == nil || prevSibling.Type() != ast.OrderedListNode { - r.output.WriteString("
    ") - } +func (r *HTMLRenderer) renderOrderedListItem(node *ast.OrderedListItem) { r.output.WriteString("
  1. ") r.RenderNodes(node.Children) r.output.WriteString("
  2. ") - if nextSibling == nil || nextSibling.Type() != ast.OrderedListNode { - r.output.WriteString("
") - } } -func (r *HTMLRenderer) renderTaskList(node *ast.TaskList) { - prevSibling, nextSibling := ast.FindPrevSiblingExceptLineBreak(node), ast.FindNextSiblingExceptLineBreak(node) - if prevSibling == nil || prevSibling.Type() != ast.TaskListNode { - r.output.WriteString("") - } } func (r *HTMLRenderer) renderMathBlock(node *ast.MathBlock) { diff --git a/renderer/html/html_test.go b/renderer/html/html_test.go index ed1d32f..9052ab9 100644 --- a/renderer/html/html_test.go +++ b/renderer/html/html_test.go @@ -48,19 +48,19 @@ func TestHTMLRenderer(t *testing.T) { }, { text: "* Hello\n* world!", - expected: ``, + expected: `
  • Hello

  • world!
  • `, }, { text: "1. Hello\n2. world\n* !", - expected: `
    1. Hello
    2. world
    `, + expected: `
  • Hello

  • world

  • !
  • `, }, { text: "- [ ] hello\n- [x] world", - expected: ``, + expected: `
  • hello

  • world
  • `, }, { text: "1. ordered\n* unorder\n- [ ] checkbox\n- [x] checked", - expected: `
    1. ordered
    `, + expected: `
  • ordered

  • unorder

  • checkbox

  • checked
  • `, }, } diff --git a/renderer/string/string.go b/renderer/string/string.go index 6a49ee5..4cd95d9 100644 --- a/renderer/string/string.go +++ b/renderer/string/string.go @@ -39,12 +39,14 @@ func (r *StringRenderer) RenderNode(node ast.Node) { r.renderHorizontalRule(n) case *ast.Blockquote: r.renderBlockquote(n) - case *ast.UnorderedList: - r.renderUnorderedList(n) - case *ast.OrderedList: - r.renderOrderedList(n) - case *ast.TaskList: - r.renderTaskList(n) + case *ast.List: + r.renderList(n) + case *ast.UnorderedListItem: + r.renderUnorderedListItem(n) + case *ast.OrderedListItem: + r.renderOrderedListItem(n) + case *ast.TaskListItem: + r.renderTaskListItem(n) case *ast.MathBlock: r.renderMathBlock(n) case *ast.Table: @@ -143,22 +145,25 @@ func (r *StringRenderer) renderBlockquote(node *ast.Blockquote) { r.output.WriteString("\n") } -func (r *StringRenderer) renderUnorderedList(node *ast.UnorderedList) { +func (r *StringRenderer) renderList(node *ast.List) { + for _, item := range node.Children { + r.RenderNodes([]ast.Node{item}) + } +} + +func (r *StringRenderer) renderUnorderedListItem(node *ast.UnorderedListItem) { r.output.WriteString(node.Symbol) r.RenderNodes(node.Children) - r.output.WriteString("\n") } -func (r *StringRenderer) renderOrderedList(node *ast.OrderedList) { +func (r *StringRenderer) renderOrderedListItem(node *ast.OrderedListItem) { r.output.WriteString(fmt.Sprintf("%s. ", node.Number)) r.RenderNodes(node.Children) - r.output.WriteString("\n") } -func (r *StringRenderer) renderTaskList(node *ast.TaskList) { +func (r *StringRenderer) renderTaskListItem(node *ast.TaskListItem) { r.output.WriteString(node.Symbol) r.RenderNodes(node.Children) - r.output.WriteString("\n") } func (r *StringRenderer) renderMathBlock(node *ast.MathBlock) { diff --git a/renderer/string/string_test.go b/renderer/string/string_test.go index 607e242..a09272a 100644 --- a/renderer/string/string_test.go +++ b/renderer/string/string_test.go @@ -28,7 +28,7 @@ func TestStringRender(t *testing.T) { }, { text: "Test\n1. Hello\n2. World", - expected: "Test\n1. Hello\n2. World\n", + expected: "Test\n1. Hello\n2. World", }, } diff --git a/restore/restore.go b/restore/restore.go index 389444a..81563b0 100644 --- a/restore/restore.go +++ b/restore/restore.go @@ -5,9 +5,6 @@ import "github.com/usememos/gomark/ast" func Restore(nodes []ast.Node) string { var result string for _, node := range nodes { - if node == nil { - continue - } result += node.Restore() } return result