1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
package utils
import (
"fmt"
"regexp"
"strings"
)
// LineIndex returns line index of search in content.
func LineIndex(content string, search string) int {
ret := -1
line := ""
for _, c := range content {
if c == '\n' {
line += ""
ret++
} else {
line += string(c)
}
if strings.Index(line, search) > -1 {
ret++
break
}
}
return ret
}
// PowerLess select titles of Power<P
func PowerLess(P int, f func(*MdTitleTree)) func(*MdTitleTree) {
return func(n *MdTitleTree) {
if n.Power < P && n.Title != "" {
f(n)
}
}
}
// LineLess select titles of Line<P
func LineLess(P int, f func(*MdTitleTree)) func(*MdTitleTree) {
return func(n *MdTitleTree) {
if n.Line < P && n.Title != "" {
f(n)
}
}
}
var mdTitle = regexp.MustCompile(`^([#]{1,6})\s*(.+)`)
func cntStr(in []string, what string) int {
c := -1
for _, i := range in {
if i == what {
c++
}
}
if c > -1 {
c++ // starts at 1
}
return c
}
// GetAllMdTitles extracts all MD titles markup.
func GetAllMdTitles(content string) []MdTitle {
ret := []MdTitle{}
allTitles := []string{}
line := ""
isInBlock := false
isInTitle := false
i := 0
for _, c := range content {
if !isInBlock && c == '\n' {
if isInTitle {
if mdTitle.MatchString(line) {
got := mdTitle.FindAllStringSubmatch(line, -1)
if len(got) > 0 {
t := got[0][2]
ret = append(ret, MdTitle{
Line: i, Title: t,
Power: len(got[0][1]),
Duplicate: cntStr(allTitles, t),
})
allTitles = append(allTitles, t)
}
}
}
i++
isInTitle = false
line = ""
} else if c == '`' {
isInBlock = !isInBlock
line += string(c)
} else if c == '#' && !isInBlock {
isInTitle = true
line += string(c)
} else {
if c == '\n' {
i++
}
line += string(c)
}
}
return ret
}
// MakeTitleTree transform a raw list of titles into a tree.
func MakeTitleTree(titles []MdTitle) *MdTitleTree {
root := &MdTitleTree{}
cur := root
for _, t := range titles {
if t.Power == 1 {
nnew := &MdTitleTree{MdTitle: t, Parent: root}
root.Items = append(root.Items, nnew)
cur = nnew
} else if t.Power > cur.Power {
nnew := &MdTitleTree{MdTitle: t, Parent: cur}
cur.Items = append(cur.Items, nnew)
cur = nnew
} else if t.Power == cur.Power {
nnew := &MdTitleTree{MdTitle: t, Parent: cur.Parent}
cur.Parent.Items = append(cur.Parent.Items, nnew)
cur = nnew
} else if t.Power < cur.Power {
for {
if cur.Parent.Power <= t.Power {
break
}
cur = cur.Parent
}
cur = cur.Parent
nnew := &MdTitleTree{MdTitle: t, Parent: cur.Parent}
cur.Parent.Items = append(cur.Parent.Items, nnew)
cur = nnew
}
}
return root
}
// GetMdLinkHash encodes s to insert into an MD link.
func GetMdLinkHash(link string) string {
link = strings.ToLower(link)
link = strings.Replace(link, "/", "", -1)
link = strings.Replace(link, "$", "", -1)
link = strings.Replace(link, ">", "", -1)
link = strings.Replace(link, ".", "", -1)
link = strings.Replace(link, ";", "", -1)
link = strings.Replace(link, ":", "", -1)
link = strings.Replace(link, "!", "", -1)
link = strings.Replace(link, "'", "", -1)
link = strings.Replace(link, "|", "", -1)
link = strings.Replace(link, "[", "", -1)
link = strings.Replace(link, "]", "", -1)
link = strings.Replace(link, ",", "", -1)
link = strings.Replace(link, " ", "-", -1)
// should it be a regexp like /[a-z0-9-_]/i ?
return link
}
// MdTitleTree is an MdTitle with tree capabilities
type MdTitleTree struct {
MdTitle
Parent *MdTitleTree
Items []*MdTitleTree
}
// Traverse a tree
func (m *MdTitleTree) Traverse(f func(*MdTitleTree)) {
f(m)
for _, i := range m.Items {
i.Traverse(f)
}
}
func (m *MdTitleTree) String() string {
x := strings.Repeat("#", m.Power)
return fmt.Sprintf("%-5v %-15q Items:%v Line:%v", x, m.Title, len(m.Items), m.Line)
}
// MdTitle is a markdwon title.
type MdTitle struct {
Line int
Power int
Duplicate int
Title string
}
|