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... }