renderer.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. package notifications
  2. import (
  3. "io"
  4. "github.com/diamondburned/ningen/v3/discordmd"
  5. "github.com/yuin/goldmark/ast"
  6. gmr "github.com/yuin/goldmark/renderer"
  7. )
  8. // Using a modified version of the discordmd BasicRenderer
  9. var defaultRenderer = newRenderer()
  10. type renderer struct {
  11. config *gmr.Config
  12. }
  13. func newRenderer() *renderer {
  14. config := gmr.NewConfig()
  15. return &renderer{config}
  16. }
  17. func (r *renderer) AddOptions(opts ...gmr.Option) {
  18. for _, opt := range opts {
  19. opt.SetConfig(r.config)
  20. }
  21. }
  22. func (r *renderer) Render(w io.Writer, source []byte, n ast.Node) error {
  23. return ast.Walk(n, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
  24. switch n := n.(type) {
  25. case *ast.Document:
  26. // noop
  27. case *ast.Blockquote:
  28. io.WriteString(w, "\"")
  29. case *ast.Heading:
  30. io.WriteString(w, "\n")
  31. case *ast.FencedCodeBlock:
  32. io.WriteString(w, "\n")
  33. if entering {
  34. lines := n.Lines()
  35. for i := range lines.Len() {
  36. line := lines.At(i)
  37. io.WriteString(w, "| ")
  38. w.Write(line.Value(source))
  39. }
  40. }
  41. case *ast.AutoLink:
  42. if entering {
  43. w.Write(n.URL(source))
  44. }
  45. case *ast.Link:
  46. if !entering {
  47. io.WriteString(w, " ("+string(n.Destination)+")")
  48. }
  49. case *discordmd.Inline:
  50. if n.Attr&discordmd.AttrSpoiler != 0 {
  51. if entering {
  52. io.WriteString(w, "*spoiler*")
  53. }
  54. return ast.WalkSkipChildren, nil
  55. }
  56. case *ast.Text:
  57. if entering {
  58. w.Write(n.Segment.Value(source))
  59. switch {
  60. case n.HardLineBreak():
  61. io.WriteString(w, "\n\n")
  62. case n.SoftLineBreak():
  63. io.WriteString(w, "\n")
  64. }
  65. }
  66. case *discordmd.Mention:
  67. if entering {
  68. switch {
  69. case n.Channel != nil:
  70. io.WriteString(w, "#"+n.Channel.Name)
  71. case n.GuildUser != nil:
  72. io.WriteString(w, "@"+n.GuildUser.Username)
  73. case n.GuildRole != nil:
  74. io.WriteString(w, "@"+n.GuildRole.Name)
  75. }
  76. }
  77. case *discordmd.Emoji:
  78. if entering {
  79. io.WriteString(w, ":"+string(n.Name)+":")
  80. }
  81. }
  82. return ast.WalkContinue, nil
  83. })
  84. }