forked from lug/matterbridge
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.
This commit is contained in:
333
vendor/gitlab.com/golang-commonmark/markdown/render.go
generated
vendored
Normal file
333
vendor/gitlab.com/golang-commonmark/markdown/render.go
generated
vendored
Normal file
@@ -0,0 +1,333 @@
|
||||
// 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 (
|
||||
"io"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gitlab.com/golang-commonmark/html"
|
||||
)
|
||||
|
||||
type Renderer struct {
|
||||
w *monadicWriter
|
||||
}
|
||||
|
||||
func NewRenderer(w io.Writer) *Renderer {
|
||||
return &Renderer{newMonadicWriter(w)}
|
||||
}
|
||||
|
||||
func (r *Renderer) Render(tokens []Token, options RenderOptions) error {
|
||||
for i, tok := range tokens {
|
||||
if tok, ok := tok.(*Inline); ok {
|
||||
r.renderInline(tok.Children, options)
|
||||
} else {
|
||||
r.renderToken(tokens, i, options)
|
||||
}
|
||||
}
|
||||
|
||||
r.w.Flush()
|
||||
|
||||
return r.w.err
|
||||
}
|
||||
|
||||
func (r *Renderer) renderInline(tokens []Token, o RenderOptions) {
|
||||
for i := range tokens {
|
||||
r.renderToken(tokens, i, o)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Renderer) renderInlineAsText(tokens []Token) {
|
||||
for _, tok := range tokens {
|
||||
if text, ok := tok.(*Text); ok {
|
||||
html.WriteEscapedString(r.w, text.Content)
|
||||
} else if img, ok := tok.(*Image); ok {
|
||||
r.renderInlineAsText(img.Tokens)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var rNotSpace = regexp.MustCompile(`^\S+`)
|
||||
|
||||
func (r *Renderer) renderToken(tokens []Token, idx int, options RenderOptions) {
|
||||
tok := tokens[idx]
|
||||
|
||||
if idx > 0 && tok.Block() && !tok.Closing() {
|
||||
switch t := tokens[idx-1].(type) {
|
||||
case *ParagraphOpen:
|
||||
if t.Hidden {
|
||||
r.w.WriteByte('\n')
|
||||
}
|
||||
case *ParagraphClose:
|
||||
if t.Hidden {
|
||||
r.w.WriteByte('\n')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch tok := tok.(type) {
|
||||
case *BlockquoteClose:
|
||||
r.w.WriteString("</blockquote>")
|
||||
|
||||
case *BlockquoteOpen:
|
||||
r.w.WriteString("<blockquote>")
|
||||
|
||||
case *BulletListClose:
|
||||
r.w.WriteString("</ul>")
|
||||
|
||||
case *BulletListOpen:
|
||||
r.w.WriteString("<ul>")
|
||||
|
||||
case *CodeBlock:
|
||||
r.w.WriteString("<pre><code>")
|
||||
html.WriteEscapedString(r.w, tok.Content)
|
||||
r.w.WriteString("</code></pre>")
|
||||
|
||||
case *CodeInline:
|
||||
r.w.WriteString("<code>")
|
||||
html.WriteEscapedString(r.w, tok.Content)
|
||||
r.w.WriteString("</code>")
|
||||
|
||||
case *EmphasisClose:
|
||||
r.w.WriteString("</em>")
|
||||
|
||||
case *EmphasisOpen:
|
||||
r.w.WriteString("<em>")
|
||||
|
||||
case *Fence:
|
||||
r.w.WriteString("<pre><code")
|
||||
if tok.Params != "" {
|
||||
langName := strings.SplitN(unescapeAll(tok.Params), " ", 2)[0]
|
||||
langName = rNotSpace.FindString(langName)
|
||||
if langName != "" {
|
||||
r.w.WriteString(` class="`)
|
||||
r.w.WriteString(options.LangPrefix)
|
||||
html.WriteEscapedString(r.w, langName)
|
||||
r.w.WriteByte('"')
|
||||
}
|
||||
}
|
||||
r.w.WriteByte('>')
|
||||
html.WriteEscapedString(r.w, tok.Content)
|
||||
r.w.WriteString("</code></pre>")
|
||||
|
||||
case *Hardbreak:
|
||||
if options.XHTML {
|
||||
r.w.WriteString("<br />\n")
|
||||
} else {
|
||||
r.w.WriteString("<br>\n")
|
||||
}
|
||||
|
||||
case *HeadingClose:
|
||||
r.w.WriteString("</h")
|
||||
r.w.WriteByte("0123456789"[tok.HLevel])
|
||||
r.w.WriteString(">")
|
||||
|
||||
case *HeadingOpen:
|
||||
r.w.WriteString("<h")
|
||||
r.w.WriteByte("0123456789"[tok.HLevel])
|
||||
r.w.WriteByte('>')
|
||||
|
||||
case *Hr:
|
||||
if options.XHTML {
|
||||
r.w.WriteString("<hr />")
|
||||
} else {
|
||||
r.w.WriteString("<hr>")
|
||||
}
|
||||
|
||||
case *HTMLBlock:
|
||||
r.w.WriteString(tok.Content)
|
||||
return // no newline
|
||||
|
||||
case *HTMLInline:
|
||||
r.w.WriteString(tok.Content)
|
||||
|
||||
case *Image:
|
||||
r.w.WriteString(`<img src="`)
|
||||
html.WriteEscapedString(r.w, tok.Src)
|
||||
r.w.WriteString(`" alt="`)
|
||||
r.renderInlineAsText(tok.Tokens)
|
||||
r.w.WriteByte('"')
|
||||
|
||||
if tok.Title != "" {
|
||||
r.w.WriteString(` title="`)
|
||||
html.WriteEscapedString(r.w, tok.Title)
|
||||
r.w.WriteByte('"')
|
||||
}
|
||||
if options.XHTML {
|
||||
r.w.WriteString(" />")
|
||||
} else {
|
||||
r.w.WriteByte('>')
|
||||
}
|
||||
|
||||
case *LinkClose:
|
||||
r.w.WriteString("</a>")
|
||||
|
||||
case *LinkOpen:
|
||||
r.w.WriteString(`<a href="`)
|
||||
html.WriteEscapedString(r.w, tok.Href)
|
||||
r.w.WriteByte('"')
|
||||
if tok.Title != "" {
|
||||
r.w.WriteString(` title="`)
|
||||
html.WriteEscapedString(r.w, (tok.Title))
|
||||
r.w.WriteByte('"')
|
||||
}
|
||||
if tok.Target != "" {
|
||||
r.w.WriteString(` target="`)
|
||||
html.WriteEscapedString(r.w, tok.Target)
|
||||
r.w.WriteByte('"')
|
||||
}
|
||||
if options.Nofollow {
|
||||
r.w.WriteString(` rel="nofollow"`)
|
||||
}
|
||||
r.w.WriteByte('>')
|
||||
|
||||
case *ListItemClose:
|
||||
r.w.WriteString("</li>")
|
||||
|
||||
case *ListItemOpen:
|
||||
r.w.WriteString("<li>")
|
||||
|
||||
case *OrderedListClose:
|
||||
r.w.WriteString("</ol>")
|
||||
|
||||
case *OrderedListOpen:
|
||||
if tok.Order != 1 {
|
||||
r.w.WriteString(`<ol start="`)
|
||||
r.w.WriteString(strconv.Itoa(tok.Order))
|
||||
r.w.WriteString(`">`)
|
||||
} else {
|
||||
r.w.WriteString("<ol>")
|
||||
}
|
||||
|
||||
case *ParagraphClose:
|
||||
if tok.Hidden {
|
||||
return
|
||||
}
|
||||
if !tok.Tight {
|
||||
r.w.WriteString("</p>")
|
||||
} else if tokens[idx+1].Closing() {
|
||||
return // no newline
|
||||
}
|
||||
|
||||
case *ParagraphOpen:
|
||||
if tok.Hidden {
|
||||
return
|
||||
}
|
||||
if !tok.Tight {
|
||||
r.w.WriteString("<p>")
|
||||
}
|
||||
|
||||
case *Softbreak:
|
||||
if options.Breaks {
|
||||
if options.XHTML {
|
||||
r.w.WriteString("<br />\n")
|
||||
} else {
|
||||
r.w.WriteString("<br>\n")
|
||||
}
|
||||
} else {
|
||||
r.w.WriteByte('\n')
|
||||
}
|
||||
return
|
||||
|
||||
case *StrongClose:
|
||||
r.w.WriteString("</strong>")
|
||||
|
||||
case *StrongOpen:
|
||||
r.w.WriteString("<strong>")
|
||||
|
||||
case *StrikethroughClose:
|
||||
r.w.WriteString("</s>")
|
||||
|
||||
case *StrikethroughOpen:
|
||||
r.w.WriteString("<s>")
|
||||
|
||||
case *TableClose:
|
||||
r.w.WriteString("</table>")
|
||||
|
||||
case *TableOpen:
|
||||
r.w.WriteString("<table>")
|
||||
|
||||
case *TbodyClose:
|
||||
r.w.WriteString("</tbody>")
|
||||
|
||||
case *TbodyOpen:
|
||||
r.w.WriteString("<tbody>")
|
||||
|
||||
case *TdClose:
|
||||
r.w.WriteString("</td>")
|
||||
|
||||
case *TdOpen:
|
||||
if tok.Align != AlignNone {
|
||||
r.w.WriteString(`<td style="text-align:`)
|
||||
r.w.WriteString(tok.Align.String())
|
||||
r.w.WriteString(`">`)
|
||||
} else {
|
||||
r.w.WriteString("<td>")
|
||||
}
|
||||
|
||||
case *Text:
|
||||
html.WriteEscapedString(r.w, tok.Content)
|
||||
|
||||
case *TheadClose:
|
||||
r.w.WriteString("</thead>")
|
||||
|
||||
case *TheadOpen:
|
||||
r.w.WriteString("<thead>")
|
||||
|
||||
case *ThClose:
|
||||
r.w.WriteString("</th>")
|
||||
|
||||
case *ThOpen:
|
||||
if align := tok.Align; align != AlignNone {
|
||||
r.w.WriteString(`<th style="text-align:`)
|
||||
r.w.WriteString(align.String())
|
||||
r.w.WriteString(`">`)
|
||||
} else {
|
||||
r.w.WriteString("<th>")
|
||||
}
|
||||
|
||||
case *TrClose:
|
||||
r.w.WriteString("</tr>")
|
||||
|
||||
case *TrOpen:
|
||||
r.w.WriteString("<tr>")
|
||||
|
||||
default:
|
||||
panic("unknown token type")
|
||||
}
|
||||
|
||||
needLf := false
|
||||
if tok.Block() {
|
||||
needLf = true
|
||||
|
||||
if tok.Opening() {
|
||||
nextTok := tokens[idx+1]
|
||||
blockquote := false
|
||||
switch nextTok := nextTok.(type) {
|
||||
case *Inline:
|
||||
needLf = false
|
||||
case *ParagraphOpen:
|
||||
if nextTok.Tight || nextTok.Hidden {
|
||||
needLf = false
|
||||
}
|
||||
case *ParagraphClose:
|
||||
if nextTok.Tight || nextTok.Hidden {
|
||||
needLf = false
|
||||
}
|
||||
case *BlockquoteClose:
|
||||
blockquote = true
|
||||
}
|
||||
if !blockquote && needLf && nextTok.Closing() && nextTok.Tag() == tok.Tag() {
|
||||
needLf = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if needLf {
|
||||
r.w.WriteByte('\n')
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user