discordo/internal/markdown/renderer.go
2025-01-10 20:36:10 -05:00

118 lines
2.6 KiB
Go

package markdown
import (
"fmt"
"io"
"github.com/diamondburned/ningen/v3/discordmd"
"github.com/yuin/goldmark/ast"
gmr "github.com/yuin/goldmark/renderer"
)
var DefaultRenderer = newRenderer()
type renderer struct {
config *gmr.Config
}
func newRenderer() *renderer {
config := gmr.NewConfig()
return &renderer{config}
}
// AddOptions implements renderer.Renderer.
func (r *renderer) AddOptions(opts ...gmr.Option) {
for _, opt := range opts {
opt.SetConfig(r.config)
}
}
func (r *renderer) Render(w io.Writer, source []byte, n ast.Node) error {
return ast.Walk(n, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
switch n := n.(type) {
case *ast.Document:
// noop
case *ast.Heading:
io.WriteString(w, "\n")
case *ast.FencedCodeBlock:
io.WriteString(w, "\n")
if entering {
// body
for i := range n.Lines().Len() {
line := n.Lines().At(i)
io.WriteString(w, "| ")
w.Write(line.Value(source))
}
}
case *ast.AutoLink:
if entering {
linkColor := r.config.Options["linkColor"].(string)
io.WriteString(w, "["+linkColor+"]")
w.Write(n.URL(source))
} else {
io.WriteString(w, "[-::]")
}
case *ast.Link:
if entering {
linkColor := r.config.Options["linkColor"].(string)
io.WriteString(w, fmt.Sprintf("[%s:::%s]", linkColor, n.Destination))
} else {
io.WriteString(w, "[-:::-]")
}
case *ast.Text:
if entering {
w.Write(n.Segment.Value(source))
switch {
case n.HardLineBreak():
io.WriteString(w, "\n\n")
case n.SoftLineBreak():
io.WriteString(w, "\n")
}
}
case *discordmd.Inline:
if entering {
switch n.Attr {
case discordmd.AttrBold:
io.WriteString(w, "[::b]")
case discordmd.AttrItalics:
io.WriteString(w, "[::i]")
case discordmd.AttrUnderline:
io.WriteString(w, "[::u]")
case discordmd.AttrStrikethrough:
io.WriteString(w, "[::s]")
case discordmd.AttrMonospace:
io.WriteString(w, "[::r]")
}
} else {
io.WriteString(w, "[::-]")
}
case *discordmd.Mention:
if entering {
io.WriteString(w, "[::b]")
switch {
case n.Channel != nil:
io.WriteString(w, "#"+n.Channel.Name)
case n.GuildUser != nil:
io.WriteString(w, "@"+n.GuildUser.Username)
case n.GuildRole != nil:
io.WriteString(w, "@"+n.GuildRole.Name)
}
} else {
io.WriteString(w, "[::-]")
}
case *discordmd.Emoji:
if entering {
emojiColor := r.config.Options["emojiColor"].(string)
io.WriteString(w, "["+emojiColor+"]")
io.WriteString(w, ":"+n.Name+":")
} else {
io.WriteString(w, "[-]")
}
}
return ast.WalkContinue, nil
})
}