Skip to content

Commit

Permalink
Implement basic relative wikilink support
Browse files Browse the repository at this point in the history
Closes jackyzha0#35. This allows hugo-obsidian to intuit absolute paths from unanchored
wikilink paths. Previously, a note at `directory/note.md` would need to be
linked using `[[directory/note]]` in order for the link to be recognized by this
tool. This change allows the shorter `[[note]]` link to be used. This is
accomplished by first walking the directory tree and storing absolute paths for
every path basename, and using this to substitute link names before rendering them.

There's no test infrastructure for this project, but IWOMM
  • Loading branch information
lily-mara committed Jul 12, 2023
1 parent a7bc6ab commit 70e5335
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 18 deletions.
12 changes: 3 additions & 9 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down
10 changes: 7 additions & 3 deletions parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down
76 changes: 70 additions & 6 deletions walk.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand All @@ -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)
Expand All @@ -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
}
Expand Down Expand Up @@ -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{
Expand All @@ -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++
Expand Down

0 comments on commit 70e5335

Please sign in to comment.