diff --git a/core/file_handling/doc.go b/core/file_handling/doc.go new file mode 100644 index 0000000..f5f2eff --- /dev/null +++ b/core/file_handling/doc.go @@ -0,0 +1,2 @@ +// Package filehandling provides utilities for handling files, including reading, writing, and manipulating file contents. +package filehandling diff --git a/core/frontmatter/parser.go b/core/file_handling/frontmatter_parser.go similarity index 65% rename from core/frontmatter/parser.go rename to core/file_handling/frontmatter_parser.go index 9bcb523..571c33e 100644 --- a/core/frontmatter/parser.go +++ b/core/file_handling/frontmatter_parser.go @@ -1,9 +1,8 @@ -package frontmatter +package filehandling import ( "bytes" "errors" - "log/slog" "gopkg.in/yaml.v3" ) @@ -16,16 +15,7 @@ type FrontMatter struct { Author string `yaml:"author"` } -func ParseTags(file []byte) ([]string, error) { - fm, err := parseFrontMatter(file) - if err != nil { - return nil, err - } - slog.Debug("parsed front matter", "fm", fm) - return fm.Tags, nil -} - -func parseFrontMatter(file []byte) (*FrontMatter, error) { +func ParseFrontMatter(file []byte) (*FrontMatter, error) { content := bytes.TrimSpace(file) if bytes.HasPrefix(content, []byte("---")) { content = bytes.TrimSpace(content[3:]) @@ -36,7 +26,6 @@ func parseFrontMatter(file []byte) (*FrontMatter, error) { if idx := bytes.Index(content, []byte("---")); idx != -1 { content = bytes.TrimSpace(content[:idx]) } - slog.Debug("yaml content to parse", "content", string(content)) var fm FrontMatter if err := yaml.Unmarshal(content, &fm); err != nil { diff --git a/core/frontmatter/slug.go b/core/file_handling/slug.go similarity index 93% rename from core/frontmatter/slug.go rename to core/file_handling/slug.go index 894b782..11676f4 100644 --- a/core/frontmatter/slug.go +++ b/core/file_handling/slug.go @@ -1,4 +1,4 @@ -package frontmatter +package filehandling import ( "bytes" diff --git a/core/file_handling/template.go b/core/file_handling/template.go new file mode 100644 index 0000000..e8a5ac3 --- /dev/null +++ b/core/file_handling/template.go @@ -0,0 +1,73 @@ +package filehandling + +import ( + "os" + "strings" + "time" + + "github.com/KristianJBorgwarth/dendrite.daemon/persistence/store" +) + +type Template struct { + Content []byte + Title string + Slug string + FrontMatter *FrontMatter +} + +func NewTemplate(templateName string, title string) (*Template, error) { + var templatePath string + if templateName != "" { + templatePath = store.GetVaultStore().GetTemplatePath(templateName) + } + slug := Slugify(title) + content, err := renderTemplate(templatePath, title, slug) + if err != nil { + return nil, err + } + + fm, err := ParseFrontMatter(content) + if err != nil { + return nil, err + } + + return &Template{ + Content: content, + Title: title, + Slug: slug, + FrontMatter: fm, + }, nil +} + +func renderTemplate(templatePath string, title string, slug string) ([]byte, error) { + template, err := readTemplate(templatePath, title) + if err != nil { + return nil, err + } + + r := strings.NewReplacer( + "{{title}}", title, + "{{date}}", time.Now().Format("2006-01-02"), + "{{slug}}", slug, + "{{file}}", slug+".md", + ) + + return []byte(r.Replace(string(template))), nil +} + +func readTemplate(templatePath string, title string) ([]byte, error) { + if templatePath == "" { + return createDefaultTemplate(title), nil + } + + template, err := os.ReadFile(templatePath) + if err != nil { + return nil, err + } + + return template, nil +} + +func createDefaultTemplate(title string) []byte { + return []byte("---\ntitle: " + title + "\ndate: " + time.Now().Format("2006-01-02") + "\n---\n") +} diff --git a/core/frontmatter/doc.go b/core/frontmatter/doc.go deleted file mode 100644 index b723de9..0000000 --- a/core/frontmatter/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package frontmatter contains utilities for parsing front matter from documents. -package frontmatter diff --git a/core/handlers/create_note_handler.go b/core/handlers/create_note_handler.go index 35d049a..ca8d8ce 100644 --- a/core/handlers/create_note_handler.go +++ b/core/handlers/create_note_handler.go @@ -5,9 +5,8 @@ import ( "encoding/json" "path/filepath" - "github.com/KristianJBorgwarth/dendrite.daemon/core/frontmatter" + filehandling "github.com/KristianJBorgwarth/dendrite.daemon/core/file_handling" "github.com/KristianJBorgwarth/dendrite.daemon/core/models" - "github.com/KristianJBorgwarth/dendrite.daemon/core/template" "github.com/KristianJBorgwarth/dendrite.daemon/core/utils" "github.com/KristianJBorgwarth/dendrite.daemon/persistence/repositories" "github.com/KristianJBorgwarth/dendrite.daemon/persistence/store" @@ -34,24 +33,12 @@ func (h *CreateNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (an return nil, err } - slug := frontmatter.Slugify(cmd.Title) - - var templatePath string - if cmd.TemplateName != "" { - templatePath = store.GetVaultStore().GetTemplatePath(cmd.TemplateName) - } - - notePath := filepath.Join(store.GetVaultStore().Config.VaultPath(), cmd.Directory, slug+".md") - - data, err := template.RenderTemplate(templatePath, cmd.Title, slug) + template, err := filehandling.NewTemplate(cmd.TemplateName, cmd.Title) if err != nil { return nil, err } - tags, err := frontmatter.ParseTags(data) - if err != nil { - return nil, err - } + notePath := filepath.Join(store.GetVaultStore().Config.VaultPath(), cmd.Directory, template.Slug+".md") tx, err := h.uow.Begin() if err != nil { @@ -63,12 +50,12 @@ func (h *CreateNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (an tagRepo := repositories.NewTagRepository(tx) noteRepo := repositories.NewNoteRepository(tx) - dbTags, err := tagRepo.GetByNames(ctx, tags) + dbTags, err := tagRepo.GetByNames(ctx, template.FrontMatter.Tags) if err != nil { return nil, err } - newTags := utils.Filter(tags, func(name string) bool { + newTags := utils.Filter(template.FrontMatter.Tags, func(name string) bool { for _, t := range dbTags { if t.Name() == name { return false @@ -88,7 +75,7 @@ func (h *CreateNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (an tagModels = append(tagModels, dbTags...) - note := models.CreateNote(notePath, cmd.Title, slug) + note := models.CreateNote(notePath, cmd.Title, template.Slug) if err = noteRepo.Upsert(ctx, note); err != nil { return nil, err @@ -98,7 +85,7 @@ func (h *CreateNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (an return nil, err } - h.uow.FileStore.Stage(notePath, data) + h.uow.FileStore.Stage(notePath, template.Content) if err = h.uow.Commit(); err != nil { return nil, err diff --git a/core/template/doc.go b/core/template/doc.go deleted file mode 100644 index 66c2031..0000000 --- a/core/template/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package template provides implementations for generating notes from templates -package template diff --git a/core/template/templater.go b/core/template/templater.go deleted file mode 100644 index aee4505..0000000 --- a/core/template/templater.go +++ /dev/null @@ -1,40 +0,0 @@ -package template - -import ( - "os" - "strings" - "time" -) - -func RenderTemplate(templatePath string, title string, slug string) ([]byte, error) { - template, err := readTemplate(templatePath, title) - if err != nil { - return nil, err - } - - r := strings.NewReplacer( - "{{title}}", title, - "{{date}}", time.Now().Format("2006-01-02"), - "{{slug}}", slug, - "{{file}}", slug+".md", - ) - - return []byte(r.Replace(string(template))), nil -} - -func readTemplate(templatePath string, title string) ([]byte, error) { - if templatePath == "" { - return createDefaultTemplate(title), nil - } - - template, err := os.ReadFile(templatePath) - if err != nil { - return nil, err - } - - return template, nil -} - -func createDefaultTemplate(title string) []byte { - return []byte("---\ntitle: " + title + "\ndate: " + time.Now().Format("2006-01-02") + "\n---\n") -} diff --git a/test/test_unit/frontmatter_test.go b/test/test_unit/frontmatter_test.go index b926e96..5056cc6 100644 --- a/test/test_unit/frontmatter_test.go +++ b/test/test_unit/frontmatter_test.go @@ -1,9 +1,9 @@ -package frontmatter_test +package filehandling import ( "testing" - "github.com/KristianJBorgwarth/dendrite.daemon/core/frontmatter" + filehandling "github.com/KristianJBorgwarth/dendrite.daemon/core/file_handling" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -15,10 +15,11 @@ tags: ["test", "note"] --- This is the content of the note.` - result, err := frontmatter.ParseTags([]byte(input)) + result, err := filehandling.ParseFrontMatter([]byte(input)) require.NoError(t, err) - assert.Equal(t, []string{"test", "note"}, result) + assert.Equal(t, "My Note", result.Title) + assert.Equal(t, []string{"test", "note"}, result.Tags) } func TestParseTags_MissingDelimiter_ReturnsError(t *testing.T) { @@ -26,7 +27,7 @@ func TestParseTags_MissingDelimiter_ReturnsError(t *testing.T) { tags: ["test", "note"] This is the content of the note.` - _, err := frontmatter.ParseTags([]byte(input)) + _, err := filehandling.ParseFrontMatter([]byte(input)) assert.ErrorContains(t, err, "missing front matter delimiter") }