feat(note/save): setup save note (#17)

* feat(file): added file type

* feat(file_handler): added filehandler with placeholder func

* ref(links): updated link model and table

* feat(links): added link extration on file save

* feat(note_repo): added get by slug query
This commit is contained in:
Kristian 2026-04-11 00:01:57 +02:00 committed by GitHub
parent f2fc6ee0ee
commit c0591b6c7e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 119 additions and 4 deletions

View file

@ -0,0 +1,82 @@
package filehandling
import (
"bytes"
"os"
"path/filepath"
"regexp"
"strings"
)
type File struct {
Title string
Slug string
FrontMatter FrontMatter
Content []string
Links []ExtractedLink
}
type ExtractedLink struct {
Raw string
Display string
TargetSlug string
Line int
Col int
}
func ReadFile(path string) (*File, error) {
body, err := os.ReadFile(path)
if err != nil {
return nil, err
}
body = bytes.TrimSpace(body)
fm, err := ParseFrontMatter(body)
if err != nil {
return nil, err
}
return &File{
Title: fm.Title,
Slug: strings.TrimSuffix(filepath.Base(path), filepath.Ext(path)),
FrontMatter: *fm,
Content: strings.Split(string(body), "\n"),
Links: ExtractLinks(body),
}, nil
}
var linkRegex = regexp.MustCompile(`\[\[([^\]|]+)(?:\|([^\]]+))?\]\]`)
func ExtractLinks(body []byte) []ExtractedLink {
var links []ExtractedLink
lineStart := 0
lineNum := 1
for i := 0; i <= len(body); i++ {
if i == len(body) || body[i] == '\n' {
line := body[lineStart:i]
matches := linkRegex.FindAllSubmatchIndex(line, -1)
for _, m := range matches {
raw := string(line[m[0]:m[1]])
slug := string(line[m[2]:m[3]])
var display string
if m[4] != -1 {
display = string(line[m[4]:m[5]])
}
links = append(links, ExtractedLink{
TargetSlug: slug,
Raw: raw,
Display: display,
Line: lineNum,
Col: m[0] + 1,
})
}
lineStart = i + 1
lineNum++
}
}
return links
}

View file

@ -4,14 +4,12 @@ import (
"context"
"encoding/json"
filehandling "github.com/KristianJBorgwarth/dendrite.daemon/core/file_handling"
"github.com/KristianJBorgwarth/dendrite.daemon/persistence/repositories"
)
type saveNoteCommand struct {
Title string `json:"title"`
Content string `json:"content"`
Directory string `json:"directory"`
Tags []string `json:"tags"`
Path string `json:"path"`
}
type SaveNoteHandler struct {
@ -29,5 +27,27 @@ func (h *SaveNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (any,
return nil, err
}
file, err := filehandling.ReadFile(cmd.Path)
if err != nil {
return nil, err
}
tx, err := h.uow.Begin()
if err != nil {
return nil, err
}
defer h.uow.Rollback()
tagRepo := repositories.NewTagRepository(tx)
noteRepo := repositories.NewNoteRepository(tx)
note, err := noteRepo.GetBySlug(ctx, file.Slug)
if err != nil {
return nil, err
}
return nil, nil
}

BIN
dendrite

Binary file not shown.

View file

@ -30,3 +30,16 @@ func (r *noteRepository) Insert(ctx context.Context, note *models.Note) error {
_, err := r.Transaction.ExecContext(ctx, query, note.ID(), note.Title(), note.Path(), note.Slug())
return err
}
func (r *noteRepository) GetBySlug(ctx context.Context, slug string) (*models.Note, error) {
query := `SELECT id, title, path, slug, created_at, updated_at FROM notes WHERE slug = ?`
row := r.Transaction.QueryRowContext(ctx, query, slug)
var id, title, path, createdAt, updatedAt string
err := row.Scan(&id, &title, &path, &slug, &createdAt, &updatedAt)
if err != nil {
return nil, err
}
return models.NewNote(id, path, title, slug, createdAt, updatedAt), nil
}