forked from jshiffer/matterbridge
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)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|