func (p *parser) htmlComment(out *bytes.Buffer, data []byte, doRender bool) int {
	i := p.inlineHTMLComment(out, data)
	return p.renderHTMLBlock(out, data, i, doRender)
}
HTML comment, lax form
package blackfriday
import (
	"bytes"
	"github.com/shurcooL/sanitized_anchor_name"
)
func (p *parser) block(out *bytes.Buffer, data []byte) {
	if len(data) == 0 || data[len(data)-1] != '\n' {
		panic("block input is missing terminating newline")
	}
	if p.nesting >= p.maxNesting {
		return
	}
	p.nesting++
	for len(data) > 0 {
		if p.isPrefixHeader(data) {
			data = data[p.prefixHeader(out, data):]
			continue
		}
		if data[0] == '<' {
			if i := p.html(out, data, true); i > 0 {
				data = data[i:]
				continue
			}
		}
		if p.flags&EXTENSION_TITLEBLOCK != 0 {
			if data[0] == '%' {
				if i := p.titleBlock(out, data, true); i > 0 {
					data = data[i:]
					continue
				}
			}
		}
		if i := p.isEmpty(data); i > 0 {
			data = data[i:]
			continue
		}
		if p.codePrefix(data) > 0 {
			data = data[p.code(out, data):]
			continue
		}
		if p.flags&EXTENSION_FENCED_CODE != 0 {
			if i := p.fencedCodeBlock(out, data, true); i > 0 {
				data = data[i:]
				continue
			}
		}
		if p.isHRule(data) {
			p.r.HRule(out)
			var i int
			for i = 0; data[i] != '\n'; i++ {
			}
			data = data[i:]
			continue
		}
		if p.quotePrefix(data) > 0 {
			data = data[p.quote(out, data):]
			continue
		}
		if p.flags&EXTENSION_TABLES != 0 {
			if i := p.table(out, data); i > 0 {
				data = data[i:]
				continue
			}
		}
		if p.uliPrefix(data) > 0 {
			data = data[p.list(out, data, 0):]
			continue
		}
		if p.oliPrefix(data) > 0 {
			data = data[p.list(out, data, LIST_TYPE_ORDERED):]
			continue
		}
		if p.flags&EXTENSION_DEFINITION_LISTS != 0 {
			if p.dliPrefix(data) > 0 {
				data = data[p.list(out, data, LIST_TYPE_DEFINITION):]
				continue
			}
		}
		data = data[p.paragraph(out, data):]
	}
	p.nesting--
}
func (p *parser) isPrefixHeader(data []byte) bool {
	if data[0] != '#' {
		return false
	}
	if p.flags&EXTENSION_SPACE_HEADERS != 0 {
		level := 0
		for level < 6 && data[level] == '#' {
			level++
		}
		if data[level] != ' ' {
			return false
		}
	}
	return true
}
func (p *parser) prefixHeader(out *bytes.Buffer, data []byte) int {
	level := 0
	for level < 6 && data[level] == '#' {
		level++
	}
	i := skipChar(data, level, ' ')
	end := skipUntilChar(data, i, '\n')
	skip := end
	id := ""
	if p.flags&EXTENSION_HEADER_IDS != 0 {
		j, k := 0, 0
		for j = i; j < end-1 && (data[j] != '{' || data[j+1] != '#'); j++ {
		}
		for k = j + 1; k < end && data[k] != '}'; k++ {
		}
		if j < end && k < end {
			id = string(data[j+2 : k])
			end = j
			skip = k + 1
			for end > 0 && data[end-1] == ' ' {
				end--
			}
		}
	}
	for end > 0 && data[end-1] == '#' {
		if isBackslashEscaped(data, end-1) {
			break
		}
		end--
	}
	for end > 0 && data[end-1] == ' ' {
		end--
	}
	if end > i {
		if id == "" && p.flags&EXTENSION_AUTO_HEADER_IDS != 0 {
			id = sanitized_anchor_name.Create(string(data[i:end]))
		}
		work := func() bool {
			p.inline(out, data[i:end])
			return true
		}
		p.r.Header(out, work, level, id)
	}
	return skip
}
func (p *parser) isUnderlinedHeader(data []byte) int {
	if data[0] == '=' {
		i := skipChar(data, 1, '=')
		i = skipChar(data, i, ' ')
		if data[i] == '\n' {
			return 1
		} else {
			return 0
		}
	}
	if data[0] == '-' {
		i := skipChar(data, 1, '-')
		i = skipChar(data, i, ' ')
		if data[i] == '\n' {
			return 2
		} else {
			return 0
		}
	}
	return 0
}
func (p *parser) titleBlock(out *bytes.Buffer, data []byte, doRender bool) int {
	if data[0] != '%' {
		return 0
	}
	splitData := bytes.Split(data, []byte("\n"))
	var i int
	for idx, b := range splitData {
		if !bytes.HasPrefix(b, []byte("%")) {
			i = idx  
			break
		}
	}
	data = bytes.Join(splitData[0:i], []byte("\n"))
	p.r.TitleBlock(out, data)
	return len(data)
}
func (p *parser) html(out *bytes.Buffer, data []byte, doRender bool) int {
	var i, j int
	if data[0] != '<' {
		return 0
	}
	curtag, tagfound := p.htmlFindTag(data[1:])
	if !tagfound {
		if size := p.htmlComment(out, data, doRender); size > 0 {
			return size
		}
		if size := p.htmlHr(out, data, doRender); size > 0 {
			return size
		}
		if size := p.htmlCDATA(out, data, doRender); size > 0 {
			return size
		}
		return 0
	}
	found := false
	if !found && curtag != "ins" && curtag != "del" {
		i = 1
		for i < len(data) {
			i++
			for i < len(data) && !(data[i-1] == '<' && data[i] == '/') {
				i++
			}
			if i+2+len(curtag) >= len(data) {
				break
			}
			j = p.htmlFindEnd(curtag, data[i-1:])
			if j > 0 {
				i += j - 1
				found = true
				break
			}
		}
	}
	if !found {
		return 0
	}
	if doRender {
		end := i
		for end > 0 && data[end-1] == '\n' {
			end--
		}
		p.r.BlockHtml(out, data[:end])
	}
	return i
}
func (p *parser) renderHTMLBlock(out *bytes.Buffer, data []byte, start int, doRender bool) int {
	if i := p.isEmpty(data[start:]); i > 0 {
		size := start + i
		if doRender {
			end := size
			for end > 0 && data[end-1] == '\n' {
				end--
			}
			p.r.BlockHtml(out, data[:end])
		}
		return size
	}
	return 0
}