-
Notifications
You must be signed in to change notification settings - Fork 108
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extract the table of contents from an LCP-protected PDF (#480)
- Loading branch information
1 parent
3ecc6fa
commit 60aa620
Showing
10 changed files
with
165 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
Sources/Shared/Publication/Services/Table Of Contents/TableOfContentsService.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// | ||
// Copyright 2024 Readium Foundation. All rights reserved. | ||
// Use of this source code is governed by the BSD-style license | ||
// available in the top-level LICENSE file of the project. | ||
// | ||
|
||
import Foundation | ||
|
||
public typealias TableOfContentsServiceFactory = (PublicationServiceContext) -> TableOfContentsService? | ||
|
||
/// Returns or computes a table of contents for the publication. | ||
public protocol TableOfContentsService: PublicationService { | ||
func tableOfContents() async -> ReadResult<[Link]> | ||
} | ||
|
||
// MARK: Publication Helpers | ||
|
||
public extension Publication { | ||
/// Returns the table of contents for this publication. | ||
func tableOfContents() async -> ReadResult<[Link]> { | ||
if let service = findService(TableOfContentsService.self) { | ||
return await service.tableOfContents() | ||
} else { | ||
return .success(manifest.tableOfContents) | ||
} | ||
} | ||
} | ||
|
||
// MARK: PublicationServicesBuilder Helpers | ||
|
||
public extension PublicationServicesBuilder { | ||
mutating func setTableOfContentsServiceFactory(_ factory: TableOfContentsServiceFactory?) { | ||
if let factory = factory { | ||
set(TableOfContentsService.self, factory) | ||
} else { | ||
remove(TableOfContentsService.self) | ||
} | ||
} | ||
} |
62 changes: 62 additions & 0 deletions
62
Sources/Streamer/Parser/PDF/Services/LCPDFTableOfContentsService.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// | ||
// Copyright 2024 Readium Foundation. All rights reserved. | ||
// Use of this source code is governed by the BSD-style license | ||
// available in the top-level LICENSE file of the project. | ||
// | ||
|
||
import Foundation | ||
import ReadiumInternal | ||
import ReadiumShared | ||
|
||
/// This ``TableOfContentsService`` will load the table of contents of the | ||
/// single PDF resource in an LCPDF package, if the table of contents is missing | ||
/// from the `manifest.json` file. | ||
final class LCPDFTableOfContentsService: TableOfContentsService, PDFPublicationService, Loggable { | ||
private let manifest: Manifest | ||
private let container: Container | ||
var pdfFactory: PDFDocumentFactory | ||
|
||
init( | ||
manifest: Manifest, | ||
container: Container, | ||
pdfFactory: PDFDocumentFactory | ||
) { | ||
self.manifest = manifest | ||
self.container = container | ||
self.pdfFactory = pdfFactory | ||
} | ||
|
||
func tableOfContents() async -> ReadResult<[Link]> { | ||
await _tableOfContents() | ||
} | ||
|
||
private lazy var _tableOfContents = memoize(makeTableOfContents) | ||
|
||
private func makeTableOfContents() async -> ReadResult<[Link]> { | ||
guard | ||
manifest.tableOfContents.isEmpty, | ||
manifest.readingOrder.count == 1, | ||
let url = manifest.readingOrder.first?.url(), | ||
let resource = container[url] | ||
else { | ||
return .success(manifest.tableOfContents) | ||
} | ||
|
||
do { | ||
let toc = try await pdfFactory.open(resource: resource, at: url, password: nil).tableOfContents() | ||
return .success(toc.linksWithDocumentHREF(url)) | ||
} catch { | ||
return .failure(.decoding(error)) | ||
} | ||
} | ||
|
||
static func makeFactory(pdfFactory: PDFDocumentFactory) -> (PublicationServiceContext) -> LCPDFTableOfContentsService? { | ||
{ context in | ||
LCPDFTableOfContentsService( | ||
manifest: context.manifest, | ||
container: context.container, | ||
pdfFactory: pdfFactory | ||
) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters