1
0
Fork 0
mirror of https://github.com/diamondburned/cchat-discord.git synced 2024-12-23 04:46:43 +00:00
cchat-discord/segments/inline_attr.go

105 lines
2.2 KiB
Go

package segments
import (
"github.com/diamondburned/cchat/text"
"github.com/diamondburned/ningen/md"
"github.com/yuin/goldmark/ast"
)
type inlineState struct {
// TODO: use a stack to allow overlapping
InlineSegment
}
func (i *inlineState) add(attr md.Attribute) {
if attr.Has(md.AttrBold) {
i.attributes |= text.AttrBold
}
if attr.Has(md.AttrItalics) {
i.attributes |= text.AttrItalics
}
if attr.Has(md.AttrUnderline) {
i.attributes |= text.AttrUnderline
}
if attr.Has(md.AttrStrikethrough) {
i.attributes |= text.AttrStrikethrough
}
if attr.Has(md.AttrSpoiler) {
i.attributes |= text.AttrSpoiler
}
if attr.Has(md.AttrMonospace) {
i.attributes |= text.AttrMonospace
}
}
func (i *inlineState) remove(attr md.Attribute) {
if attr.Has(md.AttrBold) {
i.attributes &= ^text.AttrBold
}
if attr.Has(md.AttrItalics) {
i.attributes &= ^text.AttrItalics
}
if attr.Has(md.AttrUnderline) {
i.attributes &= ^text.AttrUnderline
}
if attr.Has(md.AttrStrikethrough) {
i.attributes &= ^text.AttrStrikethrough
}
if attr.Has(md.AttrSpoiler) {
i.attributes &= ^text.AttrSpoiler
}
if attr.Has(md.AttrMonospace) {
i.attributes &= ^text.AttrMonospace
}
}
func (i inlineState) copy() InlineSegment {
return i.InlineSegment
}
type InlineSegment struct {
start, end int
attributes text.Attribute
}
var _ text.Attributor = (*InlineSegment)(nil)
// inline parses an inline node. This method at the moment will always create a
// new segment for overlapping attributes.
func (r *TextRenderer) inline(n *md.Inline, enter bool) ast.WalkStatus {
// For instructions on how this works, refer to inline_attr.jpg.
// Pop the last segment if it's not empty.
if !r.inls.empty() {
r.inls.end = r.buf.Len()
// Only use this section if the length is not zero.
if r.inls.start != r.inls.end {
r.append(r.inls.copy())
}
}
if enter {
r.inls.add(n.Attr)
} else {
r.inls.remove(n.Attr)
}
// Update the start pointer of the current segment.
r.inls.start = r.buf.Len()
return ast.WalkContinue
}
func (i InlineSegment) Bounds() (start, end int) {
return i.start, i.end
}
func (i InlineSegment) Attribute() text.Attribute {
return i.attributes
}
func (i InlineSegment) empty() bool {
return i.attributes == 0 || i.start < i.end
}