feat: add markdown parser
parent
426f5ea5fe
commit
080796c15c
3
go.mod
3
go.mod
|
@ -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
8
go.sum
|
@ -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=
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue