feat: add markdown parser

main
hau 2020-11-27 16:50:32 +07:00 committed by Nguyen Tran Hau
parent 426f5ea5fe
commit 080796c15c
6 changed files with 243 additions and 0 deletions

3
go.mod
View File

@ -11,10 +11,13 @@ require (
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sebdah/goldie/v2 v2.5.3
github.com/stretchr/testify v1.6.1
github.com/urfave/cli/v2 v2.3.0
github.com/xanzy/ssh-agent v0.3.0 // indirect
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9 // indirect
golang.org/x/mod v0.3.0
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b // indirect
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
)

8
go.sum
View File

@ -72,11 +72,14 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5I
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
@ -136,3 +139,8 @@ gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

49
pkg/markdown/base.go Normal file
View File

@ -0,0 +1,49 @@
package markdown
import "strings"
//https://guides.github.com/features/mastering-markdown/
const (
headerToken = '#'
defaultListToken = '-'
alternativeListToken = '*'
spaceToken = ' '
newlineToken = '\n'
)
// Base is single markdown syntax representation
// Example: header, list, ...
type Base interface {
ToString() string
}
type header struct {
level int
text string
}
func (h *header) ToString() string {
var builder strings.Builder
for i := 0; i < h.level; i++ {
builder.WriteString(string(headerToken))
}
builder.WriteString(string(spaceToken))
text := strings.TrimSpace(h.text)
builder.WriteString(text)
return builder.String()
}
type listItem struct {
text string
}
func (i *listItem) ToString() string {
text := strings.TrimSpace(i.text)
return string(defaultListToken) + string(spaceToken) + text
}

62
pkg/markdown/base_test.go Normal file
View File

@ -0,0 +1,62 @@
package markdown
import (
"testing"
"github.com/haunt98/changeloguru/pkg/comparision"
)
func TestHeaderToString(t *testing.T) {
tests := []struct {
name string
header header
want string
}{
{
name: "level 1",
header: header{
level: 1,
text: "abc",
},
want: "# abc",
},
{
name: "level 3",
header: header{
level: 3,
text: "xyz",
},
want: "### xyz",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
got := tc.header.ToString()
comparision.Diff(t, tc.want, got)
})
}
}
func TestListItemToString(t *testing.T) {
tests := []struct {
name string
listItem listItem
want string
}{
{
name: "normal",
listItem: listItem{
text: "abc",
},
want: "- abc",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
got := tc.listItem.ToString()
comparision.Diff(t, tc.want, got)
})
}
}

52
pkg/markdown/parser.go Normal file
View File

@ -0,0 +1,52 @@
package markdown
import "strings"
const (
defaultBaseLen = 10
)
func Parse(lines []string) []Base {
bases := make([]Base, 0, defaultBaseLen)
for _, line := range lines {
if line == "" {
continue
}
if strings.HasPrefix(line, string(headerToken)) {
}
}
return bases
}
func parseHeader(line string) header {
level := 0
for _, c := range line {
if c != headerToken {
break
}
level++
}
line = strings.TrimLeft(line, string(headerToken))
line = strings.TrimSpace(line)
return header{
level: level,
text: line,
}
}
func parseListItem(line string) listItem {
line = strings.TrimLeft(line, string(defaultListToken))
line = strings.TrimLeft(line, string(alternativeListToken))
line = strings.TrimSpace(line)
return listItem{
text: line,
}
}

View File

@ -0,0 +1,69 @@
package markdown
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestParseHeader(t *testing.T) {
tests := []struct {
name string
line string
want header
}{
{
name: "level 1",
line: "# abc",
want: header{
level: 1,
text: "abc",
},
},
{
name: "level 3",
line: "### xyz",
want: header{
level: 3,
text: "xyz",
},
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
got := parseHeader(tc.line)
assert.Equal(t, tc.want, got)
})
}
}
func TestParseListItem(t *testing.T) {
tests := []struct {
name string
line string
want listItem
}{
{
name: "normal",
line: "- abc",
want: listItem{
text: "abc",
},
},
{
name: "alternative",
line: "* xyz",
want: listItem{
text: "xyz",
},
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
got := parseListItem(tc.line)
assert.Equal(t, tc.want, got)
})
}
}