Allow ticking and unticking checkboxes

This commit is contained in:
Maximilian Friedersdorff 2025-07-29 12:44:01 +01:00
parent 4aa09ce502
commit 352d9555ba
2 changed files with 24 additions and 33 deletions

View file

@ -3,7 +3,7 @@
<div class="list-group list-group-flush"> <div class="list-group list-group-flush">
{{range $note := .notes}} {{range $note := .notes}}
<a class="list-group-item list-group-item-action d-flex justify-content-between" <a class="list-group-item list-group-item-action d-flex justify-content-between"
href="{{$note.Url}}/"> href="{{$note.URL}}/">
<span>{{$note.Title}}</span> <span>{{$note.Title}}</span>
<img src="/static/icons/eye.svg" alt="Edit"> <img src="/static/icons/eye.svg" alt="Edit">
</a> </a>

View file

@ -1,10 +1,11 @@
// Notes implements a data structure for reasoning about and rendering // Package notes implements a data structure for reasoning about and rendering
// markdown notes // markdown notes
package notes package notes
import ( import (
"bytes" "bytes"
"encoding/base64" "encoding/base64"
"errors"
"fmt" "fmt"
"html/template" "html/template"
"log" "log"
@ -102,47 +103,37 @@ func (t *toggleCheckboxTransformer) Transform(node *ast.Document, reader text.Re
}) })
} }
func (r *markdown.Renderer) renderTaskCheckBox(node ast.Node, entering bool) ast.WalkStatus { func renderTaskCheckBox(writer util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
if entering { var err error
var itemPrefix []byte var _ int
l := r.rc.lists[len(r.rc.lists)-1] n, ok := node.(*astext.TaskCheckBox)
if !ok {
if l.list.IsOrdered() { return ast.WalkContinue, errors.New("not a TaskCheckBox")
itemPrefix = append(itemPrefix, []byte(fmt.Sprint(l.num))...)
r.rc.lists[len(r.rc.lists)-1].num += 1
}
itemPrefix = append(itemPrefix, l.list.Marker, ' ')
// Prefix the current line with the item prefix
r.rc.writer.PushPrefix(itemPrefix, 0, 0)
// Prefix subsequent lines with padding the same length as the item prefix
indentLen := int(max(r.config.NestedListLength, NestedListLengthMinimum))
indent := bytes.Repeat([]byte{' '}, indentLen)
r.rc.writer.PushPrefix(bytes.Repeat(indent, len(itemPrefix)), 1)
} else {
r.rc.writer.PopPrefix()
r.rc.writer.PopPrefix()
} }
return ast.WalkContinue if entering {
// Render a box if necessary
if n.IsChecked {
_, err = writer.Write([]byte("[x] "))
} else {
_, err = writer.Write([]byte("[ ] "))
}
}
return ast.WalkContinue, err
} }
func (n *Note) ToggleBox(nthBox int) { func (n *Note) ToggleBox(nthBox int) {
log.Printf("Toggling %dth box", nthBox)
checkboxTransformer := toggleCheckboxTransformer{nthBox: nthBox} checkboxTransformer := toggleCheckboxTransformer{nthBox: nthBox}
transformer := util.Prioritized(&checkboxTransformer, 0) transformer := util.Prioritized(&checkboxTransformer, 0)
renderer := markdown.NewRenderer() renderer := markdown.NewRenderer()
renderer.Register(astext.KindTaskCheckBox, func(writer util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) { renderer.Register(astext.KindTaskCheckBox, renderTaskCheckBox)
})
var buf bytes.Buffer var buf bytes.Buffer
md := goldmark.New( md := goldmark.New(goldmark.WithRenderer(renderer))
goldmark.WithExtensions(
extension.TaskList, md.Parser().AddOptions(parser.WithInlineParsers(
), util.Prioritized(extension.NewTaskCheckBoxParser(), 0),
goldmark.WithRenderer(markdown.NewRenderer()), ), parser.WithASTTransformers(transformer))
goldmark.WithParserOptions(parser.WithASTTransformers(transformer)),
)
md.Convert(n.Body, &buf) md.Convert(n.Body, &buf)
n.Body = buf.Bytes() n.Body = buf.Bytes()