diff options
Diffstat (limited to 'vendor/github.com/gomarkdown/markdown/parser/block.go')
-rw-r--r-- | vendor/github.com/gomarkdown/markdown/parser/block.go | 332 |
1 files changed, 21 insertions, 311 deletions
diff --git a/vendor/github.com/gomarkdown/markdown/parser/block.go b/vendor/github.com/gomarkdown/markdown/parser/block.go index 95438174..7d7e9f9c 100644 --- a/vendor/github.com/gomarkdown/markdown/parser/block.go +++ b/vendor/github.com/gomarkdown/markdown/parser/block.go @@ -74,9 +74,9 @@ var ( } ) -// sanitizeAnchorName returns a sanitized anchor name for the given text. +// sanitizeHeadingID returns a sanitized anchor name for the given text. // Taken from https://github.com/shurcooL/sanitized_anchor_name/blob/master/main.go#L14:1 -func sanitizeAnchorName(text string) string { +func sanitizeHeadingID(text string) string { var anchorName []rune var futureDash = false for _, r := range text { @@ -91,6 +91,9 @@ func sanitizeAnchorName(text string) string { futureDash = true } } + if len(anchorName) == 0 { + return "empty" + } return string(anchorName) } @@ -278,12 +281,6 @@ func (p *Parser) block(data []byte) { } } - // table: - // - // Name | Age | Phone - // ------|-----|--------- - // Bob | 31 | 555-1234 - // Alice | 27 | 555-4321 if p.extensions&Tables != 0 { if i := p.table(data); i > 0 { data = data[i:] @@ -422,13 +419,14 @@ func (p *Parser) prefixHeading(data []byte) int { end-- } if end > i { - if id == "" && p.extensions&AutoHeadingIDs != 0 { - id = sanitizeAnchorName(string(data[i:end])) - } block := &ast.Heading{ HeadingID: id, Level: level, } + if id == "" && p.extensions&AutoHeadingIDs != 0 { + block.HeadingID = sanitizeHeadingID(string(data[i:end])) + p.allHeadingsWithAutoID = append(p.allHeadingsWithAutoID, block) + } block.Content = data[i:end] p.addBlock(block) } @@ -492,14 +490,15 @@ func (p *Parser) prefixSpecialHeading(data []byte) int { end-- } if end > i { - if id == "" && p.extensions&AutoHeadingIDs != 0 { - id = sanitizeAnchorName(string(data[i:end])) - } block := &ast.Heading{ HeadingID: id, IsSpecial: true, Level: 1, // always level 1. } + if id == "" && p.extensions&AutoHeadingIDs != 0 { + block.HeadingID = sanitizeHeadingID(string(data[i:end])) + p.allHeadingsWithAutoID = append(p.allHeadingsWithAutoID, block) + } block.Literal = data[i:end] block.Content = data[i:end] p.addBlock(block) @@ -647,7 +646,7 @@ func (p *Parser) html(data []byte, doRender bool) int { if doRender { // trim newlines end := backChar(data, i, '\n') - htmlBLock := &ast.HTMLBlock{ast.Leaf{Content: data[:end]}} + htmlBLock := &ast.HTMLBlock{Leaf: ast.Leaf{Content: data[:end]}} p.addBlock(htmlBLock) finalizeHTMLBlock(htmlBLock) } @@ -669,7 +668,7 @@ func (p *Parser) htmlComment(data []byte, doRender bool) int { if doRender { // trim trailing newlines end := backChar(data, size, '\n') - htmlBLock := &ast.HTMLBlock{ast.Leaf{Content: data[:end]}} + htmlBLock := &ast.HTMLBlock{Leaf: ast.Leaf{Content: data[:end]}} p.addBlock(htmlBLock) finalizeHTMLBlock(htmlBLock) } @@ -701,7 +700,7 @@ func (p *Parser) htmlHr(data []byte, doRender bool) int { if doRender { // trim newlines end := backChar(data, size, '\n') - htmlBlock := &ast.HTMLBlock{ast.Leaf{Content: data[:end]}} + htmlBlock := &ast.HTMLBlock{Leaf: ast.Leaf{Content: data[:end]}} p.addBlock(htmlBlock) finalizeHTMLBlock(htmlBlock) } @@ -1005,294 +1004,6 @@ func finalizeCodeBlock(code *ast.CodeBlock) { code.Content = nil } -func (p *Parser) table(data []byte) int { - i, columns, table := p.tableHeader(data) - if i == 0 { - return 0 - } - - p.addBlock(&ast.TableBody{}) - - for i < len(data) { - pipes, rowStart := 0, i - for ; i < len(data) && data[i] != '\n'; i++ { - if data[i] == '|' { - pipes++ - } - } - - if pipes == 0 { - i = rowStart - break - } - - // include the newline in data sent to tableRow - i = skipCharN(data, i, '\n', 1) - - if p.tableFooter(data[rowStart:i]) { - continue - } - - p.tableRow(data[rowStart:i], columns, false) - } - if captionContent, id, consumed := p.caption(data[i:], []byte("Table: ")); consumed > 0 { - caption := &ast.Caption{} - p.Inline(caption, captionContent) - - // Some switcheroo to re-insert the parsed table as a child of the captionfigure. - figure := &ast.CaptionFigure{} - figure.HeadingID = id - table2 := &ast.Table{} - // Retain any block level attributes. - table2.AsContainer().Attribute = table.AsContainer().Attribute - children := table.GetChildren() - ast.RemoveFromTree(table) - - table2.SetChildren(children) - ast.AppendChild(figure, table2) - ast.AppendChild(figure, caption) - - p.addChild(figure) - p.finalize(figure) - - i += consumed - } - - return i -} - -// check if the specified position is preceded by an odd number of backslashes -func isBackslashEscaped(data []byte, i int) bool { - backslashes := 0 - for i-backslashes-1 >= 0 && data[i-backslashes-1] == '\\' { - backslashes++ - } - return backslashes&1 == 1 -} - -// tableHeaders parses the header. If recognized it will also add a table. -func (p *Parser) tableHeader(data []byte) (size int, columns []ast.CellAlignFlags, table ast.Node) { - i := 0 - colCount := 1 - headerIsUnderline := true - for i = 0; i < len(data) && data[i] != '\n'; i++ { - if data[i] == '|' && !isBackslashEscaped(data, i) { - colCount++ - } - if data[i] != '-' && data[i] != ' ' && data[i] != ':' && data[i] != '|' { - headerIsUnderline = false - } - } - - // doesn't look like a table header - if colCount == 1 { - return - } - - // include the newline in the data sent to tableRow - j := skipCharN(data, i, '\n', 1) - header := data[:j] - - // column count ignores pipes at beginning or end of line - if data[0] == '|' { - colCount-- - } - if i > 2 && data[i-1] == '|' && !isBackslashEscaped(data, i-1) { - colCount-- - } - - // if the header looks like a underline, then we omit the header - // and parse the first line again as underline - if headerIsUnderline { - header = nil - i = 0 - } else { - i++ // move past newline - } - - columns = make([]ast.CellAlignFlags, colCount) - - // move on to the header underline - if i >= len(data) { - return - } - - if data[i] == '|' && !isBackslashEscaped(data, i) { - i++ - } - i = skipChar(data, i, ' ') - - // each column header is of form: / *:?-+:? *|/ with # dashes + # colons >= 3 - // and trailing | optional on last column - col := 0 - n := len(data) - for i < n && data[i] != '\n' { - dashes := 0 - - if data[i] == ':' { - i++ - columns[col] |= ast.TableAlignmentLeft - dashes++ - } - for i < n && data[i] == '-' { - i++ - dashes++ - } - if i < n && data[i] == ':' { - i++ - columns[col] |= ast.TableAlignmentRight - dashes++ - } - for i < n && data[i] == ' ' { - i++ - } - if i == n { - return - } - // end of column test is messy - switch { - case dashes < 3: - // not a valid column - return - - case data[i] == '|' && !isBackslashEscaped(data, i): - // marker found, now skip past trailing whitespace - col++ - i++ - for i < n && data[i] == ' ' { - i++ - } - - // trailing junk found after last column - if col >= colCount && i < len(data) && data[i] != '\n' { - return - } - - case (data[i] != '|' || isBackslashEscaped(data, i)) && col+1 < colCount: - // something else found where marker was required - return - - case data[i] == '\n': - // marker is optional for the last column - col++ - - default: - // trailing junk found after last column - return - } - } - if col != colCount { - return - } - - table = &ast.Table{} - p.addBlock(table) - if header != nil { - p.addBlock(&ast.TableHeader{}) - p.tableRow(header, columns, true) - } - size = skipCharN(data, i, '\n', 1) - return -} - -func (p *Parser) tableRow(data []byte, columns []ast.CellAlignFlags, header bool) { - p.addBlock(&ast.TableRow{}) - i, col := 0, 0 - - if data[i] == '|' && !isBackslashEscaped(data, i) { - i++ - } - - n := len(data) - colspans := 0 // keep track of total colspan in this row. - for col = 0; col < len(columns) && i < n; col++ { - colspan := 0 - for i < n && data[i] == ' ' { - i++ - } - - cellStart := i - - for i < n && (data[i] != '|' || isBackslashEscaped(data, i)) && data[i] != '\n' { - i++ - } - - cellEnd := i - - // skip the end-of-cell marker, possibly taking us past end of buffer - // each _extra_ | means a colspan - for i < len(data) && data[i] == '|' && !isBackslashEscaped(data, i) { - i++ - colspan++ - } - // only colspan > 1 make sense. - if colspan < 2 { - colspan = 0 - } - - for cellEnd > cellStart && cellEnd-1 < n && data[cellEnd-1] == ' ' { - cellEnd-- - } - - block := &ast.TableCell{ - IsHeader: header, - Align: columns[col], - ColSpan: colspan, - } - block.Content = data[cellStart:cellEnd] - if cellStart == cellEnd && colspans > 0 { - // an empty cell that we should ignore, it exists because of colspan - colspans-- - } else { - p.addBlock(block) - } - - if colspan > 0 { - colspans += colspan - 1 - } - } - - // pad it out with empty columns to get the right number - for ; col < len(columns); col++ { - block := &ast.TableCell{ - IsHeader: header, - Align: columns[col], - } - p.addBlock(block) - } - - // silently ignore rows with too many cells -} - -// tableFooter parses the (optional) table footer. -func (p *Parser) tableFooter(data []byte) bool { - colCount := 1 - i := 0 - n := len(data) - for i < 3 && i < n && data[i] == ' ' { // ignore up to 3 spaces - i++ - } - for ; i < n && data[i] != '\n'; i++ { - if data[i] == '|' && !isBackslashEscaped(data, i) { - colCount++ - continue - } - // remaining data must be the = character - if data[i] != '=' { - return false - } - } - - // doesn't look like a table footer - if colCount == 1 { - return false - } - - p.addBlock(&ast.TableFooter{}) - - return true -} - // returns blockquote prefix length func (p *Parser) quotePrefix(data []byte) int { i := 0 @@ -1887,15 +1598,14 @@ func (p *Parser) paragraph(data []byte) int { eol-- } - id := "" + block := &ast.Heading{ + Level: level, + } if p.extensions&AutoHeadingIDs != 0 { - id = sanitizeAnchorName(string(data[prev:eol])) + block.HeadingID = sanitizeHeadingID(string(data[prev:eol])) + p.allHeadingsWithAutoID = append(p.allHeadingsWithAutoID, block) } - block := &ast.Heading{ - Level: level, - HeadingID: id, - } block.Content = data[prev:eol] p.addBlock(block) |