gonotes/internal/notes/notes.go

81 lines
1.9 KiB
Go
Raw Normal View History

// Notes implements a data structure for reasoning about and rendering
// markdown notes
package notes
import (
"bytes"
2025-06-27 22:56:50 +01:00
"encoding/base64"
"fmt"
2025-01-27 22:28:18 +00:00
"html/template"
"log"
"os"
"path/filepath"
2025-06-01 21:27:08 +01:00
"forgejo.gwairfelin.com/max/gonotes/internal/conf"
"github.com/yuin/goldmark"
2025-01-27 22:28:18 +00:00
"github.com/yuin/goldmark/extension"
)
// Note is the central data structure. It can be Saved, Rendered and Loaded
// using the Save, Render and LoadNote functions.
type Note struct {
Title string
2025-01-27 22:28:18 +00:00
BodyRendered template.HTML
Body []byte
}
func fmtPath(path string) string {
return fmt.Sprintf("%s.%s", path, conf.Conf.Extension)
}
// Save a note to a path derived from the title
func (n *Note) Save() error {
2025-06-27 22:56:50 +01:00
filename := filepath.Join(conf.Conf.NotesDir, fmtPath(n.EncodedTitle()))
return os.WriteFile(filename, n.Body, 0600)
}
// Render the markdown content of the note to HTML
func (n *Note) Render() {
var buf bytes.Buffer
2025-01-27 22:28:18 +00:00
md := goldmark.New(
goldmark.WithExtensions(
extension.TaskList,
),
)
err := md.Convert(n.Body, &buf)
if err != nil {
log.Fatal(err)
}
2025-01-27 22:28:18 +00:00
n.BodyRendered = template.HTML(buf.String())
}
// Load a note from the disk. The path is derived from the title
2025-06-27 22:56:50 +01:00
func LoadNote(encodedTitle string) (*Note, error) {
filename := filepath.Join(conf.Conf.NotesDir, fmtPath(encodedTitle))
body, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
2025-06-27 22:56:50 +01:00
title := DecodeTitle(encodedTitle)
return &Note{Title: title, Body: body}, nil
}
2025-06-18 21:40:42 +01:00
func DeleteNote(title string) error {
filename := filepath.Join(conf.Conf.NotesDir, fmtPath(title))
return os.Remove(filename)
}
2025-06-27 22:56:50 +01:00
func (n *Note) EncodedTitle() string {
return base64.StdEncoding.EncodeToString([]byte(n.Title))
}
func DecodeTitle(encodedTitle string) string {
title, err := base64.StdEncoding.DecodeString(encodedTitle)
if err != nil {
log.Printf("Couldn't decode base64 string '%s': %s", encodedTitle, err)
}
return string(title)
}