mirror of
https://github.com/diamondburned/cchat-discord.git
synced 2024-11-01 12:24:15 +00:00
102 lines
2.1 KiB
Go
102 lines
2.1 KiB
Go
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
|
|
}
|