renderer.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package markdown
  2. import (
  3. "fmt"
  4. "io"
  5. "github.com/diamondburned/ningen/v3/discordmd"
  6. "github.com/yuin/goldmark/ast"
  7. gmr "github.com/yuin/goldmark/renderer"
  8. )
  9. var (
  10. DefaultRenderer = newRenderer()
  11. )
  12. type renderer struct {
  13. config *gmr.Config
  14. }
  15. func newRenderer() *renderer {
  16. config := gmr.NewConfig()
  17. return &renderer{config}
  18. }
  19. // AddOptions implements renderer.Renderer.
  20. func (r *renderer) AddOptions(opts ...gmr.Option) {
  21. for _, opt := range opts {
  22. opt.SetConfig(r.config)
  23. }
  24. }
  25. func (r *renderer) Render(w io.Writer, source []byte, n ast.Node) error {
  26. return ast.Walk(n, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
  27. switch n := n.(type) {
  28. case *ast.Document:
  29. // noop
  30. case *ast.FencedCodeBlock:
  31. io.WriteString(w, "\n")
  32. if entering {
  33. // body
  34. for i := 0; i < n.Lines().Len(); i++ {
  35. line := n.Lines().At(i)
  36. io.WriteString(w, "| ")
  37. w.Write(line.Value(source))
  38. }
  39. }
  40. case *ast.Link:
  41. if entering {
  42. io.WriteString(w, fmt.Sprintf("[:::%s]", n.Destination))
  43. } else {
  44. io.WriteString(w, "[:::-]")
  45. }
  46. case *ast.Text:
  47. if entering {
  48. value := n.Segment.Value(source)
  49. w.Write(value)
  50. }
  51. case *discordmd.Inline:
  52. if entering {
  53. switch n.Attr {
  54. case discordmd.AttrBold:
  55. io.WriteString(w, "[::b]")
  56. case discordmd.AttrItalics:
  57. io.WriteString(w, "[::i]")
  58. case discordmd.AttrUnderline:
  59. io.WriteString(w, "[::u]")
  60. case discordmd.AttrStrikethrough:
  61. io.WriteString(w, "[::s]")
  62. case discordmd.AttrMonospace:
  63. io.WriteString(w, "[::r]")
  64. }
  65. } else {
  66. io.WriteString(w, "[::-]")
  67. }
  68. case *discordmd.Mention:
  69. if entering {
  70. io.WriteString(w, "[::b]")
  71. switch {
  72. case n.Channel != nil:
  73. io.WriteString(w, "#"+n.Channel.Name)
  74. case n.GuildUser != nil:
  75. io.WriteString(w, "@"+n.GuildUser.Username)
  76. case n.GuildRole != nil:
  77. io.WriteString(w, "@"+n.GuildRole.Name)
  78. }
  79. } else {
  80. io.WriteString(w, "[::-]")
  81. }
  82. case *discordmd.Emoji:
  83. if entering {
  84. emojiColor := r.config.Options["emojiColor"].(string)
  85. io.WriteString(w, "["+emojiColor+"]")
  86. io.WriteString(w, ":"+n.Name+":")
  87. } else {
  88. io.WriteString(w, "[::-]")
  89. }
  90. }
  91. return ast.WalkContinue, nil
  92. })
  93. }