/* * Wiki - A wiki with editor * Copyright (c) 2021-2021 Peter Stuifzand * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package main import ( "encoding/json" "fmt" "html/template" "log" "os" "path/filepath" "regexp" "strings" ) type Reference struct { Link ParsedLink Name string } type Refs map[string][]Reference func processBackrefs(dirname string, page Page) error { filename := filepath.Join(dirname, "backrefs.json") refs := make(Refs) err := loadBackrefs(filename, refs) if err != nil { return fmt.Errorf("while loading backrefs: %w", err) } err = processBackrefsForPage(page, refs) if err != nil { return fmt.Errorf("while processing backrefs for %q: %w", page.Name, err) } if err = saveBackrefs(filename, refs); err != nil { return fmt.Errorf("while saving backrefs: %w", err) } return nil } func saveBackrefs(filename string, refs Refs) error { f, err := os.Create(filename) if err != nil { return err } defer f.Close() return json.NewEncoder(f).Encode(&refs) } func processBackrefsForPage(page Page, refs Refs) error { content := page.Content var listItems []ListItem var links []ParsedLink err := json.NewDecoder(strings.NewReader(content)).Decode(&listItems) if err == nil { for _, item := range listItems { if item.Fleeting { continue } foundLinks, err := ParseLinks(item.ID, item.Text) if err != nil { continue } links = append(links, foundLinks...) } } else { links, err = ParseLinks(page.Name, page.Content) if err != nil { return err } } link: for _, link := range links { for i, ref := range refs[link.PageName] { if ref.Link.ID == link.ID { refs[link.PageName][i].Link = link continue link } } refs[link.PageName] = append(refs[link.PageName], Reference{link, page.Name}) } return nil } func getBackrefs(fp *FilePages, p string) (map[string][]Backref, error) { refs := make(Refs) p = strings.Replace(p, " ", "_", -1) filename := filepath.Join(fp.dirname, "backrefs.json") err := loadBackrefs(filename, refs) if err != nil { return nil, err } result := make(map[string][]Backref) for _, ref := range refs[p] { title := strings.Replace(ref.Name, "_", " ", -1) if _, e := result[ref.Name]; !e { result[ref.Name] = nil } line := strings.TrimLeft(ref.Link.Line, " ") if line[0] == '*' && line[1] == ' ' { line = line[2:] } metaKV, err := regexp.Compile(`(\w+)::\s+(.*)`) if err != nil { log.Fatal(err) } line = metaKV.ReplaceAllString(line, "**[[$1]]**: $2") pageText := renderMarkdown2(renderLinks(line, false)) editPageText := renderMarkdown2(renderLinks(line, true)) removeBrackets := func(r rune) rune { if r == '[' || r == ']' || r == '*' { return -1 } return r } result[ref.Name] = append(result[ref.Name], Backref{ Name: ref.Name, Title: title, LineHTML: template.HTML(pageText), LineEditHTML: template.HTML(editPageText), Line: strings.Map(removeBrackets, ref.Link.Line), }) } return result, nil } func loadBackrefs(filename string, refs Refs) error { f, err := os.Open(filename) if err != nil { return err } defer f.Close() err = json.NewDecoder(f).Decode(&refs) if err != nil { return err } return nil }