split into packages

This commit is contained in:
ston1th 2018-02-09 22:38:47 +01:00
commit c5d41b0965
26 changed files with 328 additions and 449 deletions

112
pkg/index/index.go Normal file
View file

@ -0,0 +1,112 @@
// Copyright (C) 2017 Marius Schellenberger
package main
import (
"fmt"
"os"
"github.com/blevesearch/bleve"
"github.com/blevesearch/bleve/document"
)
type IndexPage struct {
Title string `json:"title"`
Search string `json:"search"`
}
func indexErr(i interface{}) error {
return fmt.Errorf("index: %s", i)
}
type Index struct {
i bleve.Index
}
func NewIndex(path string) (i *Index, err error) {
var bi bleve.Index
if _, err = os.Stat(path); os.IsNotExist(err) {
mapping := bleve.NewIndexMapping()
bi, err = bleve.New(path, mapping)
if err != nil {
err = indexErr(err)
return
}
i = &Index{index: bi}
_, err = i.Index(indexName, welcome, defUser, true)
if err != nil {
err = indexErr(err)
return
}
} else {
bi, err = bleve.Open(path)
if err != nil {
err = indexErr(err)
return
}
i = &Index{index: bi}
}
i.cache = NewIndexCache()
return
}
func NewDumpIndex(path string) (i *Index, err error) {
bi, err := bleve.OpenUsing(path, map[string]interface{}{"read_only": true})
if err != nil {
err = indexErr(err)
return
}
i = &Index{index: bi}
return
}
func (i *Index) Close() error {
return i.i.Close()
}
func (i *Index) Add(ip IndexPage) error {
doc, _ := i.i.Document(ip.Title)
if doc != nil {
err := i.Delete(ip.Title)
if err != nil {
return err
}
}
return i.i.Index(ip.Title, ip)
}
func (i *Index) Delete(title string) error {
return i.i.Delete(title)
}
type Result struct {
Title string
Text string
}
func (i *Index) Search(search string) (results []Result, err error) {
req := bleve.NewSearchRequest(bleve.NewQueryStringQuery("title:" + search + " search:" + search))
req.Highlight = bleve.NewHighlightWithStyle("html")
req.Size = maxSearchResult
res, err := i.i.Search(req)
if err != nil {
return
}
for _, hit := range res.Hits {
if hit == nil {
continue
}
title := hit.ID
text := ""
for fragField, frags := range hit.Fragments {
if fragField == "title" || fragField == "search" {
for _, f := range frags {
text += f
}
break
}
}
results = append(results, Result{title, text})
}
return
}

154
pkg/index/render.go Normal file
View file

@ -0,0 +1,154 @@
// Copyright (C) 2017 Marius Schellenberger
package main
import (
"html/template"
"regexp"
"strconv"
"strings"
"github.com/blevesearch/bleve/analysis"
htmlFilter "github.com/blevesearch/bleve/analysis/char_filters/html_char_filter"
"github.com/russross/blackfriday"
)
var filter = makeFilter()
func makeFilter() analysis.CharFilter {
f, _ := htmlFilter.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 -]+")
)
type rendered struct {
Index template.HTML
Text template.HTML
MD string
Raw []byte
}
func (r *rendered) Article() *Article {
return &Article{
Index: r.Index,
Text: r.Text,
MD: r.MD,
Search: whiteSpace.ReplaceAllString(string(filter.Filter(r.Raw)), " "),
}
}
func (r *rendered) Snippet() *Snippet {
return &Snippet{
Index: r.Index,
Text: r.Text,
MD: r.MD,
}
}
func render(text string) *rendered {
rend := blackfriday.MarkdownCommon([]byte(text))
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)
return &rendered{
Index: template.HTML(index),
Text: template.HTML(html),
MD: text,
Raw: rend,
}
}
func spaceReplace(s string) string {
return whiteSpace.ReplaceAllString(s, "+")
//TODO remove
//return strings.Replace(s, " ", "+", -1)
}
func makeLinkTitle(t string) (newTitle string, title string) {
title = titleRe.ReplaceAllString(t, "")
newTitle = spaceReplace(title)
return
}
func buildIndex(html string) (string, string) {
var ret string
m := make(map[string]int)
hn := reIndex.FindAllStringSubmatch(html, -1)
html = reHeader.ReplaceAllString(html, `${1} id="${2}">${2}${3}`)
html = reLink.ReplaceAllStringFunc(html, spaceReplace)
for k, v := range hn {
link, _ := makeLinkTitle(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
}
func renderResult(res []Result) (html string) {
//TODO fmt.Sprintf ?
for r := range res {
html += `<a href="/` + r.LinkTitle + `"><b>` + r.Title + "</b></a>" +
`<pre style="white-space: pre-wrap">` + r.Text + "</pre><br>"
}
}