Георги обнови решението на 02.12.2013 22:59 (преди над 4 години)
+package main
+
+import (
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+type MarkdownParser struct {
+ data string
+}
+
+func NewMarkdownParser(text string) *MarkdownParser {
+ result := new(MarkdownParser)
+ result.data = text
+ return result
+}
+
+func (mp *MarkdownParser) Headers() []string {
+ h1re := regexp.MustCompile(`(?m)(^#\s.+(\s?)#*$)|(^(.+)\n(=+)$)`)
+ trimRe := regexp.MustCompile(`(?m)^# |( #+$)|\n(=+)$`)
+ result := h1re.FindAllString(mp.data, -1)
+ for key, val := range result {
+ result[key] = strings.Trim(trimRe.ReplaceAllString(val, ""), "\n")
+ }
+ return result
+}
+
+func (mp *MarkdownParser) SubHeadersOf(header string) []string {
+ str := strings.SplitN(mp.data, header, 2)[1]
+ h1re := regexp.MustCompile(`(?m)(^#\s.+(\s?)#*$)|(^(.+)\n(=+)$)`)
+ str = h1re.Split(str, -1)[0]
+ h2re := regexp.MustCompile(`(?m)(^##\s.+(\s?)#*$)|(^(.+)\n(-+)$)`)
+ trimRe := regexp.MustCompile(`(?m)^## |( #+$\n?)|\n(-+)$\n?|\n`)
+ result := h2re.FindAllString(str, -1)
+ for key, val := range result {
+ result[key] = trimRe.ReplaceAllString(val, "")
+ }
+ return result
+}
+
+func (mp *MarkdownParser) Names() []string {
+ sentRe := regexp.MustCompile(`[A-ZА-Я][^\.\?!]*[\.\?!]`)
+ nameRe := regexp.MustCompile(`(?m)\s(([A-ZА-Я][a-zа-я]*)[\s-]+)+([A-ZА-Я][a-zа-я]*)`)
+ sentences := sentRe.FindAllString(mp.data, -1)
+ var result []string
+ for _, v := range sentences {
+ for _, item := range nameRe.FindAllString(v, -1) {
+ result = append(result, strings.Trim(item, " "))
+ }
+ }
+ return result
+}
+
+func (mp *MarkdownParser) PhoneNumbers() []string {
+ phoneRe := regexp.MustCompile(`(?m)\s(\+?)(\s*\-?\s*(\(?)(\d+)(\)?))+(\s|$)`)
+ result := phoneRe.FindAllString(mp.data, -1)
+ for k, v := range result {
+ result[k] = strings.Trim(strings.Trim(v, " "), "\n")
+ }
+ return result
+}
+
+func (mp *MarkdownParser) Links() []string {
+ nameLinkRe := regexp.MustCompile(`\[.+\]\(.+\)`)
+ linkRe := regexp.MustCompile(`\(.+\)`)
+ result := nameLinkRe.FindAllString(mp.data, -1)
+ for k, v := range result {
+ result[k] = strings.Trim(strings.Trim(linkRe.FindString(v), ")"), "(")
+ }
+ return result
+}
+
+func (mp *MarkdownParser) Emails() []string {
+ emailRe := regexp.MustCompile(`(?m)(\s|^)([\w\d][\w\._+-]+)@([\da-zA-Z\.-]+)\.([a-zA-Z]{2,6})`)
+ result := emailRe.FindAllString(mp.data, -1)
+ for k, v := range result {
+ result[k] = strings.Trim(strings.Trim(v, " "), "\n")
+ }
+ return result
+}
+
+func (mp *MarkdownParser) GenerateTableOfContents() string {
+ var result string
+ h1s := mp.Headers()
+ for k, v := range h1s {
+ result += strconv.Itoa(k+1) + ". "
+ result += v + "\n"
+ h2s := mp.SubHeadersOf(v)
+ for k1, v1 := range h2s {
+ result += strconv.Itoa(k+1) + "." + strconv.Itoa(k1+1) + " "
+ result += v1 + "\n"
+ h3s := mp.SubHgrs(v1, 3)
+ for k2, v2 := range h3s {
+ result += strconv.Itoa(k+1) + "." + strconv.Itoa(k1+1) + "." + strconv.Itoa(k2+1) + " "
+ result += v2 + "\n"
+ h4s := mp.SubHgrs(v2, 4)
+ for k3, v3 := range h4s {
+ result += strconv.Itoa(k+1) + "." + strconv.Itoa(k1+1) + "." + strconv.Itoa(k2+1) + "." + strconv.Itoa(k3+1) + " "
+ result += v3 + "\n"
+ h5s := mp.SubHgrs(v3, 5)
+ for k4, v4 := range h5s {
+ result += strconv.Itoa(k+1) + "." + strconv.Itoa(k1+1) + "." + strconv.Itoa(k2+1) + "." + strconv.Itoa(k3+1) + "." + strconv.Itoa(k4+1) + " "
+ result += v4 + "\n"
+ h6s := mp.SubHgrs(v4, 6)
+ for k5, v5 := range h6s {
+ result += strconv.Itoa(k+1) + "." + strconv.Itoa(k1+1) + "." + strconv.Itoa(k2+1) + "." + strconv.Itoa(k3+1) + "." + strconv.Itoa(k4+1) + "." + strconv.Itoa(k5+1) + " "
+ result += v5 + "\n"
+ }
+ }
+ }
+ }
+ }
+ }
+ return result
+}
+
+func (mp *MarkdownParser) SubHgrs(header string, n int) []string {
+ h2re := regexp.MustCompile(`(?m)(^##\s.+(\s?)#*$)|(^(.+)\n(-+)$)`)
+ h3re := regexp.MustCompile(`(?m)^###\s.+(\s#*)?$`)
+ h4re := regexp.MustCompile(`(?m)^#{4}\s.+(\s?)#*$`)
+ h5re := regexp.MustCompile(`(?m)^#{5}\s.+(\s?)#*$`)
+ h6re := regexp.MustCompile(`(?m)^#{6}\s.+(\s?)#*$`)
+ trimRe := regexp.MustCompile(`(?m)^#+ |( #+$\n?)`)
+ var result []string
+ str := strings.SplitN(mp.data, header, 2)[1]
+ switch {
+ case n == 3:
+ str = h2re.Split(str, -1)[0]
+ result = h3re.FindAllString(str, -1)
+ for key, val := range result {
+ result[key] = strings.Trim(trimRe.ReplaceAllString(val, ""), "\n")
+ }
+ case n == 4:
+ str = h3re.Split(str, -1)[0]
+ result = h4re.FindAllString(str, -1)
+ for key, val := range result {
+ result[key] = strings.Trim(trimRe.ReplaceAllString(val, ""), "\n")
+ }
+ case n == 5:
+ str = h4re.Split(str, -1)[0]
+ result = h5re.FindAllString(str, -1)
+ for key, val := range result {
+ result[key] = strings.Trim(trimRe.ReplaceAllString(val, ""), "\n")
+ }
+ case n == 6:
+ str = h5re.Split(str, -1)[0]
+ result = h6re.FindAllString(str, -1)
+ for key, val := range result {
+ result[key] = strings.Trim(trimRe.ReplaceAllString(val, ""), "\n")
+ }
+ }
+ return result
+}
- Това ниво на влагане в
GenerateTableOfContents
изобщо не ми харесва -
case
-овете вSubHgrs
са доста еднакви. Помисли си как би могъл да ги експортнеш в ламбда - Някои неща са публични без да има нужда от това. Оставяй публични само тези методи/функции/типове, които сме описали като изискване