package parser import ( "github.com/yuin/goldmark/ast" "github.com/yuin/goldmark/text" "github.com/yuin/goldmark/util" ) type codeBlockParser struct { } // CodeBlockParser is a BlockParser implementation that parses indented code blocks. var defaultCodeBlockParser = &codeBlockParser{} // NewCodeBlockParser returns a new BlockParser that // parses code blocks. func NewCodeBlockParser() BlockParser { return defaultCodeBlockParser } func (b *codeBlockParser) Trigger() []byte { return nil } func (b *codeBlockParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) { line, segment := reader.PeekLine() pos, padding := util.IndentPosition(line, reader.LineOffset(), 4) if pos < 0 || util.IsBlank(line) { return nil, NoChildren } node := ast.NewCodeBlock() reader.AdvanceAndSetPadding(pos, padding) _, segment = reader.PeekLine() node.Lines().Append(segment) reader.Advance(segment.Len() - 1) return node, NoChildren } func (b *codeBlockParser) Continue(node ast.Node, reader text.Reader, pc Context) State { line, segment := reader.PeekLine() if util.IsBlank(line) { node.Lines().Append(segment.TrimLeftSpaceWidth(4, reader.Source())) return Continue | NoChildren } pos, padding := util.IndentPosition(line, reader.LineOffset(), 4) if pos < 0 { return Close } reader.AdvanceAndSetPadding(pos, padding) _, segment = reader.PeekLine() node.Lines().Append(segment) reader.Advance(segment.Len() - 1) return Continue | NoChildren } func (b *codeBlockParser) Close(node ast.Node, reader text.Reader, pc Context) { // trim trailing blank lines lines := node.Lines() length := lines.Len() - 1 source := reader.Source() for length >= 0 { line := lines.At(length) if util.IsBlank(line.Value(source)) { length-- } else { break } } lines.SetSliced(0, length+1) } func (b *codeBlockParser) CanInterruptParagraph() bool { return false } func (b *codeBlockParser) CanAcceptIndentedLine() bool { return true }