87 lines
2.4 KiB
Go
87 lines
2.4 KiB
Go
|
// Copyright (c) 2022 Tulir Asokan
|
||
|
//
|
||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||
|
|
||
|
package format
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/yuin/goldmark"
|
||
|
"github.com/yuin/goldmark/extension"
|
||
|
"github.com/yuin/goldmark/renderer/html"
|
||
|
|
||
|
"maunium.net/go/mautrix/event"
|
||
|
"maunium.net/go/mautrix/format/mdext"
|
||
|
)
|
||
|
|
||
|
const paragraphStart = "<p>"
|
||
|
const paragraphEnd = "</p>"
|
||
|
|
||
|
var Extensions = goldmark.WithExtensions(extension.Strikethrough, extension.Table, mdext.Spoiler)
|
||
|
var HTMLOptions = goldmark.WithRendererOptions(html.WithHardWraps(), html.WithUnsafe())
|
||
|
|
||
|
var withHTML = goldmark.New(Extensions, HTMLOptions)
|
||
|
var noHTML = goldmark.New(Extensions, HTMLOptions, goldmark.WithExtensions(mdext.EscapeHTML))
|
||
|
|
||
|
// UnwrapSingleParagraph removes paragraph tags surrounding a string if the string only contains a single paragraph.
|
||
|
func UnwrapSingleParagraph(html string) string {
|
||
|
html = strings.TrimRight(html, "\n")
|
||
|
if strings.HasPrefix(html, paragraphStart) && strings.HasSuffix(html, paragraphEnd) {
|
||
|
htmlBodyWithoutP := html[len(paragraphStart) : len(html)-len(paragraphEnd)]
|
||
|
if !strings.Contains(htmlBodyWithoutP, paragraphStart) {
|
||
|
return htmlBodyWithoutP
|
||
|
}
|
||
|
}
|
||
|
return html
|
||
|
}
|
||
|
|
||
|
func RenderMarkdownCustom(text string, renderer goldmark.Markdown) event.MessageEventContent {
|
||
|
var buf strings.Builder
|
||
|
err := renderer.Convert([]byte(text), &buf)
|
||
|
if err != nil {
|
||
|
panic(fmt.Errorf("markdown parser errored: %w", err))
|
||
|
}
|
||
|
htmlBody := UnwrapSingleParagraph(buf.String())
|
||
|
return HTMLToContent(htmlBody)
|
||
|
}
|
||
|
|
||
|
func HTMLToContent(html string) event.MessageEventContent {
|
||
|
text := HTMLToMarkdown(html)
|
||
|
if html != text {
|
||
|
return event.MessageEventContent{
|
||
|
FormattedBody: html,
|
||
|
Format: event.FormatHTML,
|
||
|
MsgType: event.MsgText,
|
||
|
Body: text,
|
||
|
}
|
||
|
}
|
||
|
return event.MessageEventContent{
|
||
|
MsgType: event.MsgText,
|
||
|
Body: text,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func RenderMarkdown(text string, allowMarkdown, allowHTML bool) event.MessageEventContent {
|
||
|
var htmlBody string
|
||
|
|
||
|
if allowMarkdown {
|
||
|
rndr := withHTML
|
||
|
if !allowHTML {
|
||
|
rndr = noHTML
|
||
|
}
|
||
|
return RenderMarkdownCustom(text, rndr)
|
||
|
} else if allowHTML {
|
||
|
htmlBody = strings.Replace(text, "\n", "<br>", -1)
|
||
|
return HTMLToContent(htmlBody)
|
||
|
} else {
|
||
|
return event.MessageEventContent{
|
||
|
MsgType: event.MsgText,
|
||
|
Body: text,
|
||
|
}
|
||
|
}
|
||
|
}
|