When detecting the format, detect its version as well
There is no need to detect the format and then the version when both can be done at the same time. Add a benchmark as well, on large and small atom and rss files.
This commit is contained in:
parent
688b73b7ae
commit
45d486b919
12 changed files with 3608 additions and 160 deletions
|
@ -27,7 +27,7 @@ func TestParseAtom03(t *testing.T) {
|
|||
</entry>
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("http://diveintomark.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("http://diveintomark.org/", bytes.NewReader([]byte(data)), "0.3")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ func TestParseAtom03WithoutFeedTitle(t *testing.T) {
|
|||
</entry>
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("http://diveintomark.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("http://diveintomark.org/", bytes.NewReader([]byte(data)), "0.3")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ func TestParseAtom03WithoutEntryTitleButWithLink(t *testing.T) {
|
|||
</entry>
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("http://diveintomark.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("http://diveintomark.org/", bytes.NewReader([]byte(data)), "0.3")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ func TestParseAtom03WithoutEntryTitleButWithSummary(t *testing.T) {
|
|||
</entry>
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("http://diveintomark.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("http://diveintomark.org/", bytes.NewReader([]byte(data)), "0.3")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ func TestParseAtom03WithoutEntryTitleButWithXMLContent(t *testing.T) {
|
|||
</entry>
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("http://diveintomark.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("http://diveintomark.org/", bytes.NewReader([]byte(data)), "0.3")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -197,7 +197,7 @@ func TestParseAtom03WithSummaryOnly(t *testing.T) {
|
|||
</entry>
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("http://diveintomark.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("http://diveintomark.org/", bytes.NewReader([]byte(data)), "0.3")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ func TestParseAtom03WithXMLContent(t *testing.T) {
|
|||
</entry>
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("http://diveintomark.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("http://diveintomark.org/", bytes.NewReader([]byte(data)), "0.3")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -259,7 +259,7 @@ func TestParseAtom03WithBase64Content(t *testing.T) {
|
|||
</entry>
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("http://diveintomark.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("http://diveintomark.org/", bytes.NewReader([]byte(data)), "0.3")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ func TestParseAtomSample(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("http://example.org/feed.xml", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("http://example.org/feed.xml", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ func TestParseFeedWithoutTitle(t *testing.T) {
|
|||
<updated>2003-12-13T18:30:02Z</updated>
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ func TestParseEntryWithoutTitleButWithURL(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ func TestParseEntryWithoutTitleButWithSummary(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ func TestParseEntryWithoutTitleButWithXHTMLContent(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -206,7 +206,7 @@ func TestParseFeedURL(t *testing.T) {
|
|||
<updated>2003-12-13T18:30:02Z</updated>
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -238,7 +238,7 @@ func TestParseFeedWithRelativeURL(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -272,7 +272,7 @@ func TestParseEntryWithRelativeURL(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.net/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.net/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -298,7 +298,7 @@ func TestParseEntryURLWithTextHTMLType(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.net/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.net/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -324,7 +324,7 @@ func TestParseEntryURLWithNoRelAndNoType(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.net/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.net/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -350,7 +350,7 @@ func TestParseEntryURLWithAlternateRel(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.net/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.net/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -378,7 +378,7 @@ func TestParseEntryTitleWithWhitespaces(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -412,7 +412,7 @@ func TestParseEntryWithPlainTextTitle(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -459,7 +459,7 @@ func TestParseEntryWithHTMLTitle(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -497,7 +497,7 @@ func TestParseEntryWithXHTMLTitle(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -524,7 +524,7 @@ func TestParseEntryWithEmptyXHTMLTitle(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -551,7 +551,7 @@ func TestParseEntryWithXHTMLTitleWithoutDiv(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -577,7 +577,7 @@ func TestParseEntryWithNumericCharacterReferenceTitle(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -603,7 +603,7 @@ func TestParseEntryWithDoubleEncodedEntitiesTitle(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -629,7 +629,7 @@ func TestParseEntryWithXHTMLSummary(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -671,7 +671,7 @@ func TestParseEntryWithHTMLSummary(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -723,7 +723,7 @@ func TestParseEntryWithTextSummary(t *testing.T) {
|
|||
</entry>
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -776,7 +776,7 @@ func TestParseEntryWithTextContent(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -821,7 +821,7 @@ func TestParseEntryWithHTMLContent(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -852,7 +852,7 @@ func TestParseEntryWithXHTMLContent(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -881,7 +881,7 @@ func TestParseEntryWithAuthorName(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -910,7 +910,7 @@ func TestParseEntryWithoutAuthorName(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -941,7 +941,7 @@ func TestParseEntryWithMultipleAuthors(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -969,7 +969,7 @@ func TestParseEntryWithoutAuthor(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1000,7 +1000,7 @@ func TestParseFeedWithMultipleAuthors(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1025,7 +1025,7 @@ func TestParseFeedWithoutAuthor(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1075,7 +1075,7 @@ func TestParseEntryWithEnclosures(t *testing.T) {
|
|||
</entry>
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1135,7 +1135,7 @@ func TestParseEntryWithoutEnclosureURL(t *testing.T) {
|
|||
</entry>
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1168,7 +1168,7 @@ func TestParseEntryWithPublished(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1194,7 +1194,7 @@ func TestParseEntryWithPublishedAndUpdated(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1206,7 +1206,7 @@ func TestParseEntryWithPublishedAndUpdated(t *testing.T) {
|
|||
|
||||
func TestParseInvalidXml(t *testing.T) {
|
||||
data := `garbage`
|
||||
_, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
_, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err == nil {
|
||||
t.Error("Parse should returns an error")
|
||||
}
|
||||
|
@ -1221,7 +1221,7 @@ func TestParseTitleWithSingleQuote(t *testing.T) {
|
|||
</feed>
|
||||
`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1240,7 +1240,7 @@ func TestParseTitleWithEncodedSingleQuote(t *testing.T) {
|
|||
</feed>
|
||||
`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1259,7 +1259,7 @@ func TestParseTitleWithSingleQuoteAndHTMLType(t *testing.T) {
|
|||
</feed>
|
||||
`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1278,7 +1278,7 @@ func TestParseWithHTMLEntity(t *testing.T) {
|
|||
</feed>
|
||||
`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1297,7 +1297,7 @@ func TestParseWithInvalidCharacterEntity(t *testing.T) {
|
|||
</feed>
|
||||
`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1330,7 +1330,7 @@ A website: http://example.org/</media:description>
|
|||
</entry>
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1396,7 +1396,7 @@ A website: http://example.org/</media:description>
|
|||
</entry>
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1467,7 +1467,7 @@ func TestParseRepliesLinkRelationWithHTMLType(t *testing.T) {
|
|||
</entry>
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1511,7 +1511,7 @@ func TestParseRepliesLinkRelationWithXHTMLType(t *testing.T) {
|
|||
</entry>
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1550,7 +1550,7 @@ func TestParseRepliesLinkRelationWithNoType(t *testing.T) {
|
|||
</entry>
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1590,7 +1590,7 @@ func TestAbsoluteCommentsURL(t *testing.T) {
|
|||
</entry>
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1631,7 +1631,7 @@ func TestParseFeedWithCategories(t *testing.T) {
|
|||
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1661,7 +1661,7 @@ func TestParseFeedWithIconURL(t *testing.T) {
|
|||
<icon>http://example.org/icon.png</icon>
|
||||
</feed>`
|
||||
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)))
|
||||
feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data)), "10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
package atom // import "miniflux.app/v2/internal/reader/atom"
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
|
@ -17,14 +16,13 @@ type atomFeed interface {
|
|||
}
|
||||
|
||||
// Parse returns a normalized feed struct from a Atom feed.
|
||||
func Parse(baseURL string, r io.ReadSeeker) (*model.Feed, error) {
|
||||
func Parse(baseURL string, r io.ReadSeeker, version string) (*model.Feed, error) {
|
||||
var rawFeed atomFeed
|
||||
if getAtomFeedVersion(r) == "0.3" {
|
||||
if version == "0.3" {
|
||||
rawFeed = new(atom03Feed)
|
||||
} else {
|
||||
rawFeed = new(atom10Feed)
|
||||
}
|
||||
r.Seek(0, io.SeekStart)
|
||||
|
||||
if err := xml_decoder.NewXMLDecoder(r).Decode(rawFeed); err != nil {
|
||||
return nil, fmt.Errorf("atom: unable to parse feed: %w", err)
|
||||
|
@ -32,25 +30,3 @@ func Parse(baseURL string, r io.ReadSeeker) (*model.Feed, error) {
|
|||
|
||||
return rawFeed.Transform(baseURL), nil
|
||||
}
|
||||
|
||||
func getAtomFeedVersion(data io.ReadSeeker) string {
|
||||
decoder := xml_decoder.NewXMLDecoder(data)
|
||||
for {
|
||||
token, _ := decoder.Token()
|
||||
if token == nil {
|
||||
break
|
||||
}
|
||||
|
||||
if element, ok := token.(xml.StartElement); ok {
|
||||
if element.Name.Local == "feed" {
|
||||
for _, attr := range element.Attr {
|
||||
if attr.Name.Local == "version" && attr.Value == "0.3" {
|
||||
return "0.3"
|
||||
}
|
||||
}
|
||||
return "1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
return "1.0"
|
||||
}
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package atom // import "miniflux.app/v2/internal/reader/atom"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDetectAtom10(t *testing.T) {
|
||||
data := `<?xml version="1.0" encoding="utf-8"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
|
||||
<title>Example Feed</title>
|
||||
<link href="http://example.org/"/>
|
||||
<updated>2003-12-13T18:30:02Z</updated>
|
||||
<author>
|
||||
<name>John Doe</name>
|
||||
</author>
|
||||
<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
|
||||
|
||||
<entry>
|
||||
<title>Atom-Powered Robots Run Amok</title>
|
||||
<link href="http://example.org/2003/12/13/atom03"/>
|
||||
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
|
||||
<updated>2003-12-13T18:30:02Z</updated>
|
||||
<summary>Some text.</summary>
|
||||
</entry>
|
||||
|
||||
</feed>`
|
||||
|
||||
version := getAtomFeedVersion(bytes.NewReader([]byte(data)))
|
||||
if version != "1.0" {
|
||||
t.Errorf(`Invalid Atom version detected: %s`, version)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDetectAtom03(t *testing.T) {
|
||||
data := `<?xml version="1.0" encoding="utf-8"?>
|
||||
<feed version="0.3" xmlns="http://purl.org/atom/ns#">
|
||||
<title>dive into mark</title>
|
||||
<link rel="alternate" type="text/html" href="http://diveintomark.org/"/>
|
||||
<modified>2003-12-13T18:30:02Z</modified>
|
||||
<author><name>Mark Pilgrim</name></author>
|
||||
<entry>
|
||||
<title>Atom 0.3 snapshot</title>
|
||||
<link rel="alternate" type="text/html" href="http://diveintomark.org/2003/12/13/atom03"/>
|
||||
<id>tag:diveintomark.org,2003:3.2397</id>
|
||||
<issued>2003-12-13T08:29:29-04:00</issued>
|
||||
<modified>2003-12-13T18:30:02Z</modified>
|
||||
<summary type="text/plain">This is a test</summary>
|
||||
<content type="text/html" mode="escaped"><![CDATA[<p>HTML content</p>]]></content>
|
||||
</entry>
|
||||
</feed>`
|
||||
|
||||
version := getAtomFeedVersion(bytes.NewReader([]byte(data)))
|
||||
if version != "0.3" {
|
||||
t.Errorf(`Invalid Atom version detected: %s`, version)
|
||||
}
|
||||
}
|
|
@ -21,12 +21,12 @@ const (
|
|||
)
|
||||
|
||||
// DetectFeedFormat tries to guess the feed format from input data.
|
||||
func DetectFeedFormat(r io.ReadSeeker) string {
|
||||
func DetectFeedFormat(r io.ReadSeeker) (string, string) {
|
||||
data := make([]byte, 512)
|
||||
r.Read(data)
|
||||
|
||||
if bytes.HasPrefix(bytes.TrimSpace(data), []byte("{")) {
|
||||
return FormatJSON
|
||||
return FormatJSON, ""
|
||||
}
|
||||
|
||||
r.Seek(0, io.SeekStart)
|
||||
|
@ -41,14 +41,19 @@ func DetectFeedFormat(r io.ReadSeeker) string {
|
|||
if element, ok := token.(xml.StartElement); ok {
|
||||
switch element.Name.Local {
|
||||
case "rss":
|
||||
return FormatRSS
|
||||
return FormatRSS, ""
|
||||
case "feed":
|
||||
return FormatAtom
|
||||
for _, attr := range element.Attr {
|
||||
if attr.Name.Local == "version" && attr.Value == "0.3" {
|
||||
return FormatAtom, "0.3"
|
||||
}
|
||||
}
|
||||
return FormatAtom, "1.0"
|
||||
case "RDF":
|
||||
return FormatRDF
|
||||
return FormatRDF, ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FormatUnknown
|
||||
return FormatUnknown, ""
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
|
||||
func TestDetectRDF(t *testing.T) {
|
||||
data := `<?xml version="1.0"?><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://my.netscape.com/rdf/simple/0.9/"></rdf:RDF>`
|
||||
format := DetectFeedFormat(strings.NewReader(data))
|
||||
format, _ := DetectFeedFormat(strings.NewReader(data))
|
||||
|
||||
if format != FormatRDF {
|
||||
t.Errorf(`Wrong format detected: %q instead of %q`, format, FormatRDF)
|
||||
|
@ -19,7 +19,7 @@ func TestDetectRDF(t *testing.T) {
|
|||
|
||||
func TestDetectRSS(t *testing.T) {
|
||||
data := `<?xml version="1.0"?><rss version="2.0"><channel></channel></rss>`
|
||||
format := DetectFeedFormat(strings.NewReader(data))
|
||||
format, _ := DetectFeedFormat(strings.NewReader(data))
|
||||
|
||||
if format != FormatRSS {
|
||||
t.Errorf(`Wrong format detected: %q instead of %q`, format, FormatRSS)
|
||||
|
@ -28,7 +28,7 @@ func TestDetectRSS(t *testing.T) {
|
|||
|
||||
func TestDetectAtom10(t *testing.T) {
|
||||
data := `<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"></feed>`
|
||||
format := DetectFeedFormat(strings.NewReader(data))
|
||||
format, _ := DetectFeedFormat(strings.NewReader(data))
|
||||
|
||||
if format != FormatAtom {
|
||||
t.Errorf(`Wrong format detected: %q instead of %q`, format, FormatAtom)
|
||||
|
@ -37,7 +37,7 @@ func TestDetectAtom10(t *testing.T) {
|
|||
|
||||
func TestDetectAtom03(t *testing.T) {
|
||||
data := `<?xml version="1.0" encoding="utf-8"?><feed version="0.3" xmlns="http://purl.org/atom/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en"></feed>`
|
||||
format := DetectFeedFormat(strings.NewReader(data))
|
||||
format, _ := DetectFeedFormat(strings.NewReader(data))
|
||||
|
||||
if format != FormatAtom {
|
||||
t.Errorf(`Wrong format detected: %q instead of %q`, format, FormatAtom)
|
||||
|
@ -46,7 +46,7 @@ func TestDetectAtom03(t *testing.T) {
|
|||
|
||||
func TestDetectAtomWithISOCharset(t *testing.T) {
|
||||
data := `<?xml version="1.0" encoding="ISO-8859-15"?><feed xmlns="http://www.w3.org/2005/Atom"></feed>`
|
||||
format := DetectFeedFormat(strings.NewReader(data))
|
||||
format, _ := DetectFeedFormat(strings.NewReader(data))
|
||||
|
||||
if format != FormatAtom {
|
||||
t.Errorf(`Wrong format detected: %q instead of %q`, format, FormatAtom)
|
||||
|
@ -60,7 +60,7 @@ func TestDetectJSON(t *testing.T) {
|
|||
"title" : "Example"
|
||||
}
|
||||
`
|
||||
format := DetectFeedFormat(strings.NewReader(data))
|
||||
format, _ := DetectFeedFormat(strings.NewReader(data))
|
||||
|
||||
if format != FormatJSON {
|
||||
t.Errorf(`Wrong format detected: %q instead of %q`, format, FormatJSON)
|
||||
|
@ -71,7 +71,7 @@ func TestDetectUnknown(t *testing.T) {
|
|||
data := `
|
||||
<!DOCTYPE html> <html> </html>
|
||||
`
|
||||
format := DetectFeedFormat(strings.NewReader(data))
|
||||
format, _ := DetectFeedFormat(strings.NewReader(data))
|
||||
|
||||
if format != FormatUnknown {
|
||||
t.Errorf(`Wrong format detected: %q instead of %q`, format, FormatUnknown)
|
||||
|
|
|
@ -19,10 +19,11 @@ var ErrFeedFormatNotDetected = errors.New("parser: unable to detect feed format"
|
|||
// ParseFeed analyzes the input data and returns a normalized feed object.
|
||||
func ParseFeed(baseURL string, r io.ReadSeeker) (*model.Feed, error) {
|
||||
r.Seek(0, io.SeekStart)
|
||||
switch DetectFeedFormat(r) {
|
||||
format, version := DetectFeedFormat(r)
|
||||
switch format {
|
||||
case FormatAtom:
|
||||
r.Seek(0, io.SeekStart)
|
||||
return atom.Parse(baseURL, r)
|
||||
return atom.Parse(baseURL, r, version)
|
||||
case FormatRSS:
|
||||
r.Seek(0, io.SeekStart)
|
||||
return rss.Parse(baseURL, r)
|
||||
|
|
|
@ -4,10 +4,31 @@
|
|||
package parser // import "miniflux.app/v2/internal/reader/parser"
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkParse(b *testing.B) {
|
||||
var testCases = map[string][]string{
|
||||
"large_atom.xml": {"https://dustri.org/b", ""},
|
||||
"large_rss.xml": {"https://dustri.org/b", ""},
|
||||
"small_atom.xml": {"https://github.com/miniflux/v2/commits/main", ""},
|
||||
}
|
||||
for filename := range testCases {
|
||||
data, err := os.ReadFile("./testdata/" + filename)
|
||||
if err != nil {
|
||||
b.Fatalf(`Unable to read file %q: %v`, filename, err)
|
||||
}
|
||||
testCases[filename][1] = string(data)
|
||||
}
|
||||
for range b.N {
|
||||
for _, v := range testCases {
|
||||
ParseFeed(v[0], strings.NewReader(v[1]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func FuzzParse(f *testing.F) {
|
||||
f.Add("https://z.org", `<?xml version="1.0" encoding="utf-8"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
|
|
1638
internal/reader/parser/testdata/large_atom.xml
vendored
Normal file
1638
internal/reader/parser/testdata/large_atom.xml
vendored
Normal file
File diff suppressed because it is too large
Load diff
1472
internal/reader/parser/testdata/large_rss.xml
vendored
Normal file
1472
internal/reader/parser/testdata/large_rss.xml
vendored
Normal file
File diff suppressed because it is too large
Load diff
396
internal/reader/parser/testdata/small_atom.xml
vendored
Normal file
396
internal/reader/parser/testdata/small_atom.xml
vendored
Normal file
|
@ -0,0 +1,396 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xml:lang="en-US">
|
||||
<id>tag:github.com,2008:/miniflux/v2/commits/main</id>
|
||||
<link type="text/html" rel="alternate" href="https://github.com/miniflux/v2/commits/main"/>
|
||||
<link type="application/atom+xml" rel="self" href="https://github.com/miniflux/v2/commits/main.atom"/>
|
||||
<title>Recent Commits to v2:main</title>
|
||||
<updated>2024-03-12T05:30:27Z</updated>
|
||||
<entry>
|
||||
<id>tag:github.com,2008:Grit::Commit/6d97f8b4582414b6ce69467656824690057d4793</id>
|
||||
<link type="text/html" rel="alternate" href="https://github.com/miniflux/v2/commit/6d97f8b4582414b6ce69467656824690057d4793"/>
|
||||
<title>
|
||||
Parse podcast categories
|
||||
</title>
|
||||
<updated>2024-03-12T05:30:27Z</updated>
|
||||
<media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/323546?s=30&v=4"/>
|
||||
<author>
|
||||
<name>fguillot</name>
|
||||
<uri>https://github.com/fguillot</uri>
|
||||
</author>
|
||||
<content type="html">
|
||||
<pre style='white-space:pre-wrap;width:81ex'>Parse podcast categories</pre>
|
||||
</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>tag:github.com,2008:Grit::Commit/f8e50947f2885047155a8070dddab133a5c685c2</id>
|
||||
<link type="text/html" rel="alternate" href="https://github.com/miniflux/v2/commit/f8e50947f2885047155a8070dddab133a5c685c2"/>
|
||||
<title>
|
||||
Move iTunes and GooglePlay XML definitions to their own packages
|
||||
</title>
|
||||
<updated>2024-03-12T05:09:31Z</updated>
|
||||
<media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/323546?s=30&v=4"/>
|
||||
<author>
|
||||
<name>fguillot</name>
|
||||
<uri>https://github.com/fguillot</uri>
|
||||
</author>
|
||||
<content type="html">
|
||||
<pre style='white-space:pre-wrap;width:81ex'>Move iTunes and GooglePlay XML definitions to their own packages</pre>
|
||||
</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>tag:github.com,2008:Grit::Commit/9a637ce95e05459adc4712027e6a07eaabcfe657</id>
|
||||
<link type="text/html" rel="alternate" href="https://github.com/miniflux/v2/commit/9a637ce95e05459adc4712027e6a07eaabcfe657"/>
|
||||
<title>
|
||||
Refactor RSS parser to use default namespace
|
||||
</title>
|
||||
<updated>2024-03-12T04:07:13Z</updated>
|
||||
<media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/323546?s=30&v=4"/>
|
||||
<author>
|
||||
<name>fguillot</name>
|
||||
<uri>https://github.com/fguillot</uri>
|
||||
</author>
|
||||
<content type="html">
|
||||
<pre style='white-space:pre-wrap;width:81ex'>Refactor RSS parser to use default namespace
|
||||
|
||||
This change avoid some limitations of the Go XML parser regarding XML namespaces</pre>
|
||||
</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>tag:github.com,2008:Grit::Commit/d3a85b049b14d4a4ddd6b813134b2abd45fe5e8d</id>
|
||||
<link type="text/html" rel="alternate" href="https://github.com/miniflux/v2/commit/d3a85b049b14d4a4ddd6b813134b2abd45fe5e8d"/>
|
||||
<title>
|
||||
jsminifier: set JavaScript version
|
||||
</title>
|
||||
<updated>2024-03-12T02:02:52Z</updated>
|
||||
<media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/323546?s=30&v=4"/>
|
||||
<author>
|
||||
<name>fguillot</name>
|
||||
<uri>https://github.com/fguillot</uri>
|
||||
</author>
|
||||
<content type="html">
|
||||
<pre style='white-space:pre-wrap;width:81ex'>jsminifier: set JavaScript version</pre>
|
||||
</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>tag:github.com,2008:Grit::Commit/5bcb37901c60463b27e1211e0f68295f213b19e6</id>
|
||||
<link type="text/html" rel="alternate" href="https://github.com/miniflux/v2/commit/5bcb37901c60463b27e1211e0f68295f213b19e6"/>
|
||||
<title>
|
||||
Use crypto.GenerateRandomBytes instead of doing it by hand
|
||||
</title>
|
||||
<updated>2024-03-11T23:31:43Z</updated>
|
||||
<media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/325724?s=30&v=4"/>
|
||||
<author>
|
||||
<name>jvoisin</name>
|
||||
<uri>https://github.com/jvoisin</uri>
|
||||
</author>
|
||||
<content type="html">
|
||||
<pre style='white-space:pre-wrap;width:81ex'>Use crypto.GenerateRandomBytes instead of doing it by hand
|
||||
|
||||
This makes the code a bit shorter, and properly handle
|
||||
cryptographic error conditions.</pre>
|
||||
</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>tag:github.com,2008:Grit::Commit/9c8a7dfffe2f4596dcbde2c923a7539914bb252f</id>
|
||||
<link type="text/html" rel="alternate" href="https://github.com/miniflux/v2/commit/9c8a7dfffe2f4596dcbde2c923a7539914bb252f"/>
|
||||
<title>
|
||||
Make use of HashFromBytes everywhere
|
||||
</title>
|
||||
<updated>2024-03-11T22:22:22Z</updated>
|
||||
<media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/325724?s=30&v=4"/>
|
||||
<author>
|
||||
<name>jvoisin</name>
|
||||
<uri>https://github.com/jvoisin</uri>
|
||||
</author>
|
||||
<content type="html">
|
||||
<pre style='white-space:pre-wrap;width:81ex'>Make use of HashFromBytes everywhere
|
||||
|
||||
It feels a bit silly to have a function and to not make use of it.</pre>
|
||||
</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>tag:github.com,2008:Grit::Commit/74e4032ffc9faad4fec602f283a32d2af8dec47e</id>
|
||||
<link type="text/html" rel="alternate" href="https://github.com/miniflux/v2/commit/74e4032ffc9faad4fec602f283a32d2af8dec47e"/>
|
||||
<title>
|
||||
Small refactor of app.js
|
||||
</title>
|
||||
<updated>2024-03-11T22:18:57Z</updated>
|
||||
<media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/325724?s=30&v=4"/>
|
||||
<author>
|
||||
<name>jvoisin</name>
|
||||
<uri>https://github.com/jvoisin</uri>
|
||||
</author>
|
||||
<content type="html">
|
||||
<pre style='white-space:pre-wrap;width:81ex'>Small refactor of app.js
|
||||
|
||||
- replace a lot of `let` with `const`
|
||||
- inline some `querySelectorAll` calls
|
||||
- reduce the scope of some variables
|
||||
- use some ternaries where it makes sense
|
||||
- inline one-line functions</pre>
|
||||
</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>tag:github.com,2008:Grit::Commit/fd1fee852cb35fa0f5b0ed6dc0c23b4a6ce368c3</id>
|
||||
<link type="text/html" rel="alternate" href="https://github.com/miniflux/v2/commit/fd1fee852cb35fa0f5b0ed6dc0c23b4a6ce368c3"/>
|
||||
<title>
|
||||
Simplify DomHelper.getVisibleElements
|
||||
</title>
|
||||
<updated>2024-03-11T22:03:00Z</updated>
|
||||
<media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/325724?s=30&v=4"/>
|
||||
<author>
|
||||
<name>jvoisin</name>
|
||||
<uri>https://github.com/jvoisin</uri>
|
||||
</author>
|
||||
<content type="html">
|
||||
<pre style='white-space:pre-wrap;width:81ex'>Simplify DomHelper.getVisibleElements
|
||||
|
||||
Use a `filter` instead of a loop with an index.</pre>
|
||||
</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>tag:github.com,2008:Grit::Commit/c51a3270da1f6af796b7d23fa4b434ccf11818e7</id>
|
||||
<link type="text/html" rel="alternate" href="https://github.com/miniflux/v2/commit/c51a3270da1f6af796b7d23fa4b434ccf11818e7"/>
|
||||
<title>
|
||||
GitHub Actions: Add basic ESLinter checks
|
||||
</title>
|
||||
<updated>2024-03-11T03:57:27Z</updated>
|
||||
<media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/323546?s=30&v=4"/>
|
||||
<author>
|
||||
<name>fguillot</name>
|
||||
<uri>https://github.com/fguillot</uri>
|
||||
</author>
|
||||
<content type="html">
|
||||
<pre style='white-space:pre-wrap;width:81ex'>GitHub Actions: Add basic ESLinter checks</pre>
|
||||
</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>tag:github.com,2008:Grit::Commit/45fa641d26a5f68e663aa9af72e97523d8d63c1e</id>
|
||||
<link type="text/html" rel="alternate" href="https://github.com/miniflux/v2/commit/45fa641d26a5f68e663aa9af72e97523d8d63c1e"/>
|
||||
<title>
|
||||
Fix JavaScript linter path in GitHub Actions
|
||||
</title>
|
||||
<updated>2024-03-11T03:37:18Z</updated>
|
||||
<media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/323546?s=30&v=4"/>
|
||||
<author>
|
||||
<name>fguillot</name>
|
||||
<uri>https://github.com/fguillot</uri>
|
||||
</author>
|
||||
<content type="html">
|
||||
<pre style='white-space:pre-wrap;width:81ex'>Fix JavaScript linter path in GitHub Actions</pre>
|
||||
</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>tag:github.com,2008:Grit::Commit/fd8f25916b025a92b1b8349ef9d0acdb832a9e8e</id>
|
||||
<link type="text/html" rel="alternate" href="https://github.com/miniflux/v2/commit/fd8f25916b025a92b1b8349ef9d0acdb832a9e8e"/>
|
||||
<title>
|
||||
First steps towards trusted-types support
|
||||
</title>
|
||||
<updated>2024-03-11T03:14:30Z</updated>
|
||||
<media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/325724?s=30&v=4"/>
|
||||
<author>
|
||||
<name>jvoisin</name>
|
||||
<uri>https://github.com/jvoisin</uri>
|
||||
</author>
|
||||
<content type="html">
|
||||
<pre style='white-space:pre-wrap;width:81ex'>First steps towards trusted-types support
|
||||
|
||||
Refactor away some trival usages of `.innerHTML`. Unfortunately, there is no way to
|
||||
enabled trusted-types in report-only mode via `&lt;meta&gt;` tags, see
|
||||
https://github.com/w3c/webappsec-csp/issues/277</pre>
|
||||
</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>tag:github.com,2008:Grit::Commit/826e4d654f511ea8d1d385bdc09cbed69ff6a70f</id>
|
||||
<link type="text/html" rel="alternate" href="https://github.com/miniflux/v2/commit/826e4d654f511ea8d1d385bdc09cbed69ff6a70f"/>
|
||||
<title>
|
||||
Replace DomHelper.findParent with .closest
|
||||
</title>
|
||||
<updated>2024-03-11T03:06:54Z</updated>
|
||||
<media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/325724?s=30&v=4"/>
|
||||
<author>
|
||||
<name>jvoisin</name>
|
||||
<uri>https://github.com/jvoisin</uri>
|
||||
</author>
|
||||
<content type="html">
|
||||
<pre style='white-space:pre-wrap;width:81ex'>Replace DomHelper.findParent with .closest
|
||||
|
||||
See https://developer.mozilla.org/en-US/docs/Web/API/Element/closest</pre>
|
||||
</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>tag:github.com,2008:Grit::Commit/d9d17f0d69d1dafb3bd9d81bf9fc27df3def4f4c</id>
|
||||
<link type="text/html" rel="alternate" href="https://github.com/miniflux/v2/commit/d9d17f0d69d1dafb3bd9d81bf9fc27df3def4f4c"/>
|
||||
<title>
|
||||
Use a `Set` instead of an array in a KeyboardHandler's member
|
||||
</title>
|
||||
<updated>2024-03-11T02:41:13Z</updated>
|
||||
<media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/325724?s=30&v=4"/>
|
||||
<author>
|
||||
<name>jvoisin</name>
|
||||
<uri>https://github.com/jvoisin</uri>
|
||||
</author>
|
||||
<content type="html">
|
||||
<pre style='white-space:pre-wrap;width:81ex'>Use a `Set` instead of an array in a KeyboardHandler&#39;s member
|
||||
|
||||
The variable `triggers` is only used to check if in contains a particular
|
||||
value. Given that the number of keyboard shortcuts is starting to be
|
||||
significant, let&#39;s future-proof the performances and use a `Set` instead of an
|
||||
`Array` instead.</pre>
|
||||
</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>tag:github.com,2008:Grit::Commit/eaaeb68474ff194f682e9521a848d7ab2c89348e</id>
|
||||
<link type="text/html" rel="alternate" href="https://github.com/miniflux/v2/commit/eaaeb68474ff194f682e9521a848d7ab2c89348e"/>
|
||||
<title>
|
||||
Fix conditions to publish packages in GitHub workflows
|
||||
</title>
|
||||
<updated>2024-03-10T19:25:13Z</updated>
|
||||
<media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/323546?s=30&v=4"/>
|
||||
<author>
|
||||
<name>fguillot</name>
|
||||
<uri>https://github.com/fguillot</uri>
|
||||
</author>
|
||||
<content type="html">
|
||||
<pre style='white-space:pre-wrap;width:81ex'>Fix conditions to publish packages in GitHub workflows</pre>
|
||||
</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>tag:github.com,2008:Grit::Commit/382885f14403526adfa6c303927889c76fd5a1eb</id>
|
||||
<link type="text/html" rel="alternate" href="https://github.com/miniflux/v2/commit/382885f14403526adfa6c303927889c76fd5a1eb"/>
|
||||
<title>
|
||||
Update changeLog
|
||||
</title>
|
||||
<updated>2024-03-10T17:50:47Z</updated>
|
||||
<media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/323546?s=30&v=4"/>
|
||||
<author>
|
||||
<name>fguillot</name>
|
||||
<uri>https://github.com/fguillot</uri>
|
||||
</author>
|
||||
<content type="html">
|
||||
<pre style='white-space:pre-wrap;width:81ex'>Update changeLog</pre>
|
||||
</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>tag:github.com,2008:Grit::Commit/0f7b047b0a81253b6d146e05d561545303016b74</id>
|
||||
<link type="text/html" rel="alternate" href="https://github.com/miniflux/v2/commit/0f7b047b0a81253b6d146e05d561545303016b74"/>
|
||||
<title>
|
||||
Bump github.com/go-jose/go-jose/v3 from 3.0.1 to 3.0.3
|
||||
</title>
|
||||
<updated>2024-03-08T04:59:42Z</updated>
|
||||
<media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/in/29110?s=30&v=4"/>
|
||||
<author>
|
||||
<name>dependabot</name>
|
||||
<uri>https://github.com/dependabot</uri>
|
||||
</author>
|
||||
<content type="html">
|
||||
<pre style='white-space:pre-wrap;width:81ex'>Bump github.com/go-jose/go-jose/v3 from 3.0.1 to 3.0.3
|
||||
|
||||
Bumps [github.com/go-jose/go-jose/v3](https://github.com/go-jose/go-jose) from 3.0.1 to 3.0.3.
|
||||
- [Release notes](https://github.com/go-jose/go-jose/releases)
|
||||
- [Changelog](https://github.com/go-jose/go-jose/blob/v3.0.3/CHANGELOG.md)
|
||||
- [Commits](https://github.com/go-jose/go-jose/compare/v3.0.1...v3.0.3)
|
||||
|
||||
---
|
||||
updated-dependencies:
|
||||
- dependency-name: github.com/go-jose/go-jose/v3
|
||||
dependency-type: indirect
|
||||
...
|
||||
|
||||
Signed-off-by: dependabot[bot] &lt;support@github.com&gt;</pre>
|
||||
</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>tag:github.com,2008:Grit::Commit/a074773e6c5d3b2066094cbac0502094aa364713</id>
|
||||
<link type="text/html" rel="alternate" href="https://github.com/miniflux/v2/commit/a074773e6c5d3b2066094cbac0502094aa364713"/>
|
||||
<title>
|
||||
Use an io.ReadSeeker instead of an io.Reader to parse feeds
|
||||
</title>
|
||||
<updated>2024-03-07T04:13:39Z</updated>
|
||||
<media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/325724?s=30&v=4"/>
|
||||
<author>
|
||||
<name>jvoisin</name>
|
||||
<uri>https://github.com/jvoisin</uri>
|
||||
</author>
|
||||
<content type="html">
|
||||
<pre style='white-space:pre-wrap;width:81ex'>Use an io.ReadSeeker instead of an io.Reader to parse feeds
|
||||
|
||||
This will allow to make use of func (*Reader) Seek, instead of re-recreating a
|
||||
new reader. It&#39;s a large commit for a small change, but anything to simply the
|
||||
reader/buffer/ReadAll/… mess is a step in the right direction I think, and it
|
||||
should enable more follow-up simplifications.</pre>
|
||||
</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>tag:github.com,2008:Grit::Commit/3d0126be0b8a603401b7593250f80b0a8042b995</id>
|
||||
<link type="text/html" rel="alternate" href="https://github.com/miniflux/v2/commit/3d0126be0b8a603401b7593250f80b0a8042b995"/>
|
||||
<title>
|
||||
Speed the sanitizer up a bit, again
|
||||
</title>
|
||||
<updated>2024-03-06T03:31:50Z</updated>
|
||||
<media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/325724?s=30&v=4"/>
|
||||
<author>
|
||||
<name>jvoisin</name>
|
||||
<uri>https://github.com/jvoisin</uri>
|
||||
</author>
|
||||
<content type="html">
|
||||
<pre style='white-space:pre-wrap;width:81ex'>Speed the sanitizer up a bit, again
|
||||
|
||||
- allow youtube urls to start with `www`
|
||||
- use `strings.Builder` instead of a `bytes.Buffer`
|
||||
- use a `strings.NewReader` instead of a `bytes.NewBufferString`
|
||||
- sprinkles a couple of `continue` to make the code-flow more obvious
|
||||
- inline calls to `inList`, and put their parameters in the right order
|
||||
- simplify isPixelTracker
|
||||
- simplify `isValidIframeSource`, by extracting the hostname and comparing it
|
||||
directly, instead of using the full url and checking if it starts with
|
||||
multiple variations of the same one (`//`, `http:`, `https://` multiplied by
|
||||
``/`www.`)
|
||||
- add a benchmark</pre>
|
||||
</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>tag:github.com,2008:Grit::Commit/eda2e2f3f5c278e44e2def72caedc33667a0fb6c</id>
|
||||
<link type="text/html" rel="alternate" href="https://github.com/miniflux/v2/commit/eda2e2f3f5c278e44e2def72caedc33667a0fb6c"/>
|
||||
<title>
|
||||
Bump golang.org/x/oauth2 from 0.17.0 to 0.18.0
|
||||
</title>
|
||||
<updated>2024-03-05T23:39:07Z</updated>
|
||||
<media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/in/29110?s=30&v=4"/>
|
||||
<author>
|
||||
<name>dependabot</name>
|
||||
<uri>https://github.com/dependabot</uri>
|
||||
</author>
|
||||
<content type="html">
|
||||
<pre style='white-space:pre-wrap;width:81ex'>Bump golang.org/x/oauth2 from 0.17.0 to 0.18.0
|
||||
|
||||
Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.17.0 to 0.18.0.
|
||||
- [Commits](https://github.com/golang/oauth2/compare/v0.17.0...v0.18.0)
|
||||
|
||||
---
|
||||
updated-dependencies:
|
||||
- dependency-name: golang.org/x/oauth2
|
||||
dependency-type: direct:production
|
||||
update-type: version-update:semver-minor
|
||||
...
|
||||
|
||||
Signed-off-by: dependabot[bot] &lt;support@github.com&gt;</pre>
|
||||
</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>tag:github.com,2008:Grit::Commit/111e3f2106646cd29f7f74c0102f2a570c598e2e</id>
|
||||
<link type="text/html" rel="alternate" href="https://github.com/miniflux/v2/commit/111e3f2106646cd29f7f74c0102f2a570c598e2e"/>
|
||||
<title>
|
||||
Reuse a Reader instead of copying to a buffer when parsing an atom feed
|
||||
</title>
|
||||
<updated>2024-03-05T01:36:10Z</updated>
|
||||
<media:thumbnail height="30" width="30" url="https://avatars.githubusercontent.com/u/325724?s=30&v=4"/>
|
||||
<author>
|
||||
<name>jvoisin</name>
|
||||
<uri>https://github.com/jvoisin</uri>
|
||||
</author>
|
||||
<content type="html">
|
||||
<pre style='white-space:pre-wrap;width:81ex'>Reuse a Reader instead of copying to a buffer when parsing an atom feed</pre>
|
||||
</content>
|
||||
</entry>
|
||||
</feed>
|
|
@ -69,7 +69,7 @@ func (f *SubscriptionFinder) FindSubscriptions(websiteURL, rssBridgeURL string)
|
|||
}
|
||||
|
||||
// Step 1) Check if the website URL is a feed.
|
||||
if feedFormat := parser.DetectFeedFormat(f.feedResponseInfo.Content); feedFormat != parser.FormatUnknown {
|
||||
if feedFormat, _ := parser.DetectFeedFormat(f.feedResponseInfo.Content); feedFormat != parser.FormatUnknown {
|
||||
f.feedDownloaded = true
|
||||
return Subscriptions{NewSubscription(responseHandler.EffectiveURL(), responseHandler.EffectiveURL(), feedFormat)}, nil
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue