mirror of
https://github.com/cwinfo/matterbridge.git
synced 2024-12-25 19:55:44 +00:00
04567c765e
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.
230 lines
3.8 KiB
Go
230 lines
3.8 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 "strings"
|
||
|
||
func exclquest(b byte) bool {
|
||
return b == '!' || b == '?'
|
||
}
|
||
|
||
func byteToLower(b byte) byte {
|
||
if b >= 'A' && b <= 'Z' {
|
||
return b - 'A' + 'a'
|
||
}
|
||
return b
|
||
}
|
||
|
||
var replChar = [256]bool{
|
||
'(': true,
|
||
'!': true,
|
||
'+': true,
|
||
',': true,
|
||
'-': true,
|
||
'.': true,
|
||
'?': true,
|
||
}
|
||
|
||
func performReplacements(s string) string {
|
||
var ss []string
|
||
|
||
start := 0
|
||
for i := 0; i < len(s); i++ {
|
||
b := s[i]
|
||
|
||
if replChar[b] {
|
||
|
||
outer:
|
||
switch b {
|
||
case '(':
|
||
if i+2 >= len(s) {
|
||
break
|
||
}
|
||
|
||
b2 := s[i+1]
|
||
|
||
b2 = byteToLower(b2)
|
||
switch b2 {
|
||
case 'c', 'r', 'p':
|
||
if s[i+2] != ')' {
|
||
break outer
|
||
}
|
||
switch b2 {
|
||
case 'c':
|
||
if start < i {
|
||
ss = append(ss, s[start:i])
|
||
}
|
||
ss = append(ss, "©")
|
||
case 'r':
|
||
if start < i {
|
||
ss = append(ss, s[start:i])
|
||
}
|
||
ss = append(ss, "®")
|
||
case 'p':
|
||
if start < i {
|
||
ss = append(ss, s[start:i])
|
||
}
|
||
ss = append(ss, "§")
|
||
}
|
||
i += 2
|
||
start = i + 1
|
||
continue
|
||
|
||
case 't':
|
||
if i+3 >= len(s) {
|
||
break outer
|
||
}
|
||
if s[i+3] != ')' || byteToLower(s[i+2]) != 'm' {
|
||
break outer
|
||
}
|
||
if start < i {
|
||
ss = append(ss, s[start:i])
|
||
}
|
||
ss = append(ss, "™")
|
||
i += 3
|
||
start = i + 1
|
||
continue
|
||
default:
|
||
break outer
|
||
}
|
||
|
||
case '+':
|
||
if i+1 >= len(s) || s[i+1] != '-' {
|
||
break
|
||
}
|
||
if start < i {
|
||
ss = append(ss, s[start:i])
|
||
}
|
||
ss = append(ss, "±")
|
||
i++
|
||
start = i + 1
|
||
continue
|
||
|
||
case '.':
|
||
if i+1 >= len(s) || s[i+1] != '.' {
|
||
break
|
||
}
|
||
|
||
j := i + 2
|
||
for j < len(s) && s[j] == '.' {
|
||
j++
|
||
}
|
||
if start < i {
|
||
ss = append(ss, s[start:i])
|
||
}
|
||
if i == 0 || !(s[i-1] == '?' || s[i-1] == '!') {
|
||
ss = append(ss, "…")
|
||
} else {
|
||
ss = append(ss, "..")
|
||
}
|
||
i = j - 1
|
||
start = i + 1
|
||
continue
|
||
|
||
case '?', '!':
|
||
if i+3 >= len(s) {
|
||
break
|
||
}
|
||
if !(exclquest(s[i+1]) && exclquest(s[i+2]) && exclquest(s[i+3])) {
|
||
break
|
||
}
|
||
if start < i {
|
||
ss = append(ss, s[start:i])
|
||
}
|
||
ss = append(ss, s[i:i+3])
|
||
j := i + 3
|
||
for j < len(s) && exclquest(s[j]) {
|
||
j++
|
||
}
|
||
i = j - 1
|
||
start = i + 1
|
||
continue
|
||
|
||
case ',':
|
||
if i+1 >= len(s) || s[i+1] != ',' {
|
||
break
|
||
}
|
||
if start < i {
|
||
ss = append(ss, s[start:i])
|
||
}
|
||
ss = append(ss, ",")
|
||
j := i + 2
|
||
for j < len(s) && s[j] == ',' {
|
||
j++
|
||
}
|
||
i = j - 1
|
||
start = i + 1
|
||
continue
|
||
|
||
case '-':
|
||
if i+1 >= len(s) || s[i+1] != '-' {
|
||
break
|
||
}
|
||
if i+2 >= len(s) || s[i+2] != '-' {
|
||
if start < i {
|
||
ss = append(ss, s[start:i])
|
||
}
|
||
ss = append(ss, "–")
|
||
i++
|
||
start = i + 1
|
||
continue
|
||
}
|
||
if i+3 >= len(s) || s[i+3] != '-' {
|
||
if start < i {
|
||
ss = append(ss, s[start:i])
|
||
}
|
||
ss = append(ss, "—")
|
||
i += 2
|
||
start = i + 1
|
||
continue
|
||
}
|
||
|
||
j := i + 3
|
||
for j < len(s) && s[j] == '-' {
|
||
j++
|
||
}
|
||
if start < i {
|
||
ss = append(ss, s[start:i])
|
||
}
|
||
ss = append(ss, s[i:j])
|
||
i = j - 1
|
||
start = i + 1
|
||
continue
|
||
}
|
||
}
|
||
}
|
||
if ss == nil {
|
||
return s
|
||
}
|
||
if start < len(s) {
|
||
ss = append(ss, s[start:])
|
||
}
|
||
return strings.Join(ss, "")
|
||
}
|
||
|
||
func ruleReplacements(s *StateCore) {
|
||
if !s.Md.Typographer {
|
||
return
|
||
}
|
||
|
||
insideLink := false
|
||
for _, tok := range s.Tokens {
|
||
if tok, ok := tok.(*Inline); ok {
|
||
for _, itok := range tok.Children {
|
||
switch itok := itok.(type) {
|
||
case *LinkOpen:
|
||
insideLink = true
|
||
case *LinkClose:
|
||
insideLink = false
|
||
case *Text:
|
||
if !insideLink {
|
||
itok.Content = performReplacements(itok.Content)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|