1
0
Fork 0
mirror of https://github.com/diamondburned/cchat-discord.git synced 2024-11-01 12:24:15 +00:00
cchat-discord/segments/md.go

102 lines
2.1 KiB
Go
Raw Normal View History

2020-06-19 01:00:24 +00:00
package segments
import (
"bytes"
"github.com/diamondburned/arikawa/discord"
"github.com/diamondburned/arikawa/state"
"github.com/diamondburned/cchat/text"
"github.com/diamondburned/ningen/md"
"github.com/yuin/goldmark/ast"
)
type TextRenderer struct {
buf *bytes.Buffer
src []byte
segs []text.Segment
inls inlineState
}
func ParseMessage(m *discord.Message, s state.Store) text.Rich {
return ParseWithMessage([]byte(m.Content), s, m, true)
}
func ParseWithMessage(b []byte, s state.Store, m *discord.Message, msg bool) text.Rich {
node := md.ParseWithMessage(b, s, m, msg)
return RenderNode(b, node)
}
func Parse(b []byte) text.Rich {
node := md.Parse(b)
return RenderNode(b, node)
}
func RenderNode(source []byte, n ast.Node) text.Rich {
buf := &bytes.Buffer{}
buf.Grow(len(source))
r := TextRenderer{
src: source,
buf: buf,
segs: make([]text.Segment, 0, n.ChildCount()),
}
ast.Walk(n, r.renderNode)
return text.Rich{
Content: buf.String(),
Segments: r.segs,
}
}
// i returns the current cursor position.
func (r *TextRenderer) i() int {
return r.buf.Len()
}
func (r *TextRenderer) append(segs ...text.Segment) {
r.segs = append(r.segs, segs...)
}
func (r *TextRenderer) renderNode(n ast.Node, enter bool) (ast.WalkStatus, error) {
switch n := n.(type) {
case *ast.Document:
case *ast.Paragraph:
if !enter {
// TODO: investigate
// r.buf.WriteByte('\n')
}
case *ast.Blockquote:
return r.blockquote(n, enter), nil
case *ast.FencedCodeBlock:
return r.codeblock(n, enter), nil
case *ast.Link:
return r.link(n, enter), nil
case *ast.AutoLink:
return r.autoLink(n, enter), nil
case *md.Inline:
return r.inline(n, enter), nil
case *md.Emoji:
return r.emoji(n, enter), nil
case *md.Mention:
return r.mention(n, enter), nil
case *ast.String:
if enter {
r.buf.Write(n.Value)
}
case *ast.Text:
if enter {
r.buf.Write(n.Segment.Value(r.src))
switch {
case n.HardLineBreak():
r.buf.WriteString("\n\n")
case n.SoftLineBreak():
r.buf.WriteByte('\n')
}
}
}
return ast.WalkContinue, nil
}