Skip to content

Commit

Permalink
feat: parse link targets
Browse files Browse the repository at this point in the history
  • Loading branch information
luissimas committed Jun 3, 2024
1 parent 8202f76 commit cc5f11e
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 19 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ build:
go build -o bin/$(BINARY_NAME) ./cmd/zettelkasten-exporter/main.go

run: build
ZETTELKASTEN_DIRECTORY=~/Documents/vault ./bin/$(BINARY_NAME)
ZETTELKASTEN_DIRECTORY=./sample ./bin/$(BINARY_NAME)
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@
- [X] Read config
- [X] Find all files recursivelly
- [X] Parse markdown links
- [ ] Exclude links to non existing files
- [ ] Collect backlinks
- [ ] Configurable ignore file patterns
- [ ] Get zettelkasten from git url
- [ ] Support private repositories (Maybe with Github's PAT?)
- [ ] Exclude links to non existing files
- [ ] Collect backlinks
- [ ] Github actions CI
- [ ] Document usage in README
- [ ] Build image and push to OCI registry
- [ ] Deploy on K8s

https://prometheus.io/docs/instrumenting/writing_exporters/
4 changes: 2 additions & 2 deletions internal/collector/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (c *Collector) CollectMetrics() error {

metrics.TotalNoteCount.Set(float64(collected.NoteCount))
for name, metric := range collected.Notes {
metrics.LinkCount.WithLabelValues(name).Set(float64(metric.LinkCount))
metrics.LinkCount.WithLabelValues(name).Set(float64(len(metric.Links)))
}

elapsed := time.Since(started)
Expand Down Expand Up @@ -87,7 +87,7 @@ func (c *Collector) collectMetrics() (Metrics, error) {
}
metrics := CollectNoteMetrics(content)
notes[path] = metrics
linkCount += metrics.LinkCount
linkCount += len(metrics.Links)
noteCount += 1

slog.Info("collected metrics from file", slog.String("path", path), slog.Any("d", d), slog.Any("err", err))
Expand Down
26 changes: 20 additions & 6 deletions internal/collector/note.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package collector

import (
"log/slog"
"slices"

"github.com/yuin/goldmark"
Expand All @@ -16,23 +17,36 @@ var md = goldmark.New(
)

type NoteMetrics struct {
LinkCount int
Links map[string]int
}

func CollectNoteMetrics(content []byte) NoteMetrics {
return NoteMetrics{LinkCount: collectLinkCount(content)}
return NoteMetrics{Links: collectLinks(content)}
}

func collectLinkCount(content []byte) int {
func collectLinks(content []byte) map[string]int {
linkKinds := []ast.NodeKind{ast.KindLink, wikilink.Kind}
reader := text.NewReader(content)
root := md.Parser().Parse(reader)
linkCount := 0
links := make(map[string]int)
ast.Walk(root, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
if entering && slices.Contains(linkKinds, n.Kind()) {
linkCount += 1
var target string
switch v := n.(type) {
case *ast.Link:
target = string(v.Destination)
case *wikilink.Node:
target = string(v.Target)
}

v, ok := links[target]
if !ok {
links[target] = 0
}
links[target] = v + 1
}
return ast.WalkContinue, nil
})
return linkCount
slog.Info("Collected links", slog.Any("links", links))
return links
}
38 changes: 30 additions & 8 deletions internal/collector/note_test.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,47 @@
package collector

import "testing"
import (
"maps"
"testing"
)

func TestCollectNoteMetrics(t *testing.T) {
data := []struct {
name string
content string
expected NoteMetrics
}{
{"empty file", "", NoteMetrics{LinkCount: 0}},
{"file with a single wiki link", "[[Link]]", NoteMetrics{LinkCount: 1}},
{"file with multiple wiki links", "[[Link]]aksdjf[[anotherlink]]\n[[link]]", NoteMetrics{LinkCount: 3}},
{"wikilink dividers", "[[something|another]]\n\n[[link]]\n[[382dlk djfs link|yeah]]", NoteMetrics{LinkCount: 3}},
{"file with markdown link", "[Link](target.md)", NoteMetrics{LinkCount: 1}},
{"file with multiple links", "okok[Link](target.md)\n**ddk**[[linked]]`test`[[anothe|link]]\n\n[test](yet-another.md)", NoteMetrics{LinkCount: 4}},
{
name: "empty file",
content: "",
expected: NoteMetrics{Links: map[string]int{}},
},
{
name: "wiki links",
content: "[[Link]]aksdjf[[something|another]]\n[[link]]",
expected: NoteMetrics{Links: map[string]int{"Link": 1, "something": 1, "link": 1}},
},
{
name: "markdown link",
content: "[Link](target.md)",
expected: NoteMetrics{Links: map[string]int{"target.md": 1}},
},
{
name: "mixed links",
content: "okok[Link](target.md)\n**ddk**[[linked]]`test`[[another|link]]\n\n[test](yet-another.md)",
expected: NoteMetrics{Links: map[string]int{"target.md": 1, "linked": 1, "another": 1, "yet-another.md": 1}},
},
{
name: "repeated links",
content: "[[target.md|link]]\n[link](target.md)\n[[link]]",
expected: NoteMetrics{Links: map[string]int{"target.md": 2, "link": 1}},
},
}

for _, d := range data {
t.Run(d.name, func(t *testing.T) {
result := CollectNoteMetrics([]byte(d.content))
if result != d.expected {
if !maps.Equal(result.Links, d.expected.Links) {
t.Errorf("Expected %v, got %v", d.expected, result)
}
})
Expand Down

0 comments on commit cc5f11e

Please sign in to comment.