package ast
import (
"fmt"
"strings"
textm "github.com/yuin/goldmark/text"
"github.com/yuin/goldmark/util"
)
type BaseInline struct {
BaseNode
}
func (b *BaseInline ) Type () NodeType {
return TypeInline
}
func (b *BaseInline ) IsRaw () bool {
return false
}
func (b *BaseInline ) HasBlankPreviousLines () bool {
panic ("can not call with inline nodes." )
}
func (b *BaseInline ) SetBlankPreviousLines (v bool ) {
panic ("can not call with inline nodes." )
}
func (b *BaseInline ) Lines () *textm .Segments {
panic ("can not call with inline nodes." )
}
func (b *BaseInline ) SetLines (v *textm .Segments ) {
panic ("can not call with inline nodes." )
}
type Text struct {
BaseInline
Segment textm .Segment
flags uint8
}
const (
textSoftLineBreak = 1 << iota
textHardLineBreak
textRaw
textCode
)
func textFlagsString(flags uint8 ) string {
buf := []string {}
if flags &textSoftLineBreak != 0 {
buf = append (buf , "SoftLineBreak" )
}
if flags &textHardLineBreak != 0 {
buf = append (buf , "HardLineBreak" )
}
if flags &textRaw != 0 {
buf = append (buf , "Raw" )
}
if flags &textCode != 0 {
buf = append (buf , "Code" )
}
return strings .Join (buf , ", " )
}
func (n *Text ) Inline () {
}
func (n *Text ) SoftLineBreak () bool {
return n .flags &textSoftLineBreak != 0
}
func (n *Text ) SetSoftLineBreak (v bool ) {
if v {
n .flags |= textSoftLineBreak
} else {
n .flags = n .flags &^ textSoftLineBreak
}
}
func (n *Text ) IsRaw () bool {
return n .flags &textRaw != 0
}
func (n *Text ) SetRaw (v bool ) {
if v {
n .flags |= textRaw
} else {
n .flags = n .flags &^ textRaw
}
}
func (n *Text ) HardLineBreak () bool {
return n .flags &textHardLineBreak != 0
}
func (n *Text ) SetHardLineBreak (v bool ) {
if v {
n .flags |= textHardLineBreak
} else {
n .flags = n .flags &^ textHardLineBreak
}
}
func (n *Text ) Merge (node Node , source []byte ) bool {
t , ok := node .(*Text )
if !ok {
return false
}
if n .Segment .Stop != t .Segment .Start || t .Segment .Padding != 0 ||
source [n .Segment .Stop -1 ] == '\n' || t .IsRaw () != n .IsRaw () {
return false
}
n .Segment .Stop = t .Segment .Stop
n .SetSoftLineBreak (t .SoftLineBreak ())
n .SetHardLineBreak (t .HardLineBreak ())
return true
}
func (n *Text ) Text (source []byte ) []byte {
return n .Segment .Value (source )
}
func (n *Text ) Dump (source []byte , level int ) {
fs := textFlagsString (n .flags )
if len (fs ) != 0 {
fs = "(" + fs + ")"
}
fmt .Printf ("%sText%s: \"%s\"\n" , strings .Repeat (" " , level ), fs , strings .TrimRight (string (n .Text (source )), "\n" ))
}
var KindText = NewNodeKind ("Text" )
func (n *Text ) Kind () NodeKind {
return KindText
}
func NewText () *Text {
return &Text {
BaseInline : BaseInline {},
}
}
func NewTextSegment (v textm .Segment ) *Text {
return &Text {
BaseInline : BaseInline {},
Segment : v ,
}
}
func NewRawTextSegment (v textm .Segment ) *Text {
t := &Text {
BaseInline : BaseInline {},
Segment : v ,
}
t .SetRaw (true )
return t
}
func MergeOrAppendTextSegment (parent Node , s textm .Segment ) {
last := parent .LastChild ()
t , ok := last .(*Text )
if ok && t .Segment .Stop == s .Start && !t .SoftLineBreak () {
t .Segment = t .Segment .WithStop (s .Stop )
} else {
parent .AppendChild (parent , NewTextSegment (s ))
}
}
func MergeOrReplaceTextSegment (parent Node , n Node , s textm .Segment ) {
prev := n .PreviousSibling ()
if t , ok := prev .(*Text ); ok && t .Segment .Stop == s .Start && !t .SoftLineBreak () {
t .Segment = t .Segment .WithStop (s .Stop )
parent .RemoveChild (parent , n )
} else {
parent .ReplaceChild (parent , n , NewTextSegment (s ))
}
}
type String struct {
BaseInline
Value []byte
flags uint8
}
func (n *String ) Inline () {
}
func (n *String ) IsRaw () bool {
return n .flags &textRaw != 0
}
func (n *String ) SetRaw (v bool ) {
if v {
n .flags |= textRaw
} else {
n .flags = n .flags &^ textRaw
}
}
func (n *String ) IsCode () bool {
return n .flags &textCode != 0
}
func (n *String ) SetCode (v bool ) {
if v {
n .flags |= textCode
} else {
n .flags = n .flags &^ textCode
}
}
func (n *String ) Text (source []byte ) []byte {
return n .Value
}
func (n *String ) Dump (source []byte , level int ) {
fs := textFlagsString (n .flags )
if len (fs ) != 0 {
fs = "(" + fs + ")"
}
fmt .Printf ("%sString%s: \"%s\"\n" , strings .Repeat (" " , level ), fs , strings .TrimRight (string (n .Value ), "\n" ))
}
var KindString = NewNodeKind ("String" )
func (n *String ) Kind () NodeKind {
return KindString
}
func NewString (v []byte ) *String {
return &String {
Value : v ,
}
}
type CodeSpan struct {
BaseInline
}
func (n *CodeSpan ) Inline () {
}
func (n *CodeSpan ) IsBlank (source []byte ) bool {
for c := n .FirstChild (); c != nil ; c = c .NextSibling () {
text := c .(*Text ).Segment
if !util .IsBlank (text .Value (source )) {
return false
}
}
return true
}
func (n *CodeSpan ) Dump (source []byte , level int ) {
DumpHelper (n , source , level , nil , nil )
}
var KindCodeSpan = NewNodeKind ("CodeSpan" )
func (n *CodeSpan ) Kind () NodeKind {
return KindCodeSpan
}
func NewCodeSpan () *CodeSpan {
return &CodeSpan {
BaseInline : BaseInline {},
}
}
type Emphasis struct {
BaseInline
Level int
}
func (n *Emphasis ) Dump (source []byte , level int ) {
m := map [string ]string {
"Level" : fmt .Sprintf ("%v" , n .Level ),
}
DumpHelper (n , source , level , m , nil )
}
var KindEmphasis = NewNodeKind ("Emphasis" )
func (n *Emphasis ) Kind () NodeKind {
return KindEmphasis
}
func NewEmphasis (level int ) *Emphasis {
return &Emphasis {
BaseInline : BaseInline {},
Level : level ,
}
}
type baseLink struct {
BaseInline
Destination []byte
Title []byte
}
func (n *baseLink ) Inline () {
}
type Link struct {
baseLink
}
func (n *Link ) Dump (source []byte , level int ) {
m := map [string ]string {}
m ["Destination" ] = string (n .Destination )
m ["Title" ] = string (n .Title )
DumpHelper (n , source , level , m , nil )
}
var KindLink = NewNodeKind ("Link" )
func (n *Link ) Kind () NodeKind {
return KindLink
}
func NewLink () *Link {
c := &Link {
baseLink : baseLink {
BaseInline : BaseInline {},
},
}
return c
}
type Image struct {
baseLink
}
func (n *Image ) Dump (source []byte , level int ) {
m := map [string ]string {}
m ["Destination" ] = string (n .Destination )
m ["Title" ] = string (n .Title )
DumpHelper (n , source , level , m , nil )
}
var KindImage = NewNodeKind ("Image" )
func (n *Image ) Kind () NodeKind {
return KindImage
}
func NewImage (link *Link ) *Image {
c := &Image {
baseLink : baseLink {
BaseInline : BaseInline {},
},
}
c .Destination = link .Destination
c .Title = link .Title
for n := link .FirstChild (); n != nil ; {
next := n .NextSibling ()
link .RemoveChild (link , n )
c .AppendChild (c , n )
n = next
}
return c
}
type AutoLinkType int
const (
AutoLinkEmail AutoLinkType = iota + 1
AutoLinkURL
)
type AutoLink struct {
BaseInline
AutoLinkType AutoLinkType
Protocol []byte
value *Text
}
func (n *AutoLink ) Inline () {}
func (n *AutoLink ) Dump (source []byte , level int ) {
segment := n .value .Segment
m := map [string ]string {
"Value" : string (segment .Value (source )),
}
DumpHelper (n , source , level , m , nil )
}
var KindAutoLink = NewNodeKind ("AutoLink" )
func (n *AutoLink ) Kind () NodeKind {
return KindAutoLink
}
func (n *AutoLink ) URL (source []byte ) []byte {
if n .Protocol != nil {
s := n .value .Segment
ret := make ([]byte , 0 , len (n .Protocol )+s .Len ()+3 )
ret = append (ret , n .Protocol ...)
ret = append (ret , ':' , '/' , '/' )
ret = append (ret , n .value .Text (source )...)
return ret
}
return n .value .Text (source )
}
func (n *AutoLink ) Label (source []byte ) []byte {
return n .value .Text (source )
}
func NewAutoLink (typ AutoLinkType , value *Text ) *AutoLink {
return &AutoLink {
BaseInline : BaseInline {},
value : value ,
AutoLinkType : typ ,
}
}
type RawHTML struct {
BaseInline
Segments *textm .Segments
}
func (n *RawHTML ) Inline () {}
func (n *RawHTML ) Dump (source []byte , level int ) {
m := map [string ]string {}
t := []string {}
for i := 0 ; i < n .Segments .Len (); i ++ {
segment := n .Segments .At (i )
t = append (t , string (segment .Value (source )))
}
m ["RawText" ] = strings .Join (t , "" )
DumpHelper (n , source , level , m , nil )
}
var KindRawHTML = NewNodeKind ("RawHTML" )
func (n *RawHTML ) Kind () NodeKind {
return KindRawHTML
}
func NewRawHTML () *RawHTML {
return &RawHTML {
Segments : textm .NewSegments (),
}
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .