Store and save metadata in frontmatter
This commit is contained in:
parent
03b6bb12ca
commit
de66fb0b77
2 changed files with 81 additions and 7 deletions
|
|
@ -3,6 +3,7 @@
|
||||||
package notes
|
package notes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
@ -23,6 +24,7 @@ import (
|
||||||
"github.com/yuin/goldmark/parser"
|
"github.com/yuin/goldmark/parser"
|
||||||
"github.com/yuin/goldmark/text"
|
"github.com/yuin/goldmark/text"
|
||||||
"github.com/yuin/goldmark/util"
|
"github.com/yuin/goldmark/util"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Note is the central data structure. It can be Saved, Rendered and Loaded
|
// 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]
|
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 {
|
func fmtPath(path string) string {
|
||||||
return fmt.Sprintf("%s.%s", path, conf.Conf.Extension)
|
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
|
// Save a note to a path derived from the title
|
||||||
func (n *Note) Save() error {
|
func (n *Note) Save() error {
|
||||||
|
frontmatter, err := n.marshalFrontmatter()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
filename := filepath.Join(conf.Conf.NotesDir, fmtPath(n.EncodedTitle()))
|
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
|
// 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
|
// LoadNote from the disk. The path is derived from the title
|
||||||
func LoadNote(encodedTitle string) (*Note, error) {
|
func LoadNote(encodedTitle string) (*Note, error) {
|
||||||
filename := filepath.Join(conf.Conf.NotesDir, fmtPath(encodedTitle))
|
filename := filepath.Join(conf.Conf.NotesDir, fmtPath(encodedTitle))
|
||||||
body, err := os.ReadFile(filename)
|
f, err := os.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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)
|
title := DecodeTitle(encodedTitle)
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
context := parser.NewContext()
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
metaData := meta.Get(context)
|
metaData := meta.Get(context)
|
||||||
|
|
|
||||||
|
|
@ -78,12 +78,16 @@ func edit(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func new(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")
|
title := r.FormValue("title")
|
||||||
if len(title) == 0 {
|
if len(title) == 0 {
|
||||||
title = "<New Note>"
|
title = "<New Note>"
|
||||||
}
|
}
|
||||||
|
|
||||||
note := ¬es.Note{Title: title}
|
note := ¬es.Note{Title: title, Owner: user}
|
||||||
|
note.Save()
|
||||||
|
notes.Notes.Add(note)
|
||||||
|
|
||||||
urlEdit := myurls.Reverse("edit", urls.Repl{"note": note.EncodedTitle()})
|
urlEdit := myurls.Reverse("edit", urls.Repl{"note": note.EncodedTitle()})
|
||||||
http.Redirect(w, r, urlEdit, http.StatusFound)
|
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) {
|
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")
|
oldTitle := r.PathValue("note")
|
||||||
|
note, ok := notes.Notes.GetOne(user, oldTitle)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
http.NotFound(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
title := r.FormValue("title")
|
title := r.FormValue("title")
|
||||||
body := r.FormValue("body")
|
body := r.FormValue("body")
|
||||||
|
|
||||||
note := ¬es.Note{Title: title, Body: []byte(body)}
|
log.Printf("About to save to note %+v", note)
|
||||||
|
note.Title = title
|
||||||
|
note.Body = []byte(body)
|
||||||
note.Save()
|
note.Save()
|
||||||
|
|
||||||
if oldTitle != note.EncodedTitle() {
|
if oldTitle != note.EncodedTitle() {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue