diff --git a/README.md b/README.md index 00511a0..7c454c5 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Vapor 4 library for converting HTML (Leaf or otherwise) into PDF files using Add the following in your `Package.swift` file ```Swift -.package(url: "https://github.com/vapor-community/wkhtmltopdf.git", from: "3.0.0"), +.package(url: "https://github.com/vapor-community/wkhtmltopdf.git", from: "4.0.0"), ``` ## 📘 Overview @@ -22,37 +22,39 @@ in the `Document` initialiser. The default is `/usr/local/bin/wkhtmltopdf`. Run it to ensure it and any dependencies are installed correctly. To create a PDF, create and configure a `Document`, add one or more `Page`s, -and then call `generatePDF(on: Request)`. Here is a full example: +and then call `generatePDF(on: threadPool, eventLoop: eventLoop)`. Here is a full example using Vapor: ```Swift import wkhtmltopdf -func pdf(_ req: Request) -> Future { - // Create document. Margins in mm, can be set individually or all at once. +func pdf(_ req: Request) -> EventLoopFuture { + // Create document. Margins in mm, can be set individually or all at once. // If no margins are set, the default is 20mm. let document = Document(margins: 15) // Create a page from an HTML string. let page1 = Page("

Page from direct HTML

") // Create a page from a Leaf template. - let page2 = try req.view().render("page_from_leaf_template") + let page2 = req.view.render("page_from_leaf_template") // Create a page from a Leaf template with Context variables. - let page3 = try req.view().render("page_from_leaf_template", [ "firstName": "Peter", - "lastName": "Pan"]) - let pages = [ page2, page3].flatten(on: req) + let context = ["firstName": "Peter", "lastName": "Pan"] + let page3 = req.view.render("page_from_leaf_template", context) + + let pages = [ page2, page3] + .flatten(on: req.eventLoop) .map { views in - return views.map { Page($0.data) } + views.map { Page($0.data) } } return pages.flatMap { pages in // Add the pages to the document document.pages = [page1] + pages // Render to a PDF - let pdf = try document.generatePDF(eventLoop: req.eventLoop) + let pdf = document.generatePDF(on: req.application.threadPool, eventLoop: req.eventLoop) // Now you can return the PDF as a response, if you want - return pdf.map { data -> Response in - return HTTPResponse( + return pdf.map { data in + return Response( status: .ok, headers: HTTPHeaders([("Content-Type", "application/pdf")]), body: .init(data: data) diff --git a/Sources/wkhtmltopdf/Document+Generate.swift b/Sources/wkhtmltopdf/Document+Generate.swift index cbbae26..4ad2c62 100644 --- a/Sources/wkhtmltopdf/Document+Generate.swift +++ b/Sources/wkhtmltopdf/Document+Generate.swift @@ -3,8 +3,7 @@ import NIO extension Document { - public func generatePDF(on threadPool: NIOThreadPool = NIOThreadPool(numberOfThreads: 1), eventLoop: EventLoop) throws -> EventLoopFuture { - threadPool.start() + public func generatePDF(on threadPool: NIOThreadPool, eventLoop: EventLoop) -> EventLoopFuture { return threadPool.runIfActive(eventLoop: eventLoop) { let fileManager = FileManager.default diff --git a/Sources/wkhtmltopdf/Document.swift b/Sources/wkhtmltopdf/Document.swift index fdd0541..7b3c832 100644 --- a/Sources/wkhtmltopdf/Document.swift +++ b/Sources/wkhtmltopdf/Document.swift @@ -16,17 +16,26 @@ public class Document { let wkArgs: [String] public var pages: [Page] = [] - - public init(size: String = "A4", zoom: String? = nil, margins all: Int? = nil, top: Int? = nil, right: Int? = nil, bottom: Int? = nil, left: Int? = nil, path: String = "/usr/local/bin/wkhtmltopdf", wkArgs: [String]? = nil) { - self.zoom = zoom ?? "1.3" + + public init(size: String = "A4", zoom: String = "1.3", margins: Int = 20, path: String = "/usr/local/bin/wkhtmltopdf", wkArgs: [String] = []) { + self.zoom = zoom self.paperSize = size - self.topMargin = all ?? top ?? 20 - self.rightMargin = all ?? right ?? 20 - self.bottomMargin = all ?? bottom ?? 20 - self.leftMargin = all ?? left ?? 20 + self.topMargin = margins + self.rightMargin = margins + self.bottomMargin = margins + self.leftMargin = margins self.launchPath = path - - self.wkArgs = wkArgs ?? [] + self.wkArgs = wkArgs } + public init(size: String = "A4", zoom: String = "1.3", top: Int = 20, right: Int = 20, bottom: Int = 20, left: Int = 20, path: String = "/usr/local/bin/wkhtmltopdf", wkArgs: [String] = []) { + self.zoom = zoom + self.paperSize = size + self.topMargin = top + self.rightMargin = right + self.bottomMargin = bottom + self.leftMargin = left + self.launchPath = path + self.wkArgs = wkArgs + } } diff --git a/Sources/wkhtmltopdf/Page.swift b/Sources/wkhtmltopdf/Page.swift index d05d38c..3d97e80 100644 --- a/Sources/wkhtmltopdf/Page.swift +++ b/Sources/wkhtmltopdf/Page.swift @@ -1,4 +1,5 @@ import Foundation +import NIO public struct Page { let content: Data @@ -7,6 +8,10 @@ public struct Page { self.content = content } + public init(_ content: ByteBuffer) { + self.content = Data(content.readableBytesView) + } + public init(_ content: String) { self.content = Data(content.utf8) } diff --git a/Tests/wkhtmltopdfTests/wkhtmltopdfTests.swift b/Tests/wkhtmltopdfTests/wkhtmltopdfTests.swift index 261e9f6..97744cc 100644 --- a/Tests/wkhtmltopdfTests/wkhtmltopdfTests.swift +++ b/Tests/wkhtmltopdfTests/wkhtmltopdfTests.swift @@ -24,7 +24,10 @@ class wkhtmltopdfTests: XCTestCase { let document = Document(margins: 15) let page1 = Page("

Page from direct HTML

") document.pages = [page1] - let data = try document.generatePDF(eventLoop: eventLoop).wait() + let threadPool = NIOThreadPool(numberOfThreads: 1) + threadPool.start() + let data = try document.generatePDF(on: threadPool, eventLoop: eventLoop).wait() + try threadPool.syncShutdownGracefully() // Cop-out test, just ensuring that the returned data is something XCTAssert(data.count > 50) // Visual test