matterbridge/vendor/gitlab.com/golang-commonmark/markdown/html_block.go
Wim 04567c765e
Add support for markdown to HTML conversion (matrix). Closes #663 (#670)
This uses our own gomatrix lib with the SendHTML function which
adds HTML to formatted_body in matrix.
golang-commonmark is used to convert markdown into valid HTML.
2019-01-06 22:25:19 +01:00

223 lines
3.7 KiB
Go

// Copyright 2015 The Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package markdown
import (
"regexp"
"strings"
)
var (
htmlBlocks = []string{
"address",
"article",
"aside",
"base",
"basefont",
"blockquote",
"body",
"caption",
"center",
"col",
"colgroup",
"dd",
"details",
"dialog",
"dir",
"div",
"dl",
"dt",
"fieldset",
"figcaption",
"figure",
"footer",
"form",
"frame",
"frameset",
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
"head",
"header",
"hr",
"html",
"iframe",
"legend",
"li",
"link",
"main",
"menu",
"menuitem",
"meta",
"nav",
"noframes",
"ol",
"optgroup",
"option",
"p",
"param",
"section",
"source",
"summary",
"table",
"tbody",
"td",
"tfoot",
"th",
"thead",
"title",
"tr",
"track",
"ul",
}
htmlBlocksSet = make(map[string]bool)
rStartCond1 = regexp.MustCompile(`(?i)^(pre|script|style)([\n\t >]|$)`)
rEndCond1 = regexp.MustCompile(`(?i)</(pre|script|style)>`)
rStartCond6 = regexp.MustCompile(`(?i)^/?(` + strings.Join(htmlBlocks, "|") + `)(\s|$|>|/>)`)
rStartCond7 = regexp.MustCompile(`(?i)^(/[a-z][a-z0-9-]*|[a-z][a-z0-9-]*(\s+[a-z_:][a-z0-9_.:-]*\s*=\s*("[^"]*"|'[^']*'|[ "'=<>\x60]))*\s*/?)>\s*$`)
)
func init() {
for _, tag := range htmlBlocks {
htmlBlocksSet[tag] = true
}
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func matchTagName(s string) string {
if len(s) < 2 {
return ""
}
i := 0
if s[0] == '/' {
i++
}
start := i
max := min(15+i, len(s))
for i < max && isLetter(s[i]) {
i++
}
if i >= len(s) {
return ""
}
switch s[i] {
case ' ', '\n', '/', '>':
return strings.ToLower(s[start:i])
default:
return ""
}
}
func ruleHTMLBlock(s *StateBlock, startLine, endLine int, silent bool) bool {
if !s.Md.HTML {
return false
}
pos := s.BMarks[startLine] + s.TShift[startLine]
max := s.EMarks[startLine]
if pos+1 >= max {
return false
}
src := s.Src
if src[pos] != '<' {
return false
}
pos++
b := src[pos]
if !htmlSecond(b) {
return false
}
nextLine := startLine + 1
var endCond func(string) bool
if pos+2 < max && isLetter(b) && rStartCond1.MatchString(src[pos:]) {
endCond = func(s string) bool {
return rEndCond1.MatchString(s)
}
} else if strings.HasPrefix(src[pos:], "!--") {
endCond = func(s string) bool {
return strings.Contains(s, "-->")
}
} else if b == '?' {
endCond = func(s string) bool {
return strings.Contains(s, "?>")
}
} else if b == '!' && pos+1 < max && isUppercaseLetter(src[pos+1]) {
endCond = func(s string) bool {
return strings.Contains(s, ">")
}
} else if strings.HasPrefix(src[pos:], "![CDATA[") {
endCond = func(s string) bool {
return strings.Contains(s, "]]>")
}
} else if pos+2 < max && (isLetter(b) || b == '/' && isLetter(src[pos+1])) {
terminator := true
if rStartCond6.MatchString(src[pos:max]) {
} else if rStartCond7.MatchString(src[pos:max]) {
terminator = false
} else {
return false
}
if silent {
return terminator
}
endCond = func(s string) bool {
return s == ""
}
} else {
return false
}
if silent {
return true
}
if !endCond(src[pos:max]) {
for nextLine < endLine {
if s.SCount[nextLine] < s.BlkIndent {
break
}
pos := s.BMarks[nextLine] + s.TShift[nextLine]
max := s.EMarks[nextLine]
lineText := src[pos:max]
if endCond(lineText) {
if pos != max {
nextLine++
}
break
}
nextLine++
}
}
s.Line = nextLine
s.PushToken(&HTMLBlock{
Content: s.Lines(startLine, nextLine, s.BlkIndent, true),
Map: [2]int{startLine, nextLine},
})
return true
}