pdf-slave 1.0.1.0 → 1.1.0.0
raw patch · 8 files changed
+99/−314 lines, 8 filesdep +pdf-slave-templatePVP ok
version bump matches the API change (PVP)
Dependencies added: pdf-slave-template
API changes (from Hackage documentation)
- Text.PDF.Slave.Template: BibtexDep :: BibTexBody -> TemplateDependency
- Text.PDF.Slave.Template: BibtexDepFile :: TemplateDependencyFile
- Text.PDF.Slave.Template: OtherDep :: DependencyBody -> TemplateDependency
- Text.PDF.Slave.Template: OtherDepFile :: TemplateDependencyFile
- Text.PDF.Slave.Template: Template :: TemplateName -> Maybe TemplateInput -> TemplateBody -> Map TemplateName TemplateDependency -> [Text] -> Template
- Text.PDF.Slave.Template: TemplateDep :: Template -> TemplateDependency
- Text.PDF.Slave.Template: TemplateDepFile :: TemplateFile -> TemplateDependencyFile
- Text.PDF.Slave.Template: TemplateFile :: TemplateName -> Maybe FilePath -> FilePath -> Map TemplateName TemplateDependencyFile -> [Text] -> TemplateFile
- Text.PDF.Slave.Template: TemplatePdfDep :: Template -> TemplateDependency
- Text.PDF.Slave.Template: TemplatePdfDepFile :: TemplateFile -> TemplateDependencyFile
- Text.PDF.Slave.Template: [templateBody] :: Template -> TemplateBody
- Text.PDF.Slave.Template: [templateDeps] :: Template -> Map TemplateName TemplateDependency
- Text.PDF.Slave.Template: [templateFileBody] :: TemplateFile -> FilePath
- Text.PDF.Slave.Template: [templateFileDeps] :: TemplateFile -> Map TemplateName TemplateDependencyFile
- Text.PDF.Slave.Template: [templateFileHaskintexOpts] :: TemplateFile -> [Text]
- Text.PDF.Slave.Template: [templateFileInput] :: TemplateFile -> Maybe FilePath
- Text.PDF.Slave.Template: [templateFileName] :: TemplateFile -> TemplateName
- Text.PDF.Slave.Template: [templateHaskintexOpts] :: Template -> [Text]
- Text.PDF.Slave.Template: [templateInput] :: Template -> Maybe TemplateInput
- Text.PDF.Slave.Template: [templateName] :: Template -> TemplateName
- Text.PDF.Slave.Template: data Template
- Text.PDF.Slave.Template: data TemplateDependency
- Text.PDF.Slave.Template: data TemplateDependencyFile
- Text.PDF.Slave.Template: data TemplateFile
- Text.PDF.Slave.Template: instance Data.Aeson.Types.Class.FromJSON Filesystem.Path.Internal.FilePath
- Text.PDF.Slave.Template: instance Data.Aeson.Types.Class.FromJSON Text.PDF.Slave.Template.Template
- Text.PDF.Slave.Template: instance Data.Aeson.Types.Class.FromJSON Text.PDF.Slave.Template.TemplateDependency
- Text.PDF.Slave.Template: instance Data.Aeson.Types.Class.FromJSON Text.PDF.Slave.Template.TemplateDependencyFile
- Text.PDF.Slave.Template: instance Data.Aeson.Types.Class.FromJSON Text.PDF.Slave.Template.TemplateFile
- Text.PDF.Slave.Template: instance Data.Aeson.Types.Class.ToJSON Filesystem.Path.Internal.FilePath
- Text.PDF.Slave.Template: instance Data.Aeson.Types.Class.ToJSON Text.PDF.Slave.Template.Template
- Text.PDF.Slave.Template: instance Data.Aeson.Types.Class.ToJSON Text.PDF.Slave.Template.TemplateDependency
- Text.PDF.Slave.Template: instance Data.Aeson.Types.Class.ToJSON Text.PDF.Slave.Template.TemplateDependencyFile
- Text.PDF.Slave.Template: instance Data.Aeson.Types.Class.ToJSON Text.PDF.Slave.Template.TemplateFile
- Text.PDF.Slave.Template: instance GHC.Generics.Generic Text.PDF.Slave.Template.Template
- Text.PDF.Slave.Template: instance GHC.Generics.Generic Text.PDF.Slave.Template.TemplateDependency
- Text.PDF.Slave.Template: instance GHC.Generics.Generic Text.PDF.Slave.Template.TemplateDependencyFile
- Text.PDF.Slave.Template: instance GHC.Generics.Generic Text.PDF.Slave.Template.TemplateFile
- Text.PDF.Slave.Template: instance GHC.Show.Show Text.PDF.Slave.Template.Template
- Text.PDF.Slave.Template: instance GHC.Show.Show Text.PDF.Slave.Template.TemplateDependency
- Text.PDF.Slave.Template: instance GHC.Show.Show Text.PDF.Slave.Template.TemplateDependencyFile
- Text.PDF.Slave.Template: instance GHC.Show.Show Text.PDF.Slave.Template.TemplateFile
- Text.PDF.Slave.Template: loadTemplateInMemory :: TemplateFile -> Sh (Either String Template)
- Text.PDF.Slave.Template: storeTemplateInFiles :: Template -> FilePath -> Sh TemplateFile
- Text.PDF.Slave.Template: type BibTexBody = Text
- Text.PDF.Slave.Template: type DependencyBody = ByteString
- Text.PDF.Slave.Template: type TemplateBibtex = Text
- Text.PDF.Slave.Template: type TemplateBody = Text
- Text.PDF.Slave.Template: type TemplateInput = Value
- Text.PDF.Slave.Template: type TemplateName = Text
+ Text.PDF.Slave.Render: loadTemplateInMemory :: TemplateFile -> Sh (Either String Template)
+ Text.PDF.Slave.Render: storeTemplateInFiles :: Template -> FilePath -> Sh TemplateFile
- Text.PDF.Slave: TemplateFile :: TemplateName -> Maybe FilePath -> FilePath -> Map TemplateName TemplateDependencyFile -> [Text] -> TemplateFile
+ Text.PDF.Slave: TemplateFile :: TemplateName -> Maybe Text -> Text -> Map TemplateName TemplateDependencyFile -> [Text] -> TemplateFile
- Text.PDF.Slave: [templateFileBody] :: TemplateFile -> FilePath
+ Text.PDF.Slave: [templateFileBody] :: TemplateFile -> Text
- Text.PDF.Slave: [templateFileInput] :: TemplateFile -> Maybe FilePath
+ Text.PDF.Slave: [templateFileInput] :: TemplateFile -> Maybe Text
- Text.PDF.Slave: data Template
+ Text.PDF.Slave: data Template :: *
- Text.PDF.Slave: data TemplateDependency
+ Text.PDF.Slave: data TemplateDependency :: *
- Text.PDF.Slave: data TemplateDependencyFile
+ Text.PDF.Slave: data TemplateDependencyFile :: *
- Text.PDF.Slave: data TemplateFile
+ Text.PDF.Slave: data TemplateFile :: *
Files
- CHANGELOG.md +5/−0
- LICENSE +2/−2
- README.md +2/−2
- app/Main.hs +2/−1
- pdf-slave.cabal +3/−15
- src/Text/PDF/Slave/Render.hs +84/−3
- src/Text/PDF/Slave/Template.hs +0/−291
- stack.yaml +1/−0
CHANGELOG.md view
@@ -1,3 +1,8 @@+1.1.0.0+=======++* Factor out `pdf-slave-template` package for compiler agnostic format definition.+ 1.0.1.0 =======
LICENSE view
@@ -1,4 +1,4 @@-Copyright Author name here (c) 2016+Copyright Anton Gushcha (c) 2016 All rights reserved. @@ -13,7 +13,7 @@ disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Author name here nor the names of other+ * Neither the name of Anton Gushcha here nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission.
README.md view
@@ -1,7 +1,7 @@ pdf-slave ========= -Tool that compiles `haskintex` (TeX with embedded Haskell) files into PDF documents.+Tool that compiles [haskintex](http://daniel-diaz.github.io/projects/haskintex/) (TeX with embedded Haskell) files into PDF documents. Templates are described in YAML format and can define dependencies. Features:@@ -28,7 +28,7 @@ located within a single template project, that describes how to build your PDF document in a declaretive way. Common work flow with pdf-slave:-* Develop template from several LaTeX files with embedded Haskell (thanks to haskintex+* Develop template from several LaTeX files with embedded Haskell (thanks to [haskintex](http://daniel-diaz.github.io/projects/haskintex/) tool) * Pack the template project into bundle all-in file.
app/Main.hs view
@@ -103,8 +103,9 @@ let bundle' = fromMaybe bundle $ (\i -> bundle { templateInput = i }) <$> optInput renderBundleToPDF bundle' baseDir Right template -> do+ inputOverwrite <- sequence $ fmap toTextWarn inputOverwritePath let template' = fromMaybe template $- (const $ template { templateFileInput = inputOverwritePath}) <$> optInput+ (const $ template { templateFileInput = inputOverwrite }) <$> optInput renderTemplateToPDF template' baseDir -- output results case pdfOutputPath of
pdf-slave.cabal view
@@ -1,5 +1,5 @@ name: pdf-slave-version: 1.0.1.0+version: 1.1.0.0 synopsis: Tool to generate PDF from haskintex templates and YAML input description: Please see README.md homepage: https://github.com/NCrashed/pdf-slave#readme@@ -21,7 +21,6 @@ exposed-modules: Text.PDF.Slave Text.PDF.Slave.Render- Text.PDF.Slave.Template default-language: Haskell2010 build-depends: base >= 4.7 && < 5@@ -32,28 +31,16 @@ , exceptions >= 0.8 && < 0.9 , haskintex >= 0.6 && < 0.8 , HaTeX >= 3.16 && < 3.18+ , pdf-slave-template == 1.1.0.0 , shelly >= 1.6 && < 1.7 , system-filepath >= 0.4 && < 0.5- , text >= 1.2 && < 1.3 , unordered-containers >= 0.2 && < 0.3 , yaml >= 0.8 && < 0.9- default-extensions:- BangPatterns DeriveGeneric- FlexibleContexts- FlexibleInstances- FunctionalDependencies- GADTs- GeneralizedNewtypeDeriving LambdaCase- MultiParamTypeClasses OverloadedStrings RecordWildCards- ScopedTypeVariables- StandaloneDeriving- TupleSections- TypeFamilies executable pdf-slave hs-source-dirs: app@@ -65,6 +52,7 @@ , bytestring >= 0.10 && < 0.11 , optparse-applicative >= 0.12 && < 0.13 , pdf-slave+ , pdf-slave-template , shelly >= 1.6 && < 1.7 , system-filepath >= 0.4 && < 0.5 , text >= 1.2 && < 1.3
src/Text/PDF/Slave/Render.hs view
@@ -8,6 +8,8 @@ , renderFromFileToPDF , renderBundleToPDF , renderTemplateToPDF+ , loadTemplateInMemory+ , storeTemplateInFiles -- * Low-level , DepFlags , DepFlag(..)@@ -135,9 +137,10 @@ minput <- case templateFileInput of Nothing -> return Nothing Just inputName -> do- cnt <- readBinary inputName+ let inputNamePath = fromText inputName+ cnt <- readBinary inputNamePath case A.eitherDecode' . BZ.fromStrict $ cnt of- Left e -> throwM $ InputFileFormatError inputName e+ Left e -> throwM $ InputFileFormatError inputNamePath e Right a -> return $ Just a renderPdfTemplate minput t baseDir outputFolder readBinary (outputFolder </> templateFileName <.> "pdf")@@ -175,7 +178,7 @@ let renderDepenency = renderTemplateDep minput baseDir outputFolder depFlags <- M.traverseWithKey renderDepenency templateFileDeps let- bodyName = dropExtension templateFileBody+ bodyName = dropExtension (fromText templateFileBody) haskintex = bash "haskintex" $ [ "-overwrite" , "-verbose"@@ -239,3 +242,81 @@ whenJust :: Applicative f => Maybe a -> (a -> f ()) -> f () whenJust Nothing _ = pure () whenJust (Just a) f = f a++-- | Load all external references of template into memory+loadTemplateInMemory :: TemplateFile -> Sh (Either String Template)+loadTemplateInMemory TemplateFile{..} = do+ inputCnt <- case templateFileInput of+ Nothing -> return $ Right Nothing+ Just fname -> do+ cnt <- readBinary . fromText $ fname+ return $ fmap Just . A.eitherDecode' . BZ.fromStrict $ cnt+ body <- readfile . fromText $ templateFileBody+ deps <- M.traverseWithKey loadDep templateFileDeps+ return $ Template+ <$> pure templateFileName+ <*> inputCnt+ <*> pure body+ <*> sequence deps+ <*> pure templateFileHaskintexOpts+ where+ loadDep name d = let+ filename = fromText name+ in case d of+ BibtexDepFile -> do+ cnt <- readfile filename+ return . pure $ BibtexDep cnt+ TemplateDepFile body -> do+ tmpl <- chdir filename $ loadTemplateInMemory body+ return $ TemplateDep <$> tmpl+ TemplatePdfDepFile body -> do+ tmpl <- chdir filename $ loadTemplateInMemory body+ return $ TemplatePdfDep <$> tmpl+ OtherDepFile -> do+ cnt <- readBinary filename+ return . pure $ OtherDep cnt++-- | Extract all external references of template into file system+storeTemplateInFiles :: Template -> FilePath -> Sh TemplateFile+storeTemplateInFiles Template{..} folder = do+ mkdir_p folder+ relInputName <- case templateInput of+ Nothing -> return Nothing+ Just input -> do+ let inputName = folder </> (templateName <> "_input") <.> "json"+ writeBinary inputName $ BZ.toStrict $ A.encode input+ fmap Just $ relativeTo folder inputName+ let bodyName = folder </> templateName <.> "htex"+ mkdir_p $ directory bodyName+ writefile bodyName templateBody+ relBodyName <- relativeTo folder bodyName+ deps <- M.traverseWithKey storeDep templateDeps+ return $ TemplateFile {+ templateFileName = templateName+ , templateFileInput = fmap toTextIgnore relInputName+ , templateFileBody = toTextIgnore relBodyName+ , templateFileDeps = deps+ , templateFileHaskintexOpts = templateHaskintexOpts+ }+ where+ storeDep name d = case d of+ BibtexDep body -> do+ let bodyName = folder </> name+ mkdir_p $ directory bodyName+ writefile bodyName body+ return BibtexDepFile+ TemplateDep template -> do+ let subfolderName = folder </> fromText name+ mkdir_p subfolderName+ dep <- storeTemplateInFiles template subfolderName+ return $ TemplateDepFile dep+ TemplatePdfDep template -> do+ let subfolderName = folder </> fromText name+ mkdir_p subfolderName+ dep <- storeTemplateInFiles template subfolderName+ return $ TemplatePdfDepFile dep+ OtherDep body -> do+ let bodyName = folder </> name+ mkdir_p $ directory bodyName+ writeBinary bodyName body+ return OtherDepFile
− src/Text/PDF/Slave/Template.hs
@@ -1,291 +0,0 @@--- | Defines document template-{-# OPTIONS_GHC -fno-warn-orphans #-}-module Text.PDF.Slave.Template(- TemplateName- , TemplateInput- , TemplateBody- , TemplateBibtex- , DependencyBody- , BibTexBody- , TemplateDependency(..)- , Template(..)- , TemplateDependencyFile(..)- , TemplateFile(..)- -- * Helpers- , loadTemplateInMemory- , storeTemplateInFiles- ) where--import Control.Monad (mzero)-import Data.ByteString (ByteString)-import Data.Monoid-import Data.Text as T-import Data.Yaml-import Filesystem.Path.CurrentOS (directory)-import GHC.Generics-import Prelude hiding (FilePath)-import Shelly as Sh--import qualified Data.Aeson as A-import qualified Data.ByteString.Base64 as B64-import qualified Data.ByteString.Lazy as BZ-import qualified Data.Map.Strict as M-import qualified Data.Text.Encoding as T---- | Template unique name-type TemplateName = Text---- | A template takes simple YAML document as input-type TemplateInput = Value---- | Template body is text with .htex content-type TemplateBody = Text---- | Template can define additional bibtex database-type TemplateBibtex = Text---- | Dependency can be a binary file-type DependencyBody = ByteString---- | Content of bibtex file-type BibTexBody = Text---- | Template has different types of dependencies, each type of the dependecy--- has own affect on rendering pipe.-data TemplateDependency =- -- | Bibtex file for references to other documents. Need call to bibtex- BibtexDep BibTexBody- -- | HTex file that need to be compiled to .tex file- | TemplateDep Template- -- | HTex file that need to be compiled to .pdf file- | TemplatePdfDep Template- -- | Any other file that doesn't need a compilation (listings, images, etc)- | OtherDep DependencyBody- deriving (Generic, Show)--instance FromJSON TemplateDependency where- parseJSON val@(Object o) = do- depType <- o .: "type"- case T.toLower . T.strip $ depType of- "bibtex" -> BibtexDep <$> o .: "body"- "template" -> TemplateDep <$> parseJSON val- "template_pdf" -> TemplatePdfDep <$> parseJSON val- "other" -> do- (t :: Text) <- o .: "body"- either (\e -> fail $ "Cannot decode dependency body (base64): " <> e) (return . OtherDep) $- B64.decode . T.encodeUtf8 $ t- _ -> fail $ "Unknown template type " <> unpack depType- parseJSON _ = mzero--instance ToJSON TemplateDependency where- toJSON d = case d of- BibtexDep body -> object [- "type" .= ("bibtex" :: Text)- , "body" .= body- ]- TemplateDep body -> let- Object o1 = object [ "type" .= ("template" :: Text) ]- Object o2 = toJSON body- in Object (o1 <> o2)- TemplatePdfDep body -> let- Object o1 = object [ "type" .= ("template_pdf" :: Text) ]- Object o2 = toJSON body- in Object (o1 <> o2)- OtherDep bs -> object [- "type" .= ("other" :: Text)- , "body" .= (T.decodeUtf8 . B64.encode $ bs)- ]---- | Description of document template-data Template = Template {- -- | Template has human readable name- templateName :: TemplateName- -- | Template expects input in YAML format- , templateInput :: Maybe TemplateInput- -- | Template contents- , templateBody :: TemplateBody- -- | Template dependencies (bibtex, listings, other htex files)- , templateDeps :: M.Map TemplateName TemplateDependency- -- | Additional flags for `haskintex`- , templateHaskintexOpts :: [Text]- } deriving (Generic, Show)--instance FromJSON Template where- parseJSON (Object o) = Template- <$> o .: "name"- <*> o .:? "input"- <*> o .: "body"- <*> o .:? "dependencies" .!= mempty- <*> o .:? "haskintex-opts" .!= mempty- parseJSON _ = mzero--instance ToJSON Template where- toJSON Template{..} = object [- "name" .= templateName- , "input" .= templateInput- , "body" .= templateBody- , "dependencies" .= templateDeps- , "haskintex-opts" .= templateHaskintexOpts- ]---- | Same as 'TemplateDependency' but keeps contents in separate files-data TemplateDependencyFile =- -- | Bibtex file for references to other documents. Need call to bibtex.- -- Name of dependency is a filename with contents.- BibtexDepFile- -- | HTex file that need to be compiled to .tex file- -- Name of dependency defines a subfolder for the template.- | TemplateDepFile TemplateFile- -- | HTex file that need to be compiled to .pdf file- -- Name of dependency deinfes a subfolder for the template.- | TemplatePdfDepFile TemplateFile- -- | Any other file that doesn't need a compilation (listings, images, etc)- -- Name of dependency is a filename with contents.- | OtherDepFile- deriving (Generic, Show)--instance FromJSON FilePath where- parseJSON (String s) = return $ Sh.fromText s- parseJSON _ = mzero--instance ToJSON FilePath where- toJSON = String . Sh.toTextIgnore--instance FromJSON TemplateDependencyFile where- parseJSON val@(Object o) = do- depType <- o .: "type"- case T.toLower . T.strip $ depType of- "bibtex" -> pure BibtexDepFile- "template" -> TemplateDepFile <$> parseJSON val- "template_pdf" -> TemplatePdfDepFile <$> parseJSON val- "other" -> pure OtherDepFile- _ -> fail $ "Unknown template type " <> unpack depType- parseJSON _ = mzero--instance ToJSON TemplateDependencyFile where- toJSON d = case d of- BibtexDepFile -> object [- "type" .= ("bibtex" :: Text)- ]- TemplateDepFile body -> let- Object o1 = object [ "type" .= ("template" :: Text) ]- Object o2 = toJSON body- in Object (o1 <> o2)- TemplatePdfDepFile body -> let- Object o1 = object [ "type" .= ("template_pdf" :: Text) ]- Object o2 = toJSON body- in Object (o1 <> o2)- OtherDepFile -> object [- "type" .= ("other" :: Text)- ]---- | Same as 'Template', but holds info about template content and dependencies--- in other files.-data TemplateFile = TemplateFile {- -- | Template has human readable name- templateFileName :: TemplateName- -- | Template expects input in JSON format. The field contains filename of the YAML file.- , templateFileInput :: Maybe FilePath- -- | Template contents filename.- , templateFileBody :: FilePath- -- | Template dependencies (bibtex, listings, other htex files)- , templateFileDeps :: M.Map TemplateName TemplateDependencyFile- -- | Additional flags for `haskintex`- , templateFileHaskintexOpts :: [Text]- } deriving (Generic, Show)--instance FromJSON TemplateFile where- parseJSON (Object o) = TemplateFile- <$> o .: "name"- <*> o .:? "input"- <*> o .: "body"- <*> o .:? "dependencies" .!= mempty- <*> o .:? "haskintex-opts" .!= mempty- parseJSON _ = mzero--instance ToJSON TemplateFile where- toJSON TemplateFile{..} = object [- "name" .= templateFileName- , "input" .= templateFileInput- , "body" .= templateFileBody- , "dependencies" .= templateFileDeps- , "haskintex-opts" .= templateFileHaskintexOpts- ]---- | Load all external references of template into memory-loadTemplateInMemory :: TemplateFile -> Sh (Either String Template)-loadTemplateInMemory TemplateFile{..} = do- inputCnt <- case templateFileInput of- Nothing -> return $ Right Nothing- Just fname -> do- cnt <- readBinary fname- return $ fmap Just . A.eitherDecode' . BZ.fromStrict $ cnt- body <- readfile templateFileBody- deps <- M.traverseWithKey loadDep templateFileDeps- return $ Template- <$> pure templateFileName- <*> inputCnt- <*> pure body- <*> sequence deps- <*> pure templateFileHaskintexOpts- where- loadDep name d = let- filename = fromText name- in case d of- BibtexDepFile -> do- cnt <- readfile filename- return . pure $ BibtexDep cnt- TemplateDepFile body -> do- tmpl <- chdir filename $ loadTemplateInMemory body- return $ TemplateDep <$> tmpl- TemplatePdfDepFile body -> do- tmpl <- chdir filename $ loadTemplateInMemory body- return $ TemplatePdfDep <$> tmpl- OtherDepFile -> do- cnt <- readBinary filename- return . pure $ OtherDep cnt---- | Extract all external references of template into file system-storeTemplateInFiles :: Template -> FilePath -> Sh TemplateFile-storeTemplateInFiles Template{..} folder = do- mkdir_p folder- relInputName <- case templateInput of- Nothing -> return Nothing- Just input -> do- let inputName = folder </> (templateName <> "_input") <.> "json"- writeBinary inputName $ BZ.toStrict $ A.encode input- fmap Just $ relativeTo folder inputName- let bodyName = folder </> templateName <.> "htex"- mkdir_p $ directory bodyName- writefile bodyName templateBody- relBodyName <- relativeTo folder bodyName- deps <- M.traverseWithKey storeDep templateDeps- return $ TemplateFile {- templateFileName = templateName- , templateFileInput = relInputName- , templateFileBody = relBodyName- , templateFileDeps = deps- , templateFileHaskintexOpts = templateHaskintexOpts- }- where- storeDep name d = case d of- BibtexDep body -> do- let bodyName = folder </> name- mkdir_p $ directory bodyName- writefile bodyName body- return BibtexDepFile- TemplateDep template -> do- let subfolderName = folder </> Sh.fromText name- mkdir_p subfolderName- dep <- storeTemplateInFiles template subfolderName- return $ TemplateDepFile dep- TemplatePdfDep template -> do- let subfolderName = folder </> Sh.fromText name- mkdir_p subfolderName- dep <- storeTemplateInFiles template subfolderName- return $ TemplatePdfDepFile dep- OtherDep body -> do- let bodyName = folder </> name- mkdir_p $ directory bodyName- writeBinary bodyName body- return OtherDepFile
stack.yaml view
@@ -37,6 +37,7 @@ # will not be run. This is useful for tweaking upstream packages. packages: - '.'+- 'pdf-slave-template' # Dependency packages to be pulled from upstream that are not in the resolver # (e.g., acme-missiles-0.3)