func NewFencedCodeBlockParser () BlockParser {
return defaultFencedCodeBlockParser
}
type fenceData struct {
char byte
indent int
length int
node ast .Node
}
var fencedCodeBlockInfoKey = NewContextKey ()
func (b *fencedCodeBlockParser ) Trigger () []byte {
return []byte {'~' , '`' }
}
func (b *fencedCodeBlockParser ) Open (parent ast .Node , reader text .Reader , pc Context ) (ast .Node , State ) {
line , segment := reader .PeekLine ()
pos := pc .BlockOffset ()
if pos < 0 || (line [pos ] != '`' && line [pos ] != '~' ) {
return nil , NoChildren
}
findent := pos
fenceChar := line [pos ]
i := pos
for ; i < len (line ) && line [i ] == fenceChar ; i ++ {
}
oFenceLength := i - pos
if oFenceLength < 3 {
return nil , NoChildren
}
var info *ast .Text
if i < len (line )-1 {
rest := line [i :]
left := util .TrimLeftSpaceLength (rest )
right := util .TrimRightSpaceLength (rest )
if left < len (rest )-right {
infoStart , infoStop := segment .Start -segment .Padding +i +left , segment .Stop -right
value := rest [left : len (rest )-right ]
if fenceChar == '`' && bytes .IndexByte (value , '`' ) > -1 {
return nil , NoChildren
} else if infoStart != infoStop {
info = ast .NewTextSegment (text .NewSegment (infoStart , infoStop ))
}
}
}
node := ast .NewFencedCodeBlock (info )
pc .Set (fencedCodeBlockInfoKey , &fenceData {fenceChar , findent , oFenceLength , node })
return node , NoChildren
}
func (b *fencedCodeBlockParser ) Continue (node ast .Node , reader text .Reader , pc Context ) State {
line , segment := reader .PeekLine ()
fdata := pc .Get (fencedCodeBlockInfoKey ).(*fenceData )