diff --git a/core/file_handling/file.go b/core/file_handling/file.go new file mode 100644 index 0000000..d15bfd4 --- /dev/null +++ b/core/file_handling/file.go @@ -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 +} diff --git a/core/handlers/note/save_note.go b/core/handlers/note/save_note.go index c7cae9b..78c4b96 100644 --- a/core/handlers/note/save_note.go +++ b/core/handlers/note/save_note.go @@ -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 } diff --git a/dendrite b/dendrite index ca1e8ca..5bfe907 100755 Binary files a/dendrite and b/dendrite differ diff --git a/persistence/repositories/note_repository.go b/persistence/repositories/note_repository.go index 6aa8a3c..140d6be 100644 --- a/persistence/repositories/note_repository.go +++ b/persistence/repositories/note_repository.go @@ -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 +}