diff --git a/Sources/OPDS/OPDS1Parser.swift b/Sources/OPDS/OPDS1Parser.swift
index 92cd83a7a..6666d1a77 100644
--- a/Sources/OPDS/OPDS1Parser.swift
+++ b/Sources/OPDS/OPDS1Parser.swift
@@ -105,6 +105,13 @@ public class OPDS1Parser: Loggable {
feed.metadata.itemsPerPage = Int(itemsPerPage)
}
+ if let iconValue = root.firstChild(tag: "icon")?.stringValue,
+ let href = URLHelper.getAbsolute(href: iconValue, base: feedURL)
+ {
+ let iconLink = Link(href: href, rel: .icon)
+ feed.links.append(iconLink)
+ }
+
for entry in root.children(tag: "entry") {
var isNavigation = true
var collectionLink: Link?
diff --git a/Sources/Shared/Publication/LinkRelation.swift b/Sources/Shared/Publication/LinkRelation.swift
index 1b9999d7e..a6f70b86a 100644
--- a/Sources/Shared/Publication/LinkRelation.swift
+++ b/Sources/Shared/Publication/LinkRelation.swift
@@ -68,6 +68,8 @@ public struct LinkRelation: Sendable {
public static let next = LinkRelation("next")
/// Refers to a resource that provides a preview of the link's context.
public static let preview = LinkRelation("preview")
+ /// Refers to an icon representing the link's context.
+ public static let icon = LinkRelation("icon")
// OPDS – https://specs.opds.io/opds-1.2.html
diff --git a/Tests/OPDSTests/Samples/wiki_1_1.opds b/Tests/OPDSTests/Samples/wiki_1_1.opds
index 76f99626f..e92f52d04 100644
--- a/Tests/OPDSTests/Samples/wiki_1_1.opds
+++ b/Tests/OPDSTests/Samples/wiki_1_1.opds
@@ -18,6 +18,7 @@
type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
Unpopular Publications
+ /images/favicon.ico?t=1516986276
2010-01-10T10:01:11Z
Spec Writer
diff --git a/Tests/OPDSTests/readium_opds1_1_test.swift b/Tests/OPDSTests/readium_opds1_1_test.swift
index a79a345e8..a35832621 100644
--- a/Tests/OPDSTests/readium_opds1_1_test.swift
+++ b/Tests/OPDSTests/readium_opds1_1_test.swift
@@ -51,10 +51,52 @@ class readium_opds1_1_test: XCTestCase {
}
func testLinks() {
- XCTAssertEqual(feed.links.count, 4)
- XCTAssertEqual(feed.links[0].rels, ["related"])
- XCTAssertEqual(feed.links[1].mediaType, MediaType("application/atom+xml;profile=opds-catalog;kind=acquisition")!)
- XCTAssertEqual(feed.links[2].href, "http://test.com/opds-catalogs/root.xml")
+ XCTAssertEqual(feed.links.count, 5)
+
+ // Has a "related" link
+ let expectedRelatedLink = Link(
+ href: "http://test.com/opds-catalogs/vampire.farming.xml",
+ mediaType: MediaType("application/atom+xml;profile=opds-catalog;kind=acquisition")!,
+ rels: ["related"]
+ )
+ let relatedLink = feed?.links.first { $0.rels.contains("related") }
+ XCTAssertEqual(relatedLink, expectedRelatedLink)
+
+ // Has a "self" link
+ let expectedSelfLink = Link(
+ href: "http://test.com/opds-catalogs/unpopular.xml",
+ mediaType: MediaType("application/atom+xml;profile=opds-catalog;kind=acquisition")!,
+ rels: ["self"]
+ )
+ let selfLink = feed?.links.first { $0.rels.contains("self") }
+ XCTAssertEqual(selfLink, expectedSelfLink)
+
+ // Has a "start" link
+ let expectedStartLink = Link(
+ href: "http://test.com/opds-catalogs/root.xml",
+ mediaType: MediaType("application/atom+xml;profile=opds-catalog;kind=navigation")!,
+ rels: ["start"]
+ )
+ let startLink = feed?.links.first { $0.rels.contains("start") }
+ XCTAssertEqual(startLink, expectedStartLink)
+
+ // Has an "up" link
+ let expectedUpLink = Link(
+ href: "http://test.com/opds-catalogs/root.xml",
+ mediaType: MediaType("application/atom+xml;profile=opds-catalog;kind=navigation")!,
+ rels: ["up"]
+ )
+ let upLink = feed?.links.first { $0.rels.contains("up") }
+ XCTAssertEqual(upLink, expectedUpLink)
+
+ // Has an "icon" link
+ let expectedIconLink = Link(
+ href: "http://test.com/images/favicon.ico?t=1516986276",
+ rels: ["icon"]
+ )
+ let iconLink = feed?.links.first { $0.rels.contains("icon") }
+ XCTAssertEqual(iconLink, expectedIconLink)
+
// TODO: add more tests...
}