123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- package parser
- import (
- "bytes"
- "github.com/gomarkdown/markdown/ast"
- )
- // sFigureLine checks if there's a figure line (e.g., !--- ) at the beginning of data,
- // and returns the end index if so, or 0 otherwise.
- func sFigureLine(data []byte, oldmarker string) (end int, marker string) {
- i, size := 0, 0
- n := len(data)
- // skip up to three spaces
- for i < n && i < 3 && data[i] == ' ' {
- i++
- }
- // check for the marker characters: !
- if i+1 >= n {
- return 0, ""
- }
- if data[i] != '!' || data[i+1] != '-' {
- return 0, ""
- }
- i++
- c := data[i] // i.e. the -
- // the whole line must be the same char or whitespace
- for i < n && data[i] == c {
- size++
- i++
- }
- // the marker char must occur at least 3 times
- if size < 3 {
- return 0, ""
- }
- marker = string(data[i-size : i])
- // if this is the end marker, it must match the beginning marker
- if oldmarker != "" && marker != oldmarker {
- return 0, ""
- }
- // there is no syntax modifier although it might be an idea to re-use this space for something?
- i = skipChar(data, i, ' ')
- if i >= n || data[i] != '\n' {
- if i == n {
- return i, marker
- }
- return 0, ""
- }
- return i + 1, marker // Take newline into account.
- }
- // figureBlock returns the end index if data contains a figure block at the beginning,
- // or 0 otherwise. It writes to out if doRender is true, otherwise it has no side effects.
- // If doRender is true, a final newline is mandatory to recognize the figure block.
- func (p *Parser) figureBlock(data []byte, doRender bool) int {
- beg, marker := sFigureLine(data, "")
- if beg == 0 || beg >= len(data) {
- return 0
- }
- var raw bytes.Buffer
- for {
- // safe to assume beg < len(data)
- // check for the end of the code block
- figEnd, _ := sFigureLine(data[beg:], marker)
- if figEnd != 0 {
- beg += figEnd
- break
- }
- // copy the current line
- end := skipUntilChar(data, beg, '\n') + 1
- // did we reach the end of the buffer without a closing marker?
- if end >= len(data) {
- return 0
- }
- // verbatim copy to the working buffer
- if doRender {
- raw.Write(data[beg:end])
- }
- beg = end
- }
- if !doRender {
- return beg
- }
- figure := &ast.CaptionFigure{}
- p.AddBlock(figure)
- p.Block(raw.Bytes())
- defer p.Finalize(figure)
- if captionContent, id, consumed := p.caption(data[beg:], []byte("Figure: ")); consumed > 0 {
- caption := &ast.Caption{}
- p.Inline(caption, captionContent)
- figure.HeadingID = id
- p.addChild(caption)
- beg += consumed
- }
- return beg
- }
|