all repos

anpi @ 2ef9e52b45dd5ef6b734c944cf861c4e633597ad

yaml to anki importer

anpi/main.go (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
add cli interface, 1 year ago
1
package main
2
3
import (
4
	"fmt"
5
	"log/slog"
6
	"os"
7
	"path/filepath"
8
	"strings"
9
10
	"github.com/alecthomas/kong"
11
	"github.com/gomarkdown/markdown"
12
	"github.com/gomarkdown/markdown/html"
13
	mdParser "github.com/gomarkdown/markdown/parser"
14
	"github.com/olexsmir/anpi/anki"
15
	"github.com/olexsmir/anpi/parser"
16
)
17
18
//nolint:gochecknoglobals // comment to make linter happy
19
var cli struct {
20
	File string `help:"path to import file" name:"file" type:"path"`
21
}
22
23
func main() {
24
	_ = kong.Parse(&cli)
25
	if err := run(cli.File); err != nil {
26
		fmt.Fprintf(os.Stderr, "error: %v\n", err)
27
		os.Exit(1)
28
	}
29
}
30
31
func run(fpath string) error {
32
	anki := anki.NewAnkiClient()
33
34
	f, err := os.ReadFile(filepath.Clean(fpath))
35
	if err != nil {
36
		return err
37
	}
38
39
	data, err := parser.Parse(f)
40
	if err != nil {
41
		return err
42
	}
43
44
	for _, deck := range data {
45
		for _, note := range deck.Notes {
46
			fields := make(map[string]string)
47
			for k, v := range note.Fields {
48
				fields[deck.FieldLookUp(k)] = fromMarkdown(v)
49
			}
50
51
			slog.Info("gotten fields", "fields", fields)
52
53
			tags := mergeTags(deck.Tags, note.Tags)
54
			nid, err := anki.AddNote(deck.Deck, deck.Type, fields, tags)
55
			if err != nil {
56
				return err
57
			}
58
59
			slog.Info("note added", "id", nid, "fields", fields)
60
		}
61
	}
62
63
	return nil
64
}
65
66
func mergeTags(global, local []string) []string {
67
	unique := make(map[string]struct{})
68
69
	for _, tag := range global {
70
		unique[tag] = struct{}{}
71
	}
72
	for _, tag := range local {
73
		unique[tag] = struct{}{}
74
	}
75
76
	result := make([]string, 0, len(unique))
77
	for tag := range unique {
78
		result = append(result, tag)
79
	}
80
81
	return result
82
}
83
84
func fromMarkdown(inp string) string {
85
	htmlFlags := html.CommonFlags | html.HrefTargetBlank
86
	opts := html.RendererOptions{Flags: htmlFlags}
87
88
	p := mdParser.New()
89
	doc := p.Parse([]byte(inp))
90
91
	str := string(markdown.Render(doc, html.NewRenderer(opts)))
92
	str = strings.ReplaceAll(str, "<p>", "")
93
	str = strings.ReplaceAll(str, "</p>", "")
94
95
	return str
96
}