Source File
block.go
Belonging Package
github.com/russross/blackfriday/v2
package blackfriday
import (
)
const (
charEntity = "&(?:#x[a-f0-9]{1,8}|#[0-9]{1,8}|[a-z][a-z0-9]{1,31});"
escapable = "[!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]"
)
var (
reBackslashOrAmp = regexp.MustCompile("[\\&]")
reEntityOrEscapedChar = regexp.MustCompile("(?i)\\\\" + escapable + "|" + charEntity)
)
if .nesting >= .maxNesting {
return
}
.nesting++
if .isPrefixHeading() {
= [.prefixHeading():]
continue
}
if .extensions&Titleblock != 0 {
if [0] == '%' {
if := .titleBlock(, true); > 0 {
= [:]
continue
}
}
}
if := .isEmpty(); > 0 {
= [:]
continue
}
if .codePrefix() > 0 {
= [.code():]
continue
}
if .extensions&FencedCode != 0 {
if := .fencedCodeBlock(, true); > 0 {
= [:]
continue
}
}
if .quotePrefix() > 0 {
= [.quote():]
continue
}
if .extensions&Tables != 0 {
if := .table(); > 0 {
= [:]
continue
}
}
if .oliPrefix() > 0 {
= [.list(, ListTypeOrdered):]
continue
}
if .extensions&DefinitionLists != 0 {
if .dliPrefix() > 0 {
= [.list(, ListTypeDefinition):]
continue
}
}
= [.paragraph():]
}
.nesting--
}
func ( *Markdown) ( NodeType, []byte) *Node {
.closeUnmatchedBlocks()
:= .addChild(, 0)
.content =
return
}
func ( *Markdown) ( []byte) bool {
if [0] != '#' {
return false
}
if .extensions&SpaceHeadings != 0 {
:= 0
for < 6 && < len() && [] == '#' {
++
}
if == len() || [] != ' ' {
return false
}
}
return true
}
func ( *Markdown) ( []byte) int {
:= 0
for < 6 && < len() && [] == '#' {
++
}
:= skipChar(, , ' ')
:= skipUntilChar(, , '\n')
:=
:= ""
if .extensions&HeadingIDs != 0 {
for = ; < -1 && ([] != '{' || [+1] != '#'); ++ {
}
for = + 1; < && [] != '}'; ++ {
if < && < {
= string([+2 : ])
=
= + 1
for > 0 && [-1] == ' ' {
--
}
}
}
for > 0 && [-1] == '#' {
if isBackslashEscaped(, -1) {
break
}
--
}
for > 0 && [-1] == ' ' {
--
}
if > {
if == "" && .extensions&AutoHeadingIDs != 0 {
= sanitized_anchor_name.Create(string([:]))
}
:= .addBlock(Heading, [:])
.HeadingID =
.Level =
}
return
}
if [0] == '-' {
:= skipChar(, 1, '-')
= skipChar(, , ' ')
if < len() && [] == '\n' {
return 2
}
return 0
}
return 0
}
func ( *Markdown) ( []byte, bool) int {
if [0] != '%' {
return 0
}
:= bytes.Split(, []byte("\n"))
var int
for , := range {
if !bytes.HasPrefix(, []byte("%")) {
= // - 1
break
}
}
= bytes.Join([0:], []byte("\n"))
:= len()
= bytes.TrimPrefix(, []byte("% "))
= bytes.Replace(, []byte("\n% "), []byte("\n"), -1)
:= .addBlock(Heading, )
.Level = 1
.IsTitleblock = true
return
}
func ( *Markdown) ( []byte, bool) int {
var , int
if [0] != '<' {
return 0
}
, := .htmlFindTag([1:])
if := .htmlComment(, ); > 0 {
return
}
if := .htmlHr(, ); > 0 {
return
}
return 0
}
if := .isEmpty([:]); > 0 {
:= +
:=
for > 0 && [-1] == '\n' {
--
}
:= .addBlock(HTMLBlock, [:])
finalizeHTMLBlock()
}
return
}
return 0
}
if == "hr" {
return 2
:= 0
if = .isEmpty([:]); == 0 {
return 0
}
+=
= 0
if >= len() {
return
}
if .extensions&LaxHTMLBlocks != 0 {
return
}
return 0
}
return +
}
for < 3 && [] == ' ' {
++
}
if [] != '*' && [] != '-' && [] != '_' {
return false
}
:= []
for < len() && < 3 && [] == ' ' {
++
}
if >= len() {
return 0, ""
}
if [] != '~' && [] != '`' {
return 0, ""
}
:= []
for < len() && [] == {
++
++
}
if < 3 {
return 0, ""
}
= string([- : ])
if != "" && != {
return 0, ""
}
, := isFenceLine([:], nil, )
if != 0 {
+=
break
}
:= skipUntilChar(, , '\n') + 1
if >= len() {
return 0
}
if {
.Write([:])
}
=
}
if {
:= .addBlock(CodeBlock, .Bytes()) // TODO: get rid of temp buffer
.IsFenced = true
finalizeCodeBlock()
}
return
}
func ( []byte) []byte {
if [0] == '\\' {
return []byte{[1]}
}
return []byte(html.UnescapeString(string()))
}
func ( []byte) []byte {
if reBackslashOrAmp.Match() {
return reEntityOrEscapedChar.ReplaceAllFunc(, unescapeChar)
}
return
}
func ( *Node) {
if .IsFenced {
:= bytes.IndexByte(.content, '\n')
:= .content[:]
:= .content[+1:]
.Info = unescapeString(bytes.Trim(, "\n"))
.Literal =
} else {
.Literal = .content
}
.content = nil
}
func ( *Markdown) ( []byte) int {
:= .addBlock(Table, nil)
, := .tableHeader()
if == 0 {
.tip = .Parent
.Unlink()
return 0
}
.addBlock(TableBody, nil)
for < len() {
, := 0,
for ; < len() && [] != '\n'; ++ {
if [] == '|' {
++
}
}
if == 0 {
=
break
}
func ( []byte, int) bool {
:= 0
for --1 >= 0 && [--1] == '\\' {
++
}
return &1 == 1
}
func ( *Markdown) ( []byte) ( int, []CellAlignFlags) {
:= 0
:= 1
for = 0; < len() && [] != '\n'; ++ {
if [] == '|' && !isBackslashEscaped(, ) {
++
}
}
if == 1 {
return
}
:=
if < len() && [] == '\n' {
++
}
:= [:]
if [0] == '|' {
--
}
if > 2 && [-1] == '|' && !isBackslashEscaped(, -1) {
--
}
= make([]CellAlignFlags, )
++
if >= len() {
return
}
if [] == '|' && !isBackslashEscaped(, ) {
++
}
= skipChar(, , ' ')
:= 0
for < len() && [] != '\n' {
:= 0
if [] == ':' {
++
[] |= TableAlignmentLeft
++
}
for < len() && [] == '-' {
++
++
}
if < len() && [] == ':' {
++
[] |= TableAlignmentRight
++
}
for < len() && [] == ' ' {
++
}
if == len() {
return
switch {
return
++
++
for < len() && [] == ' ' {
++
}
if >= && < len() && [] != '\n' {
return
}
return
++
return
}
}
if != {
return
}
.addBlock(TableHead, nil)
.tableRow(, , true)
=
if < len() && [] == '\n' {
++
}
return
}
func ( *Markdown) ( []byte, []CellAlignFlags, bool) {
.addBlock(TableRow, nil)
, := 0, 0
if [] == '|' && !isBackslashEscaped(, ) {
++
}
for = 0; < len() && < len(); ++ {
for < len() && [] == ' ' {
++
}
:=
for < len() && ([] != '|' || isBackslashEscaped(, )) && [] != '\n' {
++
}
:=
}
for < len() && [] != '\n' {
if .extensions&FencedCode != 0 {
+= - 1
break
}
}
++
}
if < len() && [] == '\n' {
++
}
+=
} else if .terminateBlockquote(, , ) {
break
func ( *Markdown) ( []byte) int {
if len() >= 1 && [0] == '\t' {
return 1
}
if len() >= 4 && [0] == ' ' && [1] == ' ' && [2] == ' ' && [3] == ' ' {
return 4
}
return 0
}
func ( *Markdown) ( []byte) int {
var bytes.Buffer
:= 0
for < len() {
:=
for < len() && [] != '\n' {
++
}
if < len() && [] == '\n' {
++
}
:= .isEmpty([:]) > 0
if := .codePrefix([:]); > 0 {
+=
=
break
}
if ([] != '*' && [] != '+' && [] != '-') ||
([+1] != ' ' && [+1] != '\t') {
return 0
}
return + 2
}
for < 3 && < len() && [] == ' ' {
++
}
if [] != '.' || !([+1] == ' ' || [+1] == '\t') {
return 0
}
return + 2
}
if [] != ':' || !([+1] == ' ' || [+1] == '\t') {
return 0
}
for < len() && [] == ' ' {
++
}
return + 2
}
func ( *Markdown) ( []byte, ListType) int {
:= 0
|= ListItemBeginningOfList
:= .addBlock(List, nil)
.ListFlags =
.Tight = true
for < len() {
:= .listItem([:], &)
if &ListItemContainsBlock != 0 {
.ListData.Tight = false
}
+=
if == 0 || &ListItemEndOfList != 0 {
break
}
&= ^ListItemBeginningOfList
}
:= .Parent
finalizeList()
.tip =
return
}
func ( *Markdown) ( []byte, *ListType) bool {
if .dliPrefix() > 0 && *&ListTypeDefinition == 0 {
return true
} else if .oliPrefix() > 0 && *&ListTypeOrdered == 0 {
return true
} else if .uliPrefix() > 0 && (*&ListTypeOrdered != 0 || *&ListTypeDefinition != 0) {
return true
}
return false
}
if > 0 {
* &= ^ListTypeTerm
}
}
if *&ListTypeDefinition != 0 {
* |= ListTypeTerm
} else {
return 0
}
}
for < len() && [] == ' ' {
++
}
:=
for > 0 && < len() && [-1] != '\n' {
++
}
.Write([:])
=
for < len() && [-1] != '\n' {
++
}
:= 0
:= 0
if [] == '\t' {
++
+= 4
} else {
for < 4 && + < && [+] == ' ' {
++
++
}
}
:= [+ : ]
, := isFenceLine(, nil, )
if != "" {
=
= ""
}
if != "" || != "" {
.Write([+ : ])
=
continue
}
}
if <= {
if .listTypeChanged(, ) {
* |= ListItemEndOfList
} else if {
* |= ListItemContainsBlock
}
break
}
if {
* |= ListItemContainsBlock
}
if == 0 {
= .Len()
}
if && < 4 {
* |= ListItemEndOfList
break
}
* |= ListItemContainsBlock
case && < 4:
:=
for < len() && [] != '\n' {
++
}
for < len()-1 && [] == '\n' {
++
}
if < len()-1 && [] != ':' && [] != ':' {
* |= ListItemEndOfList
}
} else {
* |= ListItemEndOfList
}
break
case :
.WriteByte('\n')
* |= ListItemContainsBlock
}
:= 0
for [] == ' ' {
++
}
if [len()-1] == '\n' {
--
}
var , , int
:= TabSizeDefault
if .extensions&TabSizeEight != 0 {
= TabSizeDouble
=
:= [:]
=
if := isReference(, , ); > 0 {
.renderParagraph([:])
return +
}
if .extensions&DefinitionLists != 0 {
if < len()-1 && [+1] == ':' {
return .list([:], ListTypeDefinition)
}
}
.renderParagraph([:])
return +
}
if > 0 {
.renderParagraph([:])
:= - 1
for < && [] == ' ' {
++
}
for > && [-1] == ' ' {
--
}
:= ""
if .extensions&AutoHeadingIDs != 0 {
= sanitized_anchor_name.Create(string([:]))
}
:= .addBlock(Heading, [:])
.Level =
.HeadingID =
for < len() && [] != '\n' {
++
}
return
}
}
if .extensions&LaxHTMLBlocks != 0 {
.renderParagraph([:])
return
}
}
if .isPrefixHeading() || .isHRule() {
.renderParagraph([:])
return
}
if .extensions&FencedCode != 0 {
if .fencedCodeBlock(, false) > 0 {
.renderParagraph([:])
return
}
}
if .extensions&DefinitionLists != 0 {
if .dliPrefix() != 0 {
:= .list([:], ListTypeDefinition)
return
}
}
if .extensions&NoEmptyLineBeforeBlock != 0 {
if .uliPrefix() != 0 ||
.oliPrefix() != 0 ||
.quotePrefix() != 0 ||
.codePrefix() != 0 {
.renderParagraph([:])
return
}
}
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |