mirror of
https://github.com/diamondburned/cchat-discord.git
synced 2024-12-27 14:27:43 +00:00
81 lines
1.9 KiB
Go
81 lines
1.9 KiB
Go
package blockquote
|
|
|
|
import (
|
|
"github.com/diamondburned/cchat-discord/internal/segments/renderer"
|
|
"github.com/diamondburned/cchat/text"
|
|
"github.com/diamondburned/cchat/utils/empty"
|
|
"github.com/yuin/goldmark/ast"
|
|
)
|
|
|
|
func init() {
|
|
renderer.Register(ast.KindBlockquote, blockquote)
|
|
}
|
|
|
|
func blockquote(r *renderer.Text, node ast.Node, enter bool) ast.WalkStatus {
|
|
n := node.(*ast.Blockquote)
|
|
|
|
if enter {
|
|
// Block formatting.
|
|
r.EnsureBreak()
|
|
defer r.EnsureBreak()
|
|
|
|
// Create a segment.
|
|
var seg = Segment{Start: r.Buffer.Len()}
|
|
|
|
// A blockquote contains a paragraph each line. Because Discord.
|
|
for child := n.FirstChild(); child != nil; child = child.NextSibling() {
|
|
r.Buffer.WriteString("> ")
|
|
|
|
ast.Walk(child, func(node ast.Node, enter bool) (ast.WalkStatus, error) {
|
|
// We only call when entering, since we don't want to trigger a
|
|
// hard new line after each paragraph.
|
|
if enter {
|
|
return r.RenderNode(node, enter)
|
|
}
|
|
return ast.WalkContinue, nil
|
|
})
|
|
}
|
|
|
|
// Search until the last non-whitespace.
|
|
var i = r.Buffer.Len() - 1
|
|
for bytes := r.Buffer.Bytes(); i > 0 && isSpace(bytes[i]); i-- {
|
|
}
|
|
|
|
// The ending will have a trailing character that's not covered, so
|
|
// we'll need to do that ourselves.
|
|
// End the codeblock at that non-whitespace location.
|
|
seg.End = i + 1
|
|
r.Append(seg)
|
|
}
|
|
|
|
return ast.WalkSkipChildren
|
|
}
|
|
|
|
type Segment struct {
|
|
empty.TextSegment
|
|
Start, End int
|
|
}
|
|
|
|
var (
|
|
_ text.Segment = (*Segment)(nil)
|
|
_ text.Quoteblocker = (*Segment)(nil)
|
|
)
|
|
|
|
func (b Segment) Bounds() (start, end int) {
|
|
return b.Start, b.End
|
|
}
|
|
|
|
func (b Segment) AsBlockquoter() text.Quoteblocker {
|
|
return b
|
|
}
|
|
|
|
func (b Segment) QuotePrefix() string {
|
|
return "> "
|
|
}
|
|
|
|
// isSpace is a quick function that matches if the byte is a space, a new line
|
|
// or a return carriage.
|
|
func isSpace(b byte) bool {
|
|
return b == ' ' || b == '\n' || b == '\r'
|
|
}
|