diff --git a/gateway/gateway.go b/gateway/gateway.go index 1b69c272..caf5c47b 100644 --- a/gateway/gateway.go +++ b/gateway/gateway.go @@ -231,6 +231,65 @@ func (gw *Gateway) getDestChannel(msg *config.Message, dest bridge.Bridge) []con return channels } +type renderer struct { + *blackfriday.Html +} + +func doubleSpace(out *bytes.Buffer) { + if out.Len() > 0 { + out.WriteByte('\n') + } +} + +func escapeSingleChar(char byte) (string, bool) { + if char == '"' { + return """, true + } + if char == '&' { + return "&", true + } + if char == '<' { + return "<", true + } + if char == '>' { + return ">", true + } + return "", false +} + +func attrEscape(out *bytes.Buffer, src []byte) { + org := 0 + for i, ch := range src { + if entity, ok := escapeSingleChar(ch); ok { + if i > org { + // copy all the normal characters since the last escape + out.Write(src[org:i]) + } + org = i + 1 + out.WriteString(entity) + } + } + if org < len(src) { + out.Write(src[org:]) + } +} + +// Using rather than
 helpfully keeps Google Translate from trying to process it.
+func (*renderer) BlockCode(out *bytes.Buffer, text []byte, info string) {
+	doubleSpace(out)
+
+	endOfLang := strings.IndexAny(info, "\t ")
+	if endOfLang < 0 {
+		endOfLang = len(info)
+	}
+	lang := info[:endOfLang]
+	if len(lang) == 0 || lang == "." {
+		out.WriteString("")
+	}
+	attrEscape(out, text)
+	out.WriteString("\n")
+}
+
 func (gw *Gateway) handleMessage(msg config.Message, dest *bridge.Bridge) []*BrMsgID {
 	var brMsgIDs []*BrMsgID
 
@@ -312,8 +371,8 @@ func (gw *Gateway) handleMessage(msg config.Message, dest *bridge.Bridge) []*BrM
 			url_re := regexp.MustCompile(`(((http(s)?(\:\/\/))+(www\.)?([\w\-\.\/])*(\.[a-zA-Z]{2,3}\/?))[^\s\n|]*[^.,;:\?\!\@\^\$ -])`)
 			text = url_re.ReplaceAllString(text, "$0")
 
-			htmlFlags := blackfriday.HTML_USE_XHTML
-			renderer := blackfriday.HtmlRenderer(htmlFlags, "", "")
+			const htmlFlags = 0
+			renderer := &renderer{Html: blackfriday.HtmlRenderer(htmlFlags, "", "").(*blackfriday.Html)}
 			const extensions = blackfriday.LINK_TYPE_NOT_AUTOLINK |
 			  blackfriday.EXTENSION_HARD_LINE_BREAK |
 				blackfriday.EXTENSION_STRIKETHROUGH |
@@ -390,6 +449,23 @@ func (gw *Gateway) handleMessage(msg config.Message, dest *bridge.Bridge) []*BrM
 						return ""
 					},
 				})
+				// Custom override of default code rule:
+				// This converts multiline code tags to codeblocks
+				html2md.AddRule("code", &html2md.Rule{
+					Patterns: []string{"code", "tt", "pre"},
+					Replacement: func(innerHTML string, attrs []string) string {
+						contents := attrs[1]
+						if strings.Contains(contents, "\n") {
+							r := regexp.MustCompile(`/^\t+`)
+							innerHTML = r.ReplaceAllString(contents, "  ")
+							return "\n\n```\n" + innerHTML + "```\n"
+						}
+						if len(attrs) > 1 {
+							return "`" + attrs[1] + "`"
+						}
+						return ""
+					},
+				})
 				text := html2md.Convert(text)
 
 				// colons: revert temp token
diff --git a/go.sum b/go.sum
index ac35492c..fae8d7bb 100644
--- a/go.sum
+++ b/go.sum
@@ -116,6 +116,16 @@ github.com/patcon/html2md v0.0.0-20181014143505-919a839dda6f h1:+NUzuuLINRJwP3Xp
 github.com/patcon/html2md v0.0.0-20181014143505-919a839dda6f/go.mod h1:lPwXvF3BqK5Y9DLUOOnt8DrL3tnfHL01ScB1y60aKIw=
 github.com/patcon/html2md v0.0.0-20181014143736-370b673716b2 h1:Xgh4a4ltKx6L0swVSy6PosfxWOqlMyFtFggJlJ92exc=
 github.com/patcon/html2md v0.0.0-20181014143736-370b673716b2/go.mod h1:lPwXvF3BqK5Y9DLUOOnt8DrL3tnfHL01ScB1y60aKIw=
+github.com/patcon/html2md v0.0.0-20181014154545-6e925dc319d6 h1:8ojBYXM/GoBR+s2hTBMlbJg7Dd/0BCQ6a4RvTkvLaw0=
+github.com/patcon/html2md v0.0.0-20181014154545-6e925dc319d6/go.mod h1:lPwXvF3BqK5Y9DLUOOnt8DrL3tnfHL01ScB1y60aKIw=
+github.com/patcon/html2md v0.0.0-20181014154832-97706dcd2ccb h1:5iNfFRVq5ghn4syE6+dW67Y37uKDWg9TTuMfUNpFwek=
+github.com/patcon/html2md v0.0.0-20181014154832-97706dcd2ccb/go.mod h1:lPwXvF3BqK5Y9DLUOOnt8DrL3tnfHL01ScB1y60aKIw=
+github.com/patcon/html2md v0.0.0-20181014155555-be1815a53834 h1:VR/SxJuq9iU8yIrPDWNGUObf6NW4qj/XDb3PWV+g8ZM=
+github.com/patcon/html2md v0.0.0-20181014155555-be1815a53834/go.mod h1:lPwXvF3BqK5Y9DLUOOnt8DrL3tnfHL01ScB1y60aKIw=
+github.com/patcon/html2md v0.0.0-20181014155822-8202240e20c8 h1:KpoZHAtr7KzydT+nt+B0PpaObqey6jcXH4YwtOf7o/s=
+github.com/patcon/html2md v0.0.0-20181014155822-8202240e20c8/go.mod h1:lPwXvF3BqK5Y9DLUOOnt8DrL3tnfHL01ScB1y60aKIw=
+github.com/patcon/html2md v0.0.0-20181014160912-ceba9719ce98 h1:om9mX9OvXpMyRgpy1LBfJ2w+Y3u/TG0VCeUm2Qafx9U=
+github.com/patcon/html2md v0.0.0-20181014160912-ceba9719ce98/go.mod h1:lPwXvF3BqK5Y9DLUOOnt8DrL3tnfHL01ScB1y60aKIw=
 github.com/paulrosania/go-charset v0.0.0-20151028000031-621bb39fcc83 h1:XQonH5Iv5rbyIkMJOQ4xKmKHQTh8viXtRSmep5Ca5I4=
 github.com/paulrosania/go-charset v0.0.0-20151028000031-621bb39fcc83/go.mod h1:YnNlZP7l4MhyGQ4CBRwv6ohZTPrUJJZtEv4ZgADkbs4=
 github.com/pborman/uuid v0.0.0-20160216163710-c55201b03606 h1:/CPgDYrfeK2LMK6xcUhvI17yO9SlpAdDIJGkhDEgO8A=