From 69d0e6c341ae68d05b99ae9fc4499e49040df98c Mon Sep 17 00:00:00 2001 From: James Hillyerd Date: Sat, 27 Oct 2012 15:24:29 -0700 Subject: [PATCH] Make links clickable in text view of emails --- web/helpers.go | 15 +++++++++++++-- web/helpers_test.go | 20 +++++++++++++++----- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/web/helpers.go b/web/helpers.go index 4e7d48e..af98e0e 100644 --- a/web/helpers.go +++ b/web/helpers.go @@ -5,16 +5,20 @@ import ( "github.com/jhillyerd/inbucket/log" "html" "html/template" + "regexp" "strings" "time" ) var TemplateFuncs = template.FuncMap{ "friendlyTime": friendlyTime, - "reverse": reverse, - "textToHtml": textToHtml, + "reverse": reverse, + "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 func friendlyTime(t time.Time) template.HTML { ty, tm, td := t.Date() @@ -45,6 +49,13 @@ func reverse(name string, things ...interface{}) string { // HTML display func textToHtml(text string) template.HTML { text = html.EscapeString(text) + text = urlRE.ReplaceAllStringFunc(text, wrapUrl) replacer := strings.NewReplacer("\r\n", "
\n", "\r", "
\n", "\n", "
\n") return template.HTML(replacer.Replace(text)) } + +// wrapUrl wraps a tag around the provided URL +func wrapUrl(url string) string { + unescaped := strings.Replace(url, "&", "&", -1) + return fmt.Sprintf("%s", unescaped, url) +} diff --git a/web/helpers_test.go b/web/helpers_test.go index 44936b0..b50a838 100644 --- a/web/helpers_test.go +++ b/web/helpers_test.go @@ -2,18 +2,28 @@ package web import ( "github.com/stretchrcom/testify/assert" + "html/template" "testing" ) func TestTextToHtml(t *testing.T) { // Identity - assert.Equal(t, textToHtml("html"), "html") + assert.Equal(t, textToHtml("html"), template.HTML("html")) // Check it escapes - assert.Equal(t, textToHtml(""), "<html>") + assert.Equal(t, textToHtml(""), template.HTML("<html>")) // Check for linebreaks - assert.Equal(t, textToHtml("line\nbreak"), "line
\nbreak") - assert.Equal(t, textToHtml("line\r\nbreak"), "line
\nbreak") - assert.Equal(t, textToHtml("line\rbreak"), "line
\nbreak") + assert.Equal(t, textToHtml("line\nbreak"), template.HTML("line
\nbreak")) + assert.Equal(t, textToHtml("line\r\nbreak"), template.HTML("line
\nbreak")) + assert.Equal(t, textToHtml("line\rbreak"), template.HTML("line
\nbreak")) +} + +func TestURLDetection(t *testing.T) { + assert.Equal(t, + textToHtml("http://google.com/"), + template.HTML("http://google.com/")) + assert.Equal(t, + textToHtml("http://a.com/?q=a&n=v"), + template.HTML("http://a.com/?q=a&n=v")) }