diff --git a/pkg/markdown/links.go b/pkg/markdown/links.go index 0664802a..c552cbd8 100644 --- a/pkg/markdown/links.go +++ b/pkg/markdown/links.go @@ -53,28 +53,33 @@ func removeDestination(node ast.Node) { if idx > -1 { if link, ok := node.(*ast.Link); ok { textNode := link.Children[0] - if textNode != nil && len(textNode.AsLeaf().Literal) > 0 { - // if prev sibling is text node, add this link text to it - if idx > 0 { - _n := children[idx-1] - if t, ok := _n.(*ast.Text); ok { - t.Literal = append(t.Literal, textNode.AsLeaf().Literal...) - children = removeNode(children, idx) - node.GetParent().SetChildren(children) - return + if textNode != nil { + if len(textNode.AsLeaf().Literal) > 0 { + // if prev sibling is text node, add this link text to it + if idx > 0 { + _n := children[idx-1] + if t, ok := _n.(*ast.Text); ok { + t.Literal = append(t.Literal, textNode.AsLeaf().Literal...) + children = removeNode(children, idx) + node.GetParent().SetChildren(children) + return + } } - } - // if next sibling is text node, add this link text to it - if idx < len(children)-1 { - _n := children[idx+1] - if t, ok := _n.(*ast.Text); ok { - t.Literal = append(t.Literal, textNode.AsLeaf().Literal...) - children = removeNode(children, idx) - node.GetParent().SetChildren(children) - return + // if next sibling is text node, add this link text to it + if idx < len(children)-1 { + _n := children[idx+1] + if t, ok := _n.(*ast.Text); ok { + t.Literal = append(t.Literal, textNode.AsLeaf().Literal...) + children = removeNode(children, idx) + node.GetParent().SetChildren(children) + return + } } + node.GetParent().AsContainer().Children[idx] = textNode + return } - node.GetParent().AsContainer().Children[idx] = textNode + children = removeNode(children, idx) + node.GetParent().SetChildren(children) return } } @@ -100,7 +105,7 @@ func nodeIndex(node ast.Node) int { return idx } -func updateText(node ast.Node, text []byte) { +func setText(node ast.Node, text []byte) { idx := nodeIndex(node) if idx > -1 { if link, ok := node.(*ast.Link); ok { @@ -121,7 +126,7 @@ func updateText(node ast.Node, text []byte) { // If a callback returns "" for a destination, this is interpreted as // request to remove the link destination and leave only the link text or in // case it's an image - to remvoe it completely. -// TODO: failfast vs fault tolerance support +// TODO: failfast vs fault tolerance support? func UpdateLinkRefs(documentBlob []byte, callback OnLink) ([]byte, error) { mdParser := parser.NewWithExtensions(extensions) document := markdown.Parse(documentBlob, mdParser) @@ -136,17 +141,7 @@ func UpdateLinkRefs(documentBlob []byte, callback OnLink) ([]byte, error) { if destination, text, title, err = callback(Link, l.Destination, text, l.Title); err != nil { return ast.Terminate } - if destination != nil { - updateText(_node, text) - } - if destination == nil { - removeDestination(l) - return ast.GoToNext - } - l.Destination = destination - if title != nil { - l.Title = title - } + updateLink(_node, destination, text, title) return ast.GoToNext } if l, ok := _node.(*ast.Image); ok { @@ -154,17 +149,7 @@ func UpdateLinkRefs(documentBlob []byte, callback OnLink) ([]byte, error) { if destination, text, title, err = callback(Image, l.Destination, text, l.Title); err != nil { return ast.Terminate } - if destination != nil { - updateText(_node, text) - } - if destination == nil { - removeDestination(l) - return ast.GoToNext - } - l.Destination = destination - if title != nil { - l.Title = title - } + updateLink(_node, destination, text, title) return ast.GoToNext } } @@ -176,3 +161,26 @@ func UpdateLinkRefs(documentBlob []byte, callback OnLink) ([]byte, error) { documentBlob = markdown.Render(document, r) return documentBlob, nil } + +func updateLink(node ast.Node, destination, text, title []byte) { + if text != nil { + setText(node, text) + } + if destination == nil { + removeDestination(node) + return + } + if l, ok := node.(*ast.Link); ok { + l.Destination = destination + if title != nil { + l.Title = title + } + return + } + if l, ok := node.(*ast.Image); ok { + l.Destination = destination + if title != nil { + l.Title = title + } + } +} diff --git a/pkg/markdown/links_test.go b/pkg/markdown/links_test.go index d1a9bfd4..8a5ef3eb 100644 --- a/pkg/markdown/links_test.go +++ b/pkg/markdown/links_test.go @@ -12,10 +12,10 @@ import ( func TestRemoveLink(t *testing.T) { testCases := []struct { - in string - wantLinksCount int - wantImgsCount int - wantTexts []string + in string + wantLinksCount int + wantImagesCount int + wantTexts []string }{ { `A [a0](b.md) [a1](b.md "c") ![](a.png) B`, @@ -63,7 +63,7 @@ func TestRemoveLink(t *testing.T) { } } -func TestUpdateText(t *testing.T) { +func TestSetText(t *testing.T) { testCases := []struct { in string text string @@ -74,6 +74,11 @@ func TestUpdateText(t *testing.T) { "b", 3, }, + { + `A [a0](b.md) [a1](b.md "c") ![](a.png) B`, + "", + 3, + }, } for _, tc := range testCases { t.Run("", func(t *testing.T) { @@ -82,10 +87,10 @@ func TestUpdateText(t *testing.T) { ast.WalkFunc(document, func(node ast.Node, entering bool) ast.WalkStatus { if entering { if l, ok := node.(*ast.Link); ok { - updateText(l, []byte(tc.text)) + setText(l, []byte(tc.text)) } if i, ok := node.(*ast.Image); ok { - updateText(i, []byte(tc.text)) + setText(i, []byte(tc.text)) } } return ast.GoToNext @@ -112,3 +117,96 @@ func TestUpdateText(t *testing.T) { }) } } + +//TODO: improve the test results checking +func TestUpdateLink(t *testing.T) { + testCases := []struct { + in string + destination []byte + text []byte + title []byte + wantLinkTextUpdates []string + wantLinkDestinationUpdates []string + wantLinkTitleUpdates []string + wantLinkUpdatesCount int + wantImageUpdatesCount int + }{ + { + `A [a0](b.md) [a1](b.md "c") ![](a.png) B`, + []byte("b"), + []byte("new"), + nil, + nil, + nil, + nil, + 2, + 1, + }, + { + `A [a0](b.md) [a1](b.md "c") ![](a.png) B`, + nil, + []byte(""), + nil, + nil, + nil, + nil, + 0, + 0, + }, + { + `A [a0](b.md) [a1](b.md "c") ![](a.png) B`, + nil, + []byte("A"), + nil, + nil, + nil, + nil, + 0, + 0, + }, + } + for _, tc := range testCases { + t.Run("", func(t *testing.T) { + mdParser := parser.NewWithExtensions(extensions) + document := markdown.Parse([]byte(tc.in), mdParser) + ast.WalkFunc(document, func(node ast.Node, entering bool) ast.WalkStatus { + if entering { + if l, ok := node.(*ast.Link); ok { + updateLink(l, tc.destination, tc.text, tc.title) + } + if i, ok := node.(*ast.Image); ok { + updateLink(i, tc.destination, tc.text, tc.title) + } + } + return ast.GoToNext + }) + var ( + linkUpdatesCount int + imageUpdatesCount int + ) + ast.WalkFunc(document, func(node ast.Node, entering bool) ast.WalkStatus { + if entering { + if l, ok := node.(*ast.Link); ok { + text := l.Children[0].AsLeaf().Literal + destination := l.Destination + title := l.Title + if bytes.Equal(text, tc.text) || bytes.Equal(destination, tc.destination) || bytes.Equal(title, tc.title) { + linkUpdatesCount++ + } + } + if i, ok := node.(*ast.Image); ok { + text := i.Children[0].AsLeaf().Literal + destination := i.Destination + title := i.Title + if bytes.Equal(text, tc.text) || bytes.Equal(destination, tc.destination) || bytes.Equal(title, tc.title) { + imageUpdatesCount++ + } + } + } + return ast.GoToNext + }) + assert.Equal(t, tc.wantLinkUpdatesCount, linkUpdatesCount, "link updates") + assert.Equal(t, tc.wantImageUpdatesCount, imageUpdatesCount, "image updates") + }) + } +}