Skip to content

Instantly share code, notes, and snippets.

@nondeterminischtick
Last active July 13, 2023 00:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nondeterminischtick/63e054c066faf395c36731ae01779763 to your computer and use it in GitHub Desktop.
Save nondeterminischtick/63e054c066faf395c36731ae01779763 to your computer and use it in GitHub Desktop.
Backlink map. When ran from the content folder of a hugo project will create a json file that maps the Url and Title of a page to any internal links inside it.
package main
import (
"strings"
"log"
"os"
"io/ioutil"
"path/filepath"
"encoding/json"
"regexp"
)
type LinkMap struct {
Source string `json:"source"`
SourceTitle string `json:"sourceTitle"`
Target string `json:"target"`
}
func toUrl(path string) (string) {
return "/" + strings.TrimSuffix(path, ".md") + "/"
}
func main() {
var linkMaps []LinkMap
outputFile := os.Args[1]
err := filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
//for every markdown file find all links in the document and map them to the document name and title
if strings.HasSuffix(path, ".md") {
l := regexp.MustCompile(`!?\[([^\]]*)?\]\(((https?:\/\/)?[A-Za-z0-9\:\/\. ]+)(\"(.+)\")?\)`) // [link](pattern)
t := regexp.MustCompile(`title: (.*)\n`) // YAML title
content, err := ioutil.ReadFile(path)
if err != nil {
log.Print("failed to read: " + path)
return err
}
log.Print("Reading " + path)
s := string(content)
title := t.FindStringSubmatch(s)
links := l.FindAllStringSubmatch(s, -1)
for _, link := range links {
if strings.HasSuffix(link[2], ".md") {
log.Print("---> found link: " + link[2])
newMap := LinkMap {toUrl(path), title[1], toUrl(link[2])}
linkMaps = append(linkMaps, newMap)
}
}
}
return nil
})
if err != nil {
log.Panic(err)
}
jsonLinks, err := json.Marshal(linkMaps)
if err != nil{
log.Panic(err)
}
err = os.WriteFile(outputFile, jsonLinks, 0644)
if err != nil {
log.Panic(err)
}
}
@nondeterminischtick
Copy link
Author

I am then using this json file as data for hugo to render backlinks at the end of each post using something like this

    {{ $headerWritten := false }}
    {{ $links := site.Data.links }}
    {{ range $links }}
        {{ if eq .target $me }}
            {{ if not $headerWritten }}
                <h2>Backlinks</h2>
                {{ $headerWritten = true }}
            {{ end }}
            <a href="{{ .source }}">{{.sourceTitle}}</a><br/>
        {{ end }}
    {{ end }}```

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment