Do not strip tags for entry title

Some technical blogs have titles like "</some-title>" or "This is some <code>source code</code>".

Miniflux was removing these elements which prevent rendering the title correctly.
This commit is contained in:
Frédéric Guillot 2021-01-03 11:33:10 -08:00 committed by fguillot
parent f0610bdd9c
commit 291bf96d15
7 changed files with 62 additions and 16 deletions

View file

@ -15,7 +15,6 @@ import (
"miniflux.app/model"
"miniflux.app/reader/date"
"miniflux.app/reader/media"
"miniflux.app/reader/sanitizer"
"miniflux.app/url"
)
@ -100,7 +99,7 @@ func (a *atom10Entry) Transform() *model.Entry {
}
func (a *atom10Entry) entryTitle() string {
return sanitizer.StripTags(a.Title.String())
return a.Title.String()
}
func (a *atom10Entry) entryContent() string {

View file

@ -265,7 +265,7 @@ func TestParseEntryTitleWithHTMLAndCDATA(t *testing.T) {
t.Fatal(err)
}
if feed.Entries[0].Title != "Test “Test”" {
if feed.Entries[0].Title != "Test &#8220;Test&#8221;" {
t.Errorf("Incorrect entry title, got: %q", feed.Entries[0].Title)
}
}
@ -291,7 +291,7 @@ func TestParseEntryTitleWithHTML(t *testing.T) {
t.Fatal(err)
}
if feed.Entries[0].Title != "Test Test" {
if feed.Entries[0].Title != "<code>Test</code> Test" {
t.Errorf("Incorrect entry title, got: %q", feed.Entries[0].Title)
}
}
@ -317,7 +317,7 @@ func TestParseEntryTitleWithXHTML(t *testing.T) {
t.Fatal(err)
}
if feed.Entries[0].Title != "Test Test" {
if feed.Entries[0].Title != "<code>Test</code> Test" {
t.Errorf("Incorrect entry title, got: %q", feed.Entries[0].Title)
}
}

View file

@ -12,7 +12,6 @@ import (
"miniflux.app/logger"
"miniflux.app/model"
"miniflux.app/reader/date"
"miniflux.app/reader/sanitizer"
"miniflux.app/url"
)
@ -123,9 +122,9 @@ func (j *jsonItem) GetHash() string {
}
func (j *jsonItem) GetTitle() string {
for _, value := range []string{j.Title, j.Summary, j.Text, j.HTML} {
for _, value := range []string{j.Title, j.Summary, j.Text, j.URL} {
if value != "" {
return truncate(sanitizer.StripTags(value))
return truncate(value)
}
}

View file

@ -76,7 +76,7 @@ func TestParseJsonFeed(t *testing.T) {
t.Errorf("Incorrect entry URL, got: %s", feed.Entries[1].URL)
}
if feed.Entries[1].Title != "Hello, world!" {
if feed.Entries[1].Title != "https://example.org/initial-post" {
t.Errorf(`Incorrect entry title, got: "%s"`, feed.Entries[1].Title)
}
@ -409,6 +409,33 @@ func TestParseTruncateItemTitle(t *testing.T) {
}
}
func TestParseItemTitleWithXMLTags(t *testing.T) {
data := `{
"version": "https://jsonfeed.org/version/1",
"title": "My Example Feed",
"home_page_url": "https://example.org/",
"feed_url": "https://example.org/feed.json",
"items": [
{
"title": "</example>"
}
]
}`
feed, err := Parse("https://example.org/feed.json", bytes.NewBufferString(data))
if err != nil {
t.Fatal(err)
}
if len(feed.Entries) != 1 {
t.Errorf("Incorrect number of entries, got: %d", len(feed.Entries))
}
if feed.Entries[0].Title != "</example>" {
t.Errorf("Incorrect entry title, got: %s", feed.Entries[0].Title)
}
}
func TestParseInvalidJSON(t *testing.T) {
data := `garbage`
_, err := Parse("https://example.org/feed.json", bytes.NewBufferString(data))

View file

@ -40,7 +40,6 @@ func (r *rdfFeed) Transform(baseURL string) *model.Feed {
if entry.Author == "" && r.DublinCoreCreator != "" {
entry.Author = strings.TrimSpace(r.DublinCoreCreator)
}
entry.Author = sanitizer.StripTags(entry.Author)
if entry.URL == "" {
entry.URL = feed.SiteURL

View file

@ -951,7 +951,7 @@ func TestParseInvalidXml(t *testing.T) {
}
}
func TestParseWithHTMLEntity(t *testing.T) {
func TestParseFeedTitleWithHTMLEntity(t *testing.T) {
data := `<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
<channel>
@ -970,7 +970,30 @@ func TestParseWithHTMLEntity(t *testing.T) {
}
}
func TestParseWithInvalidCharacterEntity(t *testing.T) {
func TestParseItemTitleWithHTMLEntity(t *testing.T) {
data := `<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
<channel>
<link>https://example.org/</link>
<title>Example</title>
<item>
<title>&lt;/example&gt;</title>
<link>http://www.example.org/entries/1</link>
</item>
</channel>
</rss>`
feed, err := Parse("https://example.org/", bytes.NewBufferString(data))
if err != nil {
t.Fatal(err)
}
if feed.Entries[0].Title != "</example>" {
t.Errorf(`Incorrect title, got: %q`, feed.Title)
}
}
func TestParseFeedLinkWithInvalidCharacterEntity(t *testing.T) {
data := `<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
<channel>

View file

@ -62,7 +62,6 @@ func (r *rssFeed) Transform(baseURL string) *model.Feed {
if entry.Author == "" {
entry.Author = r.feedAuthor()
}
entry.Author = sanitizer.StripTags(entry.Author)
if entry.URL == "" {
entry.URL = feed.SiteURL
@ -111,7 +110,7 @@ func (r rssFeed) feedAuthor() string {
case r.Webmaster != "":
author = r.Webmaster
}
return strings.TrimSpace(author)
return sanitizer.StripTags(strings.TrimSpace(author))
}
type rssLink struct {
@ -227,7 +226,7 @@ func (r *rssItem) entryAuthor() string {
author = r.DublinCoreCreator
}
return strings.TrimSpace(author)
return sanitizer.StripTags(strings.TrimSpace(author))
}
func (r *rssItem) entryHash() string {
@ -258,7 +257,7 @@ func (r *rssItem) entryTitle() string {
}
}
return strings.TrimSpace(sanitizer.StripTags(title))
return strings.TrimSpace(title)
}
func (r *rssItem) entryContent() string {