118 lines
2.6 KiB
Go
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
|
|
})
|
|
}
|