1package parser 2 3import ( 4 "github.com/yuin/goldmark/ast" 5 "github.com/yuin/goldmark/text" 6 "github.com/yuin/goldmark/util" 7) 8 9type codeSpanParser struct { 10} 11 12var defaultCodeSpanParser = &codeSpanParser{} 13 14// NewCodeSpanParser return a new InlineParser that parses inline codes 15// surrounded by '`' . 16func NewCodeSpanParser() InlineParser { 17 return defaultCodeSpanParser 18} 19 20func (s *codeSpanParser) Trigger() []byte { 21 return []byte{'`'} 22} 23 24func (s *codeSpanParser) Parse(parent ast.Node, block text.Reader, pc Context) ast.Node { 25 line, startSegment := block.PeekLine() 26 opener := 0 27 for ; opener < len(line) && line[opener] == '`'; opener++ { 28 } 29 block.Advance(opener) 30 l, pos := block.Position() 31 node := ast.NewCodeSpan() 32 for { 33 line, segment := block.PeekLine() 34 if line == nil { 35 block.SetPosition(l, pos) 36 return ast.NewTextSegment(startSegment.WithStop(startSegment.Start + opener)) 37 } 38 for i := 0; i < len(line); i++ { 39 c := line[i] 40 if c == '`' { 41 oldi := i 42 for ; i < len(line) && line[i] == '`'; i++ { 43 } 44 closure := i - oldi 45 if closure == opener && (i >= len(line) || line[i] != '`') { 46 segment = segment.WithStop(segment.Start + i - closure) 47 if !segment.IsEmpty() { 48 node.AppendChild(node, ast.NewRawTextSegment(segment)) 49 } 50 block.Advance(i) 51 goto end 52 } 53 } 54 } 55 if !util.IsBlank(line) { 56 node.AppendChild(node, ast.NewRawTextSegment(segment)) 57 } 58 block.AdvanceLine() 59 } 60end: 61 if !node.IsBlank(block.Source()) { 62 // trim first halfspace and last halfspace 63 segment := node.FirstChild().(*ast.Text).Segment 64 shouldTrimmed := true 65 if !(!segment.IsEmpty() && block.Source()[segment.Start] == ' ') { 66 shouldTrimmed = false 67 } 68 segment = node.LastChild().(*ast.Text).Segment 69 if !(!segment.IsEmpty() && block.Source()[segment.Stop-1] == ' ') { 70 shouldTrimmed = false 71 } 72 if shouldTrimmed { 73 t := node.FirstChild().(*ast.Text) 74 segment := t.Segment 75 t.Segment = segment.WithStart(segment.Start + 1) 76 t = node.LastChild().(*ast.Text) 77 segment = node.LastChild().(*ast.Text).Segment 78 t.Segment = segment.WithStop(segment.Stop - 1) 79 } 80 81 } 82 return node 83} 84