| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- 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:
- r.renderHeading(w)
- case *ast.Text:
- r.renderText(w, n, entering, source)
- case *ast.FencedCodeBlock:
- r.renderFencedCodeBlock(w, n, entering, source)
- case *ast.AutoLink:
- r.renderAutoLink(w, n, entering, source)
- case *ast.Link:
- r.renderLink(w, n, entering)
- case *discordmd.Inline:
- r.renderInline(w, n, entering)
- case *discordmd.Mention:
- r.renderMention(w, n, entering)
- case *discordmd.Emoji:
- r.renderEmoji(w, n, entering)
- }
- return ast.WalkContinue, nil
- })
- }
- func (r *renderer) renderHeading(w io.Writer) {
- io.WriteString(w, "\n")
- }
- func (r *renderer) renderFencedCodeBlock(w io.Writer, n *ast.FencedCodeBlock, entering bool, source []byte) {
- io.WriteString(w, "\n")
- if entering {
- // body
- lines := n.Lines()
- for i := range lines.Len() {
- line := lines.At(i)
- io.WriteString(w, "| ")
- w.Write(line.Value(source))
- }
- }
- }
- func (r *renderer) renderAutoLink(w io.Writer, n *ast.AutoLink, entering bool, source []byte) {
- if entering {
- linkColor := r.config.Options["linkColor"].(string)
- io.WriteString(w, "["+linkColor+"]")
- w.Write(n.URL(source))
- } else {
- io.WriteString(w, "[-::]")
- }
- }
- func (r *renderer) renderLink(w io.Writer, n *ast.Link, entering bool) {
- if entering {
- linkColor := r.config.Options["linkColor"].(string)
- io.WriteString(w, fmt.Sprintf("[%s:::%s]", linkColor, n.Destination))
- } else {
- io.WriteString(w, "[-:::-]")
- }
- }
- func (r *renderer) renderText(w io.Writer, n *ast.Text, entering bool, source []byte) {
- if entering {
- w.Write(n.Segment.Value(source))
- switch {
- case n.HardLineBreak():
- io.WriteString(w, "\n\n")
- case n.SoftLineBreak():
- io.WriteString(w, "\n")
- }
- }
- }
- func (r *renderer) renderInline(w io.Writer, n *discordmd.Inline, entering bool) {
- 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 {
- 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]")
- }
- }
- }
- func (r *renderer) renderMention(w io.Writer, n *discordmd.Mention, entering bool) {
- if entering {
- mentionColor := r.config.Options["mentionColor"].(string)
- _, _ = fmt.Fprintf(w, "[%s::b]", mentionColor)
- switch {
- case n.Channel != nil:
- io.WriteString(w, "#"+n.Channel.Name)
- case n.GuildUser != nil:
- username := n.GuildUser.DisplayOrUsername()
- if r.config.Options["showNicknames"].(bool) && n.GuildUser.Member != nil && n.GuildUser.Member.Nick != "" {
- username = n.GuildUser.Member.Nick
- }
- io.WriteString(w, "@"+username)
- case n.GuildRole != nil:
- io.WriteString(w, "@"+n.GuildRole.Name)
- }
- } else {
- io.WriteString(w, "[-::B]")
- }
- }
- func (r *renderer) renderEmoji(w io.Writer, n *discordmd.Emoji, entering bool) {
- if entering {
- emojiColor := r.config.Options["emojiColor"].(string)
- io.WriteString(w, "["+emojiColor+"]")
- io.WriteString(w, ":"+n.Name+":")
- } else {
- io.WriteString(w, "[-]")
- }
- }
|