diff --git a/main.go b/main.go index d5dfd44..d134eba 100644 --- a/main.go +++ b/main.go @@ -2,22 +2,16 @@ package main import ( "flag" - "github.com/BurntSushi/toml" - wikilink "github.com/abhinav/goldmark-wikilink" - "github.com/yuin/goldmark" "io/ioutil" "path/filepath" "time" + + "github.com/BurntSushi/toml" + "github.com/yuin/goldmark" ) var md goldmark.Markdown -func init() { - md = goldmark.New( - goldmark.WithExtensions(&wikilink.Extender{}), - ) -} - type Link struct { Source string `json:"source"` Target string `json:"target"` diff --git a/parse.go b/parse.go index a36c71d..cf0e65b 100644 --- a/parse.go +++ b/parse.go @@ -3,13 +3,15 @@ package main import ( "bytes" "fmt" - "github.com/PuerkitoBio/goquery" "io/ioutil" "strings" + + "github.com/PuerkitoBio/goquery" + "github.com/yuin/goldmark" ) // parse single file for links -func parse(dir, pathPrefix string) []Link { +func parse(md goldmark.Markdown, fileIndex fileIndex, dir, pathPrefix string) []Link { // read file source, err := ioutil.ReadFile(dir) if err != nil { @@ -37,8 +39,10 @@ func parse(dir, pathPrefix string) []Link { target = processTarget(target) source := processSource(trim(dir, pathPrefix, ".md")) + target = fileIndex.resolve(target) + // fmt.Printf(" '%s' => %s\n", source, target) - if !strings.HasPrefix(text, "^"){ + if !strings.HasPrefix(text, "^") { links = append(links, Link{ Source: source, Target: target, diff --git a/walk.go b/walk.go index 34e3795..978d130 100644 --- a/walk.go +++ b/walk.go @@ -9,7 +9,9 @@ import ( "strings" "time" + wikilink "github.com/abhinav/goldmark-wikilink" "github.com/adrg/frontmatter" + "github.com/yuin/goldmark" "gopkg.in/yaml.v2" ) @@ -19,6 +21,60 @@ type Front struct { Tags []string `yaml:"tags"` } +type fileIndex struct { + index map[string]string +} + +// resolve takes a link path and attempts to canonicalize it according to this +// fileIndex. If a matching canonical link cannot be found, the link is returned +// untouched. +func (i *fileIndex) resolve(path string) string { + if !isInternal(path) { + return path + } + + trimmedPath := strings.TrimLeft(path, "/") + + // If the path has any degree of nesting built into it, treat it as an absolute path + if strings.Contains(trimmedPath, "/") { + return path + } + + resolved, ok := i.index[trimmedPath] + if ok { + target := processTarget(resolved) + return target + } + + return path +} + +func buildFileIndex(root, ext string, ignorePaths map[string]struct{}) (fileIndex, error) { + index := map[string]string{} + err := filepath.WalkDir(root, func(fp string, d fs.DirEntry, e error) error { + if e != nil { + return e + } + + // path normalize fp + s := filepath.ToSlash(fp) + s = strings.ReplaceAll(s, " ", "-") + if _, ignored := ignorePaths[s]; ignored { + return nil + } else if filepath.Ext(d.Name()) == ext { + base := filepath.Base(strings.TrimSuffix(s, ".md")) + index[base] = strings.TrimPrefix(s, root) + } + + return nil + }) + if err != nil { + return fileIndex{}, err + } + + return fileIndex{index: index}, nil +} + // recursively walk directory and return all files with given extension func walk(root, ext string, index bool, ignorePaths map[string]struct{}) (res []Link, i ContentIndex) { fmt.Printf("Scraping %s\n", root) @@ -32,7 +88,15 @@ func walk(root, ext string, index bool, ignorePaths map[string]struct{}) (res [] start := time.Now() - err := filepath.WalkDir(root, func(fp string, d fs.DirEntry, e error) error { + md := goldmark.New( + goldmark.WithExtensions(&wikilink.Extender{})) + + fileIndex, err := buildFileIndex(root, ext, ignorePaths) + if err != nil { + panic(err) + } + + err = filepath.WalkDir(root, func(fp string, d fs.DirEntry, e error) error { if e != nil { return e } @@ -69,10 +133,10 @@ func walk(root, ext string, index bool, ignorePaths map[string]struct{}) (res [] title = strings.TrimSuffix(filepath.Base(fileName), filepath.Ext(fileName)) } - // default tags - if matter.Tags == nil { - matter.Tags = []string{} - } + // default tags + if matter.Tags == nil { + matter.Tags = []string{} + } // add to content and link index i[source] = Content{ @@ -81,7 +145,7 @@ func walk(root, ext string, index bool, ignorePaths map[string]struct{}) (res [] Content: body, Tags: matter.Tags, } - res = append(res, parse(s, root)...) + res = append(res, parse(md, fileIndex, s, root)...) } else { fmt.Printf("[Ignored] %s\n", d.Name()) nPrivate++