Skip to content

Commit

Permalink
Merge pull request #11 from grahamburgsma/master
Browse files Browse the repository at this point in the history
Version 4
  • Loading branch information
jdmcd authored May 13, 2020
2 parents 48b4819 + fc9cba3 commit e29131d
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 24 deletions.
26 changes: 14 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<Response> {
// Create document. Margins in mm, can be set individually or all at once.
func pdf(_ req: Request) -> EventLoopFuture<Response> {
// 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("<p>Page from direct HTML</p>")

// 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)
Expand Down
3 changes: 1 addition & 2 deletions Sources/wkhtmltopdf/Document+Generate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import NIO

extension Document {

public func generatePDF(on threadPool: NIOThreadPool = NIOThreadPool(numberOfThreads: 1), eventLoop: EventLoop) throws -> EventLoopFuture<Data> {
threadPool.start()
public func generatePDF(on threadPool: NIOThreadPool, eventLoop: EventLoop) -> EventLoopFuture<Data> {
return threadPool.runIfActive(eventLoop: eventLoop) {
let fileManager = FileManager.default

Expand Down
27 changes: 18 additions & 9 deletions Sources/wkhtmltopdf/Document.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
5 changes: 5 additions & 0 deletions Sources/wkhtmltopdf/Page.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Foundation
import NIO

public struct Page {
let content: Data
Expand All @@ -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)
}
Expand Down
5 changes: 4 additions & 1 deletion Tests/wkhtmltopdfTests/wkhtmltopdfTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ class wkhtmltopdfTests: XCTestCase {
let document = Document(margins: 15)
let page1 = Page("<p>Page from direct HTML</p>")
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
Expand Down

0 comments on commit e29131d

Please sign in to comment.