1
0
mirror of https://github.com/danog/gojekyll.git synced 2024-11-27 11:44:38 +01:00
gojekyll/filters/smartify.go

70 lines
1.9 KiB
Go
Raw Normal View History

2017-07-09 19:00:25 +02:00
package filters
// This file contains a very inefficient implementation, that scans the string multiple times.
// Replace it by a transducer if it shows up in hot spots.
import (
"fmt"
"regexp"
"strings"
)
var smartifyTransforms = []struct {
match *regexp.Regexp
repl string
}{
{regexp.MustCompile("(^|[^[:alnum:]])``(.+?)''"), "$1“$2”"},
{regexp.MustCompile(`(^|[^[:alnum:]])'`), "$1"},
{regexp.MustCompile(`'`), ""},
{regexp.MustCompile(`(^|[^[:alnum:]])"`), "$1“"},
{regexp.MustCompile(`"($|[^[:alnum:]])`), "”$1"},
{regexp.MustCompile(`(^|\s)--($|\s)`), "$1$2"},
{regexp.MustCompile(`(^|\s)---($|\s)`), "$1—$2"},
}
// replace these wherever they appear
var smartifyReplaceSpans = map[string]string{
"...": "…",
"(c)": "©",
"(r)": "®",
"(tm)": "™",
}
// replace these only if bounded by space or word boundaries
var smartifyReplaceWords = map[string]string{
// "---": "",
// "--": "—",
}
var smartifyReplacements map[string]string
var smartifyReplacementPattern *regexp.Regexp
func init() {
smartifyReplacements = map[string]string{}
disjuncts := []string{}
regexQuoter := regexp.MustCompile(`[\(\)\.]`)
escape := func(s string) string {
return regexQuoter.ReplaceAllString(s, `\$0`)
}
for k, v := range smartifyReplaceSpans {
disjuncts = append(disjuncts, escape(k))
smartifyReplacements[k] = v
}
for k, v := range smartifyReplaceWords {
disjuncts = append(disjuncts, fmt.Sprintf(`(\b|\s|^)%s(\b|\s|$)`, escape(k)))
smartifyReplacements[k] = fmt.Sprintf("$1%s$2", v)
}
p := fmt.Sprintf(`(%s)`, strings.Join(disjuncts, `|`))
smartifyReplacementPattern = regexp.MustCompile(p)
}
func smartifyFilter(s string) string {
for _, rule := range smartifyTransforms {
s = rule.match.ReplaceAllString(s, rule.repl)
}
s = smartifyReplacementPattern.ReplaceAllStringFunc(s, func(w string) string {
return smartifyReplacements[w]
})
return s
}