Store and save metadata in frontmatter

This commit is contained in:
Maximilian Friedersdorff 2025-08-08 21:10:10 +01:00
parent 03b6bb12ca
commit de66fb0b77
2 changed files with 81 additions and 7 deletions

View file

@ -3,6 +3,7 @@
package notes
import (
"bufio"
"bytes"
"encoding/base64"
"errors"
@ -23,6 +24,7 @@ import (
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/text"
"github.com/yuin/goldmark/util"
"gopkg.in/yaml.v2"
)
// Note is the central data structure. It can be Saved, Rendered and Loaded
@ -94,14 +96,48 @@ func (ns *NoteStore) Get(owner string) []*Note {
return ns.notes[owner]
}
func (ns *NoteStore) GetOne(owner string, encodedTitle string) (*Note, bool) {
notes := ns.Get(owner)
for _, note := range notes {
if note.EncodedTitle() == encodedTitle {
log.Printf("Found single note during GetOne %+v", note)
return note, true
}
}
return nil, false
}
func (ns *NoteStore) Add(note *Note) {
ns.notes[note.Owner] = append(ns.notes[note.Owner], note)
}
func fmtPath(path string) string {
return fmt.Sprintf("%s.%s", path, conf.Conf.Extension)
}
func (n *Note) marshalFrontmatter() ([]byte, error) {
frontmatter := make(map[string]interface{})
frontmatter["owner"] = n.Owner
frontmatter["viewers"] = n.Viewers
marshaled, err := yaml.Marshal(&frontmatter)
return marshaled, err
}
// Save a note to a path derived from the title
func (n *Note) Save() error {
frontmatter, err := n.marshalFrontmatter()
if err != nil {
return err
}
filename := filepath.Join(conf.Conf.NotesDir, fmtPath(n.EncodedTitle()))
return os.WriteFile(filename, n.Body, 0600)
return os.WriteFile(
filename,
[]byte(fmt.Sprintf("---\n%s---\n%s", frontmatter, n.Body)),
0600,
)
}
// Render the markdown content of the note to HTML
@ -119,15 +155,42 @@ func (n *Note) Render() {
// LoadNote from the disk. The path is derived from the title
func LoadNote(encodedTitle string) (*Note, error) {
filename := filepath.Join(conf.Conf.NotesDir, fmtPath(encodedTitle))
body, err := os.ReadFile(filename)
f, err := os.Open(filename)
if err != nil {
return nil, err
}
defer f.Close()
bodyScanner := bufio.NewScanner(f)
body := make([]byte, 0, 10)
fullBody := make([]byte, 0, 10)
inFrontmatter := false
for bodyScanner.Scan() {
fullBody = append(fullBody, bodyScanner.Bytes()...)
fullBody = append(fullBody, '\n')
text := bodyScanner.Text()
if text == "---" {
if !inFrontmatter {
inFrontmatter = true
} else {
inFrontmatter = false
break
}
}
}
for bodyScanner.Scan() {
body = append(body, bodyScanner.Bytes()...)
body = append(body, '\n')
}
title := DecodeTitle(encodedTitle)
var buf bytes.Buffer
context := parser.NewContext()
if err := md.Convert([]byte(body), &buf, parser.WithContext(context)); err != nil {
if err := md.Convert([]byte(fullBody), &buf, parser.WithContext(context)); err != nil {
return nil, err
}
metaData := meta.Get(context)

View file

@ -78,12 +78,16 @@ func edit(w http.ResponseWriter, r *http.Request) {
}
func new(w http.ResponseWriter, r *http.Request) {
user := r.Context().Value(middleware.ContextKey("user")).(string)
title := r.FormValue("title")
if len(title) == 0 {
title = "<New Note>"
}
note := &notes.Note{Title: title}
note := &notes.Note{Title: title, Owner: user}
note.Save()
notes.Notes.Add(note)
urlEdit := myurls.Reverse("edit", urls.Repl{"note": note.EncodedTitle()})
http.Redirect(w, r, urlEdit, http.StatusFound)
@ -105,13 +109,20 @@ func delete(w http.ResponseWriter, r *http.Request) {
}
func save(w http.ResponseWriter, r *http.Request) {
// user := r.Context().Value(middleware.ContextKey("user")).(string)
user := r.Context().Value(middleware.ContextKey("user")).(string)
oldTitle := r.PathValue("note")
note, ok := notes.Notes.GetOne(user, oldTitle)
if !ok {
http.NotFound(w, r)
}
title := r.FormValue("title")
body := r.FormValue("body")
note := &notes.Note{Title: title, Body: []byte(body)}
log.Printf("About to save to note %+v", note)
note.Title = title
note.Body = []byte(body)
note.Save()
if oldTitle != note.EncodedTitle() {