package main import ( "encoding/json" "fmt" "html/template" "os" "path/filepath" "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 []struct { Id string Indented int Text string } var links []ParsedLink err := json.NewDecoder(strings.NewReader(content)).Decode(&listItems) if err == nil { for _, item := range listItems { 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:] } links := renderLinks(line) pageText := renderMarkdown2(links) 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), 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 }