diff --git a/backref.go b/backref.go new file mode 100644 index 0000000..af65e53 --- /dev/null +++ b/backref.go @@ -0,0 +1,61 @@ +package main + +import ( + "encoding/json" + "os" + "path/filepath" + "strings" +) + +type Refs map[string][]string + +func processBackrefs(fp *FilePages) error { + pages, err := fp.AllPages() + + refs := make(Refs) + + if err != nil { + return err + } + + for _, page := range pages { + links, err := ParseLinks(page.Content) + + if err != nil { + return err + } + + for _, link := range links { + refs[link.PageName] = append(refs[link.PageName], page.Name) + } + } + + f, err := os.Create(filepath.Join(fp.dirname, "backrefs.json")) + if err != nil { + return err + } + defer f.Close() + + err = json.NewEncoder(f).Encode(&refs) + + return err +} + +func loadBackrefs(fp *FilePages, p string) ([]string, error) { + refs := make(Refs) + p = strings.Replace(p, " ", "_", -1) + + f, err := os.Open(filepath.Join(fp.dirname, "backrefs.json")) + if err != nil { + return nil, err + } + + defer f.Close() + + err = json.NewDecoder(f).Decode(&refs) + if err != nil { + return nil, err + } + + return refs[p], nil +} diff --git a/file.go b/file.go index 5a174b9..54a4c8c 100644 --- a/file.go +++ b/file.go @@ -27,8 +27,9 @@ func NewFilePages(dirname string) PagesRepository { return fp } -func (fp *FilePages) Get(p string) Page { - f, err := os.Open(filepath.Join(fp.dirname, strings.Replace(p, " ", "_", -1))) +func (fp *FilePages) Get(title string) Page { + name := strings.Replace(title, " ", "_", -1) + f, err := os.Open(filepath.Join(fp.dirname, name)) if err != nil { return Page{} } @@ -37,7 +38,16 @@ func (fp *FilePages) Get(p string) Page { if err != nil { return Page{} } - return Page{Content: string(body)} + refs, err := loadBackrefs(fp, name) + if err != nil { + return Page{} + } + return Page{ + Name: name, + Title: title, + Content: string(body), + Refs: refs, + } } func (fp *FilePages) Save(p string, page Page, summary, author string) error { @@ -61,6 +71,11 @@ func (fp *FilePages) Save(p string, page Page, summary, author string) error { f.WriteString(strings.Replace(page.Content, "\r\n", "\n", -1)) } + err = processBackrefs(fp) + if err != nil { + return fmt.Errorf("while processing backrefs: %v", err) + } + return saveWithGit(fp, p, summary, author) } @@ -247,3 +262,17 @@ func (fp *FilePages) RecentChanges() ([]Change, error) { return changes, nil } + +func (fp *FilePages) AllPages() ([]Page, error) { + files, err := ioutil.ReadDir(fp.dirname) + if err != nil { + return nil, err + } + + var pages []Page + for _, file := range files { + pages = append(pages, fp.Get(file.Name())) + } + + return pages, nil +} diff --git a/main.go b/main.go index 4f8d262..089c662 100644 --- a/main.go +++ b/main.go @@ -29,7 +29,15 @@ const ( // Page type Page struct { + // Name is the filename of the page + Name string + + // Title is the human-readable title of the page + Title string + Content string + + Refs []string } type DiffPage struct { @@ -63,10 +71,11 @@ type PagesRepository interface { } type indexPage struct { - Session *Session - Title string - Name string - Content template.HTML + Session *Session + Title string + Name string + Content template.HTML + Backrefs []string } type editPage struct { @@ -395,7 +404,8 @@ func (h *indexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { page = "Home" } - pageText := mp.Get(page).Content + mpPage := mp.Get(page) + pageText := mpPage.Content if pageText == "" { http.Redirect(w, r, "/edit/"+page, 302) return @@ -438,10 +448,11 @@ func (h *indexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } data := indexPage{ - Session: sess, - Title: strings.Replace(page, "_", " ", -1), - Content: template.HTML(pageText), - Name: page, + Session: sess, + Title: strings.Replace(page, "_", " ", -1), + Content: template.HTML(pageText), + Name: page, + Backrefs: mpPage.Refs, } t, err := template.ParseFiles("templates/layout.html", "templates/view.html") diff --git a/templates/view.html b/templates/view.html index 2c53364..e65525b 100644 --- a/templates/view.html +++ b/templates/view.html @@ -3,6 +3,15 @@
{{ .Content }}
+ +
+

Backrefs

+ +
{{ end }} {{ define "navbar" }} diff --git a/util.go b/util.go index 9d85bce..7d92ba1 100644 --- a/util.go +++ b/util.go @@ -2,9 +2,16 @@ package main import ( "math/rand" + "regexp" + "strings" "time" ) +type ParsedLink struct { + Name string + PageName string +} + var random *rand.Rand func init() { @@ -20,3 +27,28 @@ func RandStringBytes(n int) string { } return string(b) } + +func ParseLinks(content string) ([]ParsedLink, error) { + hrefRE := regexp.MustCompile(`#?\[\[\s*([\w.\- ]+)\s*\]\]`) + + links := hrefRE.FindAllStringSubmatch(content, -1) + + var result []ParsedLink + + for _, matches := range links { + link := matches[0] + + if link[0] == '#' { + link = strings.TrimPrefix(link, "#[[") + } else { + link = strings.TrimPrefix(link, "[[") + } + + link = strings.TrimSuffix(link, "]]") + link = strings.TrimSpace(link) + l := strings.Replace(link, " ", "_", -1) + result = append(result, ParsedLink{link, l}) + } + + return result, nil +}