packages feed

yesod-content-pdf 0.1.0.2 → 0.2.0.0

raw patch · 2 files changed

+168/−34 lines, 2 filesdep +data-defaultdep +transformersPVP ok

version bump matches the API change (PVP)

Dependencies added: data-default, transformers

API changes (from Hackage documentation)

+ Yesod.Content.PDF: A4 :: PageSize
+ Yesod.Content.PDF: Cm :: Double -> UnitReal
+ Yesod.Content.PDF: CustomPageSize :: UnitReal -> UnitReal -> PageSize
+ Yesod.Content.PDF: Landscape :: Orientation
+ Yesod.Content.PDF: Letter :: PageSize
+ Yesod.Content.PDF: Mm :: Double -> UnitReal
+ Yesod.Content.PDF: OtherPageSize :: String -> PageSize
+ Yesod.Content.PDF: OtherUnitReal :: String -> UnitReal
+ Yesod.Content.PDF: Portrait :: Orientation
+ Yesod.Content.PDF: data Orientation
+ Yesod.Content.PDF: data PageSize
+ Yesod.Content.PDF: data UnitReal
+ Yesod.Content.PDF: data WkhtmltopdfOptions
+ Yesod.Content.PDF: def :: Default a => a
+ Yesod.Content.PDF: instance Data.Default.Class.Default Yesod.Content.PDF.WkhtmltopdfOptions
+ Yesod.Content.PDF: instance GHC.Classes.Eq Yesod.Content.PDF.Orientation
+ Yesod.Content.PDF: instance GHC.Classes.Eq Yesod.Content.PDF.PageSize
+ Yesod.Content.PDF: instance GHC.Classes.Eq Yesod.Content.PDF.UnitReal
+ Yesod.Content.PDF: instance GHC.Classes.Eq Yesod.Content.PDF.WkhtmltopdfOptions
+ Yesod.Content.PDF: instance GHC.Classes.Ord Yesod.Content.PDF.Orientation
+ Yesod.Content.PDF: instance GHC.Classes.Ord Yesod.Content.PDF.PageSize
+ Yesod.Content.PDF: instance GHC.Classes.Ord Yesod.Content.PDF.UnitReal
+ Yesod.Content.PDF: instance GHC.Classes.Ord Yesod.Content.PDF.WkhtmltopdfOptions
+ Yesod.Content.PDF: instance GHC.Enum.Bounded Yesod.Content.PDF.Orientation
+ Yesod.Content.PDF: instance GHC.Enum.Enum Yesod.Content.PDF.Orientation
+ Yesod.Content.PDF: instance GHC.Show.Show Yesod.Content.PDF.Orientation
+ Yesod.Content.PDF: instance GHC.Show.Show Yesod.Content.PDF.PageSize
+ Yesod.Content.PDF: instance GHC.Show.Show Yesod.Content.PDF.UnitReal
+ Yesod.Content.PDF: instance GHC.Show.Show Yesod.Content.PDF.WkhtmltopdfOptions
+ Yesod.Content.PDF: instance Yesod.Content.PDF.ToArgs Yesod.Content.PDF.Orientation
+ Yesod.Content.PDF: instance Yesod.Content.PDF.ToArgs Yesod.Content.PDF.PageSize
+ Yesod.Content.PDF: instance Yesod.Content.PDF.ToArgs Yesod.Content.PDF.UnitReal
+ Yesod.Content.PDF: instance Yesod.Content.PDF.ToArgs Yesod.Content.PDF.WkhtmltopdfOptions
+ Yesod.Content.PDF: wkCollate :: WkhtmltopdfOptions -> Bool
+ Yesod.Content.PDF: wkCopies :: WkhtmltopdfOptions -> Int
+ Yesod.Content.PDF: wkGrayscale :: WkhtmltopdfOptions -> Bool
+ Yesod.Content.PDF: wkLowQuality :: WkhtmltopdfOptions -> Bool
+ Yesod.Content.PDF: wkMarginBottom :: WkhtmltopdfOptions -> UnitReal
+ Yesod.Content.PDF: wkMarginLeft :: WkhtmltopdfOptions -> UnitReal
+ Yesod.Content.PDF: wkMarginRight :: WkhtmltopdfOptions -> UnitReal
+ Yesod.Content.PDF: wkMarginTop :: WkhtmltopdfOptions -> UnitReal
+ Yesod.Content.PDF: wkOrientation :: WkhtmltopdfOptions -> Orientation
+ Yesod.Content.PDF: wkPageSize :: WkhtmltopdfOptions -> PageSize
+ Yesod.Content.PDF: wkTitle :: WkhtmltopdfOptions -> Maybe String
+ Yesod.Content.PDF: wkZoom :: WkhtmltopdfOptions -> Double
- Yesod.Content.PDF: html2PDF :: Html -> IO PDF
+ Yesod.Content.PDF: html2PDF :: MonadIO m => WkhtmltopdfOptions -> Html -> m PDF
- Yesod.Content.PDF: uri2PDF :: URI -> IO PDF
+ Yesod.Content.PDF: uri2PDF :: MonadIO m => WkhtmltopdfOptions -> URI -> m PDF

Files

src/Yesod/Content/PDF.hs view
@@ -1,22 +1,49 @@--- | Utilities for serving PDF from Yesod---   Uses and depends on command line utility wkhtmltopdf to render PDF from HTML+-- | Utilities for serving PDF from Yesod.+--   Uses and depends on command line utility wkhtmltopdf to render PDF from HTML.+module Yesod.Content.PDF+  ( -- * Conversion+    uri2PDF+  , html2PDF+    -- * Data type+  , PDF(..)+  , typePDF+    -- * Options+  , def+  , WkhtmltopdfOptions+  , wkCollate+  , wkCopies+  , wkGrayscale+  , wkLowQuality+  , wkPageSize+  , wkOrientation+  , wkTitle+  , wkMarginBottom+  , wkMarginLeft+  , wkMarginRight+  , wkMarginTop+  , wkZoom+  , PageSize(..)+  , Orientation(..)+  , UnitReal(..)+  ) where -module Yesod.Content.PDF where import Prelude-import Yesod.Core.Content+import Blaze.ByteString.Builder.ByteString+import Control.Monad.IO.Class (MonadIO(..)) import Data.ByteString+import Data.Conduit+import Data.Default (Default(..))+import Network.URI+import System.IO+import System.IO.Temp+import System.Process import Text.Blaze.Html import Text.Blaze.Html.Renderer.String-import Blaze.ByteString.Builder.ByteString-import System.Process-import System.IO.Temp-import System.IO-import Network.URI-import Data.Conduit+import Yesod.Core.Content  newtype PDF = PDF ByteString --- | Provide MIME type "application/pdf" as a ContentType for Yesod+-- | Provide MIME type "application/pdf" as a ContentType for Yesod. typePDF :: ContentType typePDF = "application/pdf" @@ -30,27 +57,132 @@   toContent (PDF bs) = ContentSource $ do     yield $ Chunk $ fromByteString bs --- | Use wkhtmltopdf to render a PDF given the URI pointing to an HTML document-uri2PDF :: URI -> IO PDF-uri2PDF uri = withSystemTempFile "output.pdf" $ uri2PDF' uri-  where-    uri2PDF' :: URI -> FilePath -> Handle -> IO PDF-    uri2PDF' uri' tempPDFFile tempHandle = do-      hClose tempHandle-      (_,_,_, pHandle) <- createProcess (proc "wkhtmltopdf" ["--quiet", show uri', tempPDFFile])+-- | Use wkhtmltopdf to render a PDF given the URI pointing to an HTML document.+uri2PDF :: MonadIO m => WkhtmltopdfOptions -> URI -> m PDF+uri2PDF opts = wkhtmltopdf opts . flip ($) . show++-- | Use wkhtmltopdf to render a PDF from an HTML (Text.Blaze.Html) type.+html2PDF :: MonadIO m => WkhtmltopdfOptions -> Html -> m PDF+html2PDF opts html =+  wkhtmltopdf opts $ \inner ->+  withSystemTempFile "input.html" $ \tempHtmlFp tempHtmlHandle -> do+    System.IO.hPutStrLn tempHtmlHandle $ renderHtml html+    hClose tempHtmlHandle+    inner tempHtmlFp++-- | (Internal) Call wkhtmltopdf.+wkhtmltopdf :: MonadIO m => WkhtmltopdfOptions -> ((String -> IO PDF) -> IO PDF) -> m PDF+wkhtmltopdf opts setupInput =+  liftIO $+  withSystemTempFile "output.pdf" $ \tempOutputFp tempOutputHandle -> do+    hClose tempOutputHandle+    setupInput $ \inputArg -> do+      let args = toArgs opts ++ [inputArg, tempOutputFp]+      (_, _, _, pHandle) <- createProcess (proc "wkhtmltopdf" args)       _ <- waitForProcess pHandle-      PDF <$> Data.ByteString.readFile tempPDFFile+      PDF <$> Data.ByteString.readFile tempOutputFp --- | Use wkhtmltopdf to render a PDF from an HTML (Text.Blaze.Html) type-html2PDF :: Html -> IO PDF-html2PDF html = withSystemTempFile "output.pdf" (html2PDF' html)-  where-    html2PDF' :: Html -> FilePath -> Handle -> IO PDF-    html2PDF' html' tempPDFFile tempPDFHandle = do-      hClose tempPDFHandle-      withSystemTempFile "input.html" $ \tempHtmlFile tempHtmlHandle -> do-        System.IO.hPutStrLn tempHtmlHandle $ renderHtml html'-        hClose tempHtmlHandle-        (_,_,_, pHandle) <- createProcess (proc "wkhtmltopdf" ["--quiet", tempHtmlFile, tempPDFFile])-        _ <- waitForProcess pHandle-        PDF <$> Data.ByteString.readFile tempPDFFile+-- | Options passed to wkhtmltopdf.  Please use the 'def' value+-- and then modify individual settings. For more information, see+-- <http://www.yesodweb.com/book/settings-types>.+data WkhtmltopdfOptions =+  WkhtmltopdfOptions+    { wkCollate         :: Bool+      -- ^ Collate when printing multiple copies.+    , wkCopies          :: Int+      -- ^ Number of copies to print into the PDF file.+    , wkGrayscale       :: Bool+      -- ^ Whether output PDF should be in grayscale.+    , wkLowQuality      :: Bool+      -- ^ Generate lower quality output to conserve space.+    , wkPageSize        :: PageSize+      -- ^ Page size (e.g. "A4", "Letter").+    , wkOrientation     :: Orientation+      -- ^ Orientation of the output.+    , wkTitle           :: Maybe String+      -- ^ Title of the generated PDF file.+    , wkMarginBottom    :: UnitReal+      -- ^ Bottom margin size.+    , wkMarginLeft      :: UnitReal+      -- ^ Left margin size.+    , wkMarginRight     :: UnitReal+      -- ^ Right margin size.+    , wkMarginTop       :: UnitReal+      -- ^ Top margin size.+    , wkZoom            :: Double+      -- ^ Zoom factor.+    } deriving (Eq, Ord, Show)++instance Default WkhtmltopdfOptions where+  def = WkhtmltopdfOptions+    { wkCollate         = True+    , wkCopies          = 1+    , wkGrayscale       = False+    , wkLowQuality      = False+    , wkPageSize        = A4+    , wkOrientation     = Portrait+    , wkTitle           = Nothing+    , wkMarginBottom    = Mm 10+    , wkMarginLeft      = Mm 0+    , wkMarginRight     = Mm 0+    , wkMarginTop       = Mm 10+    , wkZoom            = 1+    }++-- | Cf. 'wkPageSize'.+data PageSize =+    A4+  | Letter+  | OtherPageSize String -- ^ <http://doc.qt.io/qt-4.8/qprinter.html#PaperSize-enum>.+  | CustomPageSize UnitReal UnitReal -- ^ Height and width.+  deriving (Eq, Ord, Show)++-- | Cf. 'wkOrientation'.+data Orientation =+    Portrait+  | Landscape+  deriving (Eq, Ord, Show, Enum, Bounded)++-- | A unit of measure.+data UnitReal =+    Mm Double+  | Cm Double+  | OtherUnitReal String+  deriving (Eq, Ord, Show)++-- | (Internal) Convert options to arguments.+class ToArgs a where+  toArgs :: a -> [String]++instance ToArgs WkhtmltopdfOptions where+  toArgs opts =+      [ "--quiet"+      , if wkCollate    opts then "--collate"    else "--no-collate"+      , "--copies", show (wkCopies opts)+      , "--zoom",   show (wkZoom   opts)+      ] +++      Prelude.concat+       [ [ "--grayscale"  | True <- [wkGrayscale  opts] ]+       , [ "--lowquality" | True <- [wkLowQuality opts] ]+       , toArgs (wkPageSize    opts)+       , toArgs (wkOrientation opts)+       , maybe [] (\t -> ["--title", t]) (wkTitle opts)+       , "--margin-bottom" : toArgs (wkMarginBottom opts)+       , "--margin-left"   : toArgs (wkMarginLeft   opts)+       , "--margin-right"  : toArgs (wkMarginRight  opts)+       , "--margin-top"    : toArgs (wkMarginTop    opts)+       ]++instance ToArgs PageSize where+  toArgs A4                   = ["--page-size", "A4"]+  toArgs Letter               = ["--page-size", "Letter"]+  toArgs (OtherPageSize s)    = ["--page-size", s]+  toArgs (CustomPageSize h w) = ("--page-height" : toArgs h) ++ ("--page-width" : toArgs w)++instance ToArgs Orientation where+  toArgs o = ["--orientation", show o]++instance ToArgs UnitReal where+  toArgs (Mm x)            = [show x ++ "mm"]+  toArgs (Cm x)            = [show x ++ "cm"]+  toArgs (OtherUnitReal s) = [s]
yesod-content-pdf.cabal view
@@ -1,5 +1,5 @@ name:                yesod-content-pdf-version:             0.1.0.2+version:             0.2.0.0 synopsis:            PDF Content Type for Yesod description:         Please see README.md homepage:            https://github.com/alexkyllo/yesod-content-pdf#readme@@ -30,6 +30,8 @@                      , temporary                      , yesod-core                      , conduit+                     , data-default+                     , transformers    default-language:    Haskell2010