gowiki/pkg/render/render.go
2018-09-20 00:18:46 +02:00

125 lines
2.9 KiB
Go

// Copyright (C) 2018 Marius Schellenberger
package render
import (
"git.giftfish.de/ston1th/gowiki/pkg/core"
"github.com/blevesearch/bleve/analysis"
"github.com/blevesearch/bleve/analysis/char/html"
"github.com/russross/blackfriday"
"html/template"
"regexp"
"strconv"
"strings"
)
var filter = makeFilter()
func makeFilter() analysis.CharFilter {
f, _ := html.CharFilterConstructor(nil, nil)
return f
}
var (
reHeader = regexp.MustCompile("(<h[1-6]>)(.+)(</h[1-6]>)")
reLink = regexp.MustCompile(`id="(.+?)"`)
whiteSpace = regexp.MustCompile(`\s+`)
reIndex = regexp.MustCompile("<h([1-6])>(.+)</h[1-6]>")
titleRe = regexp.MustCompile("[^a-zA-Z0-9 -]+")
)
func Render(p *core.Page) string {
rend := blackfriday.MarkdownCommon([]byte(p.Markdown))
index, html := buildIndex(string(rend))
html = strings.Replace(html, "<table>", `<table class="table">`, -1)
html = strings.Replace(html, "</h1>", `</h1><hr>`, -1)
html = strings.Replace(html, "<a", `<a target="_blank"`, -1)
p.PageIndex = template.HTML(index)
p.HTML = template.HTML(html)
return whiteSpace.ReplaceAllString(string(filter.Filter(rend)), " ")
}
func spaceReplace(s string) string {
return whiteSpace.ReplaceAllString(s, "+")
}
func Title(title string) string {
return spaceReplace(titleRe.ReplaceAllString(title, ""))
}
func StoreTitle(section, title string) string {
return section + "/" + title
}
func UnstoreTitle(storeTitle string) (section, title string) {
if a := strings.Split(storeTitle, "/"); len(a) == 2 {
return a[0], a[1]
}
return
}
func buildIndex(html string) (string, string) {
var ret string
m := make(map[string]int)
hn := reIndex.FindAllStringSubmatch(html, -1)
html = reHeader.ReplaceAllString(html, `<a id="${2}" class="anchor"></a>${1}${2}${3}`)
html = reLink.ReplaceAllStringFunc(html, spaceReplace)
for k, v := range hn {
link := Title(v[2])
i := m[link]
m[link] = i + 1
newLink := link + strconv.Itoa(i)
html = strings.Replace(html, link+`"`, newLink+`"`, 1)
ret += before(hn, k)
ret += `<li><a href="#` + newLink + `">` + v[2] + "</a>"
ret += after(hn, k)
}
return ret, html
}
func before(arr [][]string, i int) string {
c, _ := strconv.Atoi(arr[i][1])
if c == 1 {
return `<ul type="circle">`
}
return ""
}
func after(arr [][]string, i int) string {
c, _ := strconv.Atoi(arr[i][1])
if len(arr) <= i+1 {
return closeTag(c-1) + "</ul>"
}
n, _ := strconv.Atoi(arr[i+1][1])
if n == 1 {
return closeTag(c-n) + "</ul>"
} else if n < c {
return closeTag(c - n)
} else if n > c {
return openTag(n - c)
} else if n == c {
return "</li>"
}
return ""
}
func openTag(j int) (ret string) {
for i := 0; i < j; i++ {
ret += `<ul type="circle"><li>`
}
if j > 1 {
ret = strings.Replace(ret, "circle", "none", j-1)
}
ret = ret[0 : len(ret)-4]
return
}
func closeTag(j int) (ret string) {
for i := 0; i < j; i++ {
ret += "</li></ul></li>"
}
if j > 1 {
ret = strings.Replace(ret, "</li></li>", "</li>", -1)
}
return
}