diff --git a/postrender.go b/postrender.go index f917b6e..0931e70 100644 --- a/postrender.go +++ b/postrender.go @@ -140,9 +140,7 @@ func applyBasicMarkdown(data []byte) string { func postTitle(content, friendlyId string) string { const maxTitleLen = 80 - // Strip HTML tags with bluemonday's StrictPolicy, then unescape the HTML - // entities added in by sanitizing the content. - content = html.UnescapeString(bluemonday.StrictPolicy().Sanitize(content)) + content = stripHTMLWithoutEscaping(content) content = strings.TrimLeftFunc(stripmd.Strip(content), unicode.IsSpace) eol := strings.IndexRune(content, '\n') @@ -160,9 +158,7 @@ func postTitle(content, friendlyId string) string { func friendlyPostTitle(content, friendlyId string) string { const maxTitleLen = 80 - // Strip HTML tags with bluemonday's StrictPolicy, then unescape the HTML - // entities added in by sanitizing the content. - content = html.UnescapeString(bluemonday.StrictPolicy().Sanitize(content)) + content = stripHTMLWithoutEscaping(content) content = strings.TrimLeftFunc(stripmd.Strip(content), unicode.IsSpace) eol := strings.IndexRune(content, '\n') @@ -179,6 +175,12 @@ func friendlyPostTitle(content, friendlyId string) string { return title } +// Strip HTML tags with bluemonday's StrictPolicy, then unescape the HTML +// entities added in by sanitizing the content. +func stripHTMLWithoutEscaping(content string) string { + return html.UnescapeString(bluemonday.StrictPolicy().Sanitize(content)) +} + func getSanitizationPolicy() *bluemonday.Policy { policy := bluemonday.UGCPolicy() policy.AllowAttrs("src", "style").OnElements("iframe", "video", "audio") diff --git a/posts.go b/posts.go index 4c8c76e..1bcf151 100644 --- a/posts.go +++ b/posts.go @@ -211,8 +211,7 @@ func (p Post) Summary() string { if p.Content == "" { return "" } - // Strip out HTML - p.Content = bluemonday.StrictPolicy().Sanitize(p.Content) + p.Content = stripHTMLWithoutEscaping(p.Content) // and Markdown p.Content = stripmd.Strip(p.Content) diff --git a/posts_test.go b/posts_test.go new file mode 100644 index 0000000..e423fd3 --- /dev/null +++ b/posts_test.go @@ -0,0 +1,35 @@ +package writefreely_test + +import ( + "testing" + + "github.com/guregu/null/zero" + "github.com/stretchr/testify/assert" + "github.com/writeas/writefreely" +) + +func TestPostSummary(t *testing.T) { + testCases := map[string]struct { + given writefreely.Post + expected string + }{ + "no special chars": {givenPost("Content."), "Content."}, + "HTML content": {givenPost("Content

with a

paragraph."), "Content with a paragraph."}, + "content with escaped char": {givenPost("Content's all OK."), "Content's all OK."}, + "multiline content": {givenPost(`Content +in +multiple +lines.`), "Content in multiple lines."}, + } + + for name, test := range testCases { + t.Run(name, func(t *testing.T) { + actual := test.given.Summary() + assert.Equal(t, test.expected, actual) + }) + } +} + +func givenPost(content string) writefreely.Post { + return writefreely.Post{Title: zero.StringFrom("Title"), Content: content} +}