1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-18 10:07:02 +00:00

Make links clickable in text view of emails

This commit is contained in:
James Hillyerd
2012-10-27 15:24:29 -07:00
parent e9bde25790
commit 69d0e6c341
2 changed files with 28 additions and 7 deletions

View File

@@ -5,16 +5,20 @@ import (
"github.com/jhillyerd/inbucket/log" "github.com/jhillyerd/inbucket/log"
"html" "html"
"html/template" "html/template"
"regexp"
"strings" "strings"
"time" "time"
) )
var TemplateFuncs = template.FuncMap{ var TemplateFuncs = template.FuncMap{
"friendlyTime": friendlyTime, "friendlyTime": friendlyTime,
"reverse": reverse, "reverse": reverse,
"textToHtml": textToHtml, "textToHtml": textToHtml,
} }
// From http://daringfireball.net/2010/07/improved_regex_for_matching_urls
var urlRE = regexp.MustCompile("(?i)\\b((?:[a-z][\\w-]+:(?:/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}/)(?:[^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(?:\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:'\".,<>?«»“”‘’]))")
// Friendly date & time rendering // Friendly date & time rendering
func friendlyTime(t time.Time) template.HTML { func friendlyTime(t time.Time) template.HTML {
ty, tm, td := t.Date() ty, tm, td := t.Date()
@@ -45,6 +49,13 @@ func reverse(name string, things ...interface{}) string {
// HTML display // HTML display
func textToHtml(text string) template.HTML { func textToHtml(text string) template.HTML {
text = html.EscapeString(text) text = html.EscapeString(text)
text = urlRE.ReplaceAllStringFunc(text, wrapUrl)
replacer := strings.NewReplacer("\r\n", "<br/>\n", "\r", "<br/>\n", "\n", "<br/>\n") replacer := strings.NewReplacer("\r\n", "<br/>\n", "\r", "<br/>\n", "\n", "<br/>\n")
return template.HTML(replacer.Replace(text)) return template.HTML(replacer.Replace(text))
} }
// wrapUrl wraps a <a href> tag around the provided URL
func wrapUrl(url string) string {
unescaped := strings.Replace(url, "&amp;", "&", -1)
return fmt.Sprintf("<a href=\"%s\" target=\"_blank\">%s</a>", unescaped, url)
}

View File

@@ -2,18 +2,28 @@ package web
import ( import (
"github.com/stretchrcom/testify/assert" "github.com/stretchrcom/testify/assert"
"html/template"
"testing" "testing"
) )
func TestTextToHtml(t *testing.T) { func TestTextToHtml(t *testing.T) {
// Identity // Identity
assert.Equal(t, textToHtml("html"), "html") assert.Equal(t, textToHtml("html"), template.HTML("html"))
// Check it escapes // Check it escapes
assert.Equal(t, textToHtml("<html>"), "&lt;html&gt;") assert.Equal(t, textToHtml("<html>"), template.HTML("&lt;html&gt;"))
// Check for linebreaks // Check for linebreaks
assert.Equal(t, textToHtml("line\nbreak"), "line<br/>\nbreak") assert.Equal(t, textToHtml("line\nbreak"), template.HTML("line<br/>\nbreak"))
assert.Equal(t, textToHtml("line\r\nbreak"), "line<br/>\nbreak") assert.Equal(t, textToHtml("line\r\nbreak"), template.HTML("line<br/>\nbreak"))
assert.Equal(t, textToHtml("line\rbreak"), "line<br/>\nbreak") assert.Equal(t, textToHtml("line\rbreak"), template.HTML("line<br/>\nbreak"))
}
func TestURLDetection(t *testing.T) {
assert.Equal(t,
textToHtml("http://google.com/"),
template.HTML("<a href=\"http://google.com/\" target=\"_blank\">http://google.com/</a>"))
assert.Equal(t,
textToHtml("http://a.com/?q=a&n=v"),
template.HTML("<a href=\"http://a.com/?q=a&n=v\" target=\"_blank\">http://a.com/?q=a&amp;n=v</a>"))
} }