package markup
import (
gast "github.com/yuin/goldmark/ast"
east "github.com/yuin/goldmark/extension/ast"
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/text"
)
// The rendering hooks the stylesheet keys on: task-list state, table
// column hints and GitHub-style alerts. All of them are computed here,
// at render time, and reach the page as classes the sanitizer admits by
// exact name.
// taskLists marks each task item with its state and a list made only of
// task items with md-tasks, so the stylesheet can drop the bullet that
// would otherwise sit beside the checkbox. The TaskList extension emits
// the checkbox but no class on either.
type taskLists struct{}
func (taskLists) Transform(doc *gast.Document, _ text.Reader, _ parser.Context) {
gast.Walk(doc, func(n gast.Node, entering bool) (gast.WalkStatus, error) {
list, ok := n.(*gast.List)
if !ok || !entering {
return gast.WalkContinue, nil
}
all := list.ChildCount() > 0
for li := list.FirstChild(); li != nil; li = li.NextSibling() {
box := taskBox(li)
if box == nil {
all = false
continue
}
state := "unchecked"
if box.IsChecked {
state = "checked"
}
li.SetAttributeString("class", []byte(state))
}
if all {
list.SetAttributeString("class", []byte("md-tasks"))
}
return gast.WalkContinue, nil
})
}
// taskBox is the checkbox opening a list item, or nil.
func taskBox(li gast.Node) *east.TaskCheckBox {
if fc := li.FirstChild(); fc != nil {
if b, ok := fc.FirstChild().(*east.TaskCheckBox); ok {
return b
}
}
return nil
}