-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Created first version of wkhtmltoimage
- Loading branch information
1 parent
ac3f7f3
commit 06e8323
Showing
3 changed files
with
227 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package io.github.cloudify.scala.spdf | ||
|
||
import scala.sys.process._ | ||
import java.io.File | ||
|
||
class Image(executablePath: String, config: ImageConfig) { | ||
validateExecutable_!(executablePath) | ||
|
||
/** | ||
* Runs the conversion tool to convert sourceDocument HTML into | ||
* destinationDocument image. | ||
*/ | ||
def run[A, B](sourceDocument: A, destinationDocument: B)(implicit sourceDocumentLike: SourceDocumentLike[A], destinationDocumentLike: DestinationDocumentLike[B]): Int = { | ||
val commandLine = toCommandLine(sourceDocument, destinationDocument) | ||
val process = Process(commandLine) | ||
def source = sourceDocumentLike.sourceFrom(sourceDocument) _ | ||
def sink = destinationDocumentLike.sinkTo(destinationDocument) _ | ||
|
||
(sink compose source)(process).! | ||
} | ||
|
||
/** | ||
* Generates the command line needed to execute `wkhtmltoimage` | ||
*/ | ||
private def toCommandLine[A: SourceDocumentLike, B: DestinationDocumentLike](source: A, destination: B): Seq[String] = | ||
Seq(executablePath) ++ | ||
ImageConfig.toParameters(config) ++ | ||
Seq( | ||
implicitly[SourceDocumentLike[A]].commandParameter(source), | ||
implicitly[DestinationDocumentLike[B]].commandParameter(destination) | ||
) | ||
|
||
/** | ||
* Check whether the executable is actually executable, if it isn't | ||
* a NoExecutableException is thrown. | ||
*/ | ||
private def validateExecutable_!(executablePath: String): Unit = { | ||
val executableFile = new File(executablePath) | ||
if(!executableFile.canExecute) throw new NoExecutableException(executableFile.getAbsolutePath) | ||
} | ||
|
||
} | ||
|
||
object Image { | ||
|
||
/** | ||
* Creates a new instance of Image with default configuration | ||
* @return | ||
*/ | ||
def apply(config: ImageConfig): Image = { | ||
val executablePath: String = ImageConfig.findExecutable.getOrElse { | ||
throw new NoExecutableException(System.getenv("PATH")) | ||
} | ||
|
||
apply(executablePath, config) | ||
} | ||
|
||
/** | ||
* Creates a new instance of Image with the passed configuration | ||
*/ | ||
def apply(executablePath: String, config: ImageConfig): Image = | ||
new Image(executablePath, config) | ||
|
||
} |
112 changes: 112 additions & 0 deletions
112
src/main/scala/io/github/cloudify/scala.spdf/ImageConfig.scala
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,112 @@ | ||
package io.github.cloudify.scala.spdf | ||
|
||
import scala.sys.process._ | ||
import ParamShow._ | ||
|
||
/** | ||
* Holds the configuration parameters of Pdf Kit | ||
*/ | ||
trait ImageConfig extends PdfConfig | ||
|
||
object ImageConfig { | ||
|
||
/** | ||
* An instance of the default configuration | ||
*/ | ||
object default extends ImageConfig | ||
|
||
/** | ||
* Generates a sequence of command line parameters from a `PdfKitConfig` | ||
*/ | ||
def toParameters(config: ImageConfig): Seq[String] = { | ||
import config._ | ||
Seq( | ||
allow.toParameter, | ||
background.toParameter, | ||
defaultHeader.toParameter, | ||
disableExternalLinks.toParameter, | ||
disableInternalLinks.toParameter, | ||
disableJavascript.toParameter, | ||
noPdfCompression.toParameter, | ||
disableSmartShrinking.toParameter, | ||
javascriptDelay.toParameter, | ||
enableForms.toParameter, | ||
encoding.toParameter, | ||
footerCenter.toParameter, | ||
footerFontName.toParameter, | ||
footerFontSize.toParameter, | ||
footerHtml.toParameter, | ||
footerLeft.toParameter, | ||
footerLine.toParameter, | ||
footerRight.toParameter, | ||
footerSpacing.toParameter, | ||
grayScale.toParameter, | ||
headerCenter.toParameter, | ||
headerFontName.toParameter, | ||
headerFontSize.toParameter, | ||
headerHtml.toParameter, | ||
headerLeft.toParameter, | ||
headerLine.toParameter, | ||
headerRight.toParameter, | ||
headerSpacing.toParameter, | ||
lowQuality.toParameter, | ||
marginBottom.toParameter, | ||
marginLeft.toParameter, | ||
marginRight.toParameter, | ||
marginTop.toParameter, | ||
minimumFontSize.toParameter, | ||
orientation.toParameter, | ||
outline.toParameter, | ||
outlineDepth.toParameter, | ||
pageHeight.toParameter, | ||
pageOffset.toParameter, | ||
pageSize.toParameter, | ||
pageWidth.toParameter, | ||
password.toParameter, | ||
printMediaType.toParameter, | ||
tableOfContent.toParameter, | ||
tableOfContentDepth.toParameter, | ||
tableOfContentDisableBackLinks.toParameter, | ||
tableOfContentDisableLinks.toParameter, | ||
tableOfContentFontName.toParameter, | ||
tableOfContentHeaderFontName.toParameter, | ||
tableOfContentHeaderFontSize.toParameter, | ||
tableOfContentHeaderText.toParameter, | ||
tableOfContentLevel1FontSize.toParameter, | ||
tableOfContentLevel1Indentation.toParameter, | ||
tableOfContentLevel2FontSize.toParameter, | ||
tableOfContentLevel2Indentation.toParameter, | ||
tableOfContentLevel3FontSize.toParameter, | ||
tableOfContentLevel3Indentation.toParameter, | ||
tableOfContentLevel4FontSize.toParameter, | ||
tableOfContentLevel4Indentation.toParameter, | ||
tableOfContentLevel5FontSize.toParameter, | ||
tableOfContentLevel5Indentation.toParameter, | ||
tableOfContentLevel6FontSize.toParameter, | ||
tableOfContentLevel6Indentation.toParameter, | ||
tableOfContentLevel7FontSize.toParameter, | ||
tableOfContentLevel7Indentation.toParameter, | ||
tableOfContentNoDots.toParameter, | ||
title.toParameter, | ||
userStyleSheet.toParameter, | ||
username.toParameter, | ||
useXServer.toParameter, | ||
viewportSize.toParameter, | ||
zoom.toParameter | ||
).flatten | ||
} | ||
|
||
/** | ||
* Attempts to find the `wkhtmltoimage` executable in the system path. | ||
* @return | ||
*/ | ||
def findExecutable: Option[String] = try { | ||
val os = System.getProperty("os.name").toLowerCase | ||
val cmd = if(os.contains("windows")) "where wkhtmltoimage" else "which wkhtmltoimage" | ||
|
||
Option(cmd.!!.trim).filter(_.nonEmpty) | ||
} catch { | ||
case _: RuntimeException => None | ||
} | ||
|
||
} |
51 changes: 51 additions & 0 deletions
51
src/test/scala/io/github/cloudify/scala/spdf/ImageSpec.scala
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,51 @@ | ||
package io.github.cloudify.scala.spdf | ||
|
||
import java.io.File | ||
import scala.sys.process._ | ||
import org.scalatest.Matchers | ||
import org.scalatest.WordSpec | ||
|
||
class ImageSpec extends WordSpec with Matchers { | ||
|
||
"An Image" should { | ||
|
||
"require the executionPath config" in { | ||
val file = new File("notexecutable") | ||
val filePath = file.getAbsolutePath | ||
|
||
assertThrows[NoExecutableException] { | ||
new Image(filePath, ImageConfig.default) | ||
} | ||
|
||
assertThrows[NoExecutableException] { | ||
Image(filePath, ImageConfig.default) | ||
} | ||
|
||
} | ||
|
||
PdfConfig.findExecutable match { | ||
case Some(_) => | ||
"generate an image file from an HTML string" in { | ||
|
||
val page = | ||
""" | ||
|<html><body><h1>Hello</h1></body></html> | ||
""".stripMargin | ||
|
||
val file = File.createTempFile("scala.spdf", "pdf") | ||
|
||
val image = Image(ImageConfig.default) | ||
|
||
image.run(page, file) | ||
|
||
Seq("file", file.getAbsolutePath).!! should include("PDF document") | ||
} | ||
|
||
case None => | ||
"Skipping test, missing wkhtmltopdf binary" in { true should equal(true) } | ||
} | ||
|
||
|
||
} | ||
|
||
} |